{"id":359,"date":"2016-02-29T21:01:32","date_gmt":"2016-02-29T20:01:32","guid":{"rendered":"http:\/\/h2916922.stratoserver.net:8084\/?p=359"},"modified":"2016-03-13T22:27:34","modified_gmt":"2016-03-13T21:27:34","slug":"front-backend-validation-using-the-same-script","status":"publish","type":"post","link":"https:\/\/www.ivojonker.nl\/?p=359","title":{"rendered":"Front &#038; backend validation using the same script"},"content":{"rendered":"<p>I&#8217;ve been creating web-app&#8217;s for ages. And what&#8217;s been annoying me for quite a while, is that &#8211; due to the client\/server separation &#8211; i end up duplicating a lot of client-side\u00a0validation-logic on the server-side.<\/p>\n<p>Now, as for solutions to this counter-intuitive phenomonem, i&#8217;ve encountered and implemented all of the below:<\/p>\n<ol>\n<li>None, or sloppy server-side validations are written.<br \/>\nThose lazy, or unable to know something&#8217;s wrong\u00a0or without a sense of urgency\u00a0(security or usability aspects)\u00a0will probably delay finding a solution, and end up writing no or proper validations on either one of the sides.<\/li>\n<li>Microservices-like backend validation.<br \/>\nA proper solution, but one with a lot of communication overhead limiting realtime validation.<\/li>\n<li>Statefull &#8220;External Data Source&#8221; approach.<br \/>\nAn approach where the server keeps a live model and dictates the client what valid values are. Limited as it is statefull.<\/li>\n<\/ol>\n<p>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.<\/p>\n<p><strong>The solution<\/strong><\/p>\n<p>The solution is to write all validation code in Javascript, and share the script both client &amp; 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.<\/p>\n<p>A sample project could be as fllows:<\/p>\n<ul>\n<li>Java\n<ul>\n<li>model\n<ul>\n<li>UserProfile.java<br \/>\n<em>e.g. a JPA annotated POJO that has been setup to serialize to JSON usable as front-end-model.<\/em><\/li>\n<\/ul>\n<\/li>\n<li>restapi\n<ul>\n<li>UserProfiles.java<br \/>\n<em>an interface providing the UserProfile JSON and business logic<\/em><\/li>\n<\/ul>\n<\/li>\n<li>validation\n<ul>\n<li>Validator.java<br \/>\n<em>Containing Javascript &#8216;javax.script.ScriptEngine&#8217; that exposes a validate(functionName, BusinessObject&#8230;) function<\/em><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>Web\n<ul>\n<li>sharedJS\n<ul>\n<li>UserProfileValidation.js<br \/>\n<em>That contains a function to validate a UserProfile Javascript Object.<\/em><\/li>\n<\/ul>\n<\/li>\n<li>Index.html<br \/>\nA webpage to show and manipulate UserProfiles. It makes use of the UserProfileValidation.js to check if everything is correct.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>The flow:<\/p>\n<ol>\n<li>The index.html invokes the restapi and retrieves a JSON representing a specific UserProfile.<\/li>\n<li>Upon client-side manipulation the&#8217;new&#8217; JSON is validated real-time using the functions in the UseProfileValidation.js.<\/li>\n<li>Eventually the client sends back any manipulations back to the restapi, which constructs an update UserProfile.<\/li>\n<li>When JPA wants to persist the entity, it asks the Validator to validate.<\/li>\n<li>The validator\u00a0constructs a JavascriptEngine, injects the UserProfile as JavascriptObject(using JSON), and validates using the UserProfileValidation<\/li>\n<li>Upon failure to validate, rolls-back the transaction.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been creating web-app&#8217;s for ages. And what&#8217;s been annoying me for quite a while, is that &#8211; due to the client\/server separation &#8211; i end up duplicating a lot [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-359","post","type-post","status-publish","format-standard","hentry","category-geen-categorie"],"_links":{"self":[{"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/posts\/359","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=359"}],"version-history":[{"count":5,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/posts\/359\/revisions"}],"predecessor-version":[{"id":361,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/posts\/359\/revisions\/361"}],"wp:attachment":[{"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=359"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=359"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=359"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}