NHibernate configuration issue: "entry point was not found" - sharepoint

I'm configuring NHibernate on SharePoint 2010 web application.
Previously it works fine when mappings and domain were in one project. But during refactoring process I splitted solution on several projects. I've also implemented my custom IHttpModule where I want to initialize nhibernate configuration
protected void context_BeginRequest(object sender, EventArgs e)
{
var httpApplication = sender as HttpApplication;
lock (httpApplication )
{
if (!httpApplication.Context.Items.Contains(ApplicationConstants.IsApplicationInitialized))
{
httpApplication.Context.Items.Add(ApplicationConstants.IsApplicationInitialized, true);
InitInRequest(httpApplication);
}
}
httpApplication.Context.Items.Add(ApplicationConstants.SESSION, NhibernateManager.GetSession());
}
private void InitInRequest(HttpApplication httpApplication)
{
NhibernateManager.Init(ApplicationVariables.ApplicationSettingsPath);
}
And NHibernateManager.Init():
public static void Init(string configurationFilePath)
{
specifiedConfigurationFilePath = configurationFilePath;
Configure();
InitSessionFactory();
}
private static void Configure()
{
if (config == null)
{
if (string.IsNullOrEmpty(specifiedConfigurationFilePath) == false)
{
config = new Configuration();
config = config.Configure(specifiedConfigurationFilePath);
config = Fluently.Configure(config)
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<ItemMap>())
.BuildConfiguration();
}
else
{
config = Fluently.Configure()
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<ItemMap>())
.BuildConfiguration();
}
}
}
And in BuildConfiguration() I have very strange error (InnerException): "Entry point was not found." Stack trace shows that getting mapping information is cause of error:
at System.Collections.Generic.IDictionary`2.TryGetValue(TKey key, TValue& value)
at NHibernate.Cfg.Configuration.GetClassMapping(String entityName)
at NHibernate.Cfg.Configuration.GetClassMapping(Type persistentClass)
at FluentNHibernate.PersistenceModel.Configure(Configuration cfg)
at FluentNHibernate.Cfg.MappingConfiguration.Apply(Configuration cfg)
at FluentNHibernate.Cfg.FluentConfiguration.BuildConfiguration()
All assemblies are in the GAC. I tried to copy them in _app_bin or bin but without success.
UPDATE
Please, help me! I'm stuck with this weird problem :(

I found solution.
Take a look at my configuration lines:
config = new Configuration();
config = config.Configure(specifiedConfigurationFilePath);
config = Fluently.Configure(config)
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<ItemMap>())
.BuildConfiguration();
I'm creating new nhibernate configuration object passing it to fluent-nhibernate static initializer method. This is a point where things happen. Fluent-nhibernate can't take configuration from specified file. Instead it can take nhibernate configuration object with file path specified which it then uses to build configuration.
Previous version of my application was in one assembly and this way of configuration seems to work fine. But when I split up application the issue appeared.
So to solve the problem I should to take nhibernate configuration info from web.config file. I can't merge settings of timer job and web-application in one file as I could in single-assembly project. So I had to have several configuration files and always use classic lines like that:
Fluently
.Configure()
.Mappings(p => p.FluentMappings
.AddFromAssemblyOf<ItemMap>())
.BuildConfiguration()
It's appear to be some sort of fluent-nhibernate bug or something...

Related

AzurePageable breaks operation c#

I am having difficulties working with azure pageable.
I have these dificulties in several places.......
What happens is, if i interact with an AzurePageable and something goes wrong, the thread just doesnt return ........
For example yesterday I had too many requests to Azure Appconfiguration, the following piece of code would just hang.......
// Get all the settings from Azure app configuration
private static Dictionary<string, string> GetAllXYZSettings(ConfigurationClient client)
{
var settingsSelector = new SettingSelector() { KeyFilter = "xyz:*" };
var settings = client.GetConfigurationSettings(settingsSelector);
Dictionary<string, string> config = new();
foreach (dynamic setting in settings)
{
string settingValue = (string)setting.Value;
if (!string.IsNullOrEmpty(settingValue))
{
config.Add(setting.Key, settingValue);
}
}
return config;
}
I tried several things, wrapped everything in a try catch but my thread would just not return.
How should i read the config so i can do some correct error handeling .....
Same behaviour is also observed when reading the servicebus queues.......
wrapped in try catch, didn't work

How to put JSF message bundle outside of WAR so it can be edited without redeployment?

We have a JSF application on WildFly 8 which uses the traditionally mechanism with internationalizing text by having message bundles for German and English in the WEB-INF\classes folder of the WAR and a configuration in faces-config.xml mapping a name to it and listing the locales. The application does not have a database connection, but uses REST services to communicate with a 2nd application.
Now we need to be able to change text more easily, meaning not having to build a new WAR file and do a deployment when changing a text. So I need a mechanism to have the message bundles outside of the WAR while being able to use it as before within the XHTML pages.
Two optional requirements would be to change the text and refresh the messages in the application without having to restart the application (priority 2), and to have a default bundle within the WAR, which is overwritten by the external bundle (priority 3).
My thought was to use something like Apache commons configuration to read a property file within an Application scoped bean and expose a getter under the EL name used before. But somehow it feels like having to re-implement an existing mechanism and that this should somehow be easier, maybe even with Java EE core only.
Has someone used this mechanism in such a way and can point me to some example/description on the details or has a better idea to implement the listed requirement(s)?
How to put JSF message bundle outside of WAR?
Two ways:
Add its path to the runtime classpath of the server.
Create a custom ResourceBundle implementation with a Control.
change the text and refresh the messages in the application without having to restart the application
Changing the text will be trivial. However, refreshing is not trivial. Mojarra internally caches it agressively. This has to be taken into account in case you want to go for way 1. Arjan Tijms has posted a Mojarra specific trick to clear its internal resource bundle cache in this related question: How to reload resource bundle in web application?
If changing the text happens in the webapp itself, then you could simply perform the cache cleanup in the save method. If changing the text however can happen externally, then you'd need to register a file system watch service to listen on changes (tutorial here) and then either for way 1 clear the bundle cache, or for way 2 reload internally in handleGetObject().
have a default bundle within the WAR, which is overwritten by the external bundle
When loading them from classpath, the default behavior is the other way round (resources in WAR have higher classloading precedence), so this definitely scratches way 1 and leaves us with way 2.
Below is a kickoff example of way 2. This assumes that you're using property resource bundles with a base name of text (i.e. no package) and that the external path is located in /var/webapp/i18n.
public class YourBundle extends ResourceBundle {
protected static final Path EXTERNAL_PATH = Paths.get("/var/webapp/i18n");
protected static final String BASE_NAME = "text";
protected static final Control CONTROL = new YourControl();
private static final WatchKey watcher;
static {
try {
watcher = EXTERNAL_PATH.register(FileSystems.getDefault().newWatchService(), StandardWatchEventKinds.ENTRY_MODIFY);
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
}
private Path externalResource;
private Properties properties;
public YourBundle() {
Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
setParent(ResourceBundle.getBundle(BASE_NAME, locale, CONTROL));
}
private YourBundle(Path externalResource, Properties properties) {
this.externalResource = externalResource;
this.properties = properties;
}
#Override
protected Object handleGetObject(String key) {
if (properties != null) {
if (!watcher.pollEvents().isEmpty()) { // TODO: this is naive, you'd better check resource name if you've multiple files in the folder and keep track of others.
synchronized(properties) {
try (InputStream input = new FileInputStream(externalResource.toFile())) {
properties.load(input);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
}
return properties.get(key);
}
return parent.getObject(key);
}
#Override
#SuppressWarnings({ "rawtypes", "unchecked" })
public Enumeration<String> getKeys() {
if (properties != null) {
Set keys = properties.keySet();
return Collections.enumeration(keys);
}
return parent.getKeys();
}
protected static class YourControl extends Control {
#Override
public ResourceBundle newBundle
(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
throws IllegalAccessException, InstantiationException, IOException
{
String resourceName = toResourceName(toBundleName(baseName, locale), "properties");
Path externalResource = EXTERNAL_PATH.resolve(resourceName);
Properties properties = new Properties();
try (InputStream input = loader.getResourceAsStream(resourceName)) {
properties.load(input); // Default (internal) bundle.
}
try (InputStream input = new FileInputStream(externalResource.toFile())) {
properties.load(input); // External bundle (will overwrite same keys).
}
return new YourBundle(externalResource, properties);
}
}
}
In order to get it to run, register as below in faces-config.xml.
<application>
<resource-bundle>
<base-name>com.example.YourBundle</base-name>
<var>i18n</var>
</resource-bundle>
</application>

Using property files in Web Applications [duplicate]

This question already has answers here:
How to get properties file from /WEB-INF folder in JSF?
(3 answers)
Closed 7 years ago.
I'm developing a web application(this is my first time) and pretty confused about using property files. I don't know where to put the property files.
The problem is that i have put it under the WEB_INF folder. And when i test run it as a Java Application to check whether Database connections are working according to the properties in the property file it is working without any problem.
But when i run it in a Server as a Web Application it fails to load the properties file saying it could not find the file in the path specified. I tried using every possible path i could give and changing the file directories within the whole project. But I kept getting the same error.
Then i changed my class again from scratch thinking there's some kind of a bug withing my code where i load the properties file. And it seems that it could not find the file either when deployed as a Web App. But my test application works fine. Where do i put this file and how do i use it. I have read #BalusC's answer in this thread https://stackoverflow.com/a/2161583/2999358 but i have no idea why this happens. Can someone help me on this?
I'm using Tomcat 8, Eclipse IDE and building on JSF framework.
Class where i load my properties file
public class ConfigCache {
private static final File FILE = new File("./WebContent/WEB-INF/conf/config.properties");
private static final Properties PROPERTIES = new Properties();
public static final String JDBC_DRIVER = ConfigCache.getProperty("db.driverName");
public static final String DATABASE_URL = ConfigCache.getProperty("db.url");
public static final String DATABASE_USERNAME = ConfigCache.getProperty("db.user");
public static final String DATABASE_PASSWORD = ConfigCache.getProperty("db.pass");
public ConfigCache() {
}
public static String getProperty(String key) {
if (PROPERTIES.isEmpty()) {
loadProperties();
}
Object value;
return (value = PROPERTIES.get(key)) == null ? "" : value.toString();
}
private static void loadProperties() {
if (!FILE.exists()) {
throw new IllegalArgumentException("The 'config.properties' has not been found.");
}
try {
FileInputStream fis = null;
try {
fis = new FileInputStream(FILE);
PROPERTIES.load(fis);
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException exp) {
System.out.println("IOException #" + ConfigCache.class + " # loadProperties() : " + exp);
}
}
} catch (Exception exp) {
System.out.println("Exception #" + ConfigCache.class + " # loadProperties() : " + exp);
}
}
}
Folder Structure
Try With this.
put the property in src folder.
Your file is in the WEB-INF directory. This means it's part of the war and reachable as part of the class path. That's perfectly ok, since it makes it portable and independant of the web container installation (e.g. Tomcat).
You can load any file in the class path as a resource:
getClass().getResourceAsStream("/conf/config.properties")
This means you can write your code like this:
private static void loadProperties() {
InputStream is = getClass().getResourceAsStream("/conf/config.properties");
PROPERTIES.load(fis);
}
(Error handling omitted)
You can explode (unzip) your war/ear file and see the contents or folder structure of it and find why your code doesnt work. The reason is that the folder WebContent doesnt exist in your ear/war , but does exist only when run via eclipse. This is the reason why its always better to follow the solution provided in the link posted so that you can retrieve the porperty files from classpath. The below code fetches your property file in eclipse but not in the server.
private static final File FILE = new File("./WebContent/WEB-INF/conf/config.properties");
Contents of WAR file (from JournelDev), it contains WEB-INF directory but there would be no WebContent directory above it

How to setup Autofac registration

Im new to dependency injection and Ive decided to use autofac as it seems to have the best 'out of the box' support for MVC5 (others might be better but im a newbie to this)
Im creating simple use scenarios and from the wiki ive got the following code in application_start in global.asax
protected void Application_Start()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<ArtistController>().InstancePerHttpRequest();
builder.RegisterType<ArtistService>().As<IArtistService>().SingleInstance();
builder.RegisterType<ArtistRepository>().As<IArtistRepository>().SingleInstance();
builder.RegisterType<BandMemberRepository>().As<IBandMemberRepository>).SingleInstance();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
and in my ArtistController I have this
private IArtistService _artistService;
I then have some code the retrieves and updates data, all very simple. This works ok and Im starting to get my head around the whole concept.
My question is this, do I have to register all the concrete classes Im using manually ? My app could eventually grow and I would have many, many classes so this will be a pain to manage. I did come across this
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
which as far as Im aware should register everything for me but it didnt work. Am I doing something wrong ?
ok, thanks for the advice.
the autofac website shows an example using lambdas, so I added this in global.asax
builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces();
but that didnt work, any idea why ?
I do most (90+%) of my registrations by tagging them with this attribute:
[AttributeUsage(AttributeTargets.Class)]
[JetBrains.Annotations.MeansImplicitUse]
public class AutoRegisterAttribute : Attribute {}
Then I use this module to register those classes:
public class AutoRegisterModule : Module
{
private readonly Assembly[] _assembliesToScan;
public AutoRegisterModule(params Assembly[] assembliesToScan)
{
_assembliesToScan = assembliesToScan;
}
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(_assembliesToScan)
.Where(t => t.GetCustomAttribute<AutoRegisterAttribute>(false) != null)
.AsSelf()
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
}
public static AutoRegisterModule ForCallingAssembly()
{
return new AutoRegisterModule(Assembly.GetCallingAssembly());
}
}
So when I'm building my container, I typically just do:
builder.RegisterModule(AutoRegisterModule.ForCallingAssembly());

Spec fails when run by mspec.exe, but passes when run by TD.NET

I wrote about this topic in another question.
However, I've since refactored my code to get rid of configuration access, thus allowing the specs to pass. Or so I thought. They run fine from within Visual Studio using TestDriven.Net. However, when I run them during rake using the mspec.exe tool, they still fail with a serialization exception. So I've created a completely self-contained example that does basically nothing except setup fake security credentials on the thread. This test passes just fine in TD.Net, but blows up in mspec.exe. Does anybody have any suggestions?
Update: I've discovered a work-around. After researching the issue, it seems the cause is that the assembly containing my principal object is not in the same folder as the mspec.exe. When mspec creates a new AppDomain to run my specs, that new AppDomain has to load the assembly with the principal object in order to deserialize it. That assembly is not in the same folder as the mspec EXE, so it fails. If I copied my assembly into the same folder as mspec, it works fine.
What I still don't understand is why ReSharper and TD.Net can run the test just fine? Do they not use mspec.exe to actually run the tests?
using System;
using System.Security.Principal;
using System.Threading;
using Machine.Specifications;
namespace MSpecTest
{
[Subject(typeof(MyViewModel))]
public class When_security_credentials_are_faked
{
static MyViewModel SUT;
Establish context = SetupFakeSecurityCredentials;
Because of = () =>
SUT = new MyViewModel();
It should_be_initialized = () =>
SUT.Initialized.ShouldBeTrue();
static void SetupFakeSecurityCredentials()
{
Thread.CurrentPrincipal = CreatePrincipal(CreateIdentity());
}
static MyIdentity CreateIdentity()
{
return new MyIdentity(Environment.UserName, "None", true);
}
static MyPrincipal CreatePrincipal(MyIdentity identity)
{
return new MyPrincipal(identity);
}
}
public class MyViewModel
{
public MyViewModel()
{
Initialized = true;
}
public bool Initialized { get; set; }
}
[Serializable]
public class MyPrincipal : IPrincipal
{
private readonly MyIdentity _identity;
public MyPrincipal(MyIdentity identity)
{
_identity = identity;
}
public bool IsInRole(string role)
{
return true;
}
public IIdentity Identity
{
get { return _identity; }
}
}
[Serializable]
public class MyIdentity : IIdentity
{
private readonly string _name;
private readonly string _authenticationType;
private readonly bool _isAuthenticated;
public MyIdentity(string name, string authenticationType, bool isAuthenticated)
{
_name = name;
_isAuthenticated = isAuthenticated;
_authenticationType = authenticationType;
}
public string Name
{
get { return _name; }
}
public string AuthenticationType
{
get { return _authenticationType; }
}
public bool IsAuthenticated
{
get { return _isAuthenticated; }
}
}
}
Dan,
thank you for providing a reproduction.
First off, the console runner works differently than the TestDriven.NET and ReSharper runners. Basically, the console runner has to perform a lot more setup work in that it creates a new AppDomain (plus configuration) for every assembly that is run. This is required to load the .dll.config file for your spec assembly.
Per spec assembly, two AppDomains are created:
The first AppDomain (Console) is created
implicitly when mspec.exe is
executed,
a second AppDomain is created by mspec.exe for the assembly containing the specs (Spec).
Both AppDomains communicate with each other through .NET Remoting: For example, when a spec is executed in the Spec AppDomain, it notifies the Console AppDomain of that fact. When Console receives the notification it acts accordingly by writing the spec information to the console.
This communiciation between Spec and Console is realized transparently through .NET Remoting. One property of .NET Remoting is that some properties of the calling AppDomain (Spec) are automatically included when sending notifications to the target AppDomain (Console). Thread.CurrentPrincipal is such a property. You can read more about that here: http://sontek.vox.com/library/post/re-iprincipal-iidentity-ihttpmodule-serializable.html
The context you provide will run in the Spec AppDomain. You set Thread.CurrentPrincipal in the Because. After Because ran, a notification will be issued to the Console AppDomain. The notification will include your custom MyPrincipal that the receiving Console AppDomain tries to deserialize. It cannot do that since it doesn't know about your spec assembly (as it is not included in its private bin path).
This is why you had to put your spec assembly in the same folder as mspec.exe.
There are two possible workarounds:
Derive MyPrincipal and MyIdentity from MarshalByRefObject so that they can take part in cross-AppDomain communication through a proxy (instead of being serialized)
Set Thread.CurrentPrincipal transiently in the Because
(Text is required for formatting to work -- please ignore)
Because of = () =>
{
var previousPrincipal = Thread.CurrentPrincipal;
try
{
Thread.CurrentPrincipal = new MyPrincipal(...);
SUT = new MyViewModel();
}
finally
{
Thread.CurrentPrincipal = previousPrincipal;
}
}
ReSharper, for example, handles all the communication work for us. MSpec's ReSharper Runner can hook into the existing infrastructure (that, AFAIK, does not use .NET Remoting).

Resources