Reputation: 667
I have three projects, Web, EJB3, JPA-entities. EJB3 and JPA-entities project will be exported into Web/WebContent/WEB-INF/lib as jar files. I also put MySQL driver jar file in the "WEB-INF/lib".
but...
jboss can't find MySQL driver... the following is persistence.xml:
<persistence-unit name="HandShakeEntity">
<class>net.magidea.handshake.entity.User</class>
<class>net.magidea.handshake.entity.UserItem</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="dj/4ej03" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/handshake" />
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
</properties>
</persistence-unit>
and log:
13:09:26,070 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 48) MSC000001: Failed to start service jboss.persistenceunit."HandShakeWeb.war#HandShakeEntity": org.jboss.msc.service.StartException in service jboss.persistenceunit."HandShakeWeb.war#HandShakeEntity": javax.persistence.PersistenceException: [PersistenceUnit: HandShakeEntity] Unable to build EntityManagerFactory
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:103) [jboss-as-jpa-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) [rt.jar:1.7.0_07]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) [rt.jar:1.7.0_07]
at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_07]
at org.jboss.threads.JBossThread.run(JBossThread.java:122) [jboss-threads-2.1.0.Final-redhat-1.jar:2.1.0.Final-redhat-1]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: HandShakeEntity] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:930)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:92)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.createContainerEntityManagerFactory(PersistenceUnitServiceImpl.java:200) [jboss-as-jpa-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.access$600(PersistenceUnitServiceImpl.java:57) [jboss-as-jpa-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:99) [jboss-as-jpa-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
... 4 more
Caused by: org.hibernate.service.classloading.spi.ClassLoadingException: Specified JDBC Driver com.mysql.jdbc.Driver could not be loaded
at org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl.configure(DriverManagerConnectionProviderImpl.java:111)
at org.hibernate.service.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:75)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:159)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:131)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(JdbcServicesImpl.java:223)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:89)
at org.hibernate.service.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:75)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:159)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:131)
at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:78)
at org.hibernate.cfg.Configuration.buildSettingsInternal(Configuration.java:2283)
at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2279)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1748)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:920)
... 9 more
Caused by: org.hibernate.service.classloading.spi.ClassLoadingException: Unable to load class [com.mysql.jdbc.Driver]
at org.hibernate.service.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:149)
at org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl.configure(DriverManagerConnectionProviderImpl.java:106)
... 23 more
Caused by: java.lang.ClassNotFoundException: Could not load requested class : com.mysql.jdbc.Driver
at org.hibernate.service.classloading.internal.ClassLoaderServiceImpl$AggregatedClassLoader.findClass(ClassLoaderServiceImpl.java:296)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423) [rt.jar:1.7.0_07]
at java.lang.ClassLoader.loadClass(ClassLoader.java:356) [rt.jar:1.7.0_07]
at java.lang.Class.forName0(Native Method) [rt.jar:1.7.0_07]
at java.lang.Class.forName(Class.java:264) [rt.jar:1.7.0_07]
at org.hibernate.service.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:146)
... 24 more
There is a solution I was found unexpectedly. If I put MySQL driver jar into [JBoss EAP 6.1 Home]\modules\system\layers\base\org\hibernate\main, and update module.xml to include driver jar, It's worked, but I don't know why my Web app has any relationship with hibernate module.
Upvotes: 3
Views: 3200
Reputation: 40298
This is because of how classloading works in a JEE environment. You see, there are nested classloaders, with the web application classloader coming at the end of the hierarchy. This means that while the web-app classloader can see classes loaded by its parents, its parents cannot see classes loaded by the child (the web-app CL).
In a JEE environment you have the system classloader (as always), then there would be an application server classloader (loads the API - e.g. javax.servlet.*
and the application server specific implementations). Finally there is a classloader per EAR, then a classloader per WAR, as:
system CL
|
+- Application server CL (loads e.g. Hibernate as the JPA implementation)
|
+- EAR 1 CL
| |
| +- WAR 1_1 CL
| |
| +- WAR 1_2 CL
|
+- WAR 1 CL (In your case, this loads the MySQL driver)
(this is oversimplified, just to demonstrate the principles) Each child in the tree above sees the classes loaded by its parents, but NOT classes loaded by its own children or peers.
In your case the MySQL driver JAR is placed in WEB-INF/lib
, i.e. loaded by the web-app CL, but the JPA implementation (Hibernate) is loaded by a parent CL. This CL tries to find the classes for the driver and fails for the reason explained above. This is also why things work when you put the driver in modules/
, since this is the classpath of the parent CL, the one that loads Hibernate.
In any case I think the solution is to put the driver in modules/
, as described in the "Installing the JDBC Driver" section of this. If you have a good reason to bundle things in your application, then you will have to bundle the JPA implementation too (i.e. put the Hibernate JARs in EB-INF/lib
too).
Upvotes: 4