Angular Serverside Validation with Hibernate and Redux

What is this article about?

If you develop a web application with Angular, sooner or later you will run into the following problem: Where will the data generated by the client be validated? Client side validation is included in Angular, and gives the user a fast feedback about the correctness of his data. This is a standard in today’s web application.

As most Angular Apps are running against a server side REST Interface the data has to be validated again on the server to guarantee the correctness of the data. Otherwise, incorrect data could be inserted into the database.

The problem is, how to avoid duplicating the validation logic in the client and the server. I want to show you an approach we chose, and which works fine in an intranet application we recently deployed.

Our simple approach to serverside validation with Angular

Since the application runs on an intranet – and thus it is ensured that an additional network roundtrip does not have a negative influence on the client’s reactivity – we decided to carry out the validation logic completely to server. Our ORM framework (Hibernate) has a validation feature that we were able to utilize for this. The advantage is obvious: the validation logic only needs to be implemented once.

However, this creates the challenge of transferring the validation results from the server back to the client. As the user types we call the validation endpoint frequently and update the forms error state in order to inform both, the user and the Angular application.

Deciding how to call the Validation API

Our first approach was to listen to the respective Angular Input Controls and send the data to server.The code for this would more or less like this:

But this approach had several drawbacks:

  1. Since our entity is spread over several forms, we would have to collect the different subsets of the entity and send them back to the server as a complete entity.
  2. It is hard to decide how often and when to send the data to the server. When the users exits a control (onBlur) or after each keystroke?

The Redux way

As we already have a Redux store backing all our forms we decided to trigger the validation from a Redux Effect. The code is shown below. Basically it sends the full data obejct every 300ms (but only when changes are made) to the server.

On the Server

On the server we are validating our data object by using JavaEE Bean Validation and some custom code. JavaEE Bean Validation has some nice Annotations to check fields. Further information can be found here. The code displayed here is in Kotlin, but this could be easily done with Java too.

Note: We also have some custom validation, which runs logic checks against the given data object and writes the errors into a Simple Java Map.

Displaying Errors in the Client

In the client, we perform the following operations each time the server answers a validation request.

  1. Set the error state via Angular
  2. Disable the save button

Setting errors

The first snippet demonstrates how to set an error to an Angular control. It is very important (at least for Angular Material) to mark the control as touched. Otherwise the error will not be displayed.

To display the error text, the following snippet is also needed for every input control.

To summarize what we achieved: A validation that only had to be implemented once and still applies to the server and client. This allows us an agile further development.

Conclusion

The approach really worked very well for our application. We only have to write validation logic once on the server. The data is validated every 300ms and also on saving. Of course there is a lot more to do, then displayed here. Matching the error Map which is sent from the server to the client can be quit difficult, especially when there is data in collections involeved. This snippet is some code which matches errors to forms which are in a collection.

Intranet-Only

This approach suits only intranet applications, where there is a quite fast bandwidth. Depending on the size of the dataobject there is quite a lot of data sent over the network.

We never experienced any problems in our environment.

 


Jan Blankenhorn

Entwickler bei thecodecampus

Leave a Reply

Your email address will not be published. Required fields are marked *