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.
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
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.
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
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.
Using JSR-303/JSR-349 Bean Validation API
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
@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.
Using spring’s validator interface
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.
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.