Я использую Spring Boot 2.2.6 и реализую некоторые сервисные вызовы с помощью asyn c framework. Вызов службы выполняется правильно, но если выдается исключение времени выполнения, я получаю ExecutionException
с кодом ответа 500 вместо исключения времени выполнения (требуется 404). Я понимаю, что исключение времени выполнения заключено в ExecutionException
, но я надеялся, что смогу справиться с этим с помощью существующего пользовательского обработчика исключений, без необходимости явно пытаться / перехватывать и перебрасывать исключение в контроллерах.
Вот код:
Контроллер:
@RequestMapping(value = "/articles/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ArticleDto get(@ApiParam("Article id") @PathVariable String id) throws InterruptedException, ExecutionException {
Article article = articleService.findArticleById(id).get();
return convertToEntityDto(article);
}
Метод обслуживания:
@Async
public CompletableFuture<Article> findArticleById(String id) {
Optional<Article> article = articleMongoRepository.findById(id);
if (article.isPresent()) {
return CompletableFuture.completedFuture(article.get());
} else {
throw new ArticleNotFoundException("Article " + id + " not found");
}
}
Исключение:
public class ArticleNotFoundException extends RuntimeException {
private static final long serialVersionUID = 4409790264721509169L;
public ArticleNotFoundException(String exception) {
super(exception);
}
}
Пользовательский обработчик исключений:
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(ArticleNotFoundException.class)
public final ResponseEntity<ApiResponse> handleArticleNotFoundException(ArticleNotFoundException ex, WebRequest request) {
List<String> details = new ArrayList<>();
ApiResponse exceptionResponse = new ApiResponse(HttpStatus.NOT_FOUND.value(), "ARTICLE_NOT_FOUND", ex.getMessage(),
details);
return new ResponseEntity<>(exceptionResponse, HttpStatus.NOT_FOUND);
}
Я пытался добавить метод обработки в обработчик пользовательских исключений, чтобы перебрасывать упакованное исключение, но это не сработало.
@ExceptionHandler(ExecutionException.class)
public final ResponseEntity<ApiResponse> handleExecutionException(ExecutionException ex,
WebRequest request) throws Throwable {
throw ex.getCause();
}
Любые советы о том, как лучше всего обрабатывать исключение во время выполнения. так же, как и не асинхронные c методы, будет высоко ценится.