0

I do have a class CustomResponseEntityExceptionHandler class extending ResponseEntityExceptionHandler with 2 methods one for handling wrong formats and the other one when a resource (url) is requested but does not exist. I would like to give the user a custom message instead of the default White Label Error page of Spring. I'm trying to understand why my handleResourceNotFoundException method from CustomResponseEntityExceptionHandler is not called when a non existing URI is requested but instead I keep having the White Label Error page. Thanks for your help!

curl localhost:8080/doesnotexist

This is my CustomResponseEntityExceptionHandler

@ExceptionHandler(Exception.class)
public final ResponseEntity<ErrorDetails> handleAllWrongFormatExceptions(WrongFormatException ex,
        WebRequest request) {
    ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(true));
    return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
}

@ExceptionHandler(ResourceNotFoundException.class)
public final ResponseEntity<ErrorDetails> handleResourceNotFoundException(ResourceNotFoundException ex,
        WebRequest request) {
    ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
    return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}

Simple class for holding custom error details

public class ErrorDetails {

private Date timestamp;
private String message;
private String details;

public ErrorDetails(Date timestamp, String message, String details) {

    this.timestamp = timestamp;
    this.message = message;
    this.details = details;
}

public Date getTimestamp() {
    return timestamp;
}

public String getMessage() {
    return message;
}

public String getDetails() {
    return details;
} }

And here is my controller

@Controller
public class StringManipController {

@Autowired
private StringProcessingService stringProcessingService;

@GetMapping("/")
@ExceptionHandler(ResourceNotFoundException.class)
@ResponseBody
public String home(@RequestParam(name = "value", required = false, defaultValue = "") String value) {

    return "Welcome to the String Processing Application";
}

@GetMapping("/stringDedup")
@ResponseBody
public ProcessedString doManip(@RequestParam(name = "value", required = false, defaultValue = "") String value) {

    String result = stringProcessingService.getStringManipulation(value);

    return new ProcessedString(result);

}

@GetMapping("/writeNumber")
@ResponseBody
public ProcessedString getWriteNumber(
        @RequestParam(name = "value", required = false, defaultValue = "") String value) {

    String number = stringProcessingService.getNumberToWords(value);

    return new ProcessedString(number);

} }

And here the ResourceNotFoundException class

    @ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {


    private static final long serialVersionUID = 266853955330077478L;

    public ResourceNotFoundException(String exception) {
        super(exception);
    } }
algorithmic
  • 137
  • 1
  • 4
  • 15
  • See https://stackoverflow.com/questions/23574869/404-error-redirect-in-spring-with-java-config/31436535#31436535 –  Oct 31 '18 at 13:34

1 Answers1

4

If you used Spring Boot:

@ControllerAdvice
public class CustomResponseEntityExceptionHandler {

    @ExceptionHandler(value = { NoHandlerFoundException.class })
    public ResponseEntity<Object> noHandlerFoundException(Exception ex) {

        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("test");
    }
}

or

@ControllerAdvice
public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleNoHandlerFoundException(
            NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

        return handleExceptionInternal(ex, "Test", headers, status, request);
    }
}

In the org.springframework.web.servlet.DispatcherServlet class there is a variable called throwExceptionIfNoHandlerFound. If this is set to true a method called noHandlerFound will throw a NoHandlerFoundException. Your exception handler will now catch it.

Add this property to your application.properties file: spring.mvc.throw-exception-if-no-handler-found=true

Green
  • 2,405
  • 3
  • 22
  • 46
David Araujo
  • 243
  • 1
  • 2
  • 10
  • 1
    I use spring boot 2. In my case, this is not a solution. `ResourceHttpRequestHandler` runs earlier and it does the next if (resource == null) { logger.debug("Resource not found"); response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } Any workaround in mind? – Tioma Oct 31 '19 at 11:05
  • The ResponseEntityExceptionHandler has many methods that you may provide an implementation, one of them is NoHandlerFoundException, the full list: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.html. Try also set spring.resources.add-mappings=false – David Araujo Nov 04 '19 at 13:04