Spring – Integrating JTA, Hibernate 4 and Spring 4 with WebLogic

hibernatejtaspringweblogic

I am having serious issues with implementing a JTA / Hibernate / Spring application (with WebLogic 10.3 for the server). I originally was using the Spring programmatic configuration, but have moved it over to the Spring XML configuration to filter out potential problems. It was working perfectly when I used the HibernateTransactionManager instead of the JtaTransactionManager, but now is not finding the Session for the thread.

When I look at the sessionFactory it is not null, but getSession() does not return a session.

Could you assist me in troubleshooting this? Thank you!

My Dao implementation:

import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;

...

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import mil.navy.navsupbsc.utilities.HibernateConfiguration;

@Repository
public class ContactDAOImpl implements ContactDAO {

    @Autowired
    SessionFactory sessionFactory;

    public Session getSession() {
        try {
            sessionFactory.openSession();
            return sessionFactory.getCurrentSession();
        } catch (NullPointerException e) {
            e.printStackTrace();
            throw e;
        }

    }

@SuppressWarnings("unchecked")
public List<Contact> listContact() {

    List<Contact> contactList = getSession().createCriteria(Contact.class)
            .list();
...

My Spring-Servlet.xml file is:

 <?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:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:c="http://www.springframework.org/schema/c"
    xmlns:cache="http://www.springframework.org/schema/cache" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:messages" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="packagesToScan" value="mil.navy.navsupbsc.entity" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.driverClassName">oracle.jdbc.OracleDriver</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.use_sql_comments">true</prop>
            </props>            
        </property>
    </bean>

    <mvc:annotation-driven />

    <mvc:resources mapping="/resources/**" location="/resources/" />
    <context:component-scan base-package="mil.navy.navsupbsc" />
    <tx:annotation-driven />
    <jee:jndi-lookup id="NCS" jndi-name="NCS" resource-ref="false"></jee:jndi-lookup>
    <tx:jta-transaction-manager />
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass">
            <value>
                org.springframework.web.servlet.view.tiles2.TilesView
            </value>
        </property>
    </bean>
    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles.xml</value>
            </list>
        </property>
    </bean>

</beans>

My web.xml file

  <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" metadata-complete="false" version="2.5">
      <display-name>Contact Management Suite</display-name>
      <welcome-file-list>
        <welcome-file>contact</welcome-file>
      </welcome-file-list>
      <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
                org.springframework.web.servlet.DispatcherServlet
            </servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    <resource-ref>
        <description>NCS</description>
        <res-ref-name>NCS</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>


    </web-app>

And my weblogic.xml file

    <?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app
    xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.2/weblogic-web-app.xsd">
    <wls:container-descriptor>
        <wls:prefer-application-packages>
            <wls:package-name>org.hibernate.*</wls:package-name>
        </wls:prefer-application-packages>
    </wls:container-descriptor>
    <wls:weblogic-version>10.3.5</wls:weblogic-version>
    <wls:context-root>ncms2</wls:context-root>
    <wls:resource-description>
        <wls:res-ref-name>dbDataSource</wls:res-ref-name>
        <wls:jndi-name>NCS</wls:jndi-name>

    </wls:resource-description>
</wls:weblogic-web-app>

Best Answer

Based on the answer from @M. Deinum (if you put your comments in an answer, I'll mark it as correct), I have figured out the problem.

The solution was to add the data source (referencing the JNDI data source I specified earlier) as <property name="dataSource" ref="NCS"/>. I also reference the jtaTransactionManager as <prop key="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform</prop>

NOTE: for other servers other than WebLogic, replace .WebLogicJtaPlatform with your specific server's JtaPlatform name. Specific implementations can be found at http://docs.jboss.org/hibernate/orm/4.1/javadocs/org/hibernate/service/jta/platform/internal/AbstractJtaPlatform.html

Finally, I changed the sessionFactory.openSession() to sessionFactory.getSession in my DaoImplementation file.

I hope this helps someone else as well!

Spring-Servlet.xml

<?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:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:c="http://www.springframework.org/schema/c"
    xmlns:cache="http://www.springframework.org/schema/cache" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:messages" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="packagesToScan" value="[app.package].navsupbsc.entity" />
        <property name="dataSource" ref="NCS"/>
        <property name="jtaTransactionManager" ref="transactionManager" />

        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform
                </prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.driverClassName">oracle.jdbc.OracleDriver</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.use_sql_comments">true</prop>
            </props>
        </property>
    </bean>

    <mvc:annotation-driven />

    <mvc:resources mapping="/resources/**" location="/resources/" />
    <context:component-scan base-package="[app.package.scanpath]" />
    <tx:annotation-driven transaction-manager="transactionManager" />
    <jee:jndi-lookup id="NCS" jndi-name="NCS" resource-ref="false">
    </jee:jndi-lookup>
    <tx:jta-transaction-manager id="transactionManager" />
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass">
            <value>
                org.springframework.web.servlet.view.tiles2.TilesView
            </value>
        </property>
    </bean>
    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles.xml</value>
            </list>
        </property>
    </bean>

</beans>

Sources:

http://koenserneels.blogspot.de/2012/05/migrating-from-hibernate-3-to-4-with.html

http://devblog.x-sphere.com/2008/01/23/websphere-jndi-spring-framework-hibernate/ (NOTE: I'm using <tx:jta-transaction-manager/> in place of the manual transaction manager shown in the link