API asincrone in Spring Boot

Pubblicato il 04/11/2022

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.

  • I contenuti di questo articolo sono rilasciati con licenza CC-BY 4.0
  • Eventuali spezzoni di codice presentati seguono, dove non dichiarato, licenza MIT