Spring MVC Exception Handling

We can handle exception in Spring MVC in the following ways.

  1. Controller Based: -We can define exception handler methods in our controller classes. All we need is to annotate these methods with @ExceptionHandler annotation. This annotation takes Exception class as argument.
  2. Global Exception Handler:- Spring provides @ControllerAdvice annotation that we can use with any class to define our global exception handler.
  3. HandlerExceptionResolver:-Spring Framework provides HandlerExceptionResolver interface that we can implement to create global exception handler.
    SimpleMappingExceptionResolver is the default implementation class, it allows us to configure exceptionMappings where we can specify which resource to use for a particular exception.

Let us implement the above defined ways.

Controller Based Exception Handling

We will create a very Simple Spring MVC application, wherein user has to enter few details like Age and Name. The application will throw exception for the below conditions:

  • Age < 10
  • Length of Name < 5

Project Structure:

project-structure

Dependencies:

dependencies

Let us look into AppInitializer and AppConfig classes

AppInitializer.java- We define the Servlet Mapping here
package com.spring.mvc;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class AppInitializer implements WebApplicationInitializer{
public void onStartup(ServletContext container) throws ServletException{
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
        ctx.setServletContext(container);
        ServletRegistration.Dynamic servlet = container.addServlet(“dispatcher”, new DispatcherServlet(ctx));
        servlet.setLoadOnStartup(1);
        servlet.addMapping(“/”);
}
}
AppConfig.java – We define the ViewResolver here
package com.spring.mvc;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = “com.spring.mvc.controller”)
public class AppConfig extends WebMvcConfigurerAdapter{
@Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix(“/WEB-INF/view/”);
        viewResolver.setSuffix(“.jsp”);
        return viewResolver;
}
}
Let us define the custom Exception:
CustomException.java

package com.spring.mvc.controller;

public class CustomException extends RuntimeException{

private String exceptionMsg;

public CustomException(String exceptionMsg) {

this.exceptionMsg = exceptionMsg;

}

public String getExceptionMsg(){

return this.exceptionMsg;

}

public void setExceptionMsg(String exceptionMsg) {

this.exceptionMsg = exceptionMsg;

}

}

Now let us define the TestController

TestController.java
package com.spring.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class TestController {
   @RequestMapping(value = “/”, method = RequestMethod.GET)
   public ModelAndView details() {
      return new ModelAndView(“details”);
   }
   @RequestMapping(value = “/validateDetails”, method = RequestMethod.POST)
   public String validateDetails(@RequestParam(value=”name”) String name,@RequestParam(value=”age”) int age,ModelMap model) {
      if(name.length() < 5 ){
         throw new CustomException(“Entered name is too short”);
      } else {
         model.addAttribute(“name”, name);
      }
      if( age < 10 ){
         throw new CustomException(“Entered age is too low”);
      } else {
         model.addAttribute(“age”, age);
      }
      return “result”;
   }
@ExceptionHandler(CustomException.class)
public ModelAndView handleCustomException(CustomException ex) {
ModelAndView model = new ModelAndView(“exception”);
model.addObject(“exception”, ex);
return model;
}
}
In the above class, we have defined the method handleCustomException with @ExceptionHandler(CustomException.class) to handle CustomException and it redirects to exception.jsp
Screen Shot 2018-12-27 at 12.26.37 PM
Screen Shot 2018-12-27 at 12.26.48 PM

Global Exception Handler

In this case, we define a Global Exception Handler wherein we can define methods to handle different exceptions across all the Controllers.
For this case, we will move handleCustomException method from TestController to GlobalExceptionHandler.
TestController.java

package com.spring.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class TestController {
@RequestMapping(value = “/”, method = RequestMethod.GET)
public ModelAndView details() {
return new ModelAndView(“details”);
}
@RequestMapping(value = “/validateDetails”, method = RequestMethod.POST)
public String validateDetails(@RequestParam(value=”name”) String name,@RequestParam(value=”age”) int age,ModelMap model) {

if(name.length() < 5 ){
throw new CustomException(“Entered name is too short”);
} else {
model.addAttribute(“name”, name);
}

if( age < 10 ){
throw new CustomException(“Entered age is too low”);
} else {
model.addAttribute(“age”, age);
}
return “result”;
}

}

 

GlobalExceptionHandler.java

package com.spring.mvc.controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(CustomException.class)
public ModelAndView handleCustomException(CustomException ex) {
ModelAndView model = new ModelAndView(“exception”);
model.addObject(“exception”, ex);
return model;
}
}

Using Handler Exception Resolver

In this case, we will not use the GlobalExceptionHandler, but rather define the HandlerExceptionResolver in our AppConfig and therein map the CustomException to exception page.

package com.spring.mvc;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import com.spring.mvc.controller.CustomException;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = “com.spring.mvc.controller”)
public class AppConfig extends WebMvcConfigurerAdapter{
@Bean
    HandlerExceptionResolver errorHandler () {
        SimpleMappingExceptionResolver s = new SimpleMappingExceptionResolver();
        Properties p = new Properties();
        p.setProperty(CustomException.class.getName(),”exception”);
        s.setExceptionMappings(p);
        return s;
    }
@Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix(“/WEB-INF/view/”);
        viewResolver.setSuffix(“.jsp”);
        return viewResolver;
}
}

Leave a Reply

Your email address will not be published. Required fields are marked *