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?
DeferredResult
has method setErrorResult
which can take Exception and according to the documentation:
The value may be an Exception or Throwable in which case it will be processed as if a handler raised the exception.