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(\) 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)

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