Building a wizard pattern in IBM WebSphere Portlet Factory V6.1

Learn how to implement a wizard pattern in IBM® WebSphere® Portlet Factory, using systematic, easy-to-code steps. The simplicity of the pattern makes the code more flexible for future requirements or change requests.

Share:

Amr Rekaby (rekaby@eg.ibm.com), Staff Software Engineer, IBM

Amr Rekaby is a Staff Software Engineer for IBM. He specializes in business-layer technologies, such as Hibernate, Enterprise JavaBeans, and IBM WebSphere Portlet Factory. He is working on a master's degree in computer science from Arab Academy for Science and Technology, He lives in Cairo, Egypt. You can reach him at rekaby@eg.ibm.com.



01 September 2009

Editor's note: Know a lot about this topic? Want to share your expertise? Participate in the IBM Lotus software wiki program today.

Introduction

A wizard is a graphical user interface (UI) with which users interact using a sequence of input forms. These input forms consist of steps that are presented in a specific order to allow you to enter data. A wizard is the most user-friendly solution when the quantity of data is too large to put into one input form; by categorizing the data into logical sections and making the sections steps in a flow of input pages, it is much easier to incorporate all the input data needed.

The wizard use-case is a common one that exists in almost all applications. After all the steps of the wizard are completed, a confirmation page displays, summarizing the options selected by the user during the wizard steps. Typically, the confirmation page requires an action, for example, a complete object being saved in a database.

This article describes a general pattern and its implementation in IBM WebSphere Portlet Factory 6.1 and later, so that you can solve any wizard use-case using WebSphere Portlet Factory. The pattern provides the simplest approach with respect to development concerns and code maintainability, in case of errors or change requests.

We first show the pattern from a design perspective and then go into the details of the implementation of this pattern in WebSphere Portlet Factory. To get the most from this article, you should be a developer, architect, or designer who wants to design systems using WebSphere Portlet Factory.


Wizard pattern components

Figure 1 shows an example of a wizard pattern.

Figure 1. Example wizard pattern
Example wizard pattern

As the figure shows, the pattern contains several components:

  • XSD file. This file is the normal XML schema document (XSD) file that describes the schema that the developer wants to use in this wizard. Generally, an XSD file is an abstract representation of an object's characteristics and its relationship with other objects. An XML schema represents the interrelationships between the attributes and the elements of an XML object.

    The target of the wizard is to collect data from more than one step (input form) and compile the data into one pool (variable) that contains all these fields. This variable definition is presented in an XSD file, which should contain the data type (string, integer, date, for example) for each field in this defined data type.
  • Schema. Schema is part of the pattern that was added for WebSphere Portlet Factory concepts. In a normal pattern, all that is needed is that the project references the XSD file and that you are able to create a variable of this type defined in the XSD file. Because we are mostly concerned with the general pattern in this article, we can ignore the role of schema here, or limit it to make only the application code reference the XSD, and we can use it as the defined type.
  • RDD. The RichDataDefinition component generally contains all the validation needed to be done on the schema-generated variable. These validations have many types, for example, required validation and example format validation.
  • Common variable. This schema is a variable type that is used as a pool to let all the pages (steps) in the wizard add data to it and read data from it. This pool is treated as a virtual data store that is used in input pages and in the confirmation page to add to and read from it, respectively. This pool is then ready to be passed to the business-logic data-access layer, to do whatever tasks you want to do, such as validation or database access.
  • Hierarchy builder. This component thereby divides the schema into logical categorization groups, so that the total group can be handled as one field, to increase the maintainability and reduce the development time. This approach is tricky to execute in the pattern, but there is a way to do it in WebSphere Portlet Factory (though if you attempt to apply this pattern in another technology, there might not be a way to apply this part).

    For example, if you have 50 attributes in the schema, you would divide these 50 attributes into three or four groups, depending on the number of steps in the wizard. You would treat these groups in the next steps in the pattern as if the schema contains only four fields, not 50 fields. Next, you select which attributes should display in each page; if you have 50 attributes, you should seelct an option 50 times (once for each attribute) and repeat it again for each page, to determine which option displays on this new page, and so on.

    Using this hierarchy builder, you divide the object into only three or four groups, and then you can decide on the level of groups (three or four options per page instead of 50). This approach also makes the schema more maintainable if you later want to move an attribute from one page to another; all you need to do is move the attribute from one group to a new group, and the appearance rules are applied to it automatically.

    Without this component, if you want to move an attribute, you must go to the old page, search for the attribute among 50 attributes, hide it, and then reset it to show the status in the new page so as to show the attribute. In addition, the hierarchy component provides a logical structure of the attributes, enhancing readability.

    Note that in some cases the object might contain some attributes that should never be visible, such as the identity primary key in a database, in which case you can create a group for these attributes and set it as hidden in all DataPages.
  • DataColumns. The DataColumnsModifier component sets each group that should display on the page and should be set once for each DataPage. Here you want to reap the benefits of the groups you created in the previous steps. To do this step, you must assign the groups that should display and should not display on page 1, and the same for page 2, and so on. Usually, if the wizard contains a confirmation page, it should show all groups except the hidden groups. If there is more than one confirmation page, you must also select which groups should display on each confirmation page in this step.
  • DataPage. This component binds the variable with an HTML page and is mainly applicable to WebSphere Portlet Factory implementation. If the pattern is used in another technology, this component can be changed into a layer of code or something similar. In WebSphere Portlet Factory, this component also sets whether this page is data-entry or view-only. As discussed, in your wizard use-case, you use data entry for all pages, except the confirmation page, which should always be read-only.

    The DataPage component is the key that DataColumnsModifier uses to point to a specific page (this is also a WebSphere Portlet Factory design concept and not a general case).
  • Page. Page is an HTML page containing HTML tags that serve as a wrapper for the DataPage component and other components that are rendered, such as the Next button and Breadcrumb builders.

Implementing the pattern steps

Let's now discuss the pattern's main components with respect to WebSphere Portlet Factory builders and the steps needed to implement the wizard pattern.

  • XSD file. The XSD file describes the variable, which in the sample code is the Person type. You create a folder in WEB-INF called data_def, and in this folder you create the XSD file called person.xsd. Listing 1 is the XSD code representing the Person type.

    Listing 1. XSD code representing the Person type
    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:Person="http://Person" targetNamespace="http://Person">
     <xsd:complexType name="Person">
        <xsd:sequence>
          
    	  <xsd:element name="person_id" type="xsd:integer"/>
          
    	  <xsd:element name="name" minOccurs="0">
            <xsd:simpleType>
              <xsd:restriction base="xsd:string">
                <xsd:maxLength value="300"/>
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
    	  <xsd:element name="birth_date" type="xsd:date" minOccurs="0"/>
          <xsd:element name="address" minOccurs="0">
            <xsd:simpleType>
              <xsd:restriction base="xsd:string">
                <xsd:maxLength value="300"/>
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
          <xsd:element maxOccurs="1" minOccurs="0" name="universty" >
            <xsd:simpleType>
              <xsd:restriction base="xsd:string">
                <xsd:maxLength value="300"/>
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
    
    <xsd:element maxOccurs="1" minOccurs="0" name="graduation_specialization">
            <xsd:simpleType>
              <xsd:restriction base="xsd:string">
                <xsd:maxLength value="300"/>
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:element name="Person" type="Person:Person">
        <xsd:key name="Person_Person_PrimaryKey">
          <xsd:selector xpath="."/>
          <xsd:field xpath="person_id"/>
        </xsd:key>
      </xsd:element>
    </xsd:schema>
  • Schema (schema builder). Schema builder makes the XSD file a type in the project, to create variables of this type. The schema builder references the schema file location as = /WEB-INF/data_def/person.xsd (see figure 2), which you created in the previous step.

    Figure 2. Schema builder window
    Schema builder window
  • RDD builder. The RichDataDefinition builder sets the basic validations that are done automatically on each DataPage, using a variable of the type declared in the XSD file and referenced by the schema builder. For example, these validations can be for the Name attribute, date format validation such as birth_date, expression validation, data type validation, enumeration values, and other validation and translation functionalities (see figure 3).

    Figure 3. RDD builder options
    RDD builder options
    The XML in listing 2 is the result of all the validations that you created in the sample code.

    Listing 2. Result of validations in sample code
    <DataDefinitions>
    <DataDefinition name="Person">
    <Required>true</Required>
    <DataType>Person</DataType>
    <Children>
    <DataDefinition name="person_id">
    <Label>person_id</Label>
    <Required>true</Required>
    <DataType>integer</DataType>
    </DataDefinition>
    <DataDefinition name="name" base="base_String">
    <Label>name</Label>
    <Required>true</Required>
    <DataType>string</DataType>
    </DataDefinition>
    <DataDefinition name="birth_date" base="base_Date">
    <Label>birth_date</Label>
    <Required>false</Required>
    <DataType>date</DataType>
    <ValidateExpr>Optional Date Only</ValidateExpr>
    </DataDefinition>
    <DataDefinition name="address" base="base_String">
    <Label>address</Label>
    <Required>false</Required>
    <DataType>string</DataType>
    </DataDefinition>
    <DataDefinition name="universty" base="base_String">
    <Label>universty</Label>
    <Required>false</Required>
    <DataType>string</DataType>
    </DataDefinition>
    <DataDefinition name="graduation_specialization" base="base_String">
    <Label>graduation_specialization</Label>
    <Required>false</Required>
    <DataType>string</DataType>
    </DataDefinition>
    </Children>
    </DataDefinition>
    </DataDefinitions>
  • Common variable (variable builder). This variable is the variable of the schema type that is used as the pool, with all the pages (steps) in the wizard adding data to it and reading data from it. You must select the variable Type (see figure 4) to be the same type that you defined in XSD, which was included using the schema builder.

    Figure 4. PersonSchema/Person type
    PersonSchema/Person type
  • Hierarchy builder (DataHierarchyModifier builder). To enhance maintainability, you can divide the Person schema that contains the six sample attributes into three groups (equal to the number of steps plus one hidden group). As shown in figure 5, you create three groups, separated by commas (HiddenGroup, PersonalInfoGroup, and EducationInfoGroup), where the following descriptions are true:

    • HiddenGroup contains the attributes that exist in the schema but are never shown to users; in the sample code the only field like this is person_id, which represents the primary key of the person.
    • PersonalInfoGroup contains the fields that display in the first step Personal Info Step.
    • EducationInfoGroup contains the fields that display in the first step Educational Info Step.
    Figure 5. New group names
    New group names
  • DataColumns (DataColumnsModifier builder). The DataColumnsModifier builder sets each group that should display on each page, in this case, one per DataPage. For example, figure 6 shows the DataColumnsModifier for Page 1, Personal Info Step, in which you select to show only the group specific to this page and to hide other groups.

    Figure 6. DataColumnsModifier builder for Page 1
    DataColumnsModifier builder for Page 1
    Figure 7 shows the DataColumnsModifier builder for the Confirmation page, Confirmation Step, in which you select to show all the groups except the hidden group.

    Figure 7. DataColumnsModifier builder for Confirmation page
    DataColumnsModifier builder for Confirmation page
  • DataPage (DataPage builder). This builder is a WebSphere Portlet Factory builder implementation that binds together the variable and the HTML page; you can also set this page to be data entry or view-only. As figure 8 shows, you select the Data Entry option for all pages, except the Confirmation page, which should always be read-only.

    Figure 8. DataPage for Step 2
    DataPage for Step 2
  • Page (Page builder). Page is an HTML page containing HTML tags that serve as a wrapper for the DataPage, the Next button, and Breadcrumb builders. The code in listing 3 shows a sample of the code for the Page 1 (Step 1 above) HTML, including the tags that are wrappers for the generated HTML code for the UI component.

    Listing 3. Sample Page 1 code
    <html>
    <head>
    <title>Step1 Page</title>
    </head>
    <body>
    <form name="myForm" method="post">
    <div align="center">
                    <span name="breadCrumbs"></span>
                  <span name="inputPart"></span>
          <span name="nextButtonPart"></span>
          </div>
    </form>
    </body>
    </html>

Optional steps

You can also perform the following optional steps:

  • Data Field Modifier (Data Field Modifier builder). This builder is used to change the type of generated UI component for a specific field on a specific page. For example, in the sample code, you want to change the University input field that exists on Page 2 from its normal state to render it in a combo box (see figure 9).

    Figure 9. Data Field Modifier
    Data Field Modifier
    Similarly, you use the Data Field Modifier to generate the Address field as TextArea instead of a text field (see figure 10).

    Figure 10. Address field as TextArea
    Address field as TextArea
  • Breadcrumbs (Breadcrumb builder). This builder is a WebSphere Portlet Factory builder with which you can render breadcrumbs, using easy-to-follow steps. The Breadcrumbs builder is especially useful in wizards because it helps users know which step they are on and lets them return to previous steps to change their selections in a more user-friendly way than a Back button.

    When a user returns to a previous step, you should be concerned about reinitializing the previous page, to hold the correct data entered in this step. Because you use only one variable and all the pages insert data into it, merely returning to the page is enough; the page shows the data from the pool (this one variable). Also, in the confirmation page, you don't need to collect data from many variables (if you use variable per page) because you use only one variable. The confirmation page needs to map this variable to have access to all pages data directly.

    The remaining work in breadcrumbs consists of assigning a readable name for each step that reflects the meaning of the step and its fields, such as Personal Info Step and Confirmation Step (see figure 11).

    Figure 11. Breadcrumbs builder
    Breadcrumbs builder
  • StepXValidationActionList (Action List builder). This builder exists for each step in the wizard, checking whether there are any errors (validation errors) in the step. You can also perform a runtime validation with the Action List builder. If everything is correct, the code navigates to the next step; however, if there are any errors, the user is returned to the last step to correct selection. The following code is an example of the action list that validates Step 1.

    !IF (${MethodCall/Step1PageError.hasMessages}) THEN
    Step1Page
    !ELSE
    Step2Page
    !ENDIF

Navigating the attached code sample

The code sample attached in the Downloads section is the WebSphere Portlet Factory archive project. It contains the implementation of the pattern and has two models:

  • WizardModel.model (containing the pattern implementation)
  • LookupsModel.model (a helper model demonstrating the functionality of the Data Field Modifier, imported into the WizardModel)

The code also includes the following XSD file:

/WEB-INF/data_def/person.xsd (containing the XSD of the purposed Person object)


Conclusion

By implementing this suggested pattern using WebSphere Portlet Factory, you can build a wizard using systematic, easy-to-code steps. The simplicity of the pattern makes the code more flexible for future requirements or change requests such as moving a field from one wizard step to another, adding a new field, or adding or removing validation for a field.


Download

DescriptionNameSize
sample codePortletFactoryWizardSourceArchive.zip1.14MB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=424313
ArticleTitle=Building a wizard pattern in IBM WebSphere Portlet Factory V6.1
publish-date=09012009