VMware offers training and certification to turbo-charge your progress.Learn more
This is my first post since I joined Interface21 last month. My previous blog is now officially deprecated and I won't be updating it anymore.
So what is the subject of my first post (except to introduce myself)? Validation logic. It won't be a walkthrough of how to perform validation in the Spring framework, rather it will discuss a particular bug bear of mine :)
In particular, I would like to discuss exactly what should go into validation logic. It seems to be a no-brainer answer; "logic to validate the specified data". OK, that is a no-brainer but read on :). As you know, the Spring framework provides a nice abstraction layer for your validation, via the Errors and Validator interfaces. In particular the Validator is where you apply your business specific validation rules to your populated domain object. Spring's excellent binding support is responsible for updating your domain model based on some input, the validator is responsible for ensuring that the populated domain model is semantically correct. So what is my bug bear? Time and time again I keep running across applications that allow validation logic to trickle out of the validator and into the controllers (for web apps), or even worse into the middle tier. Just before people start taking issue; I am not saying validation doesn't belong in the middle tier, I am saying that the Validator is the place to put validation logic!
The most common example of this is when you are adding a new entity, say a User. Typically the validator will perform a number of "simple" checks (fields are not null, text fields are longer than 25 characters etc.). The controller (for example) will then call the middle tier (userService.add(user)) and catch DuplicateKeyException (or a strongly typed DuplicateUserException) exception. If this exception is thrown the controller will then populate the errors object and then re-display the form.
So what's wrong with that picture? Quite simply the fact that some validation is now implicitly being done with the raising of the DuplicateKeyException indicating that validation has failed!. The DB (in this example) is validating the data to ensure it is unique before inserting it, and if not it throws the exception.
My point (that I am admittedly being very verbose in making ;)) is that this is all validation logic which belongs in the Validator. Moving this uniqueness check into the validator where it belongs(!) enables a number of benefits:
Note: there is an argument that states you are repeating your validation logic; the DB knows what is and isn't unique, so why duplicate that logic in the controller? Well, the point is that you are duplicating that logic, you are using the throwing of a DuplicateXXXException to indicate the validation failure, so this isn't really a valid argument.
There is also another argument that states that this isn't 100% guaranteed to catch all (in this case) duplicate keys. And that is true. There is a small window of opportunity after the validation has been called but before the middle tier call is made in which another process could sneak in and create the unique row, but this is a very very small window (typically milliseconds), and an OptimisticLockingException would probably thrown anyway. Also consider the nature of the data. It is highly unlikely that a single unique entitiy would be created by two different threads at the same time. If it does happen, fine. Let the exception trickle up to the container because it really is now an exceptional condition.
P.S. The rest of my blog posts will probably be just as verbose :)