0
votes

I have a spring mvc app which uses openjpa 2.1.1 as its persistence framework. It is developed as a Maven project in STS, and runs locally on vFaric TC Server (Tomcat 7).

When we first deployed the war to Websphere 8.5, we encountered classloader conflicts with the following 3 openjpa jars which were in our war file:

geronimo-jpa_2.0_spec-1.1.jar geronimo-jta_1.1_spec-1.1.1.jar validation-api-1.0.0.GA.jar

Removing these from the war and deferring to Websphere's bundled openjpa worked fine, so I changed the openjpa POM dependency scope from 'compile' to 'provided' (so that these jars would not be packaged into the war file).

Since Tomcat 7 is not Java EE compliant, I placed the 3 jars in Tomcat\lib (also tried the vfabric-tc-server lib - which wraps tomcat), but the JPA classes were not visible by the app at startup (noclassdeffound exceptions in console).

I also tried adding the jars to the server classpath from 'launch configuration' within STS - no luck there either.

Is there a class loader order that needs to be set somewhere in Tomcat such that JPA loads before the app?

What I need is a build that will work when deployed to either Tomcat or Websphere.

Any help will be much appreciated.

2

2 Answers

0
votes

In case this helps anyone, the NoClassDefFoundError was referring to a JPA class, but NOT one of those from the 3 jars I included. I ran mvn tree and found that the entire chain of JPA dependencies was:

openjpa-2.1.1.jar commons-lang-2.4.jar commons-collections-3.2.1.jar geronimo-jta_1.1_spec-1.1.1.jar geronimo-jpa_2.0_spec-1.1.jar

I also needed to add:

serp-1.12.0.jar

I originally included the validation-api-1.0.0.GA.jar in tomcat/lib as well because it had to be removed from the war to get websphere working, but placing this in tomcat/lib caused a "javax.validation.ValidationException: Unable to find default provider" so I took it out, meaning just the above 6 jars needed to be added.

0
votes

@user2743197 - First off, you need separate profiles defined in your Maven pom. Define one profile for WAS and use its OpenJPA dependency via:

    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>6.0</version>
        <scope>provided</scope>
    </dependency>

That's how I use the OpenJPA-2.1.1-SNAPSHOT binary that's bundled with WAS v8.x.x

Define another Maven profile for Tomcat that explicitly grabs all of the dependencies that you require except the few JavaEE-related specs that Tomcat does provide. So, define OpenJPA-2.1.1-SNAPSHOT as a dependency (not as "provided" of course).

Now, as for bootstrapping JPA within a war project that's deployed to Tomcat (without using Spring), I typically create a class like this:

@WebListener
public class ApplicationLifeCycleListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
       ...
       // Do some OpenJPA bootstrapping here
       // Get an EntityManager.
       EntityManager em = PersistenceUtil.getEntityManager();
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //throw new UnsupportedOperationException("Not supported yet.");
        PersistenceUtil.closeEntityManagerFactory();
    }
}

This is what I do to bootstrap Hibernate/JPA. My PersistenceUtil handles creation of an EntityManagerFactory, delivery of my EntityManager, etc.

You may want to consider TomEE instead. It will offer you the same functionality as WebSphere 8.x.x when it comes to JPA. Both rely heavily on Apache products. WebSphere 8.x.x and TomEE will allow you to use EJB 3.x, which, coupled with or without CDI, is much easier to use with JPA implementation. With Tomcat, you have to worry about handling transaction management yourself or figuring out how to leverage CDI or Spring to manage your transactions.