Feature
Java Feature — Jakarta Struts & JavaServer Faces
The add-and-remove pattern
Aug. 20, 2006 11:30 AM
The "languageList" and "chosenItem" fields and the "move" method
are accessed from the "execute" method of the form's submit action. In
the Struts implementation, this is an instance of the Struts Action
class.
/**
* Populate the lists from the hidden field.
* <p>
* @param mapping action mapping
* @param form action form
* @param request HTTP servlet request
* @param response HTTP servlet reponse
* @throws Exception
*/
public ActionForward execute( ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response ) throws Exception
{
// Populate available list from language list.
ExampleForm eForm = ( ExampleForm )form;
eForm.getAvailableList().clear();
eForm.getAvailableList().addAll( eForm.getLanguageList());
// Populate chosen list from hidden field.
eForm.getChosenList().clear();
eForm.move( eForm.getAvailableList(),
eForm.getChosenItem().split( "\\|" ),
eForm.getChosenList());
}
JavaServer Faces Implementation
What is needed to
implement this design pattern in JavaServer Faces? JSF is designed by
some of the same people who designed Struts so we hope for a smooth
migration path.
In JavaServer Faces, the JSP for the two lists is smaller, because
JSF's tags are more compact. Instead of <table>, <tr>, and
<td>, JSF uses <h:panelGrid>. Instead of
<fmt:message>, JSF uses <h:outputText>. Instead of
<html:select> and <html:optionsCollection>, JSF uses
<h:selectManyListbox> and <f:selectItems>.
<h:panelGrid columns="3" rowClasses="center">
<h:outputText value="#{bundle.available}" />
<h:outputText value="" />
<h:outputText value="#{bundle.chosen}" />
<h:selectManyListbox style="width:100px; height:120px;"
id="available" value="#{example.availableValues}"
onchange="doUpdate( false, true );">
<f:selectItems value="#{example.availableList}"/>
</h:selectManyListbox>
...
<h:selectManyListbox style="width:100px; height:120px;"
id="chosen" value="#{example.chosenValues}"
onchange="doUpdate( true, false );">
<f:selectItems value="#{example.chosenList}"/>
</h:selectManyListbox>
</h:panelGrid>
As in the Struts implementation, the
<h:selectManyListbox> tags refer to the "availableList,"
"availableValues," "chosenList," and "chosenValues" properties of the
backing JavaBean. The interfaces for these properties are identical to
the Struts implementation. Internally the Struts Bean stores List
properties as LabelValueBeans, while the JSF Bean stores them as
SelectItems.
Like the Struts implementation, the four buttons in the middle column
are implemented with standard HTML <input> tags. For JSF these
have to be enclosed in <f:verbatim> tags. Other than that, the
buttons are almost identical with the Struts implementation. The only
wrinkle is that JSF generates hierarchical element identifiers. That's
why JavaScript for JSF often contains identifiers like those with the
"form:" prefix in the code below.
<h:panelGrid columns="1">
<f:verbatim>
<input type="button" style="width:100px;"
id="add" onclick="doMove( 'form:available', 'form:chosen', false );"
value="<fmt:message key='add'/>" /><br />
<input type="button" style="width:100px;"
id="addAll" onclick="doMove( 'form:available', 'form:chosen', true );"
value="<fmt:message key='addAll'/>" /><br />
<br />
<input type="button" style="width:100px;"
id="remove" onclick="doMove( 'form:chosen', 'form:available', false );"
value="<fmt:message key='remove'/>" /><br />
<input type="button" style="width:100px;"
id="removeAll" onclick="doMove( 'form:chosen', 'form:available', true );"
value="<fmt:message key='removeAll'/>" />
</f:verbatim>
<h:inputHidden id="chosenItem" value="#{example.chosenItem}" />
</h:panelGrid>
Other than the hierarchical identifiers, the "doMove()"
and "doUpdate()" functions for JSF are identical to those in the Struts
implementation. JavaScript provides client-side interactivity in JSF
just as it does in Struts.
A convenience of JavaServer Faces is its handling of the submit action.
In JavaServer Faces, you can define the submit button to explicitly
invoke a method in the form bean:
<h:commandButton action="#{example.submit}" value="#{bundle.submit}" />
The "example:submit" method reads the hidden field and
populates the lists. Because this method is attached to the submit
button, there's no need to implement an Action object.
public String submit()
{
// Populate the available list from the language list.
availableList.clear();
availableList.addAll( languageList );
// Populate the chosen list from the hidden field.
chosenList.clear();
move( availableList, chosenItem.split( "\\|" ), chosenList );
...
return( "success" );
}
There's not much of a learning curve to JSF. Tags are
different, but they usually produce smaller JSPs. Java code is similar
and sometimes requires fewer objects.
The strongest advantage of JavaServer Faces is its component
architecture. If you get the free download of Sun's Java Studio
Creator, you'll find it contains a complete Add-and-Remove component
that you can drag-and-drop in your GUI. Sun's component includes
features such as "Move Up" and "Move Down" buttons to tweak the order
of the chosen items. We can expect many such useful components to
emerge as JSF development advances.
Conclusion
This article has described a standard
UI design pattern for making ordered selections and selections from
long lists. Implementations of this pattern were compared using Jakarta
Struts and JavaServer Faces.
JSF provides a natural migration path for projects moving from Struts.
The JSP tags are simplified; the backing bean code is similar; and if
you need JavaScript for interactivity, the same functions can be used.
JSF can be thought of as a simplified, componentized version of Struts.
Its designers have done exactly the type of work one hopes for in a
"second system": they've added useful features and reduced complexity.
For any new Web project, JavaServer Faces should be strongly
considered. For existing Struts projects, JSF provides a smooth
migration path.
Resources
- Apache Software Foundation. http://struts.apache.org/, 2006.
- Steve Aube. A Dual Listbox Selection Manager.
www.codeguru.com/Cpp/controls/listbox/article.php/c4755.
- Hans Bergsten. JavaServer Faces. O'Reilly. Sebastopol, CA. 2004.
- Heman Robinson. "Struts and JavaServer Faces: Design Patterns for List Selection." Java Developer's Journal, 11:3, 2006.
- Sun MicroSystems, Inc. Java Look and Feel Design Guidelines: Advanced Topics. Addison-Wesley Professional. New York. 2002.
- Sun MicroSystems, Inc. "JavaServer Pages Standard Tag Library."
http://java.sun.com/products/jsp/jstl/.
- Sun MicroSystems, Inc. http://developers.sun.com/prodtech/javatools/jscreator/
reference/faqs/technical/webforms/js_client_identifier.html.
- Sun Microsystems, Inc. Java Studio Creator.
http://developers.sun.com/prodtech/javatools/jscreator/.
- Jennifer Tidwell. Designing Interfaces. O'Reilly. Sebastopol, CA. 2005.
- World Wide Web Consortium. HTML 4.01 Specification.
www.w3.org/TR/html401/interact/forms.html#h-17.13. 1999.
- Weinschenk, Jamar, and Yeo, GUI Design Essentials. Wiley & Sons. New York. 1997.
About Heman RobinsonHeman Robinson is a senior developer with SAS Institute in Cary, N.C. He holds a BS in mathematics from the University of North Carolina and an MS in computer science from the University of Southern California. He has specialized in GUI design and development for 15 years and has been a Java developer since 1996.