Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle 404 page not found exception in Spring MVC with java configuration and no Web.xml

I want to handle 404 page not found exception in my Spring MVC web app, I'm using SPRING 4.2.5.RELEASE, I had read several question regarding this topic but the similar questions are using a different spring java configuration.

I have a Global Exception Handler Controller class that have all my Exceptions, this class works fine but I can't handle a 404 page not found exception.

This is the approach that I take following a tutorial

1) I created a class named ResourceNotFoundException that extends from RuntimeException and I putted this annotation over the class definition @ResponseStatus(HttpStatus.NOT_FOUND)

like this:

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

}

2) I created this method in my exception's controller class

@ExceptionHandler(ResourceNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handleResourceNotFoundException() {

    return "notFoundJSPPage";
}

But still when I put a URL that doesn't exist I get this error "No mapping found for HTTP request with URI"

The questions that I had read said that I need to enable to true an option for the Dispatcher but since my configuration it's different from the other questions and I don't have a Web.xml I couldn't apply that.

Here it's my Config.java

@EnableWebMvc
@Configuration
@ComponentScan({"config", "controllers"})
public class ConfigMVC extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");
    }

    @Bean
    public UrlBasedViewResolver setupViewResolver() {
        UrlBasedViewResolver resolver = new UrlBasedViewResolver();
        resolver.setPrefix("/WEB-INF/jsp/");
        resolver.setSuffix(".jsp");
        resolver.setViewClass(JstlView.class);
        return resolver;
    }

}

Here is my WebInitializer

public class WebInicializar implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(ConfigMVC.class);
        ctx.setServletContext(servletContext);
        Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);


    }
}

Here is my Global Exception Handler Controller

@ControllerAdvice
public class GlobalExceptionHandlerController {


    @ExceptionHandler(value = NullPointerException.class)
    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)
    public String handleAllException(Exception e) {

        System.out.println("A unknow Exception Ocurred: " + e);

        return "unknowExceptionPage";
    }


    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String handleResourceNotFoundException() {

        return "notFoundJSPPage";
    }

}

And the class I created that extends Runtime Exception

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

}
like image 999
StackQuestion Avatar asked Mar 14 '16 23:03

StackQuestion


People also ask

How does Spring MVC handle 404 error?

The 404 error code is configured properly, but it will caused the “. htm” extension handling conflict between the “servlet container” and Spring's “DispatcherServlet“. To solve it, try change the 404. htm to other file extension, for example 404.

How can an HTTP 404 status code be returned from a Spring MVC controller?

Spring MVC is a traditional application built using the Front Controller Pattern. DispatcherServlet, which acts as the front controller, is responsible for routing and request processing. As with any web application or website, Spring MVC returns the HTTP 404 response code when the requested resource can't be found.

How do you handle exceptions in Spring MVC?

Spring MVC provides exception handling for your web application to make sure you are sending your own exception page instead of the server-generated exception to the user. The @ExceptionHandler annotation is used to detect certain runtime exceptions and send responses according to the exception.

Which annotations is used for global level exception handling in a Spring MVC web application?

1. Spring @ExceptionHandler annotation. To handle exceptions in String MVC, we can define a method in controller class and use the annotation @ExceptionHandler on it. Spring configuration will detect this annotation and register the method as exception handler for argument exception class and its subclasses.


2 Answers

I solved the problem by putting this line in my onStartup method in the WebApplicationInitializer.class

this it's the line I add servlet.setInitParameter("throwExceptionIfNoHandlerFound", "true");

this is how it looks the complete method with the new line I added

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
    ctx.register(ConfigMVC.class);
    ctx.setServletContext(servletContext);
    Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
    servlet.addMapping("/");
    servlet.setLoadOnStartup(1);
    servlet.setInitParameter("throwExceptionIfNoHandlerFound", "true");
}

Then I created this controller method in my GlobalExceptionHandlerController.class

@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handle(NoHandlerFoundException ex) {

  return "my404Page";
}

and that solved my problem I deleted the handleResourceNotFoundException controller method in my GlobalExceptionHandlerController.class since it wasn't necessary and also I deleted the exception class ResourceNotFoundException.class that I created

like image 188
StackQuestion Avatar answered Sep 21 '22 14:09

StackQuestion


You can also extend AbstractAnnotationConfigDispatcherServletInitializer and override this method:

@Override
protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
    final DispatcherServlet dispatcherServlet = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
    dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
    return dispatcherServlet;
}

OR this one:

@Override
public void customizeRegistration(ServletRegistration.Dynamic registration) {
    registration.setInitParameter("throwExceptionIfNoHandlerFound", "true");
}

And finally in your ControlerAdvice use this:

@ExceptionHandler(NoHandlerFoundException.class)
public String error404(Exception ex) {

    return new ModelAndView("404");
}
like image 26
zygimantus Avatar answered Sep 18 '22 14:09

zygimantus