11
votes

I have a war application which contains JPA 2.1 API and Hibernate 4.3.0.Final ( JPA 2.1 implementation) packaged and bootstrapped using Spring container and I want to deploy this in JBoss EAP 6.1.

I am aware that JBoss EAP 6.1 is JPA 2.0 compliant so I decided to force JBoss to use JPA version and implementation from within my application

What I was trying to do was to exclude the JPA subsystem using jboss-deployment-structure.xml but what I found was that even if I comment out JPA extension and JPA subsystem from standalone.xml and put JPA subsystem exclusion in jboss-deployment-structure.xml (also excluded org.hibernate module to use the hibernate packaged in application), no JPA scanners are run ( as expected) but the moment any of the war class (in my case Spring container) refers to the javax.persistence classes, the API gets loaded from JBoss modules (modules/system/layers/base/javax/persistence/api/main/hibernate-jpa-2.0-1.0.1.Final-redhat-2.jar!) INSTEAD of the API jar supplied in the war supplied. So obviously I get exception of mismatch in the JBoss supplied API (2.0) and its implementation (2.1) in war application. One exception is for e.g., index related property of annotation javax.persistence.Table is not recognized as this is an addition in JPA 2.1 and not available in JPA 2.0

I could work-around this issue by replacing the JPA 2.0 API in the modules directory with JPA 2.1 (and pointing module.xml to the new 2.1 API jar) and everything worked fine. However I think this is not the correct way as this is like trying to change server behaviour for all applications.

Is this the intentional JBoss classloading behaviour that all specification API classes ( of which JBoss is implementer) will always take precedence no matter what the implementation used is and no matter we tell it to use a particular API from within the application. I think that making a particular spec compliant server and then providing way to override the spec version itself is somewhat contradictory but is there a way by which I can cleanly use both the API and implementation from within my application ?

Another option would be to move to Wildfly which is JPA 2.1 implementation, but my question is whether this is cleanly possible in JBoss EAP 6.1 ?

4

4 Answers

5
votes

We found another solution.
You can also exclude the jpa subsystem in jboss-deployment-structure.xml of the war:

<exclude-subsystems>
    <subsystem name="jpa" />
</exclude-subsystems>
<exclusions>
    <module name="javaee.api" />
</exclusions>
5
votes

If you're Maven this did the trick for me.

<dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>7.0</version>
    </dependency>

jboss-deployment-structure.xml

<deployment>

    <exclude-subsystems>
        <subsystem name="jpa" />
    </exclude-subsystems>

    <exclusions>
        <module name="javaee.api" />
    </exclusions>

</deployment>

3
votes

Found a solution that seems to work with hibernate-core-4.3.1.

Step 1: remove subsystem jpa from standalone.xml:

    <subsystem xmlns="urn:jboss:domain:jpa:1.1">
        <jpa default-datasource="" default-extended-persistence-inheritance="DEEP"/>
    </subsystem>

Thanks to this blog article: http://mariemjabloun.blogspot.nl/2014/02/jboss-eap-6-persistence-unit-problem.html

Step 2: exclude jpa, javaee modules in jboss-deployment-structure.xml of the war:

    <exclusions>
        <module name="javax.persistence.api"/>
        <module name="javaee.api"/>
    </exclusions>
3
votes

The above answers are great, but they are introducing other problems in many applications by excluding the whole Java EE API.

If you don't want to do so, then go to JBOSS_HOME\modules\javaee\api\main\module.xml and set export to false for javax.persistence.api, like this:

<module name="javax.persistence.api" export="false"/>

Note that this will disable the persistence API for every application deployed in the same EAP.

You still need to delete the JPA subsystem from standalone.xml, but you don't need to change jboss-deployment-structure.xml, or at least I didn't have to.