Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Spring RESTful Web Services Validation: A Complete Blueprint

DZone's Guide to

Spring RESTful Web Services Validation: A Complete Blueprint

In this post, let's discuss how to develop a REST API and validate request data.

· Integration Zone ·
Free Resource

SnapLogic is the leading self-service enterprise-grade integration platform. Download the 2018 GartnerMagic Quadrant for Enterprise iPaaS or play around on the platform, risk free, for 30 days.

In a previous post, we discussed how to handle exceptions in a Spring Boot Web MVC application. Building upon that, in this series of posts, let's discuss how to validate request data.

When developing a REST API, it's important to validate request data, and in case of invalid data, return a 4xx response with a precise body containing field-wise error details.

Let’s take an example. Say we have a signup form, as below:

public class SignupForm {

    public String email;
    public String name;
    public String password;

// getters and setters
}

And we receive the input in a controller method, as shown below:

@RestController("/users")
public class UserController {

    @Autowired
    UserService userService;

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public UserResource signup(@RequestBody SignupForm user) {
        return userService.signup(user);
    }
}

The service method that’s being called above could look like below:

@Service
public class UserService {

    public UserResource signup(SignupForm user) {
        // save the user
        // return userResource;
    }
}

So, if a field is blank, how to send an error response?

Using Bean Validation

A good way to validate input data, like the signup form above, is to use bean validation. Spring framework has good support for it. In fact, its Hibernate implementation is auto-configured by Spring Boot.

So, to validate our signup form using bean validation, first annotate its fields with constraint annotations like  @NotBlank@Email and  @Size:

public class SignupForm {

    @NotBlank
    @Email
    @Size(min=4, max=200)
    public String email;

    @NotBlank
    @Size(min=1, max=100)
    public String name;

    @NotBlank
    @Size(min=6, max=30)
    public String password;

    // getters and setters    
}

Then, annotate the SignupForm parameter in the handler with @Valid, as shown below:

@RestController("/users")
public class UserController {

    @Autowired
    UserService userService;

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public UserResource signup(@RequestBody @Valid SignupForm user) {
        return userService.signup(user);
    }
}

Now, in case of any errors, Spring would throw an exception instead of executing the controller code. The exception can then be handled in a cross-functional way (as we have discussed in a previous post), and in the next post we'll look at how exactly to do it.

But before that, one thing is worth discussing — some people prefer to do the validation in the service layer. Validation is business logic, after all, and so service layer seems ideal for it. Doing it in the service layer also allows us to do some pre-processing in the controller — see this for example.

So, how to do that? Let's resume in the next post to discuss that and many more real-world stuff, like

  • Why and how to use validation groups

  • How to display custom i18n error messages

  • How to code custom annotations — for primitive fields as well as entire forms

  • Custom validation best practices

So, see you in the next post!

With SnapLogic’s integration platform you can save millions of dollars, increase integrator productivity by 5X, and reduce integration time to value by 90%. Sign up for our risk-free 30-day trial!

Topics:
spring ,rest api ,spring boot ,bean validation ,rest web services ,java ,integration ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}