Websphere, Hibernate, JPA, with a twist of Classpath hell

Problem

Recently I had to take a .war project that utilized Hibernate 3.5 and JPA 2.0 and deploy it in WebSphere 7.0. It has been quite a long time since I worked with WebSphere and was very happy to find that it was very easy to setup and deploy my existing war.

What I didn’t expect was the Classpath mess that was to ensue and the 7 hours of research to find a solution to what appears to be a fairly common problem (but no real solution defined)

You see, WebSphere ships with a copy of OpenJPA. OpenJPA is a JPA implementation that WebSphere provides for use by developers. It just so happens though that the OpenJPA that WebSphere ships with is a JPA 1.0 implementation.

Hibernate 3.5 or > requires a JPA 2.0 implementation. Houston, we have a problem.

No problem you think. I’ve got the JPA 2.0 implementation (hibernate-jpa-2.0-api01.0.0.Final.jar) in my .war’s classpath, so I’m fine. Right?

Wrong. WebSphere puts OpenJPA on the Classpath first, no matter what. You can change the configurations (Parent first/Parent last) and it will still have OpenJPA on the Classpath before the .war file. You’ll start seeing a lot of weird errors like:
java.lang.NoSuchMethodError: javax/persistence/spi/PersistenceUnitInfo.xxxx

If you see the above you have a JPA 1.0/JPA 2.0 issue because of OpenJPA.

Solution

IBM has a Feature Pack (think library upgrade package) for WebSphere to get it to run OSGi and JPA 2.0. Once you install this everything should work fine.

Steps:

  1. Shutdown WebSphere
  2. Download the IBM Install Manager at http://www-01.ibm.com/support/docview.wss?uid=swg24027833 if you don’t already have it.
  3. Start the IBM Installation Manager
    1. Make the Install Manager aware of your WebSphere installation if it isn’t already
      1. Select IMPORT from the main page
      2. Select the installation directory of your copy of WebSphere
      3. Select next for the rest of the steps until finished
    2. Back at the main IBM Installation Manager screen select INSTALL
      1. Select the Feature Pack for OSGi Applications and JPA 2.0
      2. Install the Feature Pack
    3. Once done, exit the IBM Installation Manager
  4. Start the IBM Profile Manager
    1. In the Profile Manager, Select the Server then click AUGMENT
    2. Select the JPA 2.0 and click NEXT then click INSTALL
    3. Exit the IBM Profile Manager
  5. Start up WebSphere
    1. To Verify that the install took:
      1. Go to the web interface for the WebSphere server
      2. Select SERVERS -> SERVER TYPE -> WEBSPHERE APPLICATION SERVERS -> SERVER1 -> RUNTIME -> PRODUCT INFORMATION
      3. You should see ‘Feature Pack for OSGi Applications and Java Persistence API 2.0’
    2. Uninstall your .war, .ear, .etc and reinstall it

The errors should disappear and everything should start working!

Things to note

  • You need to be running WebSphere 7.0.0.9 or greater. If you aren’t, you can’t use the Feature Pack
  • You may need to define the persistence provider in your persistence.xml file. I didn’t have to but I found many sites suggesting that it was the solution (it wasn’t, but it couldn’t hurt). If you want to try it:
    • Add <provider>org.hibernate.ejb.HibernatePersistence</provide> between your <persistence-unit> tags
    • You will notice Hibernate starts up as soon as your app starts in WebSphere. If you haven’t fixed the above error (java.lang.NoSuchMethodError) you will just see it sooner and your app won’t start

About sseaman

Connect with me on Google+
This entry was posted in Java, Programming. Bookmark the permalink.

18 Responses to Websphere, Hibernate, JPA, with a twist of Classpath hell

  1. Marc says:

    Would you know how the same could be solved in Websphere Community Edition?

    • Jay says:

      Probably a different solution. WebSphere Community Edition is based off of Apache Geronimo and uses a different codebase. There should be a solution but it probably upgrades a little differently than WAS.

  2. sseaman says:

    I would first try to see if you can apply the Feature Pack like you can in WebSphere 7.0.

    If that is not possible, I’m not sure what options you have. A quick search of IBM’s website didn’t uncover anything. I’ll ask a friend who did a few years stint as a WebSphere admin and see if he can come up with anything.

    Good luck!

  3. Srinivas C says:

    I think there should be a solution like we have it in Weblogic where we can over-ride the class-loader settings. We ask weblogic to prefer the jars of the web-application and ignore what is there in its classpath. They call it as Filtering Class-loader

    e.g.

    org.apache.log4j.*
    antlr.*

    • sseaman says:

      WebSphere does have something like that. The thing is, it doesn’t always listen to you 😉 It appears (and this is me assuming) that WebSphere loads things into the classpath in what I would call ‘defined chunks’ based on functionality.

      When you tell it to prefer you app first it will load those first, but the classes in question (JPA) are still loaded before that because they are in a different, required ‘chunk’

  4. Hansjörg Oppermann says:

    Yes! You saved my day!

  5. Steffen Naus says:

    Hi,

    i got an similar error
    ava.lang.NoSuchMethodError: org/apache/commons/collections/IteratorUtils.singletonIterator(Ljava/lang/Object;)Lorg/apache/commons/collections/ResettableIterator;
    [25.07.11 08:57:52:088 CEST] 00000021 SystemErr R java.lang.NoSuchMethodError: org/apache/commons/collections/IteratorUtils.singletonIterator(Ljava/lang/Object;)Lorg/apache/commons/collections/ResettableIterator;
    [25.07.11 08:57:52:088 CEST] 00000021 SystemErr R at de.kivi.server.jdbc.impl.metadata.fieldaccess.PersistentFieldImpl$SingleLinkCollection.iterator(PersistentFieldImpl.java:54)

    so this mean that a class from the commons collections package is double and the class loader loads the wrong version of IteratorUtils?

  6. Steffen Naus says:

    …and a change from parent first to last would not change a bit?
    running WS 6.1

    • sseaman says:

      First I would make absolutely sure that the commons-collections jar is in your war/ear. If it is then you are correct that WebSphere is using its own copy of commons-collections and that is what is causing your error.

      You can try the parent last change and see what happens. I’m guessing WebSphere using it on a low level and the changing of that setting won’t fix things for you.

      You could see if there is a feature pack for WebSphere that updates the commons-collections (http://www-01.ibm.com/software/webservers/appserv/was/featurepacks/#) or you could try you luck and actually replace the commons-collections jar in WebSphere’s lib directory with a new one and hope for the best.

      Good luck!

  7. Bryan says:

    So i had this problem, and fixed it by installing the feature pack like you said. However i’m now seeing this error:

    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘EntityManagerFactory’ defined in class path resource [recipe-ws.spring.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: javax/persistence/spi/PersistenceUnitInfo.getValidationMode()Ljavax/persistence/ValidationMode;
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)

    When i look at the war’s class loader it says that this class is being loaded from the feature pack’s library but at the war level.

    Any ideas?

    -B

    • sseaman says:

      I recall seeing this error when I was fighting the installation. From what I recall it was actually what I used as a gauge as to if I did the installation correctly or not. My initial suggestion is to do the installation again and make sure you don’t miss any steps.

      This appears to be supported by this article https://forums.oracle.com/forums/thread.jspa?threadID=2150287M that states that it is because it is still 1.0

      Also, if you look at the docs for PersistenceUnitInfo in 1.0 (here) you will see the method does not exist. But in 2.0 (here) it does

  8. Tommy says:

    Hi, we solved this problem with adding the hibernate jpa 2.0 jar at the start of the classpath. Just added this to the genericJvmArguements:

    -Xbootclasspath/p:C:\Temp\java\hibernate-jpa-2.0-api-1.0.0.Final.jar

  9. Shane Lee says:

    Great article.

Leave a Reply

Your email address will not be published. Required fields are marked *