Using jpa2.2 on Websphere with spring/hibernate

1.1k Views Asked by At

I recently inherited a Spring/Hibernate app, and upgraded it to Spring 5.2.8, SpringSecurity 5.3.4, Hibernate 5.4.21.

We are deploying on Websphere 8.5.5 (full, not liberty).

When I try to run the application, I get an exception, of which I believe the relevant part is:

...nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'auditSessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext-hibernate.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: javax/persistence/JoinColumn.foreignKey()Ljavax/persistence/ForeignKey; (loaded from file:/C:/Program Files (x86)/IBM/WebSphere/AppServer/plugins/javax.j2ee.persistence.jar by org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@2472a612) called from class org.hibernate.cfg.AnnotationBinder (loaded from file:/C:/Program%20Files%20(x86)/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Node01Cell/nameof_war.ear/nameof.war/WEB-INF/lib/hibernate-core-5.4.21.Final.jar by com.ibm.ws.classloader.CompoundClassLoader@71ed602b[war:nameof_war/nameof.war]

I noticed that it is using the Websphere version of JPA, rather than the one I included in the jar within the war. Websphere comes with javax.j2ee.persistence.jar - JPA version 2.0, which explains the error.

An answer to another SO question led me here: https://www.ibm.com/support/knowledgecenter/en/SSAW57_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/tejb_jpa3rdparty.html

This link tried to explain how to use third-party persistence providers.

The problem is, the link says to use persistence.xml; but the application I've inherited doesn't have that xml file. It only has applicationContext-hibernate.xml and orm.xml.

I have tried creating a persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
  <persistence xmlns="http://java.sun.com/xml/ns/persistence"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
 http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
   <persistence-unit name="nameof">
      <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
      <jar-file>nameof.jar</jar-file>
   </persistence-unit>
  </persistence>

Which appears in the right place in the WAR file; but I don't know if that's correct or not - nor if I have to update any other files as well? Do I need to reference that persistence-unit somewhere else?

I've also updated the classloader in WebSphere to be parent last; but I still get the error as shown above.

What steps am I missing? What do I need do change in applicationContext-hibernate.xml (or elsewhere) to get this working?

My applicationContext-hibernate.xml looks like:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

  <bean id="auditSessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="annotatedClasses">
      <list>
        <value>com.name.class1</value>
        <value>com.name.class2</value>
        <value>etc</value>
      </list>
    </property> 
      <property name="mappingResources">
      <list>
        <value>com/name/model/orm.xml</value>
      </list>
    </property>
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.Oracle12cDialect</prop>
        <prop key="hibernate.jdbc.fetch_size">100</prop>
      </props>
    </property>
  </bean>

  <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="annotatedClasses">
      <list>
        <value>com.name.class3</value>
        <value>com.name.class4</value>
        <value>etc</value>
      </list>
    </property> 
    <property name="mappingResources">
      <list>
        <value>com/name/model/orm.xml</value>
      </list>
    </property>
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.Oracle12cDialect</prop>
        <prop key="hibernate.jdbc.fetch_size">100</prop>
        <prop key="hibernate.format_sql">true</prop>
        <prop key="hibernate.order_inserts">true</prop>  
        <prop key="hibernate.order_updates">true</prop> 
        <prop key="hibernate.jdbc.batch_size">100</prop>
      </props>
    </property>
    <property name="entityInterceptor">
      <bean class="com.name.interceptor.HibernateInterceptor">
        <property name="auditInterceptor">
            <bean class="com.name.interceptor.AuditInterceptor" />
        </property>
        <property name="comparativeAuditInterceptor">
            <bean class="com.name.interceptor.ComparativeAuditInterceptor">
                <property name="cadDao">
                    <bean class="com.name.dao.ComparativeAuditDetailsDaoImpl">
                        <property name="sessionFactory" ref="auditSessionFactory" />
                    </bean>
                </property>
                <property name="undoDao">
                    <bean class="com.name.dao.UndoDaoImpl">
                        <property name="sessionFactory" ref="auditSessionFactory" />
                    </bean>
                </property>
            </bean>
        </property>
      </bean>
    </property>
  </bean>

  <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
  </bean>


  <tx:annotation-driven transaction-manager="transactionManager"/>

  <bean id="openSessionInViewInterceptor"
        class="org.springframework.orm.hibernate5.support.OpenSessionInViewInterceptor">
    <property name="sessionFactory" ref="sessionFactory"/>
  </bean>

  <bean id="transactionInterceptor" class="com.name.TransactionalWebRequestInterceptor">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="transactionAttribute" value="PROPAGATION_REQUIRES_NEW"/>
  </bean>

</beans>
1

There are 1 best solutions below

0
On BEST ANSWER

What helped me in the end was the following post: https://medium.com/@james.tran/how-to-deploy-spring-boot-2-x-apps-on-websphere-8-5-5-d0b2e257f606

Specifically, the following step:

In the administrative console, click Applications > Application Types > WebSphere enterprise applications > application_name > Manage modules > webmodule_name.

Select Classes loaded with local class loader first (parent last) from the drop down list.

I had already done this elsewhere in the console, but not here.

Additionally, I tried the following:

https://www.ibm.com/support/pages/apar/PM26361

  1. Open the administrative console.
  2. Select Servers -> Server Types -> WebSphere application servers.
  3. Select the server you want to configure.
  4. In the Server Infrastructure area, select Java and Process Management -> Process definition.
  5. In the Server Infrastructure area, select Process Definition.
  6. In the Additional Properties area, select Java Virtual Machine.
  7. In the Additional Properties area, select Custom Properties.
  8. Select the New box.
  9. In the Name entry field, type: com.ibm.websphere.persistence.ApplicationsExcludedFromJpaProcess ing
  10. In the Value entry field, type the names of the applications to be excluded from JPA processing. If there are multiple appli[c]ations separate each with the ":" character. If you wish to specify all applications simply type the "*" character.
  11. Select OK.
  12. Restart the server.

I don't know which steps helped - I'll try and narrow it down and report back if I get a chance.