Skip to main content
spring-boot logo

Spring Boot REST web service – Part 3 – Exception Handling and Validation using @ControllerAdvice, @Valid and Custom Annotations

spring-boot logo

This is the 4th tutorial in the Spring Boot REST web service tutorial series.

Building a simple REST Service with Spring Boot

Part 1 – Spring Data and MySQL

Part 2 – CRUD, Service Layers, Assemblers and Utility classes

1)  Overview

In this tutorial, we will discuss how to handle exceptions. For an example, we want to add a new user through REST service but the user already exists. After that, we will discuss how to validate inputs like how to send a proper and readable message when missing user first name.

2) Exception Handling using @ControllerAdvice

Get the full source code from GitHub that related to Part 2. I think you remember, we get specific user details sending user ID through the Postman. What happens when we send the user ID that doesn’t exist in the database.



This error message is not meaningful.

2.1) @ControllerAdvice

Actually, there are a couple of ways to handle exceptions in the Spring. In this tutorial, we are going to use @ControllerAdvice.

The @ControllerAdivce annotation is a component annotation allowing implementation classes to be auto-detected through classpath scanning.

The @ControllerAdvice listens across the whole application for exceptions. When throws an exception, it will catch and convert it to the meaningful message.

2.2) ResourceNotFoundException

Now we are going to define a custom exception. Let say, we need to throw an exception when the application could not find the user for specific user ID. The custom exception class we can call it UserNotFoundException or ResourceNotFoundException. The UserNotFoundException specifically defines for throwing when user not found in the database. But the ResourceNotFoundException can be used for commonly for any resources. Totally, it depends on the application complexity. You can decide use common exception or define exceptions for each resource. In this tutorial, we selected the ResourceNotFoundException.

Create a package com.mydevgeek.exception and create a new class


2.3) Implement ControllerAdvice

Firstly, we need a POJO class to pass a response. Create a class that name is in the com.mydevgeek.exception.

Now, create an class in the same package.

Then, we have to change If it could not find a user for given id then it will be thrown the ResourceNotFoundException.

Then build and run the application. And send GET request via Postman.



{"errorCode":"Not Found","errorMessage":"user not found"}

It throws the 404 not-found error. Using the ControllerAdvice you can add any no of exceptions.

Frequently used HTTP status codes

  • 200 OK – the request has succeeded.
  • 201 Created – the request has succeeded and a request was created a new resource ( ex:- create a new user).
  • 204 Not Content – the request has succeeded and no need to return any content ( ex:- such as update operation)
  • 400 Bad Request – the request could not be understood.
  • 401 Unauthorized – the request require user authorization.
  • 403 Forbidden – the server refusing to fulfill the request.
  • 404 Not found – the server can not find anything that related to the request ( ex:- try to get user by id that not in the server).
  • 409 Conflict – the request can not be completed due to a resource conflict. ( ex:- user id already exist).

You can find more HTTP status code here.


3) Validation

In Part – 2, We were able to create and update a user by sending a request to the application. How do you handle the end user send request missing or null property?

We sent a request for creating a user without the first name.

Create a User via POSTMAN


{"userId":12,"fullName":"null Smith","username":"jhonx"}

It creates a user with null value. Let say, we need to validated it.

3.1) Validate using @Valid and @NotNull

@Valid is an annotation that use for Bean validation.

Add @Valid annotation into the as mentioned below.


After that, we are going to add the @NotNull annotation to the class.

Now run the application and try to send a null value for the first name.


Now we got an exception message but it’s not a meaningful for the end user. If you look at the error message you can see it threw MethodArgumentNotValidException.

What we are going to do is, add a new ExceptionHandler to the ControllerAdvice and exception converts to the meaningful error message. Add following method into the

try to send null first name and get an error message.


The message still not readable and understandable. What happens if we send first and last names as null values? We will get 2 error messages like above mentioned. So that we define the List to keep error messages in

Then modify the to take all error messages that define in the

Send the same request with null first and last name.


Now it looks pretty good. Apart from @NotNull there are many annotations to validate such as @NotBlank, @Digits, @Email, @Max, @Min etc.

3.2) Custom annotation for validating

We can implement custom annotation for validating. Once we implemented, we can use across the whole application. We will implement simple validator. Our requirement is, the username can not be “mydevgeek” it must be other value.

Add new package com.mydevgeek.util.validators. Add new annotation interface that name is

Then add a new class that name is and implement ConstraintValidator<A,T>.

Finally, add @Username annotation into the

Send a request that username is “mydevgeek”.


{"errorCode":"Validation Error","errorMessage":"Invalid inputs.","errors":["Invalid username."]}

Project Code :- GitHub

Next tutorials will be focused on Unit testing, CORS, Health Check, Logback integration.

Related Post

21868total visits,16visits today

Follow by Email