Java Tips #01 — Handle validation in an elegant manner using chain of responsibility design pattern

Aleksander Kołata
4 min readOct 6, 2019

--

Hi ! In this article I would like to present You how business requirements validation can be handled in a “stylish” way.

Case study : User registration form validation

You may say that it’s easy and boring, and You’ll probably be right — but that’s something that every Java developer have implemented at least once in the past, and that’s why I decided to choose this topic. Whether You are using an anemic domain model, hexagonal architecture or other architecture model, at some point You will have to perform validation .

Bellow examples are from a Spring Boot application — basic knowledge of Spring and Hibernate frameworks will be useful.

Let’s describe basics business requirements, which have to be fulfilled in order to sign up a new user.

  • Valid registration data — first name, last name, email, username and password.
  • Username has to be unique.
  • Email has to be unique.

Basic classes to store user’s form and validation result

These properties can be wrapped in SignUpCommand class. I like to use *Command classes, because there I can define when the command’s properties are valid, and I can simply make them immutable using @Value annotation.

SignUpCommand class

I am using javax.validation constraints annotations to verify whether command object is valid or not. Annotation Value from Project Lombok was used, because I want command object to be immutable. Registered user’s data should be the same as the data filled in a sign up form.

To store validation result, You can use a wrapper class like this:

ValidationResult class

In my opinion it’s quite convenient method return type, and it’s better than throwing an exception with validation message.

To “chain” validation steps, You can use a class like… ValidationStep ! It is a superclass for these validation steps, which we want to “chain” with each other.

ValidationStep class

Validation chaining example

Let’s introduce an interface for sign up validation:

SignUp validation service

And now we can implement it, using the classes defined above, and chain of responsibility pattern:

What is happening here?

  1. DefaultSignUpValidationService is a class which implements the SignUpValidationService interface.
  2. Annotation @Service is being used to turn this class into a Spring bean.
  3. Annotation @AllArgsConstructor from Project Lombok is being used to generate a constructor with UserRepository.
  4. UserRepository will be injected in the generated constructor. UserRepository simply extends JpaRepository from Spring Data JPA.
  5. In validate method I’ve used Chain of Responsibility design pattern, to chain all of the validation steps. Let’s describe them one by one.

CommandConstraintsValidationStep — in this step the command object is being validated. All of javax validation annotation will be verified. It’s very handy, that we don’t have to write these validators on our own. If an object is valid, then we let the flow go to the next step. If not — ValidationResult will be returned immediately. In this case, I’ve decided to perform validation manually, but it can also be done automatically using @Validated annotation — You can check it out in this article on Baeldung.

UsernameDuplicationValidationStep — this step verifies … if username is duplicated ! If it is — then invalid ValidationResult will be returned immediately.

EmailDuplicationValidationStep — email duplication verification. Because there’s no next step, if an email is unique, then ValidationResult.valid() would be returned.

I defined all of above steps as private static inner classes, because it’s an implementation detail how the validation will be performed. It is a better idea to test only the public methods — validate(SignUpCommand command). By doing so, at any point You can add/edit/remove validation steps, or make a refactor and stop using this pattern at all. Because Your tests will verify only the interface contract, You won’t have to refactor tests too, even in contract stays the same.

Comparison to other approaches:

Throwing exceptions

I can see this pattern being used often. Generally using exceptions to change the flow of code execution is a bad practice. Also is worth considering, if such common operation as a validation of business requirements should throw an exception, when data provided by application user is not valid ?

Returning booleans / validation wrapper classes

It’s a better approach, because it does not use exceptions, but in my opinion it’s too repetitive, and it makes this method unnecessarily big.

Summary

In my opinion this “style” of writing validation is more elegant than throwing exceptions or returning booleans. You can split and move validation logic to separate classes. It is easy to read what are the steps of validation. It’s not the common usage of this design pattern, but I find it very handy in this situation.

Please let me know if You liked this article :) If You prefer other approaches to validation, do not hesitate to share them in the comments !

--

--

Aleksander Kołata

Senior Full Stack Developer — Java (Spring) and TypeScript (Angular). DDD and software architecture enthusiast.