How to handle exception in DeferredResult in Spring Boot?

Viewed 4041

I have a rest method:

@RequestMapping(value = "wash/washHistory", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public DeferredResult<String> getWashHistory(@RequestParam(value = "sid", required = true, defaultValue = "") String sid,
            HttpServletResponse response, HttpServletRequest request,
            @RequestParam(value = "sort", defaultValue = "") String sortType,
            @RequestParam(value = "order", defaultValue = "") String order,
            @RequestParam(value = "limit", defaultValue = "") String limit,
            @RequestParam(value = "offset", defaultValue = "") String offset) {

        System.out.println("Thread: "+Thread.currentThread());
        final Integer managerId = checkSession(sid);      
        DeferredResult<String> defResult = new DeferredResult<>();
        new Thread(() -> {
                final String result = washController.getWashHistory( managerId, order, sortType, limit, offset);
                defResult.setResult(result);            
        }).start();
    return defResult;
    }

Inside "getWashHistory" I throw the following custom exception:

throw new InvalidUserInputException("Wrong offset", this.getClass().getSimpleName(), "getWashHist", params);

And to handle this exception I'm using the following class:

@ControllerAdvice
@EnableWebMvc
public class GlobalExceptionHandler {
 @ExceptionHandler(value = InvalidUserInputException.class)
    public ResponseEntity<String> invalidUserInputExc(InvalidUserInputException e) {
          logger.log("GMoika", e.error().getClassName(), e.error().getMethodName(), e.error().getParams(), e.error().getCause());
        return ResponseEntity.
                status(HttpStatus.BAD_REQUEST).
                body(e.error().getErrorCode());  
    }
}

It works fine as long as I am not using DeferredResult, but when I want to use non-blocking way ,time out exception occurs. I found one way to fix it:

defResult.onTimeout(new Runnable() {
        @Override
        public void run() {
            defResult.setErrorResult("Explanation goes here.");
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); //or SC_NO_CONTENT
        }
    });

But it's not what I'm looking for because I throw my own exception with specific constructor to write cause inside class where this exception is thrown. Is there any other possible ways to handle exceptions in DeferredResult in my GlobalExceptionHandler class?

3 Answers

Is there any other possible ways to handle exceptions in DeferredResult in my GlobalExceptionHandler class

I used setErrorResult method as pointed out by @jny

Here is the body of my controller's method:

DeferredResult<Wrapper<Object>> deferredResult = new DeferredResult<>();

ForkJoinPool.commonPool().submit(() -> {
    try {
        Wrapper<Object> response = ...
        deferredResult.setResult(response);
    } catch (Exception e) {
        deferredResult.setErrorResult(e);
    }
});

return deferredResult;

In this case, the exceptions thrown inside new thread, were passed to global @ExceptionHandler

Related