Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doc: @Async in an Interceptor postHandle() doesn't work [SPR-16092] #20641

Closed
spring-issuemaster opened this issue Oct 21, 2017 · 4 comments

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

commented Oct 21, 2017

Pawan Kumar opened SPR-16092 and commented

If you use a @Async("yourExecutorBeanName") in a method called by an interceptor's postHandle method (whether same class or different class), the Async nature doesn't come into picture, nor does Spring complain for a wrong bean type if doesn't exist by name of "yourExecutorBeanName".

public class EventHandlerInterceptor extends HandlerInterceptorAdapter {

    @Override
    public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final ModelAndView modelAndView) throws Exception {
      //some custom logic
      publishSomeEvent(someRequestObj);
    }

    @Async("eventHandlerExecutor")
    public void publishSomeEvent(Request someRequestObj) {
        logger.info("Inside EventHandlerInterceptor - trying for Async.. doesn't work");
        //do something Async.
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        					http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd">

    <!--Default Executor and Schedulers to pick-->
    <task:annotation-driven executor="eventHandlerExecutor"/>
    <task:executor id="eventHandlerExecutor" pool-size="30-40" queue-capacity="40"/><!--Not working inside Interceptor-->

</beans>

Backported to: 4.3.13

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 21, 2017

Juergen Hoeller commented

I'm afraid this is by design: With @EnableAsync and <task:annotation-driven>, the default is proxy-based interception which only actually works when a method call comes in through the proxy: So in your scenario, you'd have to factor out the publishSomeEvent method onto a separate delegate bean which can get independently proxied, with EventHandlerInterceptor injecting a reference to that bean (receiving a proxy) and calling publishSomeEvent through it.

Alternatively, you could also do @EnableAsync(mode=ASPECTJ) and enforce AspectJ-based weaving which allows for intercepting calls within a given object as well, not dealing with a separate proxy. However, this requires a compile-time weaving or load-time weaving setup which seems overkill for your scenario. I'd rather factor out the delegate there, letting a standard proxy arrangements do the job.

That said, we should document this rather common pitfall more clearly. I'm therefore turning this issue into a documentation task.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 22, 2017

Pawan Kumar commented

Thanks a lot @Juergen. I had indeed tried using a separate @Component bean which had a method doSomethingAsync() and was calling it from EventHandlerInterceptor through @Autowire but it now looks like there was an error in my setup (project re-build most likely) earlier which was preventing the Async to happen. I had tried it multiple times and everything looked right for the setup and should've worked, hence I raised the issue here, rather than SO.
Nevertheless it works now and what you said will indeed work through a proxy. I am ok for the Spring team to resolve this issue and perhaps open a new one for the documentation.
Thanks.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 22, 2017

Juergen Hoeller commented

Let's simply repurpose this issue for the documentation work: I've added corresponding notes to the javadoc of @EnableAsync, @EnableCaching and @EnableTransactionManagement, as well to the corresponding sections in the reference documentation.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 23, 2017

Pawan Kumar commented

Sure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.