by BehindJava

How to Handle an Exception and return custom Error Message Object in Spring Boot using @ControllerAdvice annotation

Home » springboot » How to Handle an Exception and return custom Error Message Object in Spring Boot using @ControllerAdvice annotation

In this tutorial we are going to learn about handling an exception and returning a custom error Message Object using @ControllerAdvice in Spring Boot.

@ControllerAdvice: Specialization of @Component for classes that declare @ExceptionHandler, /@InitBinder, or @ModelAttribute methods to be shared across multiple @Controller classes.

Classes annotated with @ControllerAdvice can be declared explicitly as Spring beans or auto-detected via classpath scanning. All such beans are sorted based on Ordered semantics or @Order / @Priority declarations, with Ordered semantics taking precedence over @Order / @Priority declarations.

@ControllerAdvice beans are then applied in that order at runtime. Note, however, that @ControllerAdvice beans that implement PriorityOrdered are not given priority over @ControllerAdvice beans that implement Ordered. In addition, Ordered is not honored for scoped @ControllerAdvice beans — for example if such a bean has been configured as a request-scoped or session-scoped bean.

For handling exceptions, an @ExceptionHandler will be picked on the first advice with a matching exception handler method. For model attributes and data binding initialization, @ModelAttribute and @InitBinder methods will follow @ControllerAdvice order.

Let’s have a faulty code snippet in the Rest Controller as shown in the below code snippet.

Sample Code Snippet:

@GetMapping(path = "/{userId}", produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE })
	public ResponseEntity<UserModel> getUser(@PathVariable String userId) {
		// Faulty Code
		String firtname = null;
		int len = firtname.length();

		if (user.containsKey(userId)) {
			return new ResponseEntity<UserModel>(user.get(userId), HttpStatus.CREATED);
		} else {
			return new ResponseEntity<UserModel>(HttpStatus.NO_CONTENT);
		}

	}

Now let’s create a class where we place our @ControllerAdvice annotation where you can have a centralized way to handle exceptions, binding, etc. it applies to all the defined controller.

Sample Code Snippet:

import java.util.Date;

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.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import com.behindjava.tutorial.model.CustomError;

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

	@ExceptionHandler(value = { Exception.class })
	public ResponseEntity<Object> handleAnyException(Exception ex, WebRequest req) {

		String errorMessage = ex.getLocalizedMessage();
		if (errorMessage == null)
			errorMessage = ex.toString();

		CustomError message = new CustomError(new Date(), errorMessage);

		return new ResponseEntity<Object>(message, new HttpHeaders(), HttpStatus.UNSUPPORTED_MEDIA_TYPE);

	}

}

Now we will create a controller advice that returns a custom error message for the same faulty code placed above in the GET handler mapping and to do so we will create a model class which contains time stamp and message that are passed to the object as we are returning the custom error message with timestamp and message.

Sample Code Snippet:

import java.util.Date;

public class CustomError {

	private Date timeStamp;
	private String message;

	public CustomError() {
	}

	public CustomError(Date timeStamp, String message) {
		this.timeStamp = timeStamp;
		this.message = message;
	}

	public Date getTimeStamp() {
		return timeStamp;
	}

	public void setTimeStamp(Date timeStamp) {
		this.timeStamp = timeStamp;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

}

You can test this by using post man as shown in the below image where you’ll receive the custom error message with timestamp and message.

title

Previous                                                                                                               Next