首页 > 解决方案 > 获取当前休眠会话时如何修复 NullPointerException

问题描述

在我基于 Spring 5 / Hibernate 5 构建的 WebSphere 9 应用程序中,当使用以下命令检索当前 Hibernate 会话时出现此错误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)

应用程序代码在 Spring 4.3.14.RELEASE + Hibernate 4.2.21.Final 上成功运行。

问题出现在我们升级到 Spring 5.1.1.RELEASE + Hibernate 5.2.9.Final 之后。

之前的Spring配置(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>

特性:

# 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 5.1.1.RELEASE + Hibernate 5.2.9.Final) 之后的 Spring 配置

<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>

特性:

# 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

标签: springhibernatenullpointerexceptionwebsphere

解决方案


解决了。问题的原因是我们以前构建了一些专门的东西来解决从 Hibernate 3 迁移到 4 后出现的问题。Spring 上下文包含如下非标准的东西:

<!-- 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>

删除那些豆子解决了这个问题。

这是来自类注释NonClosingOpenSessionInterceptor:“ org.springframework.orm.hibernate4.support.OpenSessionInterceptor 的特殊版本 - 如果需要 - 打开 Hibernate 会话并将其注册到 Spring 的 TransactionSynchronizationManager而不在方法调用后关闭它。如果关闭,这是必要的Hibernate 会话应该在事务完成期间通过事务管理器发生。创建此类以解决使用 org.springframework.orm.hibernate4.support.OpenSessionInterceptor 时出现的“org.hibernate.SessionException:会话已关闭!”问题与 Spring 的 PlatformTransactionManager 结合使用。 "


推荐阅读