The main goal of this project is to explore basic features of @Async
spring annotation and compare results with non-concurrent approach.
- references
This project shows how to create asynchronous queries using Spring.
Our approach is to run expensive jobs in the background and wait
for the results using Java’s CompletableFuture interface.
- spring boot concurrency options
- java executors and futures
- completable futures
- @Async annotation
- reactive programming
- virtual threads
- structured concurrency
 
- 
Enable asynchronous support: @Configuration @EnableAsync class AsyncConfig { @Bean Executor asyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); executor.setMaxPoolSize(4); executor.setQueueCapacity(500); executor.setThreadNamePrefix("EmailSender-"); executor.initialize(); return executor; } }Remark: asyncExecutor()is used to customize default behaviour and is not mandatory.
- 
Annotate method with @Async, and set return type toCompletableFuture<XXX>whereXXXis a wanted return type, for example:String customMethod() { ... }should be transformed to: CompletableFuture<String> customMethod() { ... }
- 
Consume it with Completable API, for example:- CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[]{})).join();
- CompletableFuture.allOf(completableFuture1, completableFuture2).join();
 
- 
Extract requested return (note that get()throws checked exception):- XXX xxx = completableFuture.join()
 
- email-service- microservice responsible for sending emails to given users- EmailController- REST controller; receives- login-messagemap, then asks- slow-user-servicefor- emailsand sends messages
- in EmailServicewe have the same methods:- @Asyncmethod -- asyncSend- concurrently sends messages
- non-concurrent method - send
 
- in AppRunnerwe simulate interactions and compare times
 
- slow-user-service- UserControllerreturns- Userbean (login, name, email...) for given login
- in UserRepositorywe sleep thread foruser.repository.delay.seconds(configurable inapplication.properties) and then return requested user
 
Coverage: 93%