An @Async
method in a @Service
-annotated class is not being called asynchronously - it\'s blocking the thread.
I\'ve got
I realized following the tutorial async-method tutorial code that my issue source was: the bean with the annotated @Async
method was not being created wrapped in a proxy.
I started digging and realized that there was a message saying
Bean 'NameOfTheBean' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
You can see here responses about this issue and its basically that BeanPostProcessors are required by every Bean, so every bean injected here and its dependencies will be excluded to be processed later by other BeanPostProcessors, because it corrupted the life cycle of beans. So identify which is the BeanPostProcessor
that is causing this and dont use or create beans inside of it.
In my case i had this configuration
@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
@Autowired
private Wss4jSecurityInterceptor securityInterceptor;
@Autowired
private DefaultPayloadLoggingInterceptor payloadLoggingInterceptor;
@Override
public void addInterceptors(List interceptors) {
interceptors.add(securityInterceptor);
interceptors.add(payloadLoggingInterceptor);
}
}
WsConfigurerAdapter
is actually a BeanPostProcessor
and you realize it because there is always a pattern: @Configuration
that extends classes and override some of it functions to install or tweak beans involved in some non functional features, like web service or security.
In the aforementioned example you have to override the addInterceptors
and added interceptors beans, so if you are using some annotation like @Async
inside DefaultPayloadLoggingInterceptor
it wont work. What is the solution? Get ride of WsConfigurerAdapter
to start.
After digging a bit i realized a class named PayloadRootAnnotationMethodEndpointMapping
at the end was which had all valid interceptors, so i did it manually insted of overriding a function.
@EnableWs
@Configuration
public class WebServiceConfig {
@Autowired
private Wss4jSecurityInterceptor securityInterceptor;
@Autowired
private DefaultPayloadLoggingInterceptor payloadLoggingInterceptor;
@Autowired
public void setupInterceptors(PayloadRootAnnotationMethodEndpointMapping endpointMapping) {
EndpointInterceptor[] interceptors = {
securityInterceptor,
payloadLoggingInterceptor
};
endpointMapping.setInterceptors(interceptors);
}
}
So this will be run after all BeanPostProcessor
have done their job. The setupInterceptors
function will run when that party is over and install the interceptors beans. This use case may be extrapolated to cases like Security.
Conclusions:
BeanPostProcessor
, so dont inject beans there and try to use AOP behaviour, because it wont work, and you will see Spring tells it to you with the beforementioned message in the console. In those cases dont use beans but objects (using the new
clause).@Autowired
it and add those beans like i did before.I hope this may save some time for you.