How to use Spring Exception Handler for SpringMVC: @ExceptionHandler, @ResponseStatus, @ControllerAdvice

How to use Spring Exception Handler for SpringMVC

Spring provides a cross-cutting concern solution for handling Java Excepion. So in the tutorial, JavaSampleApproach will show you how to use Spring Exception with: @ResponseStatus, @ExceptionHandler & @ControllerAdvice.
Related Articles:
How to handle Java Exception
How to use @RestControllerAdvice – New Features of Spring Framework 4.3

I. Technologies

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.1.RELEASE
– Spring Boot: 1.5.1.RELEASE

II. Overview
1. @ResponseStatus

Normally, when backend server throws an unhandled Exception, a 500 Http response will be returned.
Spring provides a way to modify http code response by @ResponseStatus for customized Exception.
Sample:

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Not Found Exception!")
public class CustomExceptionWithHttpStatusCode extends RuntimeException{
}
2. @ExceptionHandler

We can use @ExceptionHandler with a method in any Controller to handle specific exceptions that throw from any @Requestmapping:
Sample:

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.javasampleapproach.springexceptionhandler.customexception.CustomConflictException;
import com.javasampleapproach.springexceptionhandler.customexception.CustomException;
import com.javasampleapproach.springexceptionhandler.customexception.CustomExceptionWithHttpStatusCode;
import com.javasampleapproach.springexceptionhandler.customexception.CustomGeneralException;

@Controller
public class WebController {
        // ...
	// Convert a predefined exception to an HTTP Status code
	@ResponseStatus(value = HttpStatus.CONFLICT, reason = "Having conflict")
	@ExceptionHandler(CustomConflictException.class)
	public void conflict() {
		// log something
	}

	@ExceptionHandler(CustomException.class)
	public String runtimeException() {
		return "exception";
	}
}

– We can use @ResponseStatus with @ExceptionHandler to customize http response code.
– Use @ExceptionHandler to redirect to a html view page.
– Use @ExceptionHandler to build a completed ModelAndView.

3. @ControllerAdvice

We can use @ControllerAdvice to handle exception with globle scope of application, not only in an individial controller.
Sample:

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import com.javasampleapproach.springexceptionhandler.customexception.CustomGeneralException;

@ControllerAdvice
public class GlobalExceptionHandler {
	@ExceptionHandler(CustomGeneralException.class)
	public ModelAndView handleCustomGeneralException(CustomGeneralException ex) {
		ModelAndView model = new ModelAndView();
		// add needed model attributes
		model.setViewName("generalexception");
		return model;
	}

}

Now handleCustomGeneralException method is active to handle any Exception with type CustomGeneralException.class in any Controller:

@Controller
public class WebController {

        // ...

	// Convert a predefined exception to an HTTP Status code
	@ResponseStatus(value = HttpStatus.CONFLICT, reason = "Having conflict")
	@ExceptionHandler(CustomConflictException.class)
	public void conflict() {
		// log something
	}

        // ...
}
III. Practice
1. Create Spring Boot project

Create SpringBoot project with Thymeleaf view engine, add dependencies:


	org.springframework.boot
	spring-boot-starter-thymeleaf


	org.springframework.boot
	spring-boot-starter-web

2. Create CustomExceptions

Create 4 customized Exception:
– 3 simple Customized Exception:

public class CustomException extends RuntimeException{
}

public class CustomConflictException extends RuntimeException{
}

public class CustomGeneralException extends RuntimeException{
}

– 1 customized exception with @ResponseStatus:

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Not Found Exception!")
public class CustomExceptionWithHttpStatusCode extends RuntimeException{
}
3. Create simple views

Create 2 simple html views:
exception.html



 
    

Exception Page!

generalexception.html



 
    

General Exception Page!

4. Create ControllerAdvice
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import com.javasampleapproach.springexceptionhandler.customexception.CustomGeneralException;

@ControllerAdvice
public class GlobalExceptionHandler {
	@ExceptionHandler(CustomGeneralException.class)
	public ModelAndView handleCustomGeneralException() {
		ModelAndView model = new ModelAndView();
		// add needed model attributes
		model.setViewName("generalexception");
		return model;
	}

}
5. Create Web Controller
package com.javasampleapproach.springexceptionhandler.controller;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.javasampleapproach.springexceptionhandler.customexception.CustomConflictException;
import com.javasampleapproach.springexceptionhandler.customexception.CustomException;
import com.javasampleapproach.springexceptionhandler.customexception.CustomExceptionWithHttpStatusCode;
import com.javasampleapproach.springexceptionhandler.customexception.CustomGeneralException;

@Controller
public class WebController {

	@RequestMapping(value = "/normalexception")
	public void throwException() {
		throw new RuntimeException();
	}

	@RequestMapping(value = "/customexception")
	public void throwCustomException() {
		throw new CustomException();
	}

	@RequestMapping(value = "/conflictexception")
	public void throwCustomConfictException() {
		throw new CustomConflictException();
	}

	@RequestMapping(value = "/customexceptionwithhttptatuscode")
	public void throwCustomExceptionWithHttpStatusCode() {
		throw new CustomExceptionWithHttpStatusCode();
	}

	/*
	 * Use ExceptionHadler in AdviceWebController defined
	 * with @ControllerAdvice.
	 */
	@RequestMapping(value = "/customgeneralexception")
	public void throwCustomGeneralException() {
		throw new CustomGeneralException();
	}

	// Convert a predefined exception to an HTTP Status code
	@ResponseStatus(value = HttpStatus.CONFLICT, reason = "Having conflict")
	@ExceptionHandler(CustomConflictException.class)
	public void conflict() {
		// log something
	}

	@ExceptionHandler(CustomException.class)
	public String runtimeException() {
		return "exception";
	}
}

6. Result

Run the project with Spring Boot App mode, then make requests:

http://localhost:8080/normalexception
Spring Exception - normal exception

http://localhost:8080/customexception
It will be handled by public String runtimeException() then shows exception view.
Spring Exception - customized exception

http://localhost:8080/conflictexception
It will be handle by public void conflict() method with @ResponseStatus so response status code is 409(HttpStatus.CONFLICT)
Spring Exception - conflict exception

http://localhost:8080/customexceptionwithhttptatuscode
The CustomExceptionWithHttpStatusCode modifies http code response @ResponseStatus(value=HttpStatus.NOT_FOUND, reason=”Not Found Exception!”) so result is: type=Not Found, status=404
Spring Exception - custom exception with http status code

http://localhost:8080/customgeneralexception
It will be handled by: public ModelAndView handleCustomGeneralException() method in GlobalExceptionHandler class. The result is a model with generalexception.html view.
Spring Exception - gerenal exception

IV. Sourcecode

SpringExceptionHandler

2 thoughts on “How to use Spring Exception Handler for SpringMVC: @ExceptionHandler, @ResponseStatus, @ControllerAdvice”

    1. Thank you very much!

      We are on the way to develop the site more helpful!
      You can share with your friends about our articles!

      Nice day!

Leave a Reply

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