3

This is very similar to the other question here: Spring Boot @Async method in controller is executing synchronously. However my @Service method annotated with @Async is still executing synchronously. I've tried all methods from different forums to no use. Hopefully someone could help me figure out why. A simple spring boot project as below doesn't work.

AsyncConfiguration.java

@Configuration
@EnableAsync
public class AsyncConfiguration(){}

SomeService.java

@Service
public class SomeService() {
  @Async
  public void doSomething() {
    try {
      Thread.sleep(5000L);
    } catch (Exception ignore){}
  }
}

SomeController.java

@Controller
public class SomeController() {

  @Inject SomeService someService;

  @RequestMapping(value="/", method=RequestMethod.POST)
  public String doStuff() {
    someService.doSomething();
    return "mytemplate";
  }
}
9
  • you have a @Configuration on your AsyncConfiguration right? Commented Sep 14, 2015 at 9:47
  • @StéphaneNicoll Yeah I do. I'll edit the question Commented Sep 14, 2015 at 9:50
  • Your configuration looks pretty legal, so probably the root of problem somewhere else. Could you share you project on github/bitbucket or create SSCCE (sscce.org)? Commented Sep 14, 2015 at 9:54
  • can you put logging (with logging of thread name) into SomeService.dosomething() and post log output? Commented Sep 14, 2015 at 9:54
  • If it helps, I'm using the method in @Service class to send email using JavaMailSender Commented Sep 14, 2015 at 9:54

2 Answers 2

2

Here is a simple example with @Async. Follow these steps to get @Async to work in your Spring Boot application:

Step 1: Add @EnableAsync annotation and Add TaskExecutor Bean to Application Class.

Example:

@SpringBootApplication
@EnableAsync
public class AsynchronousSpringBootApplication {

    private static final Logger logger = LoggerFactory.getLogger(AsynchronousSpringBootApplication.class);

    @Bean(name="processExecutor")
    public TaskExecutor workExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setThreadNamePrefix("Async-");
        threadPoolTaskExecutor.setCorePoolSize(3);
        threadPoolTaskExecutor.setMaxPoolSize(3);
        threadPoolTaskExecutor.setQueueCapacity(600);
        threadPoolTaskExecutor.afterPropertiesSet();
        logger.info("ThreadPoolTaskExecutor set");
        return threadPoolTaskExecutor;
    }

    public static void main(String[] args) throws Exception {
  SpringApplication.run(AsynchronousSpringBootApplication.class,args);
 }
}

Step 2: Add Method which executes an Asynchronous Process

@Service
public class ProcessServiceImpl implements ProcessService {

    private static final Logger logger = LoggerFactory.getLogger(ProcessServiceImpl.class);

    @Async("processExecutor")
    @Override
    public void process() {
        logger.info("Received request to process in ProcessServiceImpl.process()");
        try {
            Thread.sleep(15 * 1000);
            logger.info("Processing complete");
        }
        catch (InterruptedException ie) {
            logger.error("Error in ProcessServiceImpl.process(): {}", ie.getMessage());
        }
    }
}

Step 3: Add an API in the Controller to execute the asynchronous processing

@Autowired
private ProcessService processService;

@RequestMapping(value = "ping/async", method = RequestMethod.GET)
    public ResponseEntity<Map<String, String>> async() {
        processService.process();
        Map<String, String> response = new HashMap<>();
        response.put("message", "Request is under process");
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

I have also written a blog and a working application on GitHub with these steps. Please check: http://softwaredevelopercentral.blogspot.com/2017/07/asynchronous-processing-async-in-spring.html

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

5 Comments

That's a good example, but do you know why the @vdkkj's code didn't work?
If you see Step 1 in my answer, a TaskExecutor Bean with name processExecutor is added to Application Class. This is very important and is used in Step 2 of my answer. I don't see that in @vdkkj's code.
@AjTechDeveloper: That could not be the problem, from the official getting started blog: "If you do not define an Executor bean, Spring creates a SimpleAsyncTaskExecutor and uses that.
hey, can you add a new url for the post now (2021 the url broke), thanks in advance
Hi @qleoz12, the blog post URL is same as above and it is working: softwaredevelopercentral.blogspot.com/2017/07/…
0

Sorry for my English. The same problem happened to me. The solution was to add

@Autowired
private SomeService someService;

In the Controller class, in this way it allows the class to contain the Beam Configurations associated with "SomeService", thus being able to execute the asynchronous method perfectly.

Here is a project with a functional asynchronous method: https://github.com/JColmenares/async-method-api-rest.git

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.