Skip to content
Advertisement

Change deferredResult HTTP status code on timeout

I am using deferredResult on Spring MVC, but using this code, the timeout still are sending back the HTTP code 503 to the client.

future.onCompletion(new Runnable() {
    @Override
    public void run() {

        if(future.isSetOrExpired()){
            response.setStatus(HttpServletResponse.SC_NO_CONTENT);
        }
    }
});

Any idea what else to try?

Advertisement

Answer

I ran into the same issue. My Spring MVC Controller method originally returned DeferredResult<Object>, but then I realised I wanted to control the HTTP status code. I found the answer here:

https://www.jayway.com/2014/09/09/asynchronous-spring-service/

@RequestMapping("/async")
DeferredResult<ResponseEntity<?>> async(@RequestParam("q") String query) {

    DeferredResult<ResponseEntity<?>> deferredResult = new DeferredResult<>();
    ListenableFuture<RepoListDto> repositoryListDto = repoListService.search(query);
    
    repositoryListDto.addCallback(
            new ListenableFutureCallback<RepoListDto>() {
                @Override
                public void onSuccess(RepoListDto result) {
                    ResponseEntity<RepoListDto> responseEntity = 
                        new ResponseEntity<>(result, HttpStatus.OK);
                    deferredResult.setResult(responseEntity);
                }

                @Override
                public void onFailure(Throwable t) {
                    log.error("Failed to fetch result from remote service", t);
                    ResponseEntity<Void> responseEntity = 
                        new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE);
                    deferredResult.setResult(responseEntity);
                }
            }
    );
    
    return deferredResult;
}

Just use DeferredResult<ResponseEntity> and you can set both the response and the Http response code in the ResponseEntity.

Advertisement