Spring @Transaction无法启动事务

15

我正在使用Spring 3和Hibernate 3。我正在尝试配置Spring声明式事务,但无论我尝试什么,Spring事务都没有启动。

这是我的配置:

文件: applicationContext-hibernate.xml

<tx:annotation-driven transaction-manager="txManager" />

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="mdbDataSource" class="org.apache.commons.dbcp.BasicDataSource">
...
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
 <property name="dataSource" ref="mdbDataSource" />
  <property name="annotatedClasses">
.....
</bean>

我有一个类ServiceLocatorImpl,它实现了ServiceLocator接口

@Service("serviceLocator")
@Transactional
public class ServiceLocatorImpl implements  ApplicationContextAware, Serializable, ServletContextAware, ServiceLocator {
public ResultObject executeService( Map objArgs )
{
      if(TransactionSynchronizationManager.isActualTransactionActive()) {
          LOGGER.debug("ServiceLocator:executeService - Active transaction found");
      } else {
        LOGGER.error("No active transaction found");
      }
         ......
}
     ....
}

我觉得我的所有配置都是正确的。但是当调用executeService方法时,TransactionSynchronizationManager.isActualTransactionActive()总是返回false。

请帮助我解决这个问题。如果需要更多信息,请告诉我。

更新:我已经将ServiceLocator连接到另一个类中,如下所示:

@Autowired
private ServiceLocator serviceLocator; // ServiceLocator is interface

我正在使用Spring 3.0.0版本。

executeService()是ServiceLocator接口中定义的一个方法。我更新了代码,以抛出异常而不仅仅记录错误。以下是堆栈跟踪,我在这个跟踪中没有看到任何代理创建。请帮忙。

    java.lang.RuntimeException: No active transaction found
at com.nihilent.venice.common.service.ServiceLocatorImpl.logTransactionStatus(ServiceLocatorImpl.java:102)
at com.nihilent.venice.common.service.ServiceLocatorImpl.executeService(ServiceLocatorImpl.java:47)
at com.nihilent.venice.web.controller.CommonController.handleRequest(CommonController.java:184)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:710)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:167)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:414)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:402)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:771)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:716)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:552)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:176)
at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145)
at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92)
at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:381)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
at org.apache.jasper.runtime.PageContextImpl.doForward(PageContextImpl.java:709)
at org.apache.jasper.runtime.PageContextImpl.forward(PageContextImpl.java:680)
at org.apache.jsp.index_jsp._jspService(index_jsp.java:57)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:386)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:176)
at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145)
at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92)
at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:381)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.nihilent.venice.web.filter.DyanamicResponseHeaderFilter.doFilter(DyanamicResponseHeaderFilter.java:33)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:118)
at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:343)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.nihilent.venice.web.filter.RequestFilter.doFilter(RequestFilter.java:44)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)

更新 [已解决] 我已经解决了问题。在提供解决方法之前,我需要提供更多信息。我的项目中使用了Spring MVC。控制器DispatchServlet在web.xml中进行配置。这个前端控制器有一个名为abc-servlet.xml的配置xml文件(abc是web.xml中servlet的名称)。我还有其他的spring配置文件,这些文件在web.xml中被定义为context-param。其中一个文件是applicationContext-hibernate.xml文件。

我在applicationContext-hibernate.xml文件中定义了txManager<tx:annotation-driven />。今天我在想@Autowired和@Transactional是否可以一起运行,于是我Google了相关信息,并找到了这个帖子:

http://forum.springsource.org/showthread.php?48815-Repository-Autowired-Transaction-not-returning-proxy-and-causes-exception

这个帖子讨论了类似的问题,它解决了问题。

我实现了其中的一个建议,在我的servlet的应用程序上下文xml中添加了<tx:annotation-driven .../>,并且问题得到了解决。

于是我把我的<tx:annotation-driven />也移到了abc-servlet.xml文件中,问题得到了解决。

我的日志现在显示出了必需的信息:

[venice] DEBUG [http-8080-1] 27 Sep 2011 14:24:06,312 ServiceLocatorImpl.logTransactionStatus(100) | ServiceLocator:executeService - Active transaction found

感谢每个人提供的帮助。也许这些信息对某个人有所帮助。我仍然想知道为什么之前不起作用的解释。


executeService() 是否实现了 ServiceLocator 中定义的方法?你能否在该方法中抛出异常而不是仅记录错误并粘贴堆栈跟踪信息?我想看看事务方面是否在堆栈上。另外,请提供确切的 Spring 版本。 - Tomasz Nurkiewicz
你能展示一下这个方法是如何被调用的吗?另外,你能检查一下ServiceLocator的实例类型是什么吗?它是一个代理实例吗? - Arun P Johny
我已经更新了问题并添加了必要的堆栈跟踪。根据更新,我正在调用bean中注入ServiceLocator实例。 executeService()ServiceLocator接口中定义。 - Prashant Kalkar
2
你可以并且应该将你的解决方案作为这个问题的答案发布(之后你可以接受它)。 - oers
建议是什么?您已经有了注释驱动的事务。将其移动有何帮助? - Mukus
非常感谢您。 - Rahul Bansal
2个回答

4
我猜你想要做的事情是类似这样的:

ServiceLocator locator = new ServiceLocatorImpl();
...
locator.executeService(someMap);

然后惊讶地发现没有交易。事务管理和所有其他Spring服务仅适用于应用程序上下文中的bean。您需要以某种方式从上下文获取实例,而不仅仅是实例化一个实例。否则,您的定位器bean将位于声明tx:annotation-driven的应用程序上下文之外。
*除非您正在使用Spring和AspectJ build-或load-time bytecode weaving编辑:问题正如我所说的那样(第二部分)。您创建了两个应用程序上下文。您在第一个上下文中创建了ServiceLocator,但只在第二个上下文中启用了注释驱动的事务。您似乎不理解上下文之间的边界。通常-至少在我的经验中,“业务”bean(例如ServiceLocator)位于根上下文中,这是由ContextLoaderListener启动并通过contextConfigLocation进行配置的上下文。配置或由DispatcherServlet使用的控制器和其他bean位于与该servlet相关联的另一个上下文中,该上下文由*-servlet.xml文件进行配置。该上下文成为根上下文的子上下文,并且其中的bean可以使用来自根上下文的bean进行注入,反之则不行。

从我的角度来看,通过将tx:annotation-driven添加到与您的DispatcherServlet关联的子上下文中,您比以前更糟糕地破坏了事物。相反,您应确保在根上下文中创建ServiceLocator,在那里事务服务已经可用并且属于它们的位置。


我没有实例化ServiceLocator,而是注入了服务定位器bean。调用信息已在原帖中更新。 - Prashant Kalkar

1
你应该简单地将其"txManager"重命名为"transactionManager"。根据EnableTransactionManagementJavaDoc

…在XML情况下,名称为"transactionManager"。默认情况下<tx:annotation-driven/>会硬编码查找名为"transactionManager"的bean…


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接