16

I have a spring boot microservice where we call multiple services(Lets say Service A and Service B). I am trying to call these two services Asynchronously on multiple threads based on some conditions and once processing is completed I would like to merge the response from Service A and ServiceB.

I know we can use @Async to run a process asynchronously and use ExecutorService to start multiple threads for a service.

But i am not Sure How to keep all things together. So looking for any suggestions here?

 @Async Service A(thread1,thread2) \ MicroService / (Merge from Response of ServiceA and ServiceB) \ @Async Service B(thread1,thread2) / 

I know this is mostly theoretically explained above, but i tried following / going through multiple websites but Most of the articles either explains about Aync or Multithreading but not sure how to wait and run two process in Async in multiple threads and continue execution after these two service calls are completed!

Any Suggestions or leads are appreciated! TIA :)

2 Answers 2

22

You need to use spring's AsyncResult class to wrap your result and then use its method .completable() to return CompletableFuture object.

When merging future object use CompletableFuture.thenCompose() and CompletableFuture.thenApply() method to merge the data like this:

CompletableFuture<Integer> result = futureData1.thenCompose(fd1Value -> futureData2.thenApply(fd2Value -> merge(fd1Value, fd2Value))); 

Here is a basic example:

Annotate Spring boot main class with @EnableAsync annotation

@SpringBootApplication @EnableAsync public class StackOverflowApplication { public static void main(String[] args) { SpringApplication.run(StackOverflowApplication.class, args); } } 

Create a sample service which will return CompletableFuture

Aservice.java

@Service public class Aservice { @Async public CompletableFuture<Integer> getData() throws InterruptedException { Thread.sleep(3000); // sleep for 3 sec return new AsyncResult<Integer>(2).completable(); // wrap integer 2 } } 

Bservice.java

@Service public class Bservice { @Async public CompletableFuture<Integer> getData() throws InterruptedException { Thread.sleep(2000); // sleep for 2 sec return new AsyncResult<Integer>(1).completable(); // wrap integer 1 } } 

Create another service which will merge other two service data

ResultService.java

@Service public class ResultService { @Autowired private Aservice aservice; @Autowired private Bservice bservice; public CompletableFuture<Integer> mergeResult() throws InterruptedException, ExecutionException { CompletableFuture<Integer> futureData1 = aservice.getData(); CompletableFuture<Integer> futureData2 = bservice.getData(); // Merge futures from Aservice and Bservice return futureData1.thenCompose( fd1Value -> futureData2.thenApply(fd2Value -> fd1Value + fd2Value)); } } 

Create a sample controller for testing

ResultController.java

@RestController public class ResultController { @Autowired private ResultService resultService; @GetMapping("/result") CompletableFuture<Integer> getResult() throws InterruptedException, ExecutionException { return resultService.mergeResult(); } } 
Sign up to request clarification or add additional context in comments.

5 Comments

Why Thread.join? Why not make the ResultController just return another CompletableFuture with the aggregation?
@EdwinDalorzo, i have updated answer as per your comment
@AjitSoman and Edwin Thanks for the response. I will try to understand whats happening here and will give a try
@AjitSoman thanks again for the complete example. But looks like above is just for Asynchronous Processing correct? For opening multiple threads can i use ExecutorService?
@JingJong, Yes, you need to create bean for Execotor like this: ` @Bean public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(3); executor.setMaxPoolSize(15); executor.setQueueCapacity(500); executor.setThreadNamePrefix("GithubLookup-"); executor.initialize(); return executor; }`. check this link for more information: spring.io/guides/gs/async-method
2

You can look to a java's CompletableFuture. The ComplitableFuture allows to union several async tasks (which also are CompletableFuture) and waits for a result of all CompletableFutures.I am not sure that it is exactly fit for your case, but it may be helpful. https://www.baeldung.com/java-completablefuture#Multiple

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.