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?
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.
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/>.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With