Spring Boot ControllerAdvice TimeoutException Not Caught - spring

I have multiple ExceptionHandler in controllerAdvice. one for TimeoutException and other for Exception classes.
When i throw new TimeoutException, it gets caught in Exception Handler not in TimeoutException Handler
below is the code:
#ControllerAdvice
public class CoreControllerAdvice {
#ExceptionHandler(value = { Exception.class })
#ResponseBody
public ResponseEntity<ErrorResponse> handleException(Exception ex) {
log.info("handleException", ex);
}
#ExceptionHandler(value = { TimeoutException.class })
#ResponseBody
public ResponseEntity<ErrorResponse> handleTimeoutException(Exception ex) {
log.info("handleTimeoutException", ex);
}
}
I throw Exception as
throw new TimeoutException("test");
Can some one help, why it is not caught by TimeoutException Handler
Thanks,

The parameter in the method handleTimeoutException seems incorrect to me, instead of Exception it should be TimeoutException.
#ExceptionHandler(value = { TimeoutException.class })
#ResponseBody
public ResponseEntity<ErrorResponse> handleTimeoutException(TimeoutException ex) {
log.info("handleTimeoutException", ex);
}

Related

Problem throwing exceptions inside CompletableFuture run async

I'm working on a microservice app, in service layout I want to invoke with CompletableFuture.runAsync(). The problem is when I want to throw exception, I have my own Handler Exception, but I can't capture error when it is produced in my catch block inside CompletedFuture shown below:
Controller:
#PostMapping(path="/offers/offer")
public CompletableFuture<Oferta> infoPropiedad(#Valid #RequestBody OfertaRequest inDTO) throws
WebServiceBadResponseException, SOAPException, IOException, InterruptedException, ExecutionException {
System.out.println("THREAD: "+Thread.currentThread().getName());
CompletableFuture<Oferta> outTO = new CompletableFuture<Oferta>();
return CompletableFuture.supplyAsync(()->{
try {
return ofertasService.ofertasService(inDTO);
} catch (Exception e) {
System.out.println("Error inesperado en la capa del controlador");
}
return null;
});
}
Service:
CompletableFuture<OfertaCrm> completableFutureCRM =
CompletableFuture.supplyAsync(()-> {
try {
return clientOferta.llamadaWebServiceOfertas(inDTOCrm);
} catch (Exception e1) {
//throw Exception and capture it with my handler class
}
});
ClientWs:
public OfertaCrm llamadaWebServiceOfertas(OfertaRequestCRM inDtoCrm)
throws SOAPException, IOException {
CompletableFuture<OfertaCrm> completableFuture = new CompletableFuture<OfertaCrm>();
logger.info("Iniciamos la llamada al WS");
//Error produces here and I want to controle it and capture with my handler class
Error handler:
#ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
#ExceptionHandler({
WebServiceBadResponseException.class,
SOAPException.class,
IOException.class
})
#ResponseBody
public ErrorMessage internalError(Exception exception) {
return new ErrorMessage(exception,exception.getMessage());
}
I could not be applying the correct form. Any idea how to throw the exception inside the supplyAsync block?
CompletableFuture will wrap the exception thrown within the execution inside a CompletionException. You can handle it by intercepting the root cause exception directly. Below is a simplified example.
Controller:
#RestController
public class SimpleController {
#Autowired
SimpleService simpleService;
#GetMapping("/testing")
public CompletableFuture<Integer> testing(){
return simpleService.doStuff();
}
}
Service:
#Service
public class SimpleService {
public CompletableFuture<Integer> doStuff(){
// 1 / 0 will throw ArithmeticException
return CompletableFuture.supplyAsync(() -> 1 / 0);
}
}
Controller Advice:
#RestControllerAdvice
public class SimpleControllerAdvice {
#ExceptionHandler(ArithmeticException.class)
public String handleCompletionException(ArithmeticException ex){
return "hello world";
}
}
GET /testing
hello world

ControllerAdvice is not triggered in my springboot application?

Actually I am working in a Kafka streams application using Spring Boot.
So here I am trying to handle exceptions globally using #ControllerAdvice but it is not working for me.
Is it possible to use #ControllerAdvice in my application.
Is this controller advice is only works when the error is coming from controller.
Note: I am not having any controller / rest controller endpoints in my application.
Can we achieve the same in some other ways?
Please share your valuable thoughts!
Main Stream:
#Autowired
private XyzTransformer xyztransformer;
#Bean
public KStream<String, ABC> processMember(#Qualifier("defaultKafkaStreamsBuilder") StreamsBuilder streamsBuilder) {
try {
LOGGER.info("streaming started...");
KStream<String, Xyz> xyStream = streamsBuilder.stream(appProperty.kafkaStreamsTopicInput)
.transformValues(() -> xyztransformer)
xyStream.to(appProperty.kafkaStreamsTopicOutput);
return memberStream;
} catch (Exception ex) {
LOGGER.error("Exception occurred in Streams " + Arrays.toString(ex.getStackTrace()));
throw ex;
}
}
TransformerClass:
#Component
public class XyzTransformer implements ValueTransformer<Xyz, Abc> {
#Override
public void close() {
}
#Override
public void init(ProcessorContext processorContext) {
}
#SneakyThrows
#Override
public Abc transform(Xyz data) {
String[] dataSourceTables = new String[]{"abc"};
try {
return Abc.builder()
.name(data.getName())
.build();
} catch (Exception ex) {
System.out.println("catched and throwing");
throw new CustomTesException("test 1");
}
}
}
ControllerAdvice:
#ControllerAdvice
public class Advice extends ResponseEntityExceptionHandler {
#ExceptionHandler(NullPointerException.class)
public final void handleAllExceptions(NullPointerException ex) {
System.out.println("it is in the handler");
System.out.println(ex.getMessage());
}
#ExceptionHandler(Exception.class)
public final void handleAllException(Exception ex) {
System.out.println("it is in the exception handler");
System.out.println(ex.getMessage());
}
#ExceptionHandler(CustomTesException.class)
public final void handleAllExceptio(CustomTesException ex) {
System.out.println("it is in the exception handler");
System.out.println(ex.getMessage());
}
}

Spring ConstraintViolation not caught

I'm using Spring Boot, and I have created a custom PathVariable validator, which I use as follows:
#GetMapping(value = "/test/{id}")
public ResponseEntity<Void> test(#PathVariable("id")
#Valid
#MyGUID(message = "ID_INVALID")
String id) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
The validor seems to do its job well - it passes when input is valid, and throws exception when not. The problem is, that my custom exception handler doesn't catch the ConstraintViolationException that is thrown. This is the top line of the stack trace:
javax.validation.ConstraintViolationException: ID_INVALID
Then I have my exeception handler class:
#ControllerAdvice
public class RestExceptionController extends ResponseEntityExceptionHandler {
#ExceptionHandler(value = ConstraintViolationException.class)
public ResponseEntity<ErrorResponse> handleConstraintViolationException(ConstraintViolationException ex,
HttpHeaders headers,
HttpStatus status,
WebRequest request) {
List<String> errorDetailsCodes = new ArrayList<>();
for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
errorDetailsCodes.add(violation.getMessage());
}
ErrorResponse errorResponse = new ErrorResponse(
status.name(),
status.value(),
ex.hashCode(),
errorDetailsCodes
);
logException(ex);
return new ResponseEntity<>(errorResponse, headers, status);
}
#ExceptionHandler(value = Exception.class)
public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.name(),
HttpStatus.INTERNAL_SERVER_ERROR.value(),
ex.hashCode()
);
logException(ex);
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
It is strange to me that despite the fact I have both a specific and a general exception handler, they are both skipped, and the system throws its own error:
{
"timestamp": 1568554746642,
"status": 500,
"error": "Internal Server Error",
"message": "ID_INVALID",
"path": "/api/logged-in-user/test/123"
}
How can I catch this exception and return my custom response?
Thanks.

Handle 404 exception in Spring

I'm trying to catch 404 error on my Spring boot + Hibernate Server when Im going to some page that doesn't exist (for example http://localhost:8080/tes (http://localhost:8080/test is working)). I've created #ControllerAdvice class but it can't catch 404 exception (other works just fine). What is problem?
#ControllerAdvice
public class GlobalExceptionHandlerController {
#ResponseStatus(value = HttpStatus.NOT_FOUND)
#ExceptionHandler(value = NullPointerException.class)
#ResponseBody
public String handleNullPointerException(Exception e) {
System.out.println("A null pointer exception ocurred " + e);
return "nullpointerExceptionPage";
}
#ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
#ExceptionHandler(value = Exception.class)
#ResponseBody
public String handleAllException(Exception e) {
System.out.println("A unknow Exception Ocurred: " + e);
return "unknowExceptionPage";
}
#ExceptionHandler(NoHandlerFoundException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
#ResponseBody
public String handleResourceNotFoundException() {
return "notFoundJSPPage";
}

#ExceptionHandler with VndErrors does not handle errors

The problem: in the following example the handlers (if commented out) with void return type work without problems. I get HttpStatus 422.
If I switch to use the version with VndErrors the handlers do not work anymore and I get HttpStatus 500, and I can't find the reason for this behavior.
#ControllerAdvice
#RequestMapping(produces = "application/vnd.error")
#ResponseBody
public class CurrencyCalculatorControllerAdvice {
// this works
#ExceptionHandler
#ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
private void handleCurrencyDetailsNotFoundException(CurrencyDetailsNotFoundException e) {}
#ExceptionHandler
#ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
private void handleCurrencyRateNotFoundException(CurrencyRateNotFoundException e) {}
// this does not work
#ExceptionHandler
#ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
VndErrors handleCurrencyDetailsNotFoundException(CurrencyDetailsNotFoundException e) {
return new VndErrors(e.getLogRef().assemble(), e.getMessage());
}
#ExceptionHandler
#ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
VndErrors handleCurrencyDetailsNotFoundException(CurrencyRateNotFoundException e) {
return new VndErrors(e.getLogRef().assemble(), e.getMessage());
}
}

Resources