Wednesday, December 05, 2007

Validation Bubbles

Over the last week, I have cooked a mini-framework on top of Struts at a client site to facilitate development in a domain-driven way inspired by the Naked Objects approach. This was done by benefiting from the latest features in Hibernate 3, which are utilized in the JBoss Seam web framework.

Validations were defined on domain model fields using Hibernate Annotations, such as @NotEmpty, @Email, and @Regex. Based on these annotations, database tables were generated automatically using the hbm2ddl tool, and validations were performed automatically utilizing a technique that I like to call Validation Bubbles.

How do Validation Bubbles work?

Whenever a model is saved, it validates itself (using the Hibernate validation framework.) If errors are found, they are wrapped and thrown in a validation exception, which bubbles up from the domain model layer to the application layer. At that point, the exception is caught by a custom Struts action super-class that stores validation messages as a request attribute. When the JSP page is being rendered, a custom JSP tag picks the validation messages from the request and renders them on the web page to the user.

What benefit do we get from Validation Bubbles?

The application layer gets cleaned up quite a bit as Struts actions do not need to invoke validation explicitly anymore. As long as a Struts action extends the custom Struts super-class that catches bubbled validation exceptions, its logic only needs to handle orchestrating the business use-case.

Additionally, by placing business validation rules on domain models, and generating the database tables and page-level validations from them automatically, we eliminate redundancy as we do not need to define the same validation rules in multiple places anymore.

Now, it would be cool if we can somehow additionally generate client-side javascript validations from the Hibernate annotations on the domain models. That will be my next endeavor.


Frederick Polgardy said...

Now, it would be cool if we can somehow additionally generate client-side javascript validations from the Hibernate annotations on the domain models. That will be my next endeavor.

That's an interesting problem to solve. Are you using Struts, Spring, and Hib together? What versions?

It seems like you'd actually want to customize the struts tags (subclassing in Struts 1.x, but you can use what's called a "theme" in Struts 2, and apply it globally which is a lot less intrusive), so that they are able to know about validation metadata for properties they're rendering.

Struts 2 does have a theme which handles JS validation to some extent, based on Struts validation, but this is a somewhat different problem.

We should get together and brainstorm about writing some Struts extensions to do this. I think it would be really useful.

Andy Maleh said...

Thanks Fred. Brainstorming would be quite helpful.

My client only has Hibernate 3 and Struts at the moment.

I was thinking of writing custom JSP tags that would automatically generate XHTML tags following the domain model field constraints. For example, a custom JSP tag could generate a text input tag with the correct max/min length according to the domain model field max/min constraints.

Additionally, I would like the custom JSP tags to include Javascript versions of the simpler validations, such as email format validation.

Alternatively, I could write code that inserts the correct Struts validator (they include built-in client-side validation with Javascript) based on the domain model field constraints (annotations), but I need to experiment with that first as Struts validators usually require the use of Struts forms, which complicate things a bit.

Another alternative is to write glue code that relies on JSF tags, kind of like how JBoss Seam does it. People may wonder at this point, why don't we just use Seam? Well, the answer to that is that the client is currently considering Spring and Grails for the future.

In any case, I am sure there are other ideas too. If you come across any, please share.

Frederick Polgardy said...

You're not using Struts forms? Interesting. I was kind of thinking that the Struts tags themselves could be solicited in the solution (by extending or theming).

I was also thinking, as you alluded to, that the right solution might be adapting the model constraints from Hibernate into objects that Struts validator API understands, and taking advantage of everything Struts validator already does.

Andy Maleh said...

Right now, I am using the Struts DynaActionForm, but I was going to drop it since it requires you to repeat yourself and respecify model fields in the Struts configuration file. I know that Spring solves that problem by binding parameters to Java POJOs directly, and I actually cooked something similar to avoid using Struts forms.