How to create a Async http call in Spring Boot

Use case in this example:

1. Client makes call to server side, returned immediately, but already start a asynchrony process in server side.

2. When the process is still running, client need to call http call to get the processing status from time to time.

3.  This example shows a processing status shared by the whole container context, as the Bean and controller scope in Spring is Singleton. You can also try to make controller and bean into session, request level if needed.Or use the session/Model to handle shared data.

4.  @Async can not be used in the controller , I test it. Callable maybe it the way for controller method.

 

– Let us take a look code.  Create one service bean and make it expose the status by a getter.

@Service
public class TestService {

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

private String status = "Not start";

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

public String getStatus() {
 return status;
 }
}

 

Then config the application to make it support the @EnableAsync and define the tread pool for Async calls.

@EnableAsync
public class MyDemoApplication {
...........................................................// for Async test code
 @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;
 }

 

Then at spring mvc controller create two method for http , start process and check process status:

 

@Autowired
 private TestService processService;
....
@GetMapping("/startAsync")
 public Result startAsync() {
 processService.process();
 statusData = processService.getStatus();
 Result rt = new Result(true, statusData);
 return rt;
 }

@GetMapping("/getAsyncStatus")
 public Result getAsyncStatus() {
 statusData = processService.getStatus();
 Result rt = new Result(true, statusData);
 return rt;
 }

Then server side is done!

Let me create a client code to test it how is works:

 testStartAsyncCall();
 testAsyncStatusCall();
 try {
 TimeUnit.SECONDS.sleep(10);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 testAsyncStatusCall();
 try {
 TimeUnit.SECONDS.sleep(10);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 testAsyncStatusCall();

 

You can see the process take 15 seconds to finish, so client side try to get the status every 10 seconds after call to start the process. so we can see how status is changed in the whole process.

My example is modified from one example post, Please refer to this post:

http://softwaredevelopercentral.blogspot.com/2017/07/asynchronous-processing-async-in-spring.html

 

 

 

Advertisements