Skip to main content

Improve JSF by Decoupling Form Rules from Presentation Components

Posted by johnreynolds on July 6, 2004 at 8:24 PM PDT

The conceptual goal of this article is to convince component developers that the rules that govern form validation should be embedded in the form definition rather then spread between business and presentation logic. This approach (which I have advocated before) simplifies the mapping between requirements and implementation, and leads to code that is easier to maintain.

Forms are first class citizens in the world of Business.

Almost all Business Processes begin with the submittal of a Form, and seldom can a Business Process proceed until the Form's input has been validated against a set of rules.

Unfortunately, in the world of User Interface Components the Form has lost its first class status. The term Form has been usurped to refer to a set of Data Fields that are presented to a user on a single screen rather then to an underlying Business Object.

Consider a web-based application for preparing US Income Taxes: Several screens may be necessary to complete a 1040 Income Tax Form, but from the developer's perspective each screen will submit a unique HTML Form.

To avoid confusion, for the remainder of this article I will use the term "Business Form".

Most UI Component Frameworks are Data Field oriented. Controls such as text boxes and drop-down lists are added to screens to gather information from a user. To insure that the user supplies correct information, the controls either constrain the user's input (as with a drop-down list), or the input data is validated against a set of rules for the individual field, or a combination of both techniques is used. Each field has its own validation rules, without respect to the field's context within an underlying Business Form.


This approach is by no means limited to web-based applications, Microsoft's Visual Basic has been renowned for providing field validations of this nature for years.

In the web world, validation of data fields is often a two stage affair. It is always best to provide feedback to a user's input as quickly as possible, so often input data is validated on the client side (this also has the advantage of reducing round-trips to the server to validate data). Data validation must always be performed on the server side for a number of reasons. Client-side validation cannot be trusted (JavaScript may be turned off, or the HTML form may be "spoofed"), and some validations require knowledge that isn't available on the client (such as verifying that a Zip Code matches a City/State combination).


Java Server Faces and Form Validation

Java Server Faces is a relatively new UI Component Framework for developing web-based Java applications. Presentation and Validation logic is encapsulated into reusable Controls to greatly reduce the complexity of building HTML based user interfaces. From its inception, JSF was designed for use with graphical design tools, and already some very promising "Visual Basic-like" development environments have been released.

Unfortunately, JSF has perpetuated the Data Field orientation of earlier UI Component Frameworks.

In JSF, validation rules are defined on a field-by-field basis. To illustrate this point, below is a simple snippet from a JSP page that incorporates a JSF "input_text" field.

<f:view>
<h:form id="myForm">
<table>
  <tr>
    <td>Social Security Number:</td>
    <td>
      <h:input_text id="borrowerSSN"
        value="#{loanAppBean.borrowerSSN}"
        required="true"
      />
    </td>
    <td>
      <!-- error message if borrowerSSN not supplied -->
      <h:messages for="borrowerSSN"/>
    </td>
  </tr>
<!-- Additional fields deleted for clarity -->
</table>
</h:form>
</f:view>

In the above snippet, the markup indicates that the user is required to supply a "borrowerSSN" (the attribute "required" is set to true). If the user submits the HTML form without supplying a "borrowerSSN", an error message will be displayed next to the input field.

Admittedly, this is a straightforward and almost trivial example of field validation, but it serves to illustrate the inherent problems with Data Field oriented validation.
In the above example, "borrowerSSN" represents a single data field of a Business Form. Possibly, all of the fields of this Business Form reside on a single web page, but possibly the Business Form requires several pages to complete. Regardless, the Business Rule:"borrowerSSN cannot be null" is embedded on this web page. If the Business Rules change, this web page will have to change.
There is not a clean mapping from the Business Requirement to the implementation of the requirement.

For trivial applications, Data Field oriented validation has few drawbacks, but consider the potential problems for applications that rely on external services.


Imagine an application that gathers the information necessary to submit a Loan Application to a Lender. The Lender provides a Web Service that accepts XML Loan Applications, and your task is to create a web-based front-end for use by borrowers. Fortunately, the Lender supplies a thorough XML Schema that defines the acceptable values, so the task of creating a UI with proper validation is relatively straightforward.

Problems begin when the Lender's Business Rules change; Returning to the previous JSF snippet, assume that "borrowerSSN" is part of the Loan Application, and that the field is "required". Assume that Federal regulations change and it becomes illegal to require a borrower to supply an SSN. The Lender's web service and your web application are now in violation of Federal law, so you'll both have to hustle to change your code. The Lender must update the XML Schema of their web service, and you must now go through all the pages of your application to make the proper changes.

This simple example illustrates why Business Form oriented validation is preferable to Data Field oriented validation. Concentrating the rules for validating a Business Form in a single interface requires a bit more "plumbing", but results in a solution that is easier to maintain then the Data Field oriented approach.


Note that consolidating the Rules for validation does not require consolidating the processing of those rules. All processes that operate on a Business Form should have access to the Form's declarative rules. If a Rule is simple enough to be evaluated by Javascript, then there is no reason why a JSF component shouldn't generate client-side Javascript when the page is rendered.

Returning once again to our JSF snippet, consider the following changes:

<f:view>
<h:form id="myForm">
<table>
<tr>
<td>Social Security Number:</td>
<td>
<h:input_text id="borrowerSSN"
      value="#{loanAppBean.borrowerSSN}"

      <!-- get validation rules from the Form -->
      validationRules="#{loanAppBean.borrowerSSNValidationRules}"
      <!-- replaces: required="true" -->
/>
</td>
<td>
<!-- error message if borrowerSSN not supplied -->
<h:messages for="borrowerSSN"/>
</td>
</tr>
<!-- Additional fields deleted for clarity -->
</table>
</h:form>
</f:view>

This mock-up is intentionally verbose to make a point: JSF works by using Java introspection to get values from Java Beans. The following line in effect invokes the "getBorrowerSSN()" method on the Java Bean that corresponds to "loanAppBean":

 
      value="#{loanAppBean.borrowerSSN}"

A similar approach could be used to obtain validation rules from a Java Bean. Conceptually, the following line gets the "borrowerSSN" validation rules from the "loanAppBean&" and passes them to the JSF "input_text" component.

      validationRules="#{loanAppBean.borrowerSSNValidationRules}"

As I mentioned earlier, this example is more verbose then need be. If a convention is adopted to define Rules in BusinessFormBeans, Java introspection can be used to obtain Values and Rules given a single field identifier.


Validation of Inter-Dependent Fields

Thus far, I've only covered validation of single fields. Business Forms frequently have Rules that govern dependencies between multiple fields. For example, if a Business Form includes a Start Date and an End Date, there will certainly be a Rule that governs both fields (the Start must be earlier then the End). Validation of this nature is often referred to as "Form Based Validation".

JSF does not explicitly handle Form Based Validation. The JSF Validation Model is strictly Component oriented. A single Component can gather multiple data values, but dependencies between Components must be handled by implementing custom Event Handlers.

JSF's hooks for implementing custom Form Based Validation are the ValueChangedListener and the ActionListener classes. A custom ValueChangedListener can be registered on any Component. Whenever the value of the Component is changed, the Listener will be invoked.


A custom ActionListener can be registered on any UICommand Component (like a "submit" button). When the Component is activated, the Listener is invoked.

With these two building blocks, it's possible to perform any necessary Form Based Validation, but making this work seamlessly with the standard JSF Validation Model requires finesse. Consider the following snippet:

<f:view>
<h:form id="myForm">
<table>
  <tr>
    <td>Start Date:</td>
    <td>
      <h:input_text id="startDate"
         value="#{loanAppBean.startDate}"
         required="true"
      />
    </td>
    <td>
      <!-- error message if startDate not supplied or > endDate -->
      <h:messages for="startDate"/>
    </td>
  </tr>
  <tr>
    <td>end Date:</td>
    <td>
      <h:input_text id="endDate"
        value="#{loanAppBean.endDate}"
        required="true"
      />
    </td>
    <td>
      <!-- error message if endDate not supplied or < startDate -->
      <h:messages for="endDate"/>
    </td>
  </tr>
</table>
</h:form>
</f:view>

The standard JSF Validation will populate the error messages if either Date is null, but a custom Event Handler must be implemented to populate the error messages if the endDate is before the startDate. The rules that apply to the fields are declared in multiple locations within the code base.

The process would be much simpler if a BusinessFormBean (a Java Bean that includes "getter" functions for declarative rules that apply to the form and each of its fields) were registered on the JSF form itself:

<f:view>
<h:form id="myForm" businessFormBean="loanAppBean" >
<table>
  <tr>
    <td>Start Date:</td>
  <td>
      <h:input_text id="startDate"
        value="#{loanAppBean.startDate}"
        required="true"
      />
    </td>
    <td>
        <!-- error message if startDate not supplied or > endDate -->
        <h:messages for="startDate"/>
    </td>
  </tr>
  <tr>
    <td>end Date:</td>
    <td>
      <h:input_text id="endDate"
        value="#{loanAppBean.endDate}"
        required="true"
      />
    </td>
    <td>
        <!-- error message if endDate not supplied or < startDate -->
        <h:messages for="endDate"/>
    </td>
  </tr>
</table>
</h:form>
</f:view>

Of course, for this technique to work "BusinessFormBean" would have to implement a standard interface for exposing Form Based Validation Rules to the JSF form component.


JSF is not unique

I hasten to mention that JSF is not alone in its approach to field validation. The Tapestry Web Component Framework (which I happen to think is great) provides Data Field and Form Based validation support that is philosophically similar to JSF. As with JSF, components can be developed for Tapestry to support Business Form oriented validation as I have suggested in this article. I fervently hope that all Component Frameworks consider adopting the approach that I am advocating in this article.

There are a number of trends that seem to be leading us towards the need to standardize a "Java Bean-like" interface for retrieving Business Form Rules:

  • XML technologies such as XMLSchema and Relax NG provide declarative validation rules for XML Documents. Rules for Web Services and UI based apps should be shared.
  • Open Source Rules Engines such as Drools are rekindling interest in Declarative Programming.
  • The W3C XForms standard defines forms in sufficient detail that browsers can generate self-validating user interface controls without explicit scripting. The definition of these rules should be independent from the decision to use XForms.
  • Tools for generating User Interfaces should support using common Business Rules across multiple applications. The definition of Business Forms within IDEs should be seperate from the generation of user interfaces and page flows (ala Apache Beehive).
  • Sun has just started the Java Server Faces Implementation Project and the JDesktop Network Components Project. This is a great opportunity for synergy and consolidation between the two projects in the area of form validation.


Simplify the Mapping from Requiements to Implementation

Component Frameworks have a lot to offer, but they can be better if they stick to presentation and rely on Business Forms to provide validation rules. I hope that I have demonstrated that JSF could be enhanced to consolidate the Rules that govern Business Forms, and that Rule consolidation simplifies the mapping between requirements and implementation. Toolsets that cleanly seperate the definition of Business Forms (and Business Processes) from the creation of User Interfaces and Page Flows will result in code that is easier to maintain and to reuse.

At the very least, I hope I've got a few more folks thinking along these lines...


Update:

There are several threads on Sun's JSF forum relating to this issue:


Recommended practice for handling page level validation?


Writing a validator that validates multiple components


Validating several fields within the same validator class


Philosophical Question: validation of input data

Update: 11Mar05 - Check out Anders Holmgren's Using Java Annotations to add Validity Constraints to Java Bean Properties.

Related Topics >>