Search code examples
spring-bootasynchronouscompletable-future

Is CompletableFuture is must use return type for AAsync spring boot annotation?


I want to Use @Async annotation on method for running it asynchronously. I have defined my ThreadExecutor as follows:

@Bean("threadPoolTaskExecutor")
public TaskExecutor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(20);
    executor.setMaxPoolSize(200);
    executor.setWaitForTasksToCompleteOnShutdown(true);
    executor.setAwaitTerminationSeconds(30);
    executor.setThreadNamePrefix("async-");
    executor.setQueueCapacity(50);
    executor.initialize();
    return executor;
}

My question is, is it mandatory to use CompletableFuture as return type for the method using @Async annotation? Will it work if my third party REST calls returns different/Custom types? for e.g.

    @Async("threadPoolTaskExecutor")
    public ResponseDTO getCapa(final List<String> vins) {
        for (String vin : vins) {
            CapabilityDTO capabilityDTO = new CapabilityDTO();
                // call third party 
                Optional<ResponseDTO> response=thirdPartyClient.getInfo();
                ..........
                 return response.get();
               }
           }

or I must use CompletableFuture<ResponseDTO> ??


Solution

  • As per the Spring Async javadoc:

    the return type is constrained to either void or Future. In the latter case, you may declare the more specific ListenableFuture or CompletableFuture types which allow for richer interaction with the asynchronous task and for immediate composition with further processing steps.

    In practice, I believe that if you declare another type, the caller will receive a null value since no value will be available at the moment of the call and it has to return immediately, so the caller won’t be able to retrieve the result.

    If you want to be able to access the result, you must thus return a Future containing it. Easiest is probably to just use

    return CompletableFuture.completedFuture(response.get())
    

    Spring Async will then take care of forwarding your result to the caller when your method returns.