API asincrone in Spring Boot
Problema
Esporre delle API asincrone in un’applicazione Spring Boot e permettere la configurazione di un numero massimo di thread per servirle. Generare un errore al superamento del limite configurato.
Lista della spesa
- Spring Boot 2.6.6
- Java 17
Soluzione
Abilita l’esecuzione di metodi asincroni in Spring Boot utilizzando l’annotazione @EnableAsync
in una classe annotata @Configuration
(questa classe servirà poi per definire il numero massimo di thread supportati)
@Configuration
@EnableAsync
public class AsyncExecutor implements AsyncConfigurer {
...
Nella configurazione definisci il comportamento dell’istanza di Executor
che si occuperà dell’esecuzione dei thread. Utilizza un ThreadPoolTaskExecutor
che permette di configurare il numero massimo di elementi da inserire nel pool di esecutori (numero rappresentato da maxLimit
)
Definisci la politica da utilizzare quando viene superato il limite di thread a disposizione, in questo caso AbortPolicy
che genera un´eccezione RejectedExecutionException
al superamento di tale numero.
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(0);
executor.setMaxPoolSize(maxLimit);
executor.setQueueCapacity(0);
executor.setThreadNamePrefix("AsynchThread-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
executor.initialize();
return executor;
}
Definisci un’API asincrona con l’annotazione @Async
@GetMapping("/api/worker")
@Async
public void elaborate() {
worker.longWork();
}
La chiamata ritornerà immediatamente una risposta al client senza aspettare la conclusione del metodo longWork
.
Per generare una risposta di errore quando viene superato il numero di thread a disposizione gestisciRejectedExecutionException
.
@ExceptionHandler(RejectedExecutionException.class)
public void handleRejectedExecution(HttpServletResponse res, Exception ex) throws IOException {
res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Too many elaborations");
}
Il codice presentato nell’articolo segue licenza CC0.
Il codice sorgente è disponibile sotto licenza CC0.