0
votes

We have a webapp deployed in JBoss EAP 7.2.1.GA including hibernate JPA.

We are getting an exception:

Caused by: java.lang.ClassCastException: org.hibernate.jpa.HibernatePersistenceProvider cannot be cast to javax.persistence.spi.PersistenceProvider

as a consequence of collision for org.hibernate.jpa.HibernatePersistenceProvider between the jar included in JBoss hibernate-core-5.3.9.Final-redhat-00002.jar and the jar included in our webapp org.hibernate.hibernate-entitymanager:5.1.10.

Because of the JBoss class loading policies, the jar defined at JBoss classpath has preference over the jar packaged in our webapp, so this is the expected behaviour by JBoss.

But we need to configure the classloading policies so the jar configured in our app has priority over the jar in the app server or, maybe, exclude the app in the appserver.

We have tried to configure jboss-deployment-structure.xml at both levels, deployment and sub-deployment war level, in order to exclude this dependency with not luck. We tried different combinations of exclusions, including excluding every single module and subsystem, but hibernate-core-5.3.9.Final-redhat-00002.jar is always loaded and we always get the ClassCastException.

In the documentation we have found this:

Native Hibernate use. Applications that use the Hibernate API directly, are referred to here as native Hibernate applications. Native Hibernate applications, can choose to use the Hibernate jars included with JBoss AS or they can package their own copy of the Hibernate jars. Applications that utilize JPA will automatically have the JBoss AS Hibernate injected onto the application deployment classpath. Meaning that JPA applications, should expect to use the Hibernate jars included in JBoss AS.

but is unclear if this means that the JPA dependencies cannot be excluded despite excluding jpa subsytem is a possibility.

So, questions:

  • Does this mean that excluding JPA subsystem does not work for JPA applications?

  • is it possible to exclude this hibernate-core-5.3.9.Final-redhat-00002.jar by configuring jboss-deployment-structure.xml file in the webapp?

  • is it possible in JBoss EAP 7.2.1.GA to revert the default priority policy so the jars on WEB-INF/lib are prioritized over the jars in the appserver?


Update 1: Regarding exclusions, we have tried to exclude in jboss-deployment-structure.xml:

  • all subsystems: ejb3, infinispan, jaxrs, jca, jdr, jpa, jsf, jmx, jaxrs, remoting, resteasy, security-manager, security, webservices, weld

  • all modules: javax.persistence.api, org.hibernate, org.jboss.as.jpa, javax.ejb.api, org.apache.commons.logging, org.slf4j, org.slf4j.ext, org.slf4j.jcl-over-slf4j, org.slf4j.impl, org.apache.log4j, org.jboss.as.jaxrs, org.jboss.resteasy, org.jboss.resteasy.resteasy-jaxrs, org.jboss.resteasy.resteasy-cdi, org.jboss.resteasy.resteasy-jaxb-provider, org.jboss.resteasy.resteasy-atom-provider, org.jboss.resteasy.resteasy-jackson-provider, org.jboss.resteasy.resteasy-jsapi, org.jboss.resteasy.resteasy-multipart-provider, org.jboss.resteasy.resteasy-crypto, org.jboss.resteasy.jose-jwt, org.jboss.resteasy.resteasy-jettison-provider, org.jboss.resteasy.resteasy-yaml-provider, org.jboss.resteasy.skeleton-key, javaee.api, javax.activation.api, javax.annotation.api, javax.el.api, javax.enterprise.api, javax.inject.api, javax.interceptor.api, javax.jms.api, javax.jws.api, javax.mail.api, javax.management.j2ee.api, javax.resource.api, javax.rmi.api, javax.security.auth.message.api, javax.security.jacc.api, javax.transaction.api, javax.validation.api, javax.xml.bind.api, javax.xml.soap.api, javax.xml.ws.api, javax.api

  • for both, the deployment and the sub-deployment

Even with all these exclusion applied at the same time, the JBoss jar is injected into the webapp so we still get ClassCastException.

I am confused about if this works like that "by design" according to this comment on official documentation: Applications that utilize JPA will automatically have the JBoss AS Hibernate injected onto the application deployment classpath. Meaning that JPA applications, should expect to use the Hibernate jars included in JBoss AS. or, otherwise, it can be excluded but we are missing something, or, maybe, is a bug.


Update 2. We tested all these application-side configuration options and none, alone or in combination, is able to prevent the JBoss hibernate jar being loaded:

In jboss-deployment-structure.xml:

  • exclude subsystem JPA on deployment
  • exclude subsystem JPA on sub-deployment
  • exclude org.hibernate module from deployment no slot
  • exclude org.hibernate module from deployment for slot main
  • exclude org.hibernate module from deployment for slot 5.3
  • exclude org.hibernate module from deployment for slot 5.3.9.Final
  • exclude org.hibernate module from subdeployment no slot
  • exclude org.hibernate module from subdeployment for slot main
  • exclude org.hibernate module from subdeployment for slot 5.3
  • exclude org.hibernate module from subdeployment for slot 5.3.9.Final
  • exclude javax.persistence.api module from deployment
  • exclude javax.persistence.api module from subdeployment
  • exclude javax.ejb.api module from deployment
  • exclude javax.ejb.api module from subdeployment
  • exclude all modules (except servlets)/subsystems for deployment/subdeployment
  • configure local-last value="false" for deployment
  • configure true

In persistence.xml:

  • configure jboss.as.jpa.providerModule to 'application'
  • configure jboss.as.jpa.providerModule to '5.1.10'
  • configure jboss.as.jpa.providerModule to 'org.hibernate:5.1.10.Final'
  • configure jboss.as.jpa.managed as false
  • xml configure

In maven several combinations and exclusions

2
Are you using Hibernate Native or are you using JPA? Is your deployment an EAR or a WAR?James R. Perkins
The offending class is org.hibernate.jpa.HibernatePersistenceProvide so we use JPA. The deployment is an ear containing a war.pellyadolfo
Is there a reason you need to include Hibernate in your deployment?James R. Perkins
It does not look a good long term plan to me to bind the application to the container as it would be probably tied to specific versions. On the other hand, doing so would require refactoring of years of code and this would be a project on its own.pellyadolfo
Well that's kind of the point of Java EE/Jakarta EE :) But if you need to exclude the servers Hibernate you'd need to exclude it from the EAR and each sub-deployment explicitly.James R. Perkins

2 Answers

1
votes
<?xml version='1.0' encoding='UTF-8'?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
  <deployment>
     <exclude-subsystems>
        <subsystem name="jpa" />
    </exclude-subsystems>
    <exclusions>
        <module name="javax.persistence.api"/>
    </exclusions>
  </deployment>
</jboss-deployment-structure>

Source: https://access.redhat.com/solutions/3332401

0
votes

After testing countless combination above of settings we found that we had a spurious declaration in the pom that made Manifest Dependencies variable to include

     Dependencies: org.infinispan,org.hibernate

By removing this legacy declaration things were back to normal.

The final combination working was:

  • exclude JPA subsystem from deployment
  • exclude JPA subsystem from subdeployment
  • exclude javax.persistence.api module from subdeployment

With this configuration we were able to exclude the built-in hibernate hibernate-core-5.3.9.Final-redhat-00002.jar and JPA 2.2 and work with the org.hibernate.hibernate-entitymanager:5.1.10 jar and JPA 2.1 included in our ear.