Spring boot with Async API call and time comparison

static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)static CompletableFuture<Void> runAsync(Runnable runnable)static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)<U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)<U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn);
  1. Spring Async annotation with compeltable future using common pool
@GetMapping("asyncwithcompeltablefutureandcommonpool")
private Result getAsyncWithCompeltableFutureAndCommonPool() throws InterruptedException {
AsyncRequestContext asyncRequestContext = new AsyncRequestContext();// multiple asynchronous lookups
long start = System.currentTimeMillis();
CompletableFuture<ToDo> result1 = service.findToDo();CompletableFuture<List<Map<String, Object>>> result2 = service.getUserComments();CompletableFuture.allOf(result1, result2).thenApply(r -> {
Result result = new Result();
List<Map<String, Object>> secondResult = new ArrayList<>();
ToDo firstResult = null;
try {
secondResult = result2.get();
firstResult = result1.get();
}
long end = System.currentTimeMillis();
LOG.info("asyncwithcompeltablefutureandcommonpool future with common pool took " + (end - start) + "ms");
result = service.marshallResponse(firstResult, secondResult);
asyncRequestContext.setResult(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return null;
}).join();
return asyncRequestContext.getResult();
}
private static final Logger logger = LoggerFactory.getLogger(AsyncDemoService.class);
private final RestTemplate restTemplate;
public AsyncDemoService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
@Async
public CompletableFuture<ToDo> findToDo() throws InterruptedException {

logger.info("findToDo thread " + Thread.currentThread().getName());

String url = "https://jsonplaceholder.typicode.com/todos/1";
ToDo result = restTemplate.getForObject(url, ToDo.class); return CompletableFuture.completedFuture(result);
}
@Async
public CompletableFuture<List<Map<String, Object>>> getUserComments() throws InterruptedException {

logger.info("getUserComments thread " + Thread.currentThread().getName());

String url = "https://jsonplaceholder.typicode.com/comments?postId=1";

List<Map<String, Object>> result = restTemplate.getForObject(url, List.class);
return CompletableFuture.completedFuture(result);
}
Output 1
@GetMapping("asyncwithcompeltablefutureandcustompool")
private Result getAsyncWithCompeltableFutureAndCustomPool() throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(10); AsyncRequestContext asyncRequestContext = new AsyncRequestContext();// multiple asynchronous lookups
long start = System.currentTimeMillis();
CompletableFuture<ToDo> result1 = service.findToDoWithoutAsyncAnnotation(executor);CompletableFuture<List<Map<String, Object>>> result2 = service.getUserCommentsWithoutAsyncAnnotation(executor);CompletableFuture.allOf(result1, result2).thenAccept(r -> {
Result result = new Result();
try {
List<Map<String, Object>> secondResult = result2.get();
ToDo firstResult = result1.get();
long end = System.currentTimeMillis();
LOG.info("asyncwithcompeltablefutureandcustompool future with custom pool took " + (end - start) + "ms");
result = service.marshallResponse(firstResult, secondResult);
asyncRequestContext.setResult(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}).join();
return asyncRequestContext.getResult();
}
public CompletableFuture<ToDo> findToDoWithoutAsyncAnnotation(ExecutorService executor)
throws InterruptedException {
CompletableFuture<ToDo> future = CompletableFuture.supplyAsync(new Supplier<ToDo>() {@Override
public ToDo get() {
logger.info("findToDo thread " + Thread.currentThread().getName());
String url = "https://jsonplaceholder.typicode.com/todos/1"; ToDo result = restTemplate.getForObject(url, ToDo.class); return result;
}
}, executor);
return future;
}
public CompletableFuture<List<Map<String, Object>>>
getUserCommentsWithoutAsyncAnnotation(ExecutorService executor)
throws InterruptedException {
CompletableFuture<List<Map<String, Object>>> future = CompletableFuture.supplyAsync(new Supplier<List<Map<String, Object>>>() {@Override
public List<Map<String, Object>> get() {

logger.info("getUserComments thread " + Thread.currentThread().getName());
String url = "https://jsonplaceholder.typicode.com/comments?postId=1"; List<Map<String, Object>> result = restTemplate.getForObject(url, List.class);return result;
}
}, executor);
return future;
}
Output 2
@GetMapping("asyncwithcompeltablefutureandcommonpoolwithoutasyncannotation")
private Result getAsyncWithCompeltableFutureAndCustomPool() throws Exception {
AsyncRequestContext asyncRequestContext = new AsyncRequestContext();// multiple asynchronous lookups
long start = System.currentTimeMillis();
CompletableFuture<ToDo> result1 = service.findToDoWithoutAsyncAnnotation();CompletableFuture<List<Map<String, Object>>> result2 = service.getUserCommentsWithoutAsyncAnnotation();CompletableFuture.allOf(result1, result2).thenAccept(r -> {
Result result = new Result();
try {
List<Map<String, Object>> secondResult = result2.get();
ToDo firstResult = result1.get();
long end = System.currentTimeMillis();
LOG.info("asyncwithcompeltablefutureandcustompool future with custom pool took " + (end - start) + "ms");
result = service.marshallResponse(firstResult, secondResult);
asyncRequestContext.setResult(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}).join();
return asyncRequestContext.getResult();
}
public CompletableFuture<ToDo> findToDoWithoutAsyncAnnotation()
throws InterruptedException {
CompletableFuture<ToDo> future = CompletableFuture.supplyAsync(new Supplier<ToDo>() {@Override
public ToDo get() {
logger.info("findToDo thread " + Thread.currentThread().getName());
String url = "https://jsonplaceholder.typicode.com/todos/1";ToDo result = restTemplate.getForObject(url, ToDo.class);return result;
}
});
return future;
}
public CompletableFuture<List<Map<String, Object>>>
getUserCommentsWithoutAsyncAnnotation()
throws InterruptedException {
CompletableFuture<List<Map<String, Object>>> future = CompletableFuture.supplyAsync(new Supplier<List<Map<String, Object>>>() {@Override
public List<Map<String, Object>> get() {

logger.info("getUserComments thread " + Thread.currentThread().getName());
String url = "https://jsonplaceholder.typicode.com/comments?postId=1";List<Map<String, Object>> result = restTemplate.getForObject(url, List.class);return result;
}
});
return future;
}
Output 3
public CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)Example:CompletableFuture<ToDo> future = CompletableFuture.supplyAsync(this::getToDo)
.orTimeout(2, TimeUnit.SECONDS);
ToDo result = future.get();
public CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)
ToDo defaultToDo = new ToDo();CompletableFuture<ToDo> future = CompletableFuture.supplyAsync(this::getToDo)
.completeOnTimeout(defaultToDo, 2,TimeUnit.SECONDS);
ToDo result = future.get();
public CompletableFuture <T> exceptionally(Function <Throwable, ? extends T> function);  


public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> bifunction);


public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {return 10 / 0;}).exceptionally(exception -> {System.err.println("exception: " + exception);return 1;});
exception: java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
CompletableFuture.supplyAsync(() -> {return 10 / 0;}).handle((input, exception) -> {if (exception != null) {System.out.println(exception);return 1;}return 0;}).thenApply(input -> input + 1).thenAccept(System.out::println);
java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero2
CompletableFuture.supplyAsync(() -> {return 10 / 0;}).whenComplete((input, exception) -> {if (exception != null) {System.out.println(exception);}}).thenApply(input -> input + 1).thenAccept(System.out::println);
java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store