JavaHow-To: Bean Validation on Spring

How-To: Bean Validation on Spring

The Bean Validation 2.0 (JSR 380)  spec is the de-facto specification every Spring developer must know to validate user input with Java beans.

One of the first steps for many new applications revolves around validating user input. In order to avoid duplicate, boilerplate code that usually tends to make your applications more complex (turning maintainability into a nightmare), the Bean Validation specification was proposed as part of the Jakarta EE/JSE project.

In this article, we’re going to dive into the universe of validations via annotations using Spring and Java. Let’s take a look at some examples.

Read: What are JavaBeans?

Setting Up a Spring Boot Project

For the sake of simplicity, we won’t focus on the minutia regarding the configuration and setup of the project. There’s plenty of material on that already and you can always use the amazing Spring Initializr web tool to create the “scaffold” or skeleton of a project.

Just make sure to add the “Spring Web” as a dependency. This will ensure that you have the relevant JSR annotations available at the classpath.

One important note to pay attention to is the fact that Bean Validation 2.0 is different from the Hibernate Validator, which also validates beans, but from a persistence standpoint instead.

Validating Java Beans via Annotations

Let’s take a look at a classic example of bean validation from a Customer Java domain class:

public class Customer {

    @NotNull(message = "Id can't be null")
    private int id;

    @NotBlank(message = "Name can't be empty")
    private String name;

    @AssertFalse
    private boolean admin;

    @Size(min = 5, max = 250, message = "Address must have between 5 and 250 chars")
    private String address;

    @Min(value = 18, message = "You should be greater than 18")
    private int age;

    @Email(message = "That's not a valid email")
    private String email;

    @PastOrPresent
    private Date creationDate;

    // getters/setters
}

Each of these annotations lives within the javax.validation.constraints package. Another great advantage of these annotations is that their names are pretty self-explanatory.

Most annotations have additional properties that you can use to customize validations, such as the minimum value allowed for an int, and the messages the API should use to throw an exception in case the validation doesn’t pass.

Another thing to keep in mind is the version of Java you may be using. Java 8 introduced various features including some new data types designed to handle dates, for example. Some of these annotations, such as @PastOrPresent (which validates if the date object value is lesser or equal than now), also accept LocalDate as one of the possible candidates, for example.

But it goes a step further and allows for automatic validation within the items of a Java list, as shown in the code below:

private List<@NotNull Integer> numbers;

Cool, isn’t it? Since we talked about Java 8, if you have any optional bean properties, the specification also supports optional validations, as shown below:

private Optional<@NotNull Integer> number;

Checking Bean Validations

When you map your Java beans properly and expose them to Spring Controller API methods, Spring takes care of everything for you automatically. Here is an example of this in action:

@Controller
@RequestMapping(value = "/customers")
public class CustomerController {

    @PostMapping
    public void addCustomer(@Valid Customer customer) {
      // save logic...
    }
}

In the Java code example above, the @Valid annotation asks Spring to make sure the object being passed in the POST body is fully validated. To do this, Spring uses the same annotations we mapped previously.

There’s another programmatic way to do this by declaring a new ValidatorFactory object. Here is how that looks in code:

ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();

Customer customer = new Customer();
// sets

Set<ConstraintViolation> violations = validator.validate(customer);

The validate() method receives a bean as a parameter to which the factory-generated validator must validate.

Whatever validation errors we may have with the bean, it will return the result as a Set of ConstraintViolation objects. In each of these objects, you can find the details of the validation error, such as the message of what happened to cause the error.

Java Bean Validation API for Spring Developers

The Java Bean Validation API is a powerful tool all Spring developers can use to directly benefit from a flexible, concise, and clean validation mechanism for your API beans – whether you’re receiving them as requests or response payloads.

There is much more you can learn about Java Bean validations, so make sure to refer to the official docs for more information.

Latest Posts

Related Stories