Search code examples
asynchronousspring-bootcontrollerspring-restcontroller

@Async in Rest Controller not working


I am developing a REST API and want to make it as an asynchronous Rest Controller, So my Controller is below:

@RestController
@Async
public class ApiController {
    List<ApiObject>  apiDataList;   

    @RequestMapping(value="/data",produces={MediaType.APPLICATION_JSON_VALUE},method=RequestMethod.GET)
    public ResponseEntity<List<ApiObject>> getData(){                                       
        List<ApiObject> apiDataList=getApiData();
        return new ResponseEntity<List<ApiObject>>(apiDataList,HttpStatus.OK);
    }
    @ResponseBody   
    public List<ApiObject>  getApiData(){
        List<ApiObject>  apiDataList3=new List<ApiObject> ();
        //do the processing
        return apiDataList3;
    }
}

Then in the Spring boot Application class I created as

@SpringBootApplication
@EnableScheduling
@EnableCaching
@EnableAsync

public class APIApplication {

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


}

After that in the server.xml I tried to add the Nio Connector like below:

<Connector maxThreads="1000" port="8080" protocol="org.apache.coyote.http11.Http11Nioprotocol"
               connectionTimeout="20000"
               redirectPort="8443" />

But the Application starts but the response is empty.Any help is appreciated


Solution

  • @Async should be annotated by method (not class). You have annotated it for class

    @Async
    public class ApiController {
    

    You have to specify for methods only (where the caller of the method will not wait)

    Example:

    @Async
    public void asyncMethodWithVoidReturnType(){
        System.out.println("Execute method asynchronously. "
          + Thread.currentThread().getName());
    }
    

    Note for Executor In spring boot it is preferable to use a bean and specify the Executor to in @Async annotation

    Executor Bean

    @Configuration
    @EnableAsync
    public class SpringAsyncConfig {
        @Bean(name = "threadPoolTaskExecutor")
        public Executor threadPoolTaskExecutor() {
            return new ThreadPoolTaskExecutor();
        }
    }
    

    Use of Executor Bean

    @Async("threadPoolTaskExecutor")
    public void asyncMethodWithConfiguredExecutor() {
        System.out.println("Execute method with configured executor - "
          + Thread.currentThread().getName());
    }
    

    Or if you have to use xml

    <task:executor id="threadPoolTaskExecutor" pool-size="5"  />
    <task:annotation-driven executor="threadPoolTaskExecutor"/>
    

    For detail document you can see here