Fotolia_69777853_XS-300x225.jpg

Getting Spring and Hibernate to place nice with WebSphere via JPA is an adventure in trial and error. In this post, I will guide you through what you need to make it work!

Just want the code? Head over to my GitHub at https://github.com/craigstjean/WebSphere-JPA-Spring-Hibernate

WebSphere 8.5 Users

Before we get started: WebSphere 8.5 supports JPA 2.0, not JPA 2.1. Be careful not to grab Hibernate JARs for JPA 2.1.

Obtaining Dependencies and Initial Setup

First thing’s first, I grabbed the following dependencies:

  • Hibernate 4.2.17.Final

    • lib/jpa/hibernate-entitymanager-4.2.17.Final.jar
    • lib/required/antlr-2.7.7.jar
    • lib/required/dom4j-1.6.1.jar
    • lib/required/hibernate-commons-annotations-4.0.2.Final.jar
    • lib/required/hibernate-core-4.2.17.Final.jar
    • lib/required/javassist-3.18.1-GA.jar
    • lib/required/jboss-logging-3.1.0.GA.jar
    • WARNING: Do not take the following JARs, they conflict with the APIs built in to WebSphere:

      *   lib/required/hibernate-jpa-2.0-api-1.0.1.Final.jar
      
      • lib/required/jboss-transaction-api_1.1_spec-1.0.1.Final.jar
  • Spring 4.1.6.RELEASE

    • aopalliance-1.0.jar
    • commons-codec-1.10.jar
    • spring-aop-4.1.6.RELEASE.jar
    • spring-beans-4.1.6.RELEASE.jar
    • spring-context-4.1.6.RELEASE.jar
    • spring-context-support-4.1.6.RELEASE.jar
    • spring-core-4.1.6.RELEASE.jar
    • spring-expression-4.1.6.RELEASE.jar
    • spring-instrument-4.1.6.RELEASE.jar
    • spring-jdbc-4.1.6.RELEASE.jar
    • spring-orm-4.1.6.RELEASE.jar
    • spring-tx-4.1.6.RELEASE.jar
    • spring-web-4.1.6.RELEASE.jar
    • spring-webmvc-4.1.6.RELEASE.jar
  • slf4j (Logging)

    • slf4j-api-1.7.12.jar
    • slf4j-simple-1.7.12.jar (just for the example)
    • jcl-over-slf4j-1.7.12.jar
      Additionally, I setup my application to use PARENT_LAST classloading. This is just something I have gotten used to, so if you have difficulties getting your code to work and you are not in PARENT_LAST, give that a try.

Setting up web.xml

First, add the following for Spring:

    <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>/WEB-INF/spring/application-context.xml</param-value>
    </context-param>

    <listener>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <listener>
       <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    <servlet>
       <servlet-name>dispatcher</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/spring/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
       <servlet-name>dispatcher</servlet-name>
       <url-pattern>/</url-pattern>
    </servlet-mapping>
Next, I have my datasource bound to jdbc/ExampleDb, and my Persistence Unit name will be Example Unit, so I added:
    <resource-ref>
       <res-ref-name>jdbc/ExampleDb</res-ref-name>
       <res-type>javax.sql.DataSource</res-type>
       <res-auth>Container</res-auth>
       <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>

    <persistence-unit-ref>
       <persistence-unit-ref-name>persistence/ExampleUnit</persistence-unit-ref-name>
       <persistence-unit-name>ExampleUnit</persistence-unit-name>
    </persistence-unit-ref>

ibm-web-bnd.xml

Don’t forget to bind your data source resource in ibm-web-bnd.xml:

<resource-ref name="jdbc/ExampleDb" binding-name="jdbc/ExampleDb" />

Spring Configuration

The servlet-context.xml has nothing special in it for this example, but the application-context.xml does. It points Spring to the WebSphere UOW Transaction Manager, and references the persistence unit to use:

    <bean id="entityManagerFactory" class="javax.persistence.Persistence" factory-method="createEntityManagerFactory">
        <constructor-arg type="java.lang.String" value="ExampleUnit" />
    </bean>

    <bean id="transactionManager"
        class="org.springframework.transaction.jta.WebSphereUowTransactionManager" />
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

persistence.xml

And lastly, the 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_2_0.xsd
version=”2.0”>
<persistence-unit name=”ExampleUnit” transaction-type=”JTA”>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:comp/env/jdbc/ExampleDb</jta-data-source>
<properties>
<property name=”hibernate.dialect” value=”org.hibernate.dialect.PostgreSQLDialect” />
<property name=”hibernate.transaction.factory_class” value=”org.hibernate.transaction.CMTTransactionFactory” />
<property name=”hibernate.transaction.jta.platform” value=”org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform” />
<property name=”hibernate.transaction.flush_before_completion” value=”true” />
<property name=”hibernate.transaction.auto_close_session” value=”true” />
<property name=”hibernate.temp.use_jdbc_metadata_defaults” value=”false” />
<property name=”hibernate.show_sql” value=”false” />
<property name=”hibernate.query.substitutions” value=”true ‘Y’, false ‘N’” />
<property name=”hibernate.cache.use_second_level_cache” value=”true” />
</properties>
</persistence-unit>
</persistence>

Here we are doing the following:

  • Setting transaction-type to JTA (Java Transaction API)
  • Setting the JPA Provider to Hibernate
  • Setting the data source to our web component’s ExampleDb
  • Setting Hibernate to use the PostgreSQL dialect
  • Setting Hibernate to use the CMTTransactionFactory for container managed transactions
  • Setting Hibernate to use Webphere’s JTA Platform
  • And so on
    Note that I did have an issue with Hibernate on startup trying to determine type information, which is what hibernate.temp.use_jdbc_metadata_defaults resolved for me. I did not have to set this when using Oracle. This did not used to occur with older versions of Hibernate (e.g. 4.1.9.Final).

Congratulations!

WebSphere is now running a Spring MVC web application, leveraging JPA 2.0 and Hibernate! For my full source, checkout GitHub at https://github.com/craigstjean/WebSphere-JPA-Spring-Hibernate

WebSphere 7.0 Users

I have had success using Hibernate 4.1.9.Final using the same configuration, though I was using version 1.0 in my persistence.xml. Also, you must place the Hibernate JPA API 2.0 JAR that is included with Hibernate in the lib directory. If you migrate to WebSphere 8.5, you must remove that JAR.