Migration from JBoss AS4 to 7 leads to problem with Hibernate
t.b Nov 3, 2011 1:54 PMHi,
currently we're still runing JBoss 4.2.2 on production but would like to upgrade to a much more recent version. For our projects we're actually using JBoss as a better servlet container, the projects contain their dependencies and implementations of EE features. They do run on plain tomcat on the developers' machines.
Unfortunately I'm having trouble getting our most recent project to work on JBoss 7.0.2. It is based on JSF (MyFaces, Richfaces), JPA (Hibernate 3 in "JPA mode") and Spring 3. Also a generic DAO implementation (http://code.google.com/p/hibernate-generic-dao/) is involved. All dependencies and implementations are included in the *.war file, the same package runs fine on Tomcat 6 and JBoss 4.2.2.
After some fiddling with the configuration to prevent JBoss from injecting Hibernate 4 - which seems to be incompatible with our Spring version - I've got it to deploy. The landing page, containing JSF/Richfaces but no database content, renders fine. When I try to login or otherwise to access the database I get an Exception.
java.lang.NullPointerException org.hibernate.impl.SessionFactoryImpl.getClassMetadata(SessionFactoryImpl.java:807) com.googlecode.genericdao.search.hibernate.HibernateMetadataUtil.get(HibernateMetadataUtil.java:92) com.googlecode.genericdao.search.hibernate.HibernateMetadataUtil.get(HibernateMetadataUtil.java:103) com.googlecode.genericdao.search.BaseSearchProcessor.prepareValue(BaseSearchProcessor.java:708) com.googlecode.genericdao.search.BaseSearchProcessor.filterToQL(BaseSearchProcessor.java:454) com.googlecode.genericdao.search.BaseSearchProcessor.generateWhereClause(BaseSearchProcessor.java:414) com.googlecode.genericdao.search.BaseSearchProcessor.generateQL(BaseSearchProcessor.java:111) com.googlecode.genericdao.search.jpa.JPASearchProcessor.searchUnique(JPASearchProcessor.java:189) com.googlecode.genericdao.dao.jpa.JPABaseDAO._searchUnique(JPABaseDAO.java:434) com.googlecode.genericdao.dao.jpa.GenericDAOImpl.searchUnique(GenericDAOImpl.java:137) de.motionet.internal.rhylia.facade.user.DefaultUserFacade.load(DefaultUserFacade.java:217) de.motionet.internal.rhylia.facade.user.DefaultUserFacade.loadUserByUsername(DefaultUserFacade.java:306) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ...
From what I can see in the code of the genericdao implementation this means that SessionFactory.getClassMetadata must have returned null for the entity classes. I am sure that Hibernate finds and knows my @Entity classes since there are a lot of log entries during the deployment that tell me there was an error creating the table because it already exists.
What I don't get is why the same code and almost the same configuration (I had to disable second level caching EhCache) works on JBoss AS 4.2.2 and on Tomcat 6 but not on JBoss AS 7.0.2 I have tried a nightly build, without success. This is the reason why I'm asking in the AS forum and not in the hibernate forum.
Here's my persistence.xml:
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="rhylia" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.hbm2ddl.auto" value="create" /> <property name="hibernate.archive.autodetection" value="class,hbm" /> <property name="hibernate.show_sql" value="false" /> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> <property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider"/> <property name="hibernate.connection.password" value="xxxxx" /> <property name="hibernate.connection.url" value="jdbc:mysql://localhost/rhylia" /> <property name="hibernate.connection.username" value="xxxxx" /> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" /> <property name="hibernate.c3p0.min_size" value="5" /> <property name="hibernate.c3p0.max_size" value="20" /> <property name="hibernate.c3p0.timeout" value="300" /> <property name="hibernate.c3p0.max_statements" value="50" /> <property name="hibernate.c3p0.idle_test_period" value="3000" /> <!-- Hibernate EJB Caching --> <!-- property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.EhCacheRegionFactory"/--> <property name="hibernate.cache.use_second_level_cache" value="false"/> <property name="hibernate.cache.use_query_cache" value="true"/> <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.EhCacheProvider" /> <property name="hibernate.cache.provider_configuration_file_resource_path" value="/ehcache.xml" /> <property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider"/> <property name="jboss.as.jpa.providerModule" value="hibernate3-bundled"/> </properties> </persistence-unit> </persistence>
Two changes made here are hibernate.cache.use_second_level_cache and adding jboss.as.jpa.providerModule. The file is included in the same jar as the entity classes.
I know I'm supposed to let the app server handle database configuration for me and receive the connection from it. If this is absolutely necessary it would be an option, but I'd prefer to skip this step. At least for now.
I added a jboss-deployment-structure.xml to exclude "org.hibernate" to prevent injecting version 4; I need 3.x for now.
What am I doing wrong? How do I get this to work? Help would be very appreciated.
Btw: is there a way to exclude implicit dependencies? Can I tell AS7 that I want it to handle a given *.war as a servlet container would, no matter what it autodetects in there?
Greetings,
Thomas