Matej Spiller-Muys opened SPR-16939 and commented
We are using method with @Scheduled
annotations inside beans that have @Transactional
methods (including @Scheduled
). The scheduled task is called using proxied been and the @Transactional
works as expected.
However as soon as we add self autowiring (so we can manage @Transactional
between method calls), then scheduled task method is called directly without proxy.
It does not work:
1. settings property: spring.aop.proxy-target-class=true
2. @EnableAspectJAutoProxy
(proxyTargetClass = true)
3. @EnableTransactionManagement
(proxyTargetClass = true)
The only workaround is to manually add @Scope
(proxyMode = ScopedProxyMode.TARGET_CLASS) to each problematic bean.
But this is error prone.
It should respect global proxy-target-class (it is default anyway in spring 5.0).
I have attached the example.
The same problem is in Spring 4.3.
Excepted stacktrace from @Scheduled
:
...
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:284)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
at springtest.MyServiceImpl$$EnhancerBySpringCGLIB$$ad7504a5.scheduled(\
Actual stacktrace from @Scheduled
:
java.lang.Exception
at springtest.MyServiceImpl.scheduled(MyServiceImpl.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
Affects: 5.0.7
Attachments: - springtest.zip (4.12 kB)
Comment From: snicoll
That's because you inject the raw instance and self-references like that can't have the semantics you expect them to have. If you insist on using self-references (please don't) you need to inject an ObjectProvider
or use @Lazy
to relax the requirements and give the context a chance to do what you expect.
See also https://github.com/spring-projects/spring-framework/issues/28299