Hibernate 3.5.x: NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval

I'm trying to upgrade to Hibernate 3.5.3-FINAL.

When running my unit tests, I now receive the following exception:

java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()Z   
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1837)

My classpath contains the following JAR's:

From the hibernate dist:

antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
javassist-3.9.0.GA.jar
jta-1.1.jar
slf4j-api-1.5.8.jar

cglib-2.2.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar
hibernate3.jar

Other jars:

blazeds-common-3.2.0.3978.jar
blazeds-core-3.2.0.3978.jar
blazeds-opt-3.2.0.3978.jar
blazeds-proxy-3.2.0.3978.jar
blazeds-remoting-3.2.0.3978.jar
commons-lang-2.3.jar
dbunit-2.4.7.jar
ejb3-persistence.jar // Note, I've tried excluding this, but I get different errors
guava-r05.jar
hsqldb-1.8.0.7.jar
junit-4.1.jar
lambdaj-2.0-with-dependencies.jar
log4j-1.2.14.jar
mockito-all-1.8.0.jar
persistence-api-1.0.jar
spring-security-core-2.0.0.jar
spring.jar
sqljdbc.jar

I've researched this, and I find answers that state my webserver must be JPA2 Compliant:

Unfortunately if your app server is not JPA 2 compliant, you are likely to be out of luck

This project is a library, not a webserver project. (Although it is eventually deployed to a webserver, I'm simply running unit tests here)

What am I missing?

<indulgent_rant>

As a sidenote, it's very frustrating that every time I upgrade Hibernate, I find myself spending hours researching conflicting jars for MethodNotFoundException or ClassNotFoundException's. There must be a simpler way?

I thought for sure that with the announcement they were merging the modules back to a single core project, that these conflicts would go away?

</indulgent_rant>


Solution 1:

As pointed out by Timo, remove persistence-api-1.0.jar.

Just in case, here are the dependencies I'm using:

org.hibernate:hibernate-entitymanager:jar:3.5.3-Final:compile
+- org.hibernate:hibernate-core:jar:3.5.3-Final:compile
|  +- antlr:antlr:jar:2.7.6:compile
|  +- commons-collections:commons-collections:jar:3.2:compile
|  +- dom4j:dom4j:jar:1.6.1:compile
|  |  \- xml-apis:xml-apis:jar:1.0.b2:compile
|  \- javax.transaction:jta:jar:1.1:compile
+- org.hibernate:hibernate-annotations:jar:3.5.3-Final:compile
|  \- org.hibernate:hibernate-commons-annotations:jar:3.2.0.Final:compile
+- cglib:cglib:jar:2.2:compile
|  \- asm:asm:jar:3.1:compile
+- javassist:javassist:jar:3.9.0.GA:compile
\- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.0.Final:compile

I'm getting them from this single declaration in my pom.xml:

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-entitymanager</artifactId>
  <version>3.5.3-Final</version>
</dependency>

This should somehow answer your indulgent rant (if I rephrase: use Maven - or know what you're doing).

Solution 2:

Remove these files from project lib location persistence-api-1.0.jar ejb3-persistence.jar

add only javax.persistence-2.0.0.jar

it contains all the required fields and atrributes.

try this it'll work for your problem.

Manish Jaiswal

Solution 3:

Try replacing persistence-api-1.0.jar with a JPA 2.0 jar.

Solution 4:

Discovered a fix for the issue at least with what I am working with: IBM WebSphere 7 and MyEclipse Blue (Spring), or Bling, ver. 10.6. I created an application that has dependencies on other projects, one of these using Hibernate 3.6.3, requiring JPA 2.0. IBM WS loads JPA 1.0 to support itself ahead of JPA 2.0 and resolves all references to JPA to ver. 1.0. In the case of IBM WS, this causes the error reported above. The only fix I have come across since now includes adding JPA 2.0 as a shared library, then setting the server to load that library ahead of its native classes, similar to the method discussed here:

http://www.mkyong.com/websphere/websphere-7-javaxpersistenceonetomany-orphanremoval-error/

But our server admins will not allow changes to the server-wide classloader policy. So I still needed to find a way to get my project to use JPA 2.0 and not 1.0. I tried a lot of things but finally went for a Hail Mary and it worked.

The fix is to add the JPA 2.0 .jar file to your .war and .ear projects and then edit the Class-Path line in the manifest file in both your .war and .ear projects to point to the .jar files. It seems they must be in both or the approach will not work, so the JPA 2.0 .jar has to be in both the .war and .ear.

In your app (.war project), add hibernate-jpa-2.0-api-1.0.0.Final.jar to the project root. MyEclipse Blue will show it as a file at that location and also listed under "Referenced Libraries" in the Package Explorer view. Then open the manifest file at /WebRoot/META-INF/MANIFEST.MF and make sure the Class-Path line reads:

Class-Path: /hibernate-jpa-2.0-api-1.0.0.Final.jar

In your .ear project, add hibernate-jpa-2.0-api-1.0.0.Final.jar to folder 'lib' at your project root. If there is no 'lib' folder there, create one. Then in /META-INF/MANIFEST.MF, make sure the Class-Path line reads:

Class-Path: /lib/hibernate-jpa-2.0-api-1.0.0.Final.jar

Make sure all files are saved and do a clean build. Then export the .ear and deploy it as usual by the Integrated Solutions Console. But there is another thing you must do before the change will work; it does require changing the class-load policy for the app, but not the server. You are much more likely to get your WAS admin to go for that than changing the classloader policy for the entire server. To make the necessary change, after installing the .ear file, follow the left-hand nav bar click trail "Applications\Application Types\Websphere enterprise applications" and click on the name of your application, then click "Class loading and update detection". Then select "Classes loaded with local class loader first (parent last)" under "Class loader order", then click Apply, then Save. Now back at click trail "Applications\Application Types\Websphere enterprise applications", either start or restart your application. Test out your app and hopefully you will be good to go.

Final note: Evey time you re-deploy your .ear file, you will need to set the classloader option I just discussed. The preference is not retained between deployments.