Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate - java.lang.NoClassDefFoundError

Implementing a web service using Hiberate for persistence layer. Works great, with no errors. However, when I write a unit test to access the Dao an encounter this error when getting an instance of the ServiceRegistry:

ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(
                    configuration.getProperties()).buildServiceRegistry();

Full stack trace:

java.util.ServiceConfigurationError: org.hibernate.integrator.spi.Integrator: Provider org.jadira.usertype.dateandtime.joda.integrator.UserTypeJodaTimeHibernateIntegrator could not be instantiated: java.lang.NoClassDefFoundError: org/jadira/usertype/dateandtime/shared/spi/AbstractVersionableUserType
    at java.util.ServiceLoader.fail(ServiceLoader.java:224)
    at java.util.ServiceLoader.access$100(ServiceLoader.java:181)
    at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:377)
    at java.util.ServiceLoader$1.next(ServiceLoader.java:445)
    at org.hibernate.service.classloading.internal.ClassLoaderServiceImpl.loadJavaServices(ClassLoaderServiceImpl.java:236)
    at org.hibernate.integrator.internal.IntegratorServiceImpl.<init>(IntegratorServiceImpl.java:53)
    at org.hibernate.service.internal.BootstrapServiceRegistryImpl.<init>(BootstrapServiceRegistryImpl.java:80)
    at org.hibernate.service.internal.BootstrapServiceRegistryImpl.<init>(BootstrapServiceRegistryImpl.java:57)
    at org.hibernate.service.ServiceRegistryBuilder.<init>(ServiceRegistryBuilder.java:76)
    at com.dg.dao.SessionConfig.getSession(SessionConfig.java:26)
    at com.dg.dao.CustomerHibernate.doGetSingleById(CustomerHibernate.java:210)
    at com.dg.dao.CustomerHibernate.getCustomerByID(CustomerHibernate.java:44)
    at com.dg.dao.test.CustomerDaoTest.testCustomerDao(CustomerDaoTest.java:27)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.NoClassDefFoundError: org/jadira/usertype/dateandtime/shared/spi/AbstractVersionableUserType

I have verified that the class does not exist in the classpath. To correct that I need to get an older version of usertype.spi.

Question is, why would it try to utilize an older class file when unit testing but work absolutely fine when running the service in a container? Has anyone seen this issue before?

like image 867
Scott Duncan Avatar asked May 30 '13 22:05

Scott Duncan


1 Answers

I figured out that this issue is caused by a clash among the following dependencies:

<dependency>
   <groupId>org.jadira.usertype</groupId>
   <artifactId>usertype.jodatime</artifactId>
   <version>2.0.1</version>
</dependency>

And

<dependency>
   <groupId>org.jadira.usertype</groupId>
   <artifactId>usertype.core</artifactId>
   <version>3.1.0.CR6</version>
</dependency>

The issue comes about in particular because both packages contain the PersistentDateTime class (although there are many other duplicate classes). Both instances of PersistentDateTime extend a class called AbstractVersionableUserType. The only thing is, the base classes here both reside in different packages. So, hibernate loads these types dynamically using reflection when creating the ServiceRegistry. The reason it bombs for junit is that hibernate is trying to load the PersistentDateTime class from the usertype.jodatime package and the actual class that needs to be loaded comes from the usertype.core package. It works in the container simply because there is a different classloader being used.

Anyway, when removing the usertype.jodatime dependency, everything works well.

like image 132
Scott Duncan Avatar answered Sep 25 '22 16:09

Scott Duncan