Validations In Spring Boot

If you are not a Medium Member you can read it here.

Hello! In this article, I’m gonna cover validations in Spring Boot. The only requirement for you to understand this topic is to be able to create controllers in Spring Boot and of course, be comfortable with Java.

You can find source code for examples here: https://github.com/kamer/validations-in-spring-boot

Why do we need both client-side and server-side validation?

In web applications, we generally use both client-side and server-side validations for form data or any other data that goes to server-side. Why do we bother with both of them?

Because we use client-side validation to validate and respond quickly. For instance, we have a field that accepts phone number. So, first of all, we should prevent user to type any character other than numbers. Also, we have a pattern that validates phone number. If we control and reject any incorrect input value on the client-side we eliminate the time for this request to go server-side and get rejected. So we can say that client-side validations are mostly used to give user fast feedback and validate syntactical things. (e.g. pattern, length, characters)

But client-side validations can be considered useless since they can be easily manipulated or disabled. Here’s a great representation what it is like to trust any kind of client-side validation.

Client-side validation

If we go on with the above image, we should create a validation mechanism that rejects any other number than 911 as input. Here’s where server-side validation comes into play. Briefly, server-side validation is our last chance to reject incorrect inputs properly. Also, we validate constraints that need more logical operations on server-side. For instance, rejecting creation of an employee if the manager of the department is not assigned yet. Enough for introduction, let’s get our hands dirty.

Javax Validation Constraints

javax.validation is the top-level package for Bean Validation API and it has some predefined annotation-based constraints in constraints package for us to use. Here are some examples.

  • If we want to check a field if it’s null, we use @NotNull annotation.

In the above example name field cannot be null. But it can be empty. If we use @NotBlank name cannot be null and must contain at least non-whitespace one character or if we use @NotEmpty annotation name cannot be null and name.length() > 0. So it can accept a String that has whitespace character.

  • If we limit any number input we use @Max and @Min annotations.
  • @Positive, @Negative, @PositiveOrZero and @NegativeOrZero annotations do what their name suggests.
  • @Size annotation gives minimum and maximum values for size of anything. (CharSequence, Collection, Map, Array)
  • @Past, @Future, @PastOrPresent, @FutureOrPresent annotations validate date types according to their name.
  • You can validate any regex pattern with @Pattern annotation.
  • No need to explain @Mail annotation.

I explained the most important ones above. If you want to see the others you can find them here.

I created a dummy example to try these constraints and show validation messages on form inputs with Thymeleaf. We should annotate controller input with @Valid to activate these constraints.

Then show error messages on Thymeleaf.

Thymeleaf Error Messages

Creating Your Own Validation Annotations

If you have followed previous chapter well you should’ve seen that you achieve almost anything with Javax Validation Constraints. But sometimes defining your own annotations can seem a much better option though.

Here’s one example. We want to validate creditCard field with @Pattern.

Do you see any problem here? It seems too ugly considering we will have at least 5 more fields with at least 2 validation annotations and so on. In this type of situation we can choose defining our own annotation.

First of all create an annotation as below.

We want our annotation to serve at runtime, to be used with field types and to be validated by CreditCardValidator class.

So here’s our validator class.

We implement ConstraintValidator<[AnnotationsName], [TargetType]> and enforcedly override initialize() and isValid() methods. initialize method is guaranteed to be run before any use of this validation and isValid method is where we reject or accept any value.

Our annotation is ready. Let’s use them like the ones above.

All validation errors are saved in BindingResult object and we can show error messages with Thymeleaf.

Combining Multiple Annotations

Another way of implementing good validations is combining multiple validation annotations. Hibernate documentation calls it Constraint composition. It’s quite simple. First of all create an annotation type and fill as below.

You can add different messages for each annotation. Then use it like the other constraints.

Creating Custom Validator Class

We’ve been through constraints so far. It’s time to create a more complicated validation with a custom validator class. In previous examples we’ve validated syntactical things. But generally we need more complicated things that possibly need a database query.

I’m repeating prior example. You have created a department in your imaginary app. Then you try to add a new employee to this department. But you want to add a constraint that requires assigning a manager before assigning an employee. So you should add a validator that checks either this department has a manager or not. This is possible with custom validator. But you can also validate simple things like regex patterns.

Let’s create one.

I’m gonna show you a simplified example. First of all, create a dummy class and fill it as below.

It will always say ‘department has no manager’ and ‘this email already exist’ whatever we enter.

Then create validator class as below. I’m gonna explain details.

This Validator interface that we extend is org.springframework.validation.Validator;. Not javax... one. This interface gives us two methods. supports() method controls if the target object is what we intended to validate and validate() method is where we control and reject things. You can reject the whole object and add a global error message with reject() or reject a single value and add an error message for this value with rejectValue(). Then you should annotate this class with @Component.

Let’s use our validator. But we will do something different than using constraints. After annotating object parameter in the controller with @Valid, we will add an InitBinder method in that controller.

This @InitBinder annotated method will initialize WebDataBinder. Since WebDataBinder prepares objects that come from requests for controllers, it can validate before the request reaches controller. That’s it. Let’s try our example.

In this article we’ve gone through Validations in Spring Application.

For questions, suggestions or corrections feel free to reach me on:

Email: kamer@kamerelciyar.com

Twitter: https://twitter.com/kamer_ee

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store