javaspringspring-bootspring-mvcasynchronous

Getting data back from @Async function call


Hi I am new to multithreading in java. Can someone please help me with this:

My service:

@Async
public List<String> doSomething(int a){
    //Do something
    return list;
}

SpringbootApplication:

@SpringBootApplication
@EnableAsync
public class Test {

    public static void main(String[] args) {
        SpringApplication.run(Test.class, args);
    }

}

Async config:

@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean(name ="taskExecutor")
    public Executor taskExecutor(){
        ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("userThread-");
        executor.initialize();
        return executor;
    }
}

Controller:

@RestController
public class Controller{
    
    @Autowired
    private Service service;

    @GetMapping("test")
    public List<String> getAll(){
        return service.doSomething(1);
    }
}

When I hit this get request from postman it is showing up blank in the response. I understand that my call is going asynchronously and the response is coming back even before the my method is called. Is there any way to see this response by changing some settings in either my postman or spring boot application


Solution

  • If you want to process the request asynchronously but also want the API client to receive the response after it finishes processing such that from the client 's point of view , the request processing still looks like synchronous , the key is to use the Servlet3 asynchronous processing feature.

    You do not need to configure it to execute asynchronously in the service level using @Aysnc. Instead configure the controller method to return CompletableFuture. Under the cover , it will trigger Servlet3 's asynchronous request processing which will process the request in another thread besides the HTTP thread that receive the request.

    So your codes should look something like:

    public class Service {
        
        //No need to add @Async
        public List<String> doSomething(int a){
            return list;
        }
    }
    
    
    @RestController
    public class Controller{
        
        @Autowired
        private Service service;
    
        @GetMapping("test")
        public CompletableFuture<List<String>> getAll(){
            return CompletableFuture.supplyAsync(()->service.doSomething(1));
        }
    }
    

    For details about the Servlet3 asynchronous request processing supported in spring-mvc , you can refer to this blog series start from this .