I’ve been creating web-app’s for ages. And what’s been annoying me for quite a while, is that – due to the client/server separation – i end up duplicating a lot of client-side validation-logic on the server-side.
Now, as for solutions to this counter-intuitive phenomonem, i’ve encountered and implemented all of the below:
- None, or sloppy server-side validations are written.
Those lazy, or unable to know something’s wrong or without a sense of urgency (security or usability aspects) will probably delay finding a solution, and end up writing no or proper validations on either one of the sides. - Microservices-like backend validation.
A proper solution, but one with a lot of communication overhead limiting realtime validation. - Statefull “External Data Source” approach.
An approach where the server keeps a live model and dictates the client what valid values are. Limited as it is statefull.
But one thing i never thought of, is to share exact the same code, both front-end and backend. But today, i saw the opportunity to do so while working on a greenfeeld side-project.
The solution
The solution is to write all validation code in Javascript, and share the script both client & serverside. The requirement that follows is that your (server-side) data-model should be representable in JSON. And that JSON should be the model for your client-side code.
A sample project could be as fllows:
- Java
- model
- UserProfile.java
e.g. a JPA annotated POJO that has been setup to serialize to JSON usable as front-end-model.
- UserProfile.java
- restapi
- UserProfiles.java
an interface providing the UserProfile JSON and business logic
- UserProfiles.java
- validation
- Validator.java
Containing Javascript ‘javax.script.ScriptEngine’ that exposes a validate(functionName, BusinessObject…) function
- Validator.java
- model
- Web
- sharedJS
- UserProfileValidation.js
That contains a function to validate a UserProfile Javascript Object.
- UserProfileValidation.js
- Index.html
A webpage to show and manipulate UserProfiles. It makes use of the UserProfileValidation.js to check if everything is correct.
- sharedJS
The flow:
- The index.html invokes the restapi and retrieves a JSON representing a specific UserProfile.
- Upon client-side manipulation the’new’ JSON is validated real-time using the functions in the UseProfileValidation.js.
- Eventually the client sends back any manipulations back to the restapi, which constructs an update UserProfile.
- When JPA wants to persist the entity, it asks the Validator to validate.
- The validator constructs a JavascriptEngine, injects the UserProfile as JavascriptObject(using JSON), and validates using the UserProfileValidation
- Upon failure to validate, rolls-back the transaction.