Search code examples
springhibernatenullpointerexceptionwebsphere

How to fix NullPointerException when getting current Hibernate Session


In my WebSphere 9 application thats built on Spring 5 / Hibernate 5 I get this error when retrieving the current Hibernate session with org.hibernate.SessionFactory.getCurrentSession():

    [9/26/19 10:41:22:405 CEST] 0001f184 DefaultMessag W org.springframework.jms.listener.AbstractMessageListenerContainer invokeErrorHandler Execution of JMS message listener failed, and no ErrorHandler has been set.
                             java.lang.IllegalStateException: An exception occured during the cumulation before the processingId could be created: java.lang.NullPointerException
    at com.tsystems.cc4.service.cumulation.CumulationHandlerImpl.cumulate(CumulationHandlerImpl.java:138)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    at java.lang.reflect.Method.invoke(Method.java:508)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at com.tsystems.cc4.service.cumulation.NonClosingOpenSessionInterceptor.invoke(NonClosingOpenSessionInterceptor.java:40)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy184.cumulate(Unknown Source)
    at com.tsystems.cc4.service.cumulation.ScheduleCommandHandler.invoke(ScheduleCommandHandler.java:62)
    at com.tsystems.cc4.service.invocation.listener.InvocationWrapperListener.onMessage(InvocationWrapperListener.java:128)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:318)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:245)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1189)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1081)
    at javax.enterprise.concurrent.ManagedExecutors$RunnableAdapter.run(ManagedExecutors.java:211)
    at com.ibm.ws.asynchbeans.SubmittedTask.run(SubmittedTask.java:711)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1909)
    Caused by: java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    at java.lang.reflect.Method.invoke(Method.java:508)
    at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
    at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:266)
    at org.springframework.orm.hibernate5.SessionFactoryUtils.getFlushMode(SessionFactoryUtils.java:125)
    at org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:100)
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:456)
    at com.tsystems.cc4.control.dao.impl.AbstractHibernateDAO.getSession(AbstractHibernateDAO.java:51)
    at com.tsystems.cc4.control.dao.impl.GenericCrudDAOImpl.readInReadOnlyMode(GenericCrudDAOImpl.java:107)
    at com.tsystems.cc4.service.cumulation.CumulationHandlerImpl.cumulate(CumulationHandlerImpl.java:120)
    ... 23 more

    [9/26/19 10:41:22:415 CEST] 0001f184 TransactionSy E org.springframework.transaction.support.TransactionSynchronizationUtils triggerBeforeCompletion TransactionSynchronization.beforeCompletion threw exception
                             java.lang.NullPointerException
    at org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCompletion(SpringSessionSynchronization.java:110)
    at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCompletion(TransactionSynchronizationUtils.java:107)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCompletion(AbstractPlatformTransactionManager.java:935)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:826)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:702)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:251)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1189)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1081)
    at javax.enterprise.concurrent.ManagedExecutors$RunnableAdapter.run(ManagedExecutors.java:211)
    at com.ibm.ws.asynchbeans.SubmittedTask.run(SubmittedTask.java:711)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1909)

The application code successfully ran on Spring 4.3.14.RELEASE + Hibernate 4.2.21.Final.

The problem occurs since we upgraded to Spring 5.1.1.RELEASE + Hibernate 5.2.9.Final.

Spring configuration before (Spring 4.3.14.RELEASE + Hibernate 4.2.21.Final):

<bean id="cumulationConfigDAO" class="com.tsystems.cc4.control.dao.impl.GenericCrudDAOImpl">
    <constructor-arg value="com.tsystems.cc4.control.model.cumulation.CumulationConfig" />
</bean>
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="controlDataSource" />
    <property name="packagesToScan" value="com.tsystems.cc4.control.model" />
    <property name="hibernateProperties">
        <value>
            hibernate.default_schema=CC4
            hibernate.dialect=org.hibernate.dialect.${jdbc.dialect}Dialect
            org.jboss.logging.provider=slf4j
            ${hib_tx_platform}
            ${hib_tx_factory}
        </value>
    </property>
</bean>

Properties:

# Settings for DB2
jdbc.dialect=DB2
# Hibernate JTA Transaction Platform configuration
hib_tx_platform=hibernate.transaction.jta.platform=org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform
hib_tx_factory=hibernate.transaction.factory_class=org.hibernate.transaction.CMTTransactionFactory

Spring configuration after (Spring 5.1.1.RELEASE + Hibernate 5.2.9.Final):

<bean id="cumulationConfigDAO" class="com.tsystems.cc4.control.dao.impl.GenericCrudDAOImpl">
    <constructor-arg name="entityClass" value="com.tsystems.cc4.control.model.cumulation.CumulationConfig" />
    <constructor-arg name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="controlDataSource" />
    <property name="packagesToScan" value="com.tsystems.cc4.control.model" />
    <property name="hibernateProperties">
        <value>
            hibernate.default_schema=CC4
            hibernate.dialect=org.hibernate.dialect.${jdbc.dialect}Dialect
            org.jboss.logging.provider=slf4j
            ${hib_tx_platform}
            ${hib_tx_factory}
            hibernate.id.new_generator_mappings=false
            hibernate.allow_update_outside_transaction=true
        </value>
    </property>
</bean>

Properties:

# Settings for DB2
jdbc.dialect=DB2
# Hibernate JTA Transaction Platform configuration
hib_tx_platform=hibernate.transaction.jta.platform=org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform
hib_tx_factory=hibernate.transaction.factory_class=org.hibernate.transaction.CMTTransactionFactory

Solution

  • Solved. The reason for the problem was some specialized stuff we had built in former times to work around problems after migrating from Hibernate 3 to 4. The Spring context contained non-standard stuff like this:

    <!-- The Hibernate interceptor, which takes care of opening and closing 
        hibernate session around method calls. -->
    <bean id="hibernateInterceptor"
        class="com.tsystems.cc4.service.cumulation.NonClosingOpenSessionInterceptor">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean>
    <!-- A proxy with the hibernate interceptor wired in so it can access 
        the persistent context -->
    <bean id="cumulationHandler" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target">
            <bean class="com.tsystems.cc4.service.cumulation.CumulationHandlerImpl" />
        </property>
        <property name="proxyInterfaces">
            <value>com.tsystems.cc4.service.cumulation.CumulationHandler</value>
        </property>
        <property name="interceptorNames">
            <value>hibernateInterceptor</value>
        </property> 
    </bean>
    

    Removing those beans solved the problem.

    Here's from the class comment of NonClosingOpenSessionInterceptor: "Specialized version of org.springframework.orm.hibernate4.support.OpenSessionInterceptor that - if necessary - opens a Hibernate session and registers it with Spring's TransactionSynchronizationManager without closing it after the method call. This is necessary if closing the Hibernate session should occur through the transaction manager during transaction completion. This class has been created to work around the "org.hibernate.SessionException: Session is closed!" problem that occurs when using org.springframework.orm.hibernate4.support.OpenSessionInterceptor in conjunction with Spring's PlatformTransactionManager."