Spring @Transaction not starting transactions

11,216

Solution 1

My guess would be that you're trying to do something like:

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

and then being surprised that there's no transaction. Transaction management and all other Spring services only apply to beans in the application context*. You need to get your instance from the context one way or another instead of just instantiating one. Or else your locator bean is in a separate application context than the one where you declare tx:annotation-driven.

*Unless you're using AspectJ build- or load-time bytecode weaving with Spring.

Edit: The problem was exactly what I said (the second part). You create two application contexts. You were creating your ServiceLocator in the first one, but you only enabled annotation-driven transactions in the second one. You appear to not understand the boundaries between the contexts. Generally--at least in my experience--the "business" beans, like your ServiceLocator, live in the root context, which is the one started by the ContextLoaderListener and configured via contextConfigLocation. Controllers and other beans that configure or are used by a DispatcherServlet live in another context associated with that servlet which is configured by the *-servlet.xml file. This context becomes a child context of the root context, and the beans in it can be injected with beans from the root context, though not vice versa.

From my perspective, you've broken things worse than they were before by adding tx:annotation-driven to the child context associated to your DispatcherServlet. Instead, you should ensure that the ServiceLocator is created in the root context, where transactional services are already available and are where they belong.

Solution 2

You should simply rename your "txManager" to "transactionManager". From the EnableTransactionManagement's JavaDoc:

…in the XML case, the name is "transactionManager". The <tx:annotation-driven/> is hard-wired to look for a bean named "transactionManager" by default…

Share:
11,216
Prashant Kalkar
Author by

Prashant Kalkar

Working at Sahaj software Solutions, Pune, India.

Updated on June 06, 2022

Comments

  • Prashant Kalkar
    Prashant Kalkar almost 2 years

    I am using Spring 3 with Hibernate 3. I am trying to configure Spring declarative transaction, but no matter what I try, Spring transaction is not getting started.

    Here is my configuration

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

    I have a class ServiceLocatorImpl which implements ServiceLocator interface

    @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");
          }
             ......
    }
         ....
    }
    

    It seems to me that all my configuration is correct. But when executeService method is called, TransactionSynchronizationManager.isActualTransactionActive() is always returning false.

    Please help me solving this problem. Let me know if any more information required.

    Update: I have wired the ServiceLocator into one of the other classes, as follows:

    @Autowired
    private ServiceLocator serviceLocator; // ServiceLocator is interface
    

    I am using Spring 3.0.0 version.

    executeService() is one the method defined in the ServiceLocator interface. I updated the code to throw exception instead of just logging an error. Following is the stack trace, I don't see any proxy creation in this trace. Please help.

        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)
    

    Update [Solved] I got the issue fixed. Before giving the answer as how it was fixed, I need to provide some more information. I am using Spring MVC in my project. The control DispatchServlet is configured in the web.xml. This front controller has a configuration xml file abc-servlet.xml (abc being the servlet name in web.xml). I have other spring configuration files too which are defined as context-param in web.xml. One of the file is applicationContext-hibernate.xml file.

    I defined the txManager and <tx:annotation-driven />, in the applicationContext-hibernate.xml file. Today I was wondering whether @Autowired and @Transactional work with together, so I Google the information, and found this thread

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

    The thread talk about similar problem, and this solves the problem.

    I implemented one of the suggestion and added <tx:annotation-driven .../> to my servlet's application context xml and it fixes the problem.

    Thinking that I also moved my <tx:annotation-driven /> into abc-servlet.xml file and it worked.

    My logs are now shoulding the required messages:

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

    Thanks to everyone for Helping. May be this information will be helpful to someone. I would still like to hear about the explanation as why it was not working earlier.

    • Tomasz Nurkiewicz
      Tomasz Nurkiewicz over 12 years
      Is executeService() implementing a method defined in ServiceLocator? Can you throw an exception from this method instead of logging an error and paste the stack trace? I want to see whether the transaction aspect is on the stack. Also please provide the exact Spring version.
    • Arun P Johny
      Arun P Johny over 12 years
      Can you show how the method is called? Also can you check what is the instance type of ServiceLocator, is it a proxy instance?
    • Prashant Kalkar
      Prashant Kalkar over 12 years
      I have updated the question with required stack track. As updated I am injecting the ServiceLocator instance in the calling bean. executeService() is defined in ServiceLocator interface.
    • oers
      oers over 12 years
      You can and should post your solution as an answer to this question(which you can accept later).
    • Mukus
      Mukus over 11 years
      What was the suggestion? You already had annotation driven transactions. How does moving that help?
    • Rahul Bansal
      Rahul Bansal over 9 years
      Thanks a lot for this.
  • Prashant Kalkar
    Prashant Kalkar over 12 years
    I am not instantiating the ServiceLocator, instead I am injecting the service locator bean. The calling information is updated in original post.
  • Ryan Stewart
    Ryan Stewart over 12 years
    @user746528: Updated my answer