【问题标题】:Spring 4.1 MVC + Hibernate 4.3 + Webflow 2.4 + OpenSessionInViewFilter = java.lang.IllegalStateException, Already value for key bound to threadSpring 4.1 MVC + Hibernate 4.3 + Webflow 2.4 + OpenSessionInViewFilter = java.lang.IllegalStateException,已绑定到线程的键值
【发布时间】:2015-06-12 06:30:21
【问题描述】:

我正在将应用程序从这些组件版本升级到最新版本:

Spring 3.0.4          -> Spring 4.1.6
Hibernate 3.3.0       -> Hibernate 4.3.8
Spring Webflow 2.0.7  -> Spring Webflow 2.4.1
Spring Security 2.0.4 -> Spring Security 3.2.6

我目前非常纠结于与 OpenSessionInViewFilter 和 Spring Webflows 相关的问题。甚至没有执行与我的 webflow 有关的代码,问题发生在 webflow 和 Hibernate SessionHolder 的初始化时。在这次 Spring/Hibernate 升级期间,我没有更改 webflow 配置,并且近 6 年来一切都在生产中运行良好。我收到以下异常,网络上几乎没有可用的帮助。堆栈跟踪长达一英里,因此我将我认为重要的部分包括在内。

2015/04/06 18:39:31 ERROR exception_jsp Stack Trace - 
org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'null' of flow 'process/order'
    at org.springframework.webflow.engine.impl.FlowExecutionImpl.wrap(FlowExecutionImpl.java:573)
    at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:227)
    at org.springframework.webflow.executor.FlowExecutorImpl.launchExecution(FlowExecutorImpl.java:140)
    at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:238)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    ...
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
    at 
...
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
    at 
...
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Already value [org.springframework.orm.hibernate4.SessionHolder@30b921ac] for key [org.hibernate.internal.SessionFactoryImpl@486fe7cb] bound to thread [http-nio-8080-exec-8]
    at org.springframework.transaction.support.TransactionSynchronizationManager.bindResource(TransactionSynchronizationManager.java:190)
    at org.springframework.webflow.persistence.HibernateFlowExecutionListener.bind(HibernateFlowExecutionListener.java:250)
    at org.springframework.webflow.persistence.HibernateFlowExecutionListener.sessionStarting(HibernateFlowExecutionListener.java:137)
    at org.springframework.webflow.engine.impl.FlowExecutionListeners.fireSessionStarting(FlowExecutionListeners.java:117)
    at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:367)
    at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:223)
    ... 76 more

web.xml的相关部分:

  <filter> 
    <filter-name>openSessionInViewFilter</filter-name> 
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
    <init-param><param-name>singleSession</param-name><param-value>false</param-value></init-param>
  </filter> 

  <filter-mapping> 
     <filter-name>openSessionInViewFilter</filter-name> 
     <url-pattern>*.htm</url-pattern> 
  </filter-mapping>

应用程序上下文配置的相关部分:

<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
  <property name="order" value="0"/>
  <property name="flowRegistry" ref="flowRegistry"/>
</bean>
<!-- Dispatches requests mapped to flows to FlowHandler implementations -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
  <property name="flowExecutor" ref="flowExecutor"/>
</bean>
...
<bean id="flowExecutionListener" class="org.springframework.webflow.persistence.HibernateFlowExecutionListener">
  <constructor-arg ref="sessionFactory" />
  <constructor-arg ref="transactionManager" />
</bean>
...
<webflow:flow-executor id="flowExecutor">
  <webflow:flow-execution-listeners>
    <webflow:listener ref="flowExecutionListener" />
    <webflow:listener ref="securityFlowExecutionListener" />
  </webflow:flow-execution-listeners>
</webflow:flow-executor>
...
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" base-path="/WEB-INF">
    <webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>

Webflow配置文件:

<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
      http://www.springframework.org/schema/webflow/spring-webflow-2.4.xsd">

<persistence-context/>

<on-start>
  <evaluate expression="orderFormFactory.createOrderForm(externalContext.sessionMap.inboxCriteria)" result="flowScope.orderForm"/>
</on-start>
...

似乎OpenSessionInViewFilter首先创建了Hibernate Session,然后HibernateFlowExecutionListener尝试创建一个而不是使用OpenSessionInViewFilter创建的一个,从而导致"Already value [org.springframework.orm.hibernate4.SessionHolder@xxxxxxxx] for key [org.hibernate.internal.SessionFactoryImpl@xxxxxxxx] bound to thread [xxxxxxxxxxxxxxx]"错误。

关于我可以调整或进一步研究以进行故障排除的任何想法?任何解决方案或解决方法?还有人看到这个吗?感谢您的帮助!

【问题讨论】:

  • 这很难。一次进行了太多主要的 jar 升级。我怀疑很多其他人都经历过这个问题。您最好的选择是将记录器设置为“调试”包路径“org.springframework.webflow”,并尝试确定 SessionHolder obj 在哪里设置了两次。此外,在进行此类重大升级时要小心。如果您有 maven 检查依赖层次结构并确保没有 jar 出于兼容性原因自动“降级”。
  • 谢谢。我同意这一点,并且我一直在解决许多问题,这是最顽固的一个。也就是说,我有一个相当简单的解决方案,我会在经过更彻底的审查后尽快发布它。

标签: java spring hibernate spring-mvc spring-webflow


【解决方案1】:

我对此的解决方案是将我的 Web 流从由 OpenSessionInViewFilter 处理中分离出来。在我进行更改之前,应用程序中以 *.htm 结尾的所有 URL 都通过 OpenSessionInViewFilter 路由。这是我更改前的 web.xml:

<filter> 
  <filter-name>openSessionInViewFilter</filter-name> 
  <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
  <init-param><param-name>singleSession</param-name><param-value>false</param-value></init-param>
</filter> 

<filter-mapping> 
  <filter-name>openSessionInViewFilter</filter-name> 
  <url-pattern>*.htm</url-pattern> 
</filter-mapping>

现在我的 web.xml 有这个配置:

<filter> 
  <filter-name>openSessionInViewFilter</filter-name> 
  <filter-class>org.somepackage.MyCustomOpenSessionInViewFilter</filter-class>
  <init-param><param-name>singleSession</param-name><param-value>false</param-value></init-param>
</filter> 

<filter-mapping> 
  <filter-name>openSessionInViewFilter</filter-name> 
  <url-pattern>*.htm</url-pattern> 
  <url-pattern>*.flow</url-pattern>
</filter-mapping>

请注意,我为 openSessionInViewFilter 的过滤器映射添加了一个新的 *.flow url 模式,现在我有一个覆盖 Spring OpenSessionInViewFilter 的自定义类(更多内容见下文)。然后,我不得不更改我的视图(以及在少数情况下为控制器)中调用 webflow 的位置的 URL 后缀,从使用“.htm”改为使用“.flow”。
因此,例如,如果我之前使用了“/customer/customer-add.htm”的 webflow url,我将其更改为“/customer/customer-add.flow”。

下一部分是我添加了一个派生自 Spring 的 OpenSessionInViewFilter 的类,其目的是将所有 *.htm URL 传递给 OpenSessionInViewFilter,同时简单地将所有 *.flow URL 转发到链中的下一个过滤器(从而允许 HibernateFlowExecutionListener最终处理 URL 并正确管理会话):

package org.somepackage;

import javax.servlet.http.HttpServletRequest;

import org.springframework.orm.hibernate4.support.OpenSessionInViewFilter;

public class MyCustomOpenSessionInViewFilter extends OpenSessionInViewFilter {

  @Override
  public boolean shouldNotFilter( HttpServletRequest request ) {
      return request.getRequestURI().contains( ".flow" );
  }   
}

最后,请注意,您应该单独为 HibernateFlowExecutionListener 保留已有的 Spring 配置 -- 无需更改:

<bean id="flowExecutionListener" class="org.springframework.webflow.persistence.HibernateFlowExecutionListener">
  <constructor-arg ref="sessionFactory" />
  <constructor-arg ref="transactionManager" />
</bean>

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 2011-05-09
  • 2011-12-11
  • 2011-07-04
  • 2012-12-22
  • 1970-01-01
  • 2010-11-19
相关资源
最近更新 更多