Thursday, March 10, 2011

GWT Validation on Client & Server

Validation isn't easy in a GWT environment. Ruby on Rails provides very nice ways of validating and it would be nice to incorporate something similar. However, that isn't possible when application logic is split between Client and Server.

for my purposes I have used the following diagram to think through how I would like to do validation.









There are roughly 4 areas that you can do validation:

1) Input Fields / Pre-client-side-object-creation
- this is nice because once everything checks out, you can easily take the values from the form elements and construct your DTO in order to send an RPC.
- At this point you can also easily make any UI updates/provide feedback

2) Client-side Object Creation
- If you validate after you have your DTO constructed you can easily share more code between Client-Server (Since the server will only deal with the actual object as opposed to form elements)
- However, it may be a little bit more tricky to update the UI to provide feedback

3) Pre-Database (or external service)
- Of course you want to validate on the server too. You can choose to only validate on the server but you may have errors when trying to go from a form element to a specific type during object creation. At this point you can only double check the client side validation. Any more and you will probably have to hit the database (or some other service)

4) Database or External Service
- You will need to validate uniqueness or referential integrity and you will have to use the DB for that.


On the Client, you need to decide how often to validate since GWT makes it easy to validate on every keystroke, a new onFocus, or on submit. You will also have to decide how interactive you want to be when updating the UI. If you don't care about the UI, you may be able to get away with just creating the client-side objects (any form value not compatible with the java type can just be null? or 0? oh this is a problem...)

On the server you would like to reuse the validation code used in client but that is not always possible given the route you choose to take and the complexity of your solution. You will probably want to provide some sort of Exception that the client can handle and update appropriately.

My Solution:

I have decided to validate on the client before creating the DTO object. I have built a framework which allows me to create a "check" for each form element by passing it a UIObject (which it uses to abstract the value and updates accordingly on any errors) and another optional UIObject (SimplePanel) which I use to inject any messages. I then call a chain of methods on this "check" object setting the properties of the check (nil, blank, only_if, min, max, range, a list of possible values, etc) (I got this chaining idea from http://gwt-vl.sourceforge.net/). Currently I only have IntegerValidator and StringValidator which both extend a general Validator which provides base functionality for updating the UIObject and extracting the appropriate value for a range of UIObjects - Will need to add things like Date/Time/Etc Validator

Since I want to do certain actions on the client that I do not need on the server, I have found it easier to just recreate the IntegerServerValidator and use a very similar format.

On the server I have been battling with what type of Exceptions do I throw when there is an error. I have created regular custom exceptions for "UserAlreadyExists" etc. However, know I am toying with creating a single Exception which will wrap other Errors allowing me to pass in multiple errors at a time and bundle some functionality.

There are many different approaches and many available libraries. It requires a good bit of thought and planning to either create your own framework or use someone else's