Spring @Transaction не запускает транзакции

Я использую 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. Этот фронт-контроллер имеет XML-файл конфигурации abc-servlet.xml (abc — это имя сервлета в web.xml). У меня есть и другие файлы конфигурации Spring, которые определены как context-param в web.xml. Один из файлов applicationContext-hibernate.xml файл.

Я определил txManager и <tx:annotation-driven /> в файле applicationContext-hibernate.xml. Сегодня мне было интересно, работают ли @Autowired и @Transactional вместе, поэтому я погуглил информацию и нашел эту тему.

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

Тема говорит о похожей проблеме, и это решает проблему.

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

Думая, что я также переместил свой <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

Спасибо всем за помощь. Может эта информация будет кому-то полезна. Я все еще хотел бы услышать объяснение, почему это не работало раньше.


person Prashant Kalkar    schedule 26.09.2011    source источник
comment
Реализует ли executeService() метод, определенный в ServiceLocator? Можете ли вы выдать исключение из этого метода вместо регистрации ошибки и вставки трассировки стека? Я хочу увидеть, находится ли аспект транзакции в стеке. Также укажите точную версию Spring.   -  person Tomasz Nurkiewicz    schedule 27.09.2011
comment
Можете ли вы показать, как вызывается метод? Также вы можете проверить тип экземпляра ServiceLocator, является ли он экземпляром прокси?   -  person Arun P Johny    schedule 27.09.2011
comment
Я обновил вопрос, указав требуемую дорожку стека. После обновления я ввожу экземпляр ServiceLocator в вызывающий компонент. executeService() определяется в интерфейсе ServiceLocator.   -  person Prashant Kalkar    schedule 27.09.2011
comment
Вы можете и должны опубликовать свое решение в качестве ответа на этот вопрос (который вы можете принять позже).   -  person oers    schedule 15.12.2011
comment
Что было предложено? У вас уже были транзакции, управляемые аннотациями. Как это помогает?   -  person Mukus    schedule 31.01.2013
comment
Большое спасибо за это.   -  person Rahul Bansal    schedule 26.01.2015


Ответы (2)


Я предполагаю, что вы пытаетесь сделать что-то вроде:

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

а потом удивляемся, что нет транзакции. Управление транзакциями и все другие службы Spring применяются только к bean-компонентам в контексте приложения*. Вам нужно так или иначе получить свой экземпляр из контекста, а не просто создавать его экземпляр. Или же ваш компонент-локатор находится в другом контексте приложения, чем тот, в котором вы объявляете tx:annotation-driven.

*Если вы не используете Сплетение байт-кода AspectJ во время сборки или загрузки с помощью Spring.

Редактировать: Проблема была именно в том, что я сказал (вторая часть). Вы создаете два контекста приложения. В первом вы создавали свой ServiceLocator, но во втором включили только транзакции, основанные на аннотациях. Вы видимо не понимаете границ между контекстами. Как правило, по крайней мере, по моему опыту, "бизнес"-бины, такие как ваш ServiceLocator, живут в корневом контексте, который запускается ContextLoaderListener и настраивается через contextConfigLocation. Контроллеры и другие компоненты, которые настраиваются или используются DispatcherServlet, живут в другом контексте, связанном с этим сервлетом, который настроен в файле *-servlet.xml. Этот контекст становится дочерним контекстом корневого контекста, и компоненты в нем могут быть внедрены с компонентами из корневого контекста, но не наоборот.

С моей точки зрения, вы испортили ситуацию еще хуже, чем раньше, добавив tx:annotation-driven в дочерний контекст, связанный с вашим DispatcherServlet. Вместо этого следует убедиться, что ServiceLocator создан в корневом контексте, где транзакционные службы уже доступны и находятся там, где им и место.

person Ryan Stewart    schedule 27.09.2011
comment
Я не создаю экземпляр ServiceLocator, вместо этого я ввожу bean-компонент локатора службы. Информация о звонках обновлена ​​в исходном посте. - person Prashant Kalkar; 27.09.2011
comment
@ user746528: обновил мой ответ - person Ryan Stewart; 28.09.2011

Вы должны просто переименовать свой «txManager» в «transactionManager». Из JavaDocEnableTransactionManagement >:

… в случае с XML имя — «transactionManager». <tx:annotation-driven/> жестко запрограммирован на поиск bean-компонента с именем «transactionManager» по умолчанию…

person Sergio    schedule 09.02.2015