Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Apache Shale Takes JavaServer Faces to the Next Level : Page 2

Apache Shale, the newest sibling of the Struts framework, leverages JavaServer Faces to enable componentized presentation-tier development. Get started with Shale's Dialog Manager, Validations, and JNDI services.


Wizard Creation with Dialog Manager

Apache Shale offers an extra pair of hands to assist in Web-based wizard creation with its Dialog Manager. The Dialog Manager has two parts:
  1. The dialog-config.xml configuration file, which specifies how various pages and Java classes are linked together based on their transition values
  2. The values returned by the JSF Command UI controls (JSF's <h:button/> and <h:link/>'s action value), in either JSPs or Java function calls

To learn how to use Dialog Manager, explore the Launch Party Registration application. This application is a typical 'previous-next' wizard that steps users through the registration process. The user registers, optionally pays, and sets email and snail mail preferences. Figure 1 shows the UML state diagram representing the application.

Click to enlarge

Figure 1. Launch Party Application State Diagram

The application has two wizards: 'Create New Registration' and 'Process Payment'. 'Create New Registration' focuses on gathering and processing registration information, while 'Process Payment' only collects payments. 'Process Payment' stands by itself and you potentially can use it from other wizards including 'Create New Registration'. The beauty here is that 'Process Payment', and for that matter large portions of 'Create New Registration', can change independently of each other if they do not break the contracts of transition values they share. In this case, 'Process Payment' is designed to offer only the credit card payment method. However, you can change it to offer other forms of payment (check, PayPal, barter, etc.) without needing to change 'Create New Registration'—a separation of concern that we all can love.

Looking back at the UML diagram in Figure 1, the user walks through the following activities during the Create New Registration and Process Payment processes:

  1. Create New Registration
    • User ID: User supplies email address (which is the user ID), password, full name, and phone number
    • Register: System registers the user with above supplied information
    • Email Preferences: User sets email preferences and might optionally pay for it using 'Process Payment' wizard
    • Snail Mail Preferences: User sets snail mail preferences
    • Save Preferences: Finally, system saves the preferences and exits the application
  2. Process Payment
    • Credit Card: User supplies credit card information
    • Process Credit Card: System processes the above supplied information
    • Thank you for payment: enough said!

Listing 1 shows the dialog-config.xml file for the sample application. If you compare it side by side with Figure 1, you will notice close parallels between the two:

... <dialogs> <!— New Registration Dialog —> <dialog name="Create New Registration" start="User ID"> <transition outcome="start" target="User ID"/> <transition outcome="exit" target="Exit"/> <!— User Name —> <view name="User ID" viewId="/userid.jsp"> <transition outcome="next" target="Register"/> </view> <action name="Register" method="#{registrationBean.createNewRegistration}"> <transition outcome="success" target="Email Preferences"/> </action> <view name="Email Preferences" viewId="/emailPreferences.jsp"> <transition outcome="next" target="Snail Preferences"/> <transition outcome="payNow" target="Payment"/> </view> <subdialog name="Payment" dialogName="Process Payment"> <transition outcome="next" target="Email Preferences"/> <transition outcome="cancel" target="Email Preferences"/> </subdialog> <view name="Snail Preferences" viewId="/snailPreferences.jsp"> <transition outcome="previous" target="Email Preferences"/> <transition outcome="finish" target="Save Preferences"/> </view> <action name="Save Preferences" method="#{preferencesBean.save}"> <transition outcome="success" target="Exit"/> </action> <end name="Exit" viewId="/goodBye.jsp"/> </dialog> <!— Take Payment Dialog —> <dialog name="Process Payment" start="Credit Card"> ... </dialog> </dialogs> Listing 1. dialog-config.xml

The dialog-config.xml file represents wizards with the <dialog> nodes 'Create New Registration' and 'Process Payment'. Each of these <dialog> nodes consists of views such as User ID, actions such as Register, transitions, and an end node for each dialog.

You can prompt the dialogs into action by having the command button return dialog:XXXX, where XXXX is the name of the dialog defined in dialog-config.xml file. The 'Create New Registration' dialog is launched when the user clicks on commandButton in start.jsp as shown in Listing 2 below. Notice that the name of the dialog is dialog:Create New Registration:

... <h:commandButton id="startNewRegistration" action="dialog:Create New Registration"
value="Start New Registration>>"/> ... Listing 2. dialog:Create New Registration Action Value in start.jsp

Let's go over each of the constituents of <dialog>, namely the <view>, <action>, <transition>, and <end> constructs. Views are used when you require direct user interaction via a presentation technology (for sake of simplicity, assume JSP is the presentation technology). These JSPs are JSF-enabled, which means they use HTML and Core JSF tag libraries. They return String values to the Apache Shale engine via its Command UI controls (JSF's <h:button/> and <h:link/>'s action attribute). Listing 3 shows two buttons with the action values next and exit in userid.jsp:

... <h:form id="userid" onsubmit="return validateForm(this);"> ... <h:commandButton id="next" action="next" value="Next >>"/> <h:commandButton id="exit" action="exit" immediate="true" value="Exit"/> </h:form> ... Listing 3. userid.jsp Showing commandButton with Action Attribute

Actions are used when you need to make calls to functions on Java objects. Action Java classes can be POJOs or ViewControllers (another Shale feature). Just like the CommandUI in JSP, these Java functions also need to return a String value. Listing 4 shows the String 'success' returned by the POJO RegistrationBean:

... public class RegistrationBean { ... public String createNewRegistration() { return "success"; } ... } Listing 4. RegistrationBean java Class Showing Value Returned by
createNewRegistration Function

Both View and Action essentially will return String outcomes. These String values are used by Apache Shale Dialog Manager's Transition construct. Transitions map values returned by Views and Actions to the next target View or Action. Transitions can be defined either at the dialog level or the local state level (View or Action). The Shale engine uses dialog-level Transitions when it cannot match String outcomes from View or Action to local Transitions. Listing 5 shows how the values of next and exit returned by userid.jsp are mapped by User ID's local and dialog's global transition. 'Next' is mapped locally at the View level, while 'Exit' is mapped at the dialog level:

... <dialog name="Create New Registration" start="User ID"> ... <transition outcome="exit" target="Exit"/> <!— User Name —> <view name="User ID" viewId="/userid.jsp"> <transition outcome="next" target="Register"/> </view> <action name="Register" method="#{registrationBean.createNewRegistration}"> <transition outcome="success" target="Email Preferences"/> </action> ... Listing 5. Transitions for 'Next' and 'Exit' Values Returned by userid.jsp

The end node indicates the end of the dialog. The Dialog Manager's internal engine knows to pop up the dialog when it reaches End. Shale recommends this reading to understand the Dialog Manager internals.

No discussion of Dialog Manager is complete without addressing the self-contained subDialogs, and the sample application's candidate for that job is the 'Process Payment' dialog. During the registration process, the user can choose whether or not to pay (don't we all wish). The 'Process Payment' comes into play only when the user explicitly chooses to do so.

Listing 6 shows how it all fits together:

... <dialogs> <!— New Registration Dialog —> <dialog name="Create New Registration" start="User ID"> ... <subdialog name="Payment" dialogName="Process Payment"> <transition outcome="next" target="Email Preferences"/> <transition outcome="cancel" target="Email Preferences"/> </subdialog> ... </dialog> <!— Take Payment Dialog —> <dialog name="Process Payment" start="Credit Card"> <view name="Credit Card" viewId="/creditcard.jsp"> <transition outcome="submit" target="Process Credit Card"/> <transition outcome="cancel" target="Exit"/> </view> <action name="Process Credit Card" method="#{paymentBean.processCreditCard} "> <transition outcome="success" target="Thank You For Payment"/> </action> <view name="Thank You For Payment" viewId="/thankYouForPayment.jsp"> <transition outcome="next" target="Exit"/> </view> <end name="Exit"/> </dialog> </dialogs> Listing 6. Subdialog and Process Payment Dialog

Notice how subDialog in 'Create New Registration' invokes the 'Process Payment' dialog.

In the 'Process Payment' dialog's End node, 'Exit' is missing the viewId attribute. Thus, when the 'Credit Card' and 'Thank You For Payment' Views return the 'cancel' and 'next' outcomes respectively, they pop up via 'Exit' back to subDialog in the 'Create New Registration' dialog. The subDialog 'Payment' node in 'Create New Registration' then handles these outcomes by its defined transactions. These transitions route both 'cancel' and 'next' to 'Email Preferences'.

The only contract between 'Create New Registration' and 'Process Payment' is that when subDialog in the 'Create New Registration' dialog calls the 'Process Payment' dialog, the subDialog handles the outcome returned by 'Process Payment'.

Dialog Manager's icing on all its features is its dialog-scoped state information. The sample application uses this feature in emailPreferences.jsp, where values are stored in the #{dialog.data.receiveEmail} and #{dialog.data.alternateEmail} attributes, which Dialog Manager manages. These values go out of scope once the user steps out of the dialog.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.