Getting Started with Apache Struts
Tutorial - Apache Struts 2 - From Soup to Nuts - Part 2
Terminally Pretty – Struts Tags
Often, much of the coding effort in a web application goes into the pages. The Struts 2 Tags help us create localized, dynamic web applications with a minimum of coding, reducing effort by reducing code. The listing “A localization-ready form using Struts tags.” shows the source code for a simple input form.
A localization-ready form using Struts tags
<s:actionerror/> <s:form action="RegisterSave" validate="true"> <s:textfield key"username"/> <s:password key="password"/> <s:password key=password2.label" name="Password2"/>e <s:submit key="save"/> <s:submit key="cancel" action="MainMenu" onclick="form.onsubmit=null"/> </s:form>
The key attribute refers to a Message Properties file, in the standard Java format, that contains the text to use as the label, along with other terms, such as error messages. The listing “A message properties file” shows a simple properties file for our form.
A message properties file
username = Username password = Password password2.label = Repeat password save = Save cancel = Cancel
The figure below “Struts 2 Data Entry Form” shows the page rendered in a web browser.
Figure - Struts 2 Data Entry Form
The two use cases for Message properties are normalization and localization. Many terms are used more than once, and so should be defined only once. Also, many enterprise applications are presented in multiple languages, and Struts 2 supports adding Message Property files for different locales. The key attribute can also be used as the name of the property used to populate the field from a dynamic value passed to the page.
Telling it Like it is – Value Stack
To manage values being passed to a page, Struts 2 uses a “Value Stack”. When a Struts tag needs a value, the framework searches the Value Stack in Last In First Out order (LIFO). If you push a JavaBean with a Username property onto the stack last, then the tag will find that value first. The Value Stack encapsulates the standard Java scopes, along with framework elements, and any custom objects you would like to push onto the stack. The Struts 2 Validators use the Value Stack to redisplay incorrect form input. A default value might have been set by a database call, and another value entered by the user into a form. The user’s value is last on stack, and so it’s found first if the page is redisplayed. Figure 3 “Struts 2 Value Stack” illustrates how the system searches for property values.
Figure 3: Struts 2 Value Stack
The Value Stack solves a thorny problem in validating input. You might have an Integer field on a JavaBean, but on the input form, the user enters “Blue” instead of a number. The framework can’t store “Blue” in an Integer field. So, we either have to throw-away the incorrect value, or complicate how we store a value destined for an Integer property. In Struts 1, for example, we use ActionForms to capture and validate input as Strings.
Many developers would then code a similar but different set of JavaBeans to capture the value in its native type, for transfer to a database system. In Struts 2, the framework can validate input and transfer it to a “POJO” JavaBean with typed properties, without creating and maintaining a special ActionForm. The Struts 2 Validators push the offending input onto the Value Stack, so it can be validated and corrected before populating a value object.
Hard Name, Easy Code – OGNL
Underlying the tags is a powerful expression and binding language called OGNL, or Object Graph Notation Language. Most Java web developers will find the feature set similar to the JST Expression Language, but much more capable. OGNL works hand-in-glove with the Value Stack, making it easy to retrieve a value from a certain scope, or just the last value pushed.
- Get the username from the User object in Session scope only: <p>Username: <s:property name="#session.user.username" /> </p>
- Get the username propery last pushed onto the stack: <p>Username: <s:property name="username" /> </p>
New Tags for Old – Control, Data, and UI
A variety of custom tags are available in Struts 2, which can be grouped into three flavors: Control, Data, and UI. The Control tags allow a page to
- change its presentation on the fly, by using operations like if, elseif, and else; or
- generate markup with operations like append, iterator, merge, sort, and subset.
The Data tags mange dynamic values and behaviors, with operations like a, action, bean, date, debug, i18n, include, param, property, push, set, text, and url. The Form UI Tags replicate and extend the standard HTML tags, with operations like form, label checkbox, radio, optgroup, textfield, textarea, and password – along with enhanced controls like checkboxlist, combobox, doubleselect, among several others. Finally, Non-Form UI Tags, provide error handling with operations like fielderror, actionerror, and actionmessage.
Less is More - Themes
Most often, the dynamic data emitted by many of the tags is wrapped in a predictable envelope of basic HTML. To make pages easier to build, the UI Tags can include routine markup, so you don’t have to. The framework ships with standard themes that include different sets of standard markup.
- The Simple Theme does not output markup. You can add your own – pretty much like a standard HTML tag.
- The XHMTL Theme is the default theme, and does things like put forms into a two-column table layout, with labels, client and server-side validation, and error handling (just by specifying the field).
- The CCS XHTML Theme is designed to replicate the XHTML theme, but entirely in CSS.
The listing “HTML source generated by Struts Tags” shows the code the XHTML template generated for our data entry form.
HTML Source generated by Struts Tags
<form id="RegistrationSave" name="RegistrationSave" action="/struts2-mailreader/RegistrationSave.do" method="post"> <table class="wwFormTable"> <tr> <td class="tdLabel"><label for="Registration_save_username" class="label">Username:</label></td> <td><input type="text" name="username" value="" id="Registration_save_username"/></td> </tr> <tr> <td class="tdLabel"><label for="RegistrationSavePassword" class="label">Password:</label></td> <td><input type="password" name="password" value="" id="RegistrationSavePassword"/></td> </tr> <tr> <td class="tdLabel"><label for="RegistrationSavePassword2" class="label">(Repeat) Password:</label></td> <td><input type="password" name="password2" id="RegistrationSavePassword2"/></td> </tr> </table></form>
The templating system is designed so that you override the markup for a single control, or replace all the standard markup with your own custom theme.