0

I'm toying with asynchronous calls to reduce some waiting time on client side when calling a page.

As a experiement i have a controller that calls a pojo with a method annotated with @Async. In that menthod i sleep for 10000 ms to simulation operation to test whether my theory works, and it seems not to. Code below and further information can be found after it:

Test Controller

@Conroller
public class TestController {
@RequestMapping("/test")
public String testAsyncCall() {

new AsyncTestClass().asyncOpOne();

return "secondpage";
}
}

Asynchronous Class containing the @Async annotated method

public class AsyncTestClass {
@Async
public void asyncOpOne() {
try {
        Thread.sleep(10000);
        System.out.println("done working");
    } catch (InterruptedException e) {
        //
    }
}
}

Now from my understanding when the client makes the call to "/test" in their browser the controller should return call the asynchronous method and instantly return "secondpage" to be rendered.

What is happening is that the controller doesn't return the second page until the 10000 ms in the asynchronous call has finished, only then it returns the secondpage.

FYI @EnableAsync is added to one of my config files (using Java Configuration).

What am i doing wrong here that is causing the controller to wait for the async to finish its sleep before continuing?

8
  • 2
    You aren't using the Spring configured instance but are constructing a new one yourself... Use the one configured by spring. Commented Apr 16, 2015 at 13:18
  • @M.Deinum can you clarify, i don't understand what you mean by that Commented Apr 16, 2015 at 13:19
  • 1
    You are doing new AsyncTestClass which means you are constructing an instance yourself, outside the control of spring so basically your @Async is useless. Add a bean for the AsyncTestClass and inject that into your controller. Commented Apr 16, 2015 at 13:20
  • So does that mean all methods i annotate @Async should be in a bean and injected? Commented Apr 16, 2015 at 13:22
  • @Aeseir Correct, otherwise you don't get the AOP-enabled proxy. Commented Apr 16, 2015 at 13:25

1 Answer 1

4

Spring uses AOP to apply @Async behavior to your beans (the same goes for @Transactional for instance).

Spring will only apply AOP to beans it knows, as you are constructing a new instance outside of the scope of Spring the @Async does nothing. Simply add it as a bean to your configuration and inject it into your controller.

@Bean
public AsyncTestClass asyncTestClass() {
    return new AsyncTestClass():
}

Then in your calling class.

@Conroller
public class TestController {

    @Autowired
    private AsyncTestClass asyncTestClass;

    @RequestMapping("/test")
    public String testAsyncCall() {

        asyncTestClass.asyncOpOne();
        return "secondpage";
    }
}
Sign up to request clarification or add additional context in comments.

Comments

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.