-1

I am running web services using spring boot. The below snippet is from controller. I have a custom exception class(which extends RuntimeException). To handle exceptions, I have a controller advice as well.

When someMethod() throws a custom exception, I expect to get a 400 - Bad Request. But, completable future bounds the exception and I always receive 500 - Internal Server Error.

CompletableFuture.supplyAsync(() -> {
      return someMethod();
}
).whenCompleteAsync((response, throwable) -> {
  
});

ControllerAdvice

@ControllerAdvice
public class CustomExceptionHandler extends Throwable {


@Order(Ordered.HIGHEST_PRECEDENCE)
@ExceptionHandler(value = CustomException.class)
public ResponseEntity<ErrorResponse> handleCustomException(
  CustomException ex) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode("400");
errorResponse.setDescription(ex.getMessage());
return new ResponseEntity<>(errorResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST);
 }


@ExceptionHandler(value = Exception.class)
public ResponseEntity<ErrorResponse> handleGenericExceptions(Exception exception) {

ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode("500");
errorResponse.setDescription(exception.getMessage());
return new ResponseEntity<>(errorResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
  }
 }

If I throw the custom exception outside of completable future, I get the expected 400 - Bad Request. In the other hand, If I don't have a handler for global exception, I get 400 Bad Request even it is thrown inside of completable future. But, both are not acceptable. I had done this to find the root cause.

How to deal this scenario?

Prabhakaran
  • 177
  • 1
  • 1
  • 11
  • You're using async, so the exception doesn't occur in the controller thread, which means it's not caught by the advice. Not sure where the 500 comes from, you'd need to post the rest of the controller for that. – daniu Jun 19 '21 at 08:23
  • It it caught by the advice. I tried changing the description in the "handleGenericExceptions()" inside the advice. In this case, I received the updated description in the response. And I mentioned the other things that I tried. The exception is caught by the advice. That is for sure. – Prabhakaran Jun 19 '21 at 08:26
  • Can you please share more error logs or to be more clear complete stacktrace? – silentsudo Jun 19 '21 at 14:34

1 Answers1

-1

When the underlying logic is called using the completable future, irrespective of the exceptions captured, all the exceptions will be wrapped by the completable future and thrown as a CompletionException. So, we have to either handle the CompletionException and return the appropriate response from the global handler or when you call some method, catch the exception there itself, instead of re-throwing it, create the response object(with error code and description) that you want to send and return the object.

Prabhakaran
  • 177
  • 1
  • 1
  • 11