Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot - Handling NoHandlerFoundException

Read the Spring Reference Guide on how to handle NoHandlerFoundException and found that Spring sets, by default, throwExceptionIfNoHandlerFound to false.

Knowing that, I thought it was a good idea to set this parameter to true.

I'm using Spring Boot.

Did so:

MyConfig.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

@SpringBootApplication
public class MyConfig {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(MyConfig.class, args);
        context.getBean(DispatcherServlet.class).setThrowExceptionIfNoHandlerFound(true);

        // ...
    }
}

Alright, now throwExceptionIfNoHandlerFound is equals true. However, that didn't worked as expected. The DispatcherServlet continued not throwing the NoHandlerFoundException. This way, I was unable to handle it.

CustomExceptionHandler.java (this didn't worked)

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity <Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // do my own handle ...

        // then, return ...
    }

}

After a bit of search, found that adding @EnableWebMvc should work. Then, I did add this annotation to my CustomExceptionHandler

CustomExceptionHandler.java (this did worked)

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@EnableWebMvc
@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity <Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // do my own handle ...

        // then, return ...
    }

}

This way, the handle works. However, I'm using Spring Boot. The Spring Boot docs suggests that if I insert @EnableWebMvc, I would lose some Spring Boot MVC Auto-configuration features, since I would take complete controll of Spring MVC. (See here).

"If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc."

Would I lose Spring MVC Auto-configuration? I mean, the @EnableWebMvc, in my case, it's not in a @Configuration class.

My question is based on the fact that I'm not sure how this code above works, and I want to know if there's another way of doing this without losing the Spring MVC Auto-configuration. Could someone explain?

like image 479
Matheus Cirillo Avatar asked Jun 26 '18 17:06

Matheus Cirillo


People also ask

What causes NoHandlerFoundException?

Class NoHandlerFoundException By default when the DispatcherServlet can't find a handler for a request it sends a 404 response. However if its property "throwExceptionIfNoHandlerFound" is set to true this exception is raised and may be handled with a configured HandlerExceptionResolver.

What is @EnableWebMvc?

The @EnableWebMvc annotation is used for enabling Spring MVC in an application and works by importing the Spring MVC Configuration from WebMvcConfigurationSupport. The XML equivalent with similar functionality is <mvc:annotation-driven/>.

What is ResponseEntityExceptionHandler spring boot?

public abstract class ResponseEntityExceptionHandler extends Object. A convenient base class for @ControllerAdvice classes that wish to provide centralized exception handling across all @RequestMapping methods through @ExceptionHandler methods.


1 Answers

Spring Boot auto-configuration will automatically add a ResourceHttpRequestHandler to deal with serving static resource. By default this handler is mapped against /** and is the last item in the handler chain.

What this means is the DispatcherServlet won't throw a NoHandlerFoundException because it found the resource handler. The resource handler processes the request and calls response.sendError(HttpServletResponse.SC_NOT_FOUND) to return a 404.

If you don't want this behavior, you can add the following to your application.properties:

spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

The will configure the dispatcher servlet to throw the exception and also tell Spring Boot not to register the resource handler.

Before you go too far down that route, you might want to look at this section of the reference docs to see if it wouldn't be better to handle those errors in a different way. It's not totally clear from your question what you're actually trying to do in your error handler, but if it's just dealing with 404s then there's probably a better way.

like image 190
Phil Webb Avatar answered Sep 18 '22 15:09

Phil Webb