Struts Tip #5 - Use coarse-grained ActionForms
The biggest hassle for any Struts developer can maintaining the #@$!% ActionForms. The ActionForm provides several important services to an application, since it is
- a firewall,
- a buffer for the HTML controls, and
- a mutable transfer object.
As a firewall it keeps untrusted input from passing directly into your application. As a field buffer, it stores new input so it can verified before it is passed to more trusting parts of your application, As a mutable transfer object (fka value object), the ActionForm provides an extensible container where data can collected and passed in a batch to one or more business or resource layer objects.
But, in practice, you usually need a different form-bean for each HTML form in your application. This makes it easy to store the data for each form under its own attribute, and to fine-tune the validation for each form.
Hey -- what's that about form-beans? I thought we were talking about ActionForms?
This is an important distinction. Each HTML form typically needs its own form-bean, but a form-bean is not an ActionForm. A form-bean identifies which ActionForm to use, in the same way an action-mapping identifies which Action class to use. Many Struts developers share Actions between action-mapping, but tend to forget that you can share ActionForms between form-beans too.
While ActionForms are vital objects, they are not subtle. Typically, they are a pure data-only JavaBean, with nothing but accessors and mutators. Occasionally, there is a helper method to transform data from one type to another, but even those are a simple wrappers around standard library functions. With the Struts-Validator, most ActionForms don't even need to subclass validate(). All that's needed is to define a formset for each form-bean, or attribute, that needs validation.
So, why bother with more than one ActionForm class? The form-bean determines the runtime attribute name, and therefore the formset the Struts-Validator will use. Neither the validator nor the autopopulation utilities care if there are more properties a form than are used with a given request. And, null properties consume fewer resources that instantiating yet another class. So why not just put all the application's properties together in a single ActionForm?
Worst case, you can define a base ActionForm with all the properties you need, and subclass to provide any custom validations. Meanwhile, by aggregating your application's properties into a single ActionForm, several key benefits are realized.
- Better Manageability. Implementing ActionForms as fine-grained containers results in a large number of objects in the application, many of which have redundant properties. This consumes both system and developer resources, and can negatively impact application performance and long-term maintenance.
- Relationships are preserved. Most HTML forms represent, in part, a SQL view, which includes properties from several different tables. If an ActionForm contains properties for all the fields, any relationship can represented.
- Schema independance. When ActionForms are fine-grained, each ActionForm usually represents a single row in a database. This ties the presentation layer to the database schema, rather than to the greater business model. When the schema changes, fine-grained ActionForm objects may also need to changed. Coarse-grained ActionForms change less frequently, since if a field is moved from one table to another, it will still available the form. If a field is introduced or renamed, only one ActionForm object needs to adjusted.
In a larger application being developed by a team, you may want more than one ActionForm for the application (even if you don't "need" one). There may, for example, be one ActionForm each each major segment of the application being handled by a smaller group or pair of programmers within the team. The important thing is to try and group together all the properties that will be used together, so that they are not continually re-defined throughout several related classes. ActionForms are objects too and can be subclassed like any other object.
So the next time you need an ActionForm to go with a new form-bean, think twice before creating a new class. Maybe you already have one you can reuse.
----- For more about aggregate entities in J2EE applications, see < http://developer.java.sun.com/developer/restricted/patterns/AggregateEntity.html >. About Ted. Ted Husted is an active Struts Committer and co-author of Java Web Development with Struts and Professional JSP Site Design. Ted also moderates the Struts mailing list and the JGuru Struts FAQ. --- MVC-Programmers mailing list
Copyright Ted Husted 2002. All rights reserved.
For more about aggregate entities in J2EE applications, see < http://developer.java.sun.com/developer/restricted/patterns/AggregateEntity.html >.
About Ted. Ted Husted is an active Struts Committer and co-author of Java Web Development with Struts and Professional JSP Site Design. Ted also moderates the Struts mailing list and the JGuru Struts FAQ.
MVC-Programmers mailing list