Validating REST API using Spring

In this post, we will discuss in details of Validating REST API using Spring. It is important to validate incoming data in the REST web services that can cause trouble in the business process or logic. Read our previous article, for understanding basics of building REST API using Spring.

Introduction

When building REST API, we expect RESTful service to have a certain structure or format. We expect REST API request to follow this structure and constraints. We can not assume that API request will follow structure and constraints. How to handle if REST request is not meeting constraints.

We need to think about following questions while designing our REST API.

How should I validate REST API data?

What message should I send if data validation fails?

One of the fundamental principles of RESTful services is to think about “Consumers” while designing your REST web services. We should keep in mind below design principles for validating REST API in Spring.

REST API should return a clear message indicating what was wrong int he request.

API should try to provide information on what can be done to fix the error.

Well defined response status.

Spring MVC provides a number of build in options for REST API date validation. We will cover different options in this post.It is up to your requirement to determine which approach fulfill your use case.

1. Simple Spring MVC Validation

If our REST API is using @RequestParam or @PathVaraible, Spring provides out of the box support for validating it. Here is a simple use case for validating REST data using Spring

@GetMapping("/greeting") public Greeting sayHello(@RequestParam(value = "name") String name){ return new Greeting(1, "Hello "+name); }

This is the simplest validation provided by Spring MVC. It will validate incoming request. Spring will send a detailed message back to the consumer in case we are missing required data in the REST API.

If we run our application without passing name in the request parameter, Spring will send a detailed error response back to the consumer.

{ "timestamp": 1517983914615, "status": 400, "error": "Bad Request", "exception": "org.springframework.web.bind.MissingServletRequestParameterException", "message": "Required String parameter 'name' is not present", "path": "/greeting" }

We will talk about customizing error response in our exception handling post.

2. REST Validation using Bean Validation (JSR303)

Real life REST API’s are more complex than a simple method with few parameters. Enterprise REST API involve complex domain models and also require the ability to validate REST API data.

Spring MVC provides build in support for JSR303 (Bean Validation). Bean Validation comes with an extensive list of validation available out of the box along with the ability to create custom validations.

With Spring Bean Validation support, we need to annotate out DTO with required annotations and build in validation support will ensure to validate incoming data before passing it to our business layer.

For the list of build in validation, please refer to Hibernate Validator.

Here is our sample customer DTO

public class Customer { @NotNull(message = "Please provide first Name") private String firstName; @NotNull(message = "Please provide last Name") private String lastName; @NotNull @Min(value = 18, message = "Age should be equal or more than 18") private int age; @Email(message = "Please provide valid email address") private String email; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }

before we move ahead, let’s discuss what we are trying to validate in our DTO

We will not accept null values for firstName and lastName (You can also add @notEmpty annotation from Hibernate validator)

Age should not be null and should be greater than or equal to 18.

We need a valid email address for the customer.

Bean Validation provides us a way not only to validate REST API request but also provide consumer-centric error messages.

We are using the hard-coded message in the class itself, but Spring provides the way to use a localized properties file for localized messages.

@RestController @RequestMapping("/api/rest") public class CustomerController { @PostMapping("/customer") public ResponseEntity<?> createCustomer(@Valid @RequestBody Customer customer){ HttpHeaders responseHeader = new HttpHeaders(); return new ResponseEntity<>(customer, responseHeader, HttpStatus.CREATED); } }

If we run our code, with following input

We will get following response back from our REST API.

timestamp": 1518066946111, "status": 400, "error": "Bad Request", "exception": "org.springframework.web.bind.MethodArgumentNotValidException", "errors": [], "message": "Validation failed for object='customer'. Error count: 1", "path": "/api/rest/customer"

If we will send all values in correct format and data type, REST API will send success response back to the consumer

< HTTP : 201 Created { "firstName": "Umesh", "lastName": "Awasthi", "age": 18, "email": "[email protected]" }

3. Custom Spring Validator

JSR 303 bean validation provides a number of out of the box validator. For enterprise applications, we will get into a situation where out of the box validator will not fulfill our business requirements.

Spring provides flexibility to create our own custom validator and uses these custom validations. Please read Spring MVC Custom Validator for more detail.

You can use same domain object for different endpoints. Let’s take the example of our customer.

If we are creating a new customer, we do not need customer id and it can be null.

For updating customer, we need customer id to identify customer for the update.

For such use cases, you don’t need 2 separate objects but can use Grouping constraints feature provided by JSR 303.

Summary

In this post, we discussed different options for Validating REST API using Spring. Validating data is essential for the Spring REST API. Data validation perform data sanity and provide additional security check for data insertion.

We discussed build in validation support from Spring and Spring MVC along with an option to create customer validator in Spring if out of the box validator is not sufficient for the business needs.

In our next articles on building REST API with Spring, we will discuss REST Resource Naming Best Practices.