Hibernate version: Hibernate 3
I have been trying to deploy multiple applications that all use hibernate. If I package all jars from my application, my model, and from hibernate into a massive deployment it all works beautifully.
However, when I try to deploy hibernate as a reusable service (with its own classloader), I ran into some problems that I came up with hacked fixes for. But I would be curious if anyone has more brilliant insights or alternative/better solutions. If it makes any difference, my application, model, and hibernate service are all deployed as Eclipse plugins.
(Apologies in advance if this posting is horrible to read... I guess that's what happens with ClassLoaders.)
Anyhow, in order to load my application's config file, mapping files, and model classes when using hibernate as a separately deployed service, my calling application sets the thread's context class loader as described elsewhere in the forum.
While this worked for hibernate's use of my application's resources, my proxy interfaces could not be loaded by cglib
(see the
cglib issue)
and my ehcache.xml file could not be loaded by ehcache
(see the
ehcache issue)
since these projects do not use the thread's context class loader to load the required application specific resources.
As described in those issue reports, I hacked a solution with changes to 4 lines of code. (Note that the cglib change required a line change in my local copy of SessionFactoryImpl since the two nested protected interfaces run into some IllegalAccessError problems with the modified cglib using the thread's context class loader unless (1) the interfaces are public, or (2) the ClassLoader for SessionFactoryImpl is passed into cglib when calling KeyFactory.create.
Anyone have better ideas????
Also, something feels odd to me about having to manually set the thread's context class loader in my application. If I set the context class loader back to its original value after loading the configuration and building the session factory, I also get exceptions. (I believe this is
recommended practice).
In particular, when queries are executed after I have reset it, I get the following stack trace (note that biocentric is both my schema and root package name... so I don't know which the error refers to... I assume the package, since we're talking about class loaders):
Caused by: org.hibernate.QueryException: undefined alias: biocentric [select experiment from biocentric.model.experiment.impl.Experiment experiment order by experiment.title]
at org.hibernate.hql.PathExpressionParser.token(PathExpressionParser.java:129)
at org.hibernate.hql.ParserHelper.parse(ParserHelper.java:29)
at org.hibernate.hql.FromParser.token(FromParser.java:192)
at org.hibernate.hql.ClauseParser.token(ClauseParser.java:86)
at org.hibernate.hql.PreprocessingParser.token(PreprocessingParser.java:107)
at org.hibernate.hql.ParserHelper.parse(ParserHelper.java:29)
at org.hibernate.hql.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:177)
at org.hibernate.hql.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:148)
at org.hibernate.impl.SessionFactoryImpl.getQuery(SessionFactoryImpl.java:386)
at org.hibernate.impl.SessionImpl.getQueries(SessionImpl.java:830)
at org.hibernate.impl.SessionImpl.find(SessionImpl.java:801)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:84)
at common.model.hibernate.HibernateQuery.list(HibernateQuery.java:131)
Does this mean I would have to set the context class loader before each call to the session api?
So, in the end, unless someone has some brilliant solutions, I think I'll probably reluctantly go back to my deployment where hibernate, my model, and its hibernate configuration files are deployed repeatedly with each application using them. However, it feels like I'm yielding to technical dificulties of Java/classloaders rather than conceptual problems.
(Note that I don't blame hibernate for these difficulties, you guys are excellent.)
Anyhow, thanks for reading this...... Go get some sleep.[/url]