|
My test case is a bit complex. I'm using Tomcat and I have my hibernate libs in the WEB-INF/lib of my web application. However I have a "service factory" that lives in the Tomcat shared/lib classpath which maintains an instance of my hibernate persistence wrapper. The persistence wrapper passes itself to the service factory along with its classloader. Now in web application B, I get an instance of my persistence wrapper and I use it to load in the hibernate mapping files in webapp B. As long as lazy="false" it works fine. Otherwise if lazy is true, I get this stack trace: net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null And why is it not enough for you to set the current thread context classloader before and after the calls ? But in any case having both hibernate in server lib and your web app sounds like a really bad idea. I don't think I explained well enough-- here's the actual structure webappA/WEB-INF/lib webappB/ shared/lib So webappB has access to the PersistenceService interface since it's in shared/lib, but the actual impl is in webappA and has webapp A's classloader. To recap, if lazy is false,then webappB can use the concrete PersistenceServiceImpl to load in the mapping files in B. However, if lazy is true, then the proxies need to be created. I then tried experimenting with Configuration.addResource(mappingFile, classLoader) in the PersistenceServiceImpl so that it could use webapp B's classloader to locate its mapping file and was greeted with this error: Caused by: java.lang.NoClassDefFoundError: org/hibernate/proxy/HibernateProxy which seems in line with the reporter of http://opensource.atlassian.com/projects/hibernate/browse/HHH-2318 In a nutshell I am trying to figure out any possible way where the hibernate and co. jars do not need to be placed in every single webapp. Thanks, Jason so remove the hibernate jars you have in webapp's and just use the one in the server lib. But only load classes when you actually are inside the scope of the webapp! Nothing weird about this. But it is definitly not recommended to use libs from server libs since it very often (always?) result in redeployment Here's a patch against hibernate 3.1.3, which changes the order of interfaces so that the class HibernateProxy is located as the last one. This problem seems to be present in hibernate 3.2.5ga as well; I guess that this fix would also apply there. We seem to have this issue, too, with Hibernate 3.2.6. The hibernate-3.1.patch solves the problem for us. Specific details:
Problem: Hibernate is not able to load the CGLIB generated proxy class. Our analysis shows that the CGLIB generated byte code that references the application class interfaces cannot be loaded. This is because hibernate does not tell CGLIB which class loader to use and CGLIB implicitly takes the one from the first interface of the generated proxy. This often is a hibernate provided interface (HibernateProxy), coming from class loader "J". This class loader has no access to the classes from class loader "A", where the application interfaces come from, so CGLIB cannot load the proxy class. The following alternatives have been evaluated and rejected:
The patch provided by Pietu above (hibernate-3.1.patch) solves the problem, we would be glad to see it in a future hibernate release. I still have the feeling that the ClassLoader for the generated proxy classes should be defined explicitly by hibernate. A patch for 3.2.6 to implement b) will follow, soon. Attached the patch in agreement with Martin Kneissl: HibernateSpecifyClassLoaderToCGLIB.patch This patch worked for us and is as unobtrusive as it can be. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
what exactly does not work here ? testcase?
I load classes constantly from a different classloader; namely the one that is set via the current context thread classloader.