8

I'm using spring annotations for configuring Controllers(@EnableWebMvc), services(@service and @ComponentScan). In one of my services I have a method annotated with @Async and I also have @EnableAsync added on my config class. When one of MVC controller calls the service method which is annotated with @Async I expect the controller to return immediately without waiting for the service method to complete. By it does not. When I setup the break point in the service method I see that it is in fact running in a seperate thread i.e. the stacktrace does show that it is using SimpleAsyncTaskExecutor as I configured below.

Here is the annotation in my configuration class looks like

@Configuration
@EnableWebMvc
@EnableScheduling
@ComponentScan(basePackages = "com.mypackage")
@EnableAsync
public class WebApplicationConfig extends WebMvcConfigurerAdapter implements AsyncConfigurer {
...
...
@Override
    public Executor getAsyncExecutor() {
        SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor("SimpleExecutor-");
        executor.setConcurrencyLimit(props.getIntegerProperty(SysProps.EMAIL_SENDER_CONCURRENT_THREAD_LIMIT));
        return executor;
    }

And here is my MVC controller method looks like

    @Autowired 
    private EmailService emailService;
    @ResponseStatus(value = HttpStatus.CREATED)
    @RequestMapping(value = "/asset/{assetId}/slideshare/email", method = RequestMethod.POST, produces = JSON_UTF8)
    @ResponseBody
    @ApiResponseObject
    public Link createAndEmailSlideShareLink(@PathVariable final String assetId,
                                             @RequestParam(value = "email") final String email,
                                             @RequestParam(value = "message", required = false) final String message,
                                             final HttpServletRequest request) {
    Link link = linkService.createLink()
    emailService.sendSlideShareAssetEmail(user,link...
    return link;
}

And the service method looks like this

@Async
public void sendSlideShareAssetEmail(User user, String email, String msg, String link, Asset asset) {

Why doesn't the MVC controller does not return immediately?

7
  • Post the controller class. What's the return value? Commented May 7, 2015 at 22:30
  • @chrylis I updated the post with the code from the controller class. Please check Commented May 7, 2015 at 22:33
  • You didn't actually post the content of the controller method. Commented May 8, 2015 at 0:38
  • The primary thing I was looking for was how you were constructing the return value, which does appear to be independent of the async call. Commented May 8, 2015 at 1:33
  • I think i know the problem but before i provide answer can you please show me your code where you extend AbstractAnnotationConfigDispatcherServletInitializer so i can confirm. Commented May 8, 2015 at 3:58

1 Answer 1

0

My guess is that your EmailService bean is being included from two different contexts.

This answer from Ryan Stewart explains the problem/solution in more detail.

Do you have other configurations that are being used? Is there a *-servlet.xml or other servlets defined in your web.xml that might bring your EmailService into the root context?

Do you have a ContextLoaderListener or ServletContextListener defined? Perhaps those are picking up your EmailService in addition to the component scan.

Including your entire source tree as the component-scan path seems suspicious. Try restricting the paths you use in your component scan to exclude your EmailService and see if its still running executing in a SimpleAsyncTaskExecutor. If it is than you know its being brought in from a different context. Once you find the other context you should be able to exclude it there and add it back to your component-scan or EnableAsync in the other context.

Sign up to request clarification or add additional context in comments.

1 Comment

Can you provide a short description of the solution? Otherwise this is only a comment and not an answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.