Find out how to validate a RESTFul request when posting to a spring controller using the bean validation API and spring's validator interface.
Detailed Video Notes
When making a post to a RESTFul webservice it is a good practice to trigger client side validation providing immediate feedback to users and apply secure coding practices by performing server side validation early in the request process. This tutorial will focus on how to validate your REST webservice request with the spring framework.
Getting started
Spring framework has the flexibility to be configured with both JSR-303, JSR-349 bean validation or by implementing spring Validator
interface to meet your organizations choice of validation. We will set up a spring boot project where boot does it's magic and turns on validation automatically for us. By examining actuator endpoint http://localhost:8080/beans
, OptionalValidatorFactoryBean
is declared as the mvcValidator
and uses hibernate validator implementation. If you are setting up validation outside of boot you will need to include pom entry and include mvc:annotation-driven
in your configuration file. Further configuration can be reviewed at spring's validation documentation.
Project setup
[1:3]
We will copy files from episode 10 where we showed how to get started building rest service and modify the AgencyController class by adding method = RequestMethod.GET
to the @RequestMapping
. Creating a new method saveAgency()
and applying @RequestMapping(value = "/agencies", method = RequestMethod.POST)
to handle the post request. You will notice that both saveAgency
and getAgencies
have the same URL mapping. The differentiator is the method equals in the @RequestMapping which instructs spring to map a POST request to this method. If you recall @RestController
was introduced in Spring 4 and combines the @Controller
and a @ResponseBody
eliminating the need to wrap each method.
AgencyController
AgencyResource
Using JSR-303/JSR-349 Bean Validation API
[1:40]
Adding @Valid @RequestBody to controller
JSR-303 is a standardization on java bean validation while JSR-349 improves on the initial version. The @Valid
annotation is part of java bean validation API and is not a spring-specific construct. By adding it to the input parameter within a method in @Controller
we will trigger validation. Adding the @RequestBody
will indicate the annotated method parameter should be generated from the body of the HTTP request. In other words, spring will use jackson to transform json from the body of the request to a java object. Let's modify the AgencyResouce object with some standard self explanatory javax validation constraints.
Next we will need to add the @Valid
and @RequestBody
annotation to our method parameters. By adding these two annotations we have instructed spring to bind JSON from the body of the POST to the AgencyResource and then run validation.
Triggering validation with a POST
Making a POST to http://localhost:8080/agencies
using advanced rest client with the following json will cause the a 404. The response indicates that the field "name" cannot be null and the "id" as rejected and must be greater or equal to 20.
Request JSON
Response
Using spring’s validator interface
[2:29]
To demonstrate using the spring validator interface we will add two new classes and modify the controller.
Policy support classes
First adding a class PolicyResource that represents the policy domain. Notice that there is no java validation constraints on the fields. We will create a PolicyValidator class that extends org.springframework.validation.Validator
interface. In the validate method calling ValidationUtils.rejectIfEmpty
will create an error if name is empty.
Modifying the controller
In the controller we first need to notify spring's DataBinder that we have a validator to run when binding to a request parameter. Second we will add the url mapping and method to handle the request that looks structurally similar to the JSR-303 implementation above. If this was production code we probably would of created a separate controller to handle policy requests.
Triggering validation with a request
Making a request to http://localhost:8080/policies
with the following JSON as the request body will trigger a validation error stating the name cannot be empty.
Request JSON
Response
We didn't get into specific ways to handle the exception within your spring rest application but hope that this will give a high level way to handle validation within your RESTFul controllers. Thanks for joining today's level up lunch.