Ankit Kathait
Ankit Kathait

Reputation: 125

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

Upvotes: 0

Views: 3194

Answers (3)

User9123
User9123

Reputation: 1733

You can return CompletableFuture. You will receive http response when CompleteableFuture will be completed.

Service:

@Async
public CompletableFuture<List<String>> doSomething() {
    return CompletableFuture.completedFuture(Arrays.asList("1", "2", "3"));
} 

Controller:

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

Upvotes: 1

Ken Chan
Ken Chan

Reputation: 90527

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 .

Upvotes: 3

Alexander Radchenko
Alexander Radchenko

Reputation: 893

If you want to use async I would split your single request into so called "start task" and "get task result" requests. Your application returns "request id" for "start task" request. Then you use "request id" when performing "get task result". Such a scenario is a common way in the Batch Processing task. If you use Spring, you may be interesting investigating Spring Batch framework, which has Start/Stop/Restart job functionality among others.

Upvotes: 1

Related Questions