Reputation: 5963
I am building a Spring 4 MVC app. And it is completely configured using Java Annotations. There is no web.xml
. The app is configured by using instance of AbstractAnnotationConfigDispatcherServletInitializer
and WebMvcConfigurerAdapter
like so,
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.example.*"})
@EnableTransactionManagement
@PropertySource("/WEB-INF/properties/application.properties")
public class WebAppConfig extends WebMvcConfigurerAdapter {
...
}
and
public class WebAppInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
...
}
I am now trying to add a global/catch-all exception handler for 404 pages i.e. HttpStatus.NOT_FOUND
but no success. Below are some of the ways I tried.
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
@ControllerAdvice
public class GlobalExceptionHandlerController {
@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND)
public ModelAndView handleException (NoSuchRequestHandlingMethodException ex) {
ModelAndView mav = new ModelAndView();
return mav;
}
@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND)
public ModelAndView handleExceptiond (NoHandlerFoundException ex) {
ModelAndView mav = new ModelAndView();
return mav;
}
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(NoHandlerFoundException.class)
public void handleConflict() {
}
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(NoSuchRequestHandlingMethodException.class)
public void handlesdConflict() {
}
}
None of these methods get executed. I am at a loss as to how to handle this. I do not want to use web.xml
becasue then I would have to create one just for this.
Upvotes: 11
Views: 19255
Reputation: 1804
I resolved the problem with the following entry in my application.yml
server.error.whitelabel.enabled: false
spring.mvc.throw-exception-if-no-handler-found: true
and the following ControllerExceptionHandler:
@ControllerAdvice
public class ControllerExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String processMethodNotSupportedException(Exception exception) {
exception.printStackTrace();
return "error";
}
}
and last but not least i added a template "/html/error.html"
Upvotes: 3
Reputation: 420
I can't comment on the above post by @Ysak (reputation<50), however I can confirm that this method does work with the setup described by the OP.
I will add that from another guide I also had the DefaultServletHandling configured in my WebConfig to fix a separate issue, as below:
@Configuration
@EnableWebMvc
@ComponentScan("com.acme.tat.controllers")
public class WebConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {
...
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
With this set to enable, there is no Exception thrown. Once I removed this line and set up manual resourceHandlers everything worked as expected.
It took me around 2.5 hours to set up 404 redirecting because of this simple one line method.
Upvotes: 0
Reputation: 2755
Instead overriding registerDispatcherServlet
one can override the createDispatcherServlet
method as follows.
@Override
protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
DispatcherServlet ds = new DispatcherServlet(servletAppContext);
ds.setThrowExceptionIfNoHandlerFound(true);
return ds;
}
Upvotes: 3
Reputation: 1059
Enable DispatcherServlet throw a NoHandlerFoundException through web.xml configuartion.
<init-param>
<param-name>throwExceptionIfNoHandlerFound</param-name>
<param-value>true</param-value>
</init-param>
Upvotes: 7
Reputation: 280000
By default, the DispatcherServlet
does not throw a NoHandlerFoundException
. You need to enable that.
The AbstractAnnotationConfigDispatcherServletInitializer
should let you override how the DispatcherServlet
is created. Do that and call
DispatcherServlet dispatcherServlet = ...; // might get it from super implementation
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
Upvotes: 15