Spring from the Trenches: Adding Validation to a REST API

I am a bit ashamed to admit this but until yesterday, I had no idea that I can add validation to a REST API by using the @Valid and the @RequestBody annotations. This was not working in Spring MVC 3.0 and for some reason I had not noticed that the support for this was added in Spring MVC 3.1. I never liked the old approach because I had to

Inject the Validator and MessageSource beans to my controller so that I can validate the request and fetch the localized error messages if the validation fails.

Call the validation method in every controller method which input must be validated.

Move the validation logic into a common base class which is extended by the controller classes.

When I noticed that I don’t have to do these things anymore, I decided to write this blog post and share my findings with all of you.

Note: If we want to use the JSR-303 backed validation with Spring Framework, we have to add a JSR-303 provider to our classpath. The example applications of this blog post use Hibernate Validator 4.2.0 which is the reference implementation of the Bean Validation API (JSR-303).

Let’s start by taking a look at the DTO class used in this blog post. The source code of the CommentDTO class looks as follows:

We have now added a new method to our controller and added validation to it. When the validation fails, a MethodArgumentNotValidException is thrown. Let’s find out how we can return a meaningful response to the user of our API when the validation fails.

Handling Validation Errors

We can implement the logic which handles the validation errors by following these steps:

Implement the data transfer objects which contains the information returned to the user of our REST API.

Implement the exception handler method.

These steps are described with more details in the following.

Creating the Data Transfer Objects

First, we have to create the data transfer objects which contains the information returned to the user of our REST API. We can do this by following these steps:

Create a DTO which contains the information of a single validation error.

The implementation of the second DTO is rather simple. It contains a list of FieldErrorDTO objects and a method which is used to add new field errors to the list. The source code of the ValidationErrorDTO looks as follows:

We Are Almost There

We have now added validation to our REST API with Spring MVC 3.1. This implementation has one major benefit over the old approach:

We can trigger the validation process by using the @Valid annotation.

However, the methods annotated with the @ExceptionHandler annotation will be triggered only when the configured exception is thrown from the controller class which contains the exception handler method. This means that if our application has more than one controller, we have to create a common base class for our controllers and move the logic which handles the validation errors to that class. This might not sound like a big deal but we should prefer composition over inheritance.

Spring MVC 3.2 provides the tools which we can use to remove the need of inheritance from our controllers. Let’s move on and find out how this is done.

We Are Finally There

Thanks to Spring MVC 3.2, we have now implemented an elegant solution where the validation is triggered by the @Valid annotation, and the exception handling logic is moved to a separate class. I think that we can call it a day and enjoy the results of our work.

Summary

This blog post has taught us that

If we want to add validation to a REST API when we are using Spring 3.0, we have to implement the validation logic ourself.

Spring 3.1 made it possible to add validation to a REST API by using the @Valid annotation. However, we have to create a common base class which contains the exception handling logic. Each controller which requires validation must extend this base class.

When we are using Spring 3.2, we can trigger the validation process by using the @Valid annotation and extract the exception handling logic into a separate class.

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

and many more ....

7 Responses to "Spring from the Trenches: Adding Validation to a REST API"

I think you should mention that your example also requires the use of Hibernate. Otherwise, having to use JSR-303 in place of the Hibernate annotations, which seems like overkill when used in conjunction with spring libraries. I was hoping there were some Spring annots that worked like the Hibernate/JSR-303 ones. anyone know of any?

I agree that it is probably a good idea to mention to that the example uses Hibernate Validator 4.X which is the reference implementation of the JSR-303 (It does not require that you use Hibernate ORM).

What did you mean when you said that using Hibernate annotations seems like an overkill? I think that it is a great thing that Spring added support for JSR-303. After all, there is no reason to reinvent the wheel.

By the way, I also noticed that Hibernate Validator 5 has been released. I will probably check it out and update the example projects to use that if I don’t encounter any problems.

I agree that it is probably a good idea to mention to that the example uses Hibernate Validator 4.X which is the reference implementation of the JSR-303 (It does not require that you use Hibernate ORM).

What did you mean when you said that using Hibernate annotations seems like an overkill? I think that it is a great thing that Spring added support for JSR-303. After all, there is no reason to reinvent the wheel.

By the way, I also noticed that Hibernate Validator 5.x has been released. I will probably check it out and update the example projects to use that if I encounter any problems.

– after success I insert new row to table and if error occur i want to parse json with error messages and show errors on page, but i can not extract json from error resposnse (in error: function ….). Can you give me some advice about this problem?

Second: In class RestErrorHandler you are using MessageSource and LocaleContextHolder.getLocale() to localize error messages. In Logger output I see, that in my case are used only default error messages. I have configured ResourceBundleMessageSource and I have messages.properties in resources with correct “keys” (NotEmpty.book.title, …) and if I use localization in page () it works correctly.

I would really appreciate if you could give me some advice. I hope it is understandable, my english is not very good.

The answers of that question explain how you can get the response text. Use the JSON.parse() method for parsing the returned JSON document.

Second, what is the type of the validated object? The class name is used in the key of the validation message. If we assume that the type of the validated object is BookDTO, the correct key is NotEmpty.bookDTO.title. If you use “regular” forms, you can use the name of the form object instead of the class name. However, I have not found a way to do this when REST is used.

Newsletter

Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

Email address:

Join Us

With 1,043,221 monthly unique visitors and over 500 authors we are placed among the top Java related sites around. Constantly being on the lookout for partners; we encourage you to join us. So If you have a blog with unique and interesting content then you should check out our JCG partners program. You can also be a guest writer for Java Code Geeks and hone your writing skills!