WebSphere Portal
Page sequences
Page sequences is an extension to the Struts Portlet Framework that leverages much of the existing Struts functionality to support the design and implementation of multi-screen flows within a Struts application. This extension supports the generation of an event driven screen flow model that allows the developer to concentrate on solution-specific tasks.
Currently, Struts applications are left to manage navigation issues and deal with Forms whose logical contents cross page boundaries. Typical business transactions require more than one interaction with the user, therefore spanning more than one JSP page and action. Page sequences leverage much of the existing Struts functionality and extends the Struts framework to support the design and implementation of multi-screen flows within a Struts application, resulting in the following advantages:
- The configuration explicitly defines the exact flow of pages and actions.
- The screen flow automically ensures that the correct sequence is followed and that the user cannot back up and submit the same form multiple times.
- The screen flow supports separation of data from one screen flow to another.
- If the business logic is implemented properly, the order of screens within the flow can be changed without requiring major configuration and code changes.
The following subtopics describe page sequences in Struts portlets.
WebSphere Portal includes an example WAR file for demonstrating page sequences. See Struts demo portlets for more information.
Architecture
When clients send requests to the Page Sequences Framework, they are routed to the controller. The controller acts as a manager that services all the client requests, communicating with various back-end objects and service providers and returning the appropriate JSPs to be rendered. The controller services the client requests on behalf of the page sequences by communicating with a set of configurable lightweight exit beans. The exit beans are able to invoke back-end business objects so that a developer can focus on specific tasks coded in the exits and presentation style.
Page sequences architecture Page sequences use an XML file for configuration, using a format specifically designed to represent screen flows. The configuration file is read during initialization and configuration errors are detected at this time. In addition, all configured classes and methods defined by name are also loaded at initialization time to improve performance and to detect any that cannot be loaded.
Page Sequences scenario
The following scenario is an example of how Page Sequences can resolve common application issues dealing with transactions crossing multiple screens. John is a buyer who wants to create an engineered-to-order Request for Quotation (RFQ). From John's perspective, the RFQ contains a sequence of steps:
- Providing basic information about the RFQ, such as the project start date and time frame
- Providing the project specifications by responding to a set of system-generated questionnaires
- Uploading some project related documents, such as design documents and milestones
- Reviewing the RFQ and modifying the data, if necessary, before submitting
- Submitting the RFQ to the system
For this scenario, the business task is to create not only an RFQ but also the screen flow involved in achieving the previously described steps. The Page Sequences extension to the Struts Portlet Framework resolves the following issues when creating the screen flow for the RFQ described in this scenario:
- Synchronizing the server and client state. When a user uses the browser's history buttons to go forward or backward, the server state becomes stale, and the next submission of a form in the screen flow will be inconsistent with the server state.
- Keeping track of user actions or events generated on different screens.
- Collecting and validating data from the screens before submitting to the back-end applications.
- Resubmitting data. Once the screen flow is over, a user could use the browser's back button and resubmit the data.
The Page Sequences extension addresses these problems by collecting and submitting data to the system to achieve the business task. It is modeled as a finite state machine (FSM), with states being the screens or pages and events or actions being the user interactions, through form submissions, on pages. The screen flow can be modeled as a state diagram, shown below. Each rectangle represents a state, which is mapped to a JSP, and each arc is a transition from one JSP to another JSP. The screen flow starts with the black dot, which is the entry point or source, and ends at the black dot with a circle, which is the sink or end page. A transition is invoked when a user performs an action on the page, such as pressing a button, thereby sending an action or event to the Struts Portlet Framework.
Screen flow for RFQ scenario The state of the screen flow is maintained with the client rather than the server. The Page Sequence controller synchronizes the state with the client state every time an action is invoked on any screen in the screen flow. This procedure makes state synchronization simpler. For this purpose, every screen in the screen flow carries a small piece of information via two hidden fields in all of the forms.
Exits in Page Sequences
An exit is a callback or hook function that can be configured to be invoked when a particular event occurs in the life cycle of the screen flow. Exits are available through special Page Sequences classes that can be extended to provide the appropriate functionality. When an event occurs in the screen flow, the corresponding exit is invoked.
The default behavior of exits is to do nothing if they are not overridden. The Page Sequence controller provides a mechanism for the developer to override user actions, such as pressing a button. An action, and the resulting page, might depend on the data that the user enters on the current page. For example, when collecting data through a series of questionnaires, the answers selected on one page determines which questions appear on the next page, as well as whether to ask additional questions or stop the process. In this case, part of the screen flow contains a questionnaire page with an action that renders the same page as the resulting page. To avoid an infinite loop, the page can have a guard exit that can override the previous action when there are no more questions to ask. The guard exit would either return null indicating that the regular action should be used or the name of one of the specially defined actions. The indicated action, either the default one or one of the specially defined ones ind icates the resulting page. These specially defined actions are called guarded actions. Although this allows the screen flow to be somewhat more dynamic, note that it is not totally dynamic; all the possible actions are still configured as either regular or guarded actions.
The Page Sequences extension follows the configuration and invokes the exit methods at appropriate times. The developer must decide when to use an exit and what exit should be used. Exits and pages should not assume any specific sequence of pages; instead, it should be left to the page sequence to manage the screen flow, which can be modified at deployment time. There are eight types of exits associated with Page Sequences.
- Start exit
- This exit is invoked before starting the state machine of the page sequence. This exit is the best place to initialize the screen flow. A typical initialization could retrieve back-end data that is used throughout the screen flow or connect to a back-end business object. This exit is extendable in the PageSequence class.
A start exit should not be misinterpreted as the entered exit on the first page or the done exit on the entry point transition. In a given screen flow, there can be more than one first page and more than one entry point transitions. Returning to the RFQ scenario, John can define a screen flow for editing and modifying a drafted version of an RFQ. This screen flow might be the same as the RFQ creation screen flow, except the screen flow is started from the summary page so that the user can see whatever work has been done on that particular RFQ. John can introduce an entry point transition to the summary page, which makes that page another first page in the screen flow. To avoid repetition of code in the done exits on the entry point transition for the screen flow initializations, a start exit can be configured.
- Stop exit
- A stop exit is invoked just before the state machine is halted. This exit is intended for screen flow cleanup, for example, releasing database connections or back-end object obtained in the start exit. This exit is extendable in the PageSequence class.
- Entered exit
- This exit is invoked before entering a state or page. The entered exit should be used to load data that needs to be displayed on the page. You can create simple view beans from the back-end data structures and set them in the request object as attributes. On subsequent pages, these view beans can be read and displayed through standard JSP tags, custom tags, or both. This exit is extendable in the PageSequencePage class.
An entered exit should not be used to read the request parameters or form values from the previous page because pages are not always in the same sequence. Reconfiguration of such a page sequence for a different screen flow would require the recoding of exits. For this reason, an entered exit should not be used for cleaning up page specific data for the previous page. Exits should not be tied with specific page order or sequence.
- Done exit
- This exit is invoked on taking a state transition and before entering the next state or page in the sequence. The done exit is used to read form data submitted on the previous page and store the data for further processing. In cases where a common part of the form is submitted for all actions on a page, a common function can be written to process the request object and can be invoked in all the action done exits. This exit is extendable in the PageSequenceAction class.
- Leaving exit
- The leaving exit is invoked before leaving a state. This exit can be used to clean up the page-specific scratch data created in the previous state. Usually, you do not need to handle this exit since the data is cleaned up when the page sequence ends. This exit is extendable in the PageSequencePage class.
A page can contain more than one form to collect data and submit it to the server through different actions, so you should not use the leaving exit to read the form data since the exit code must have conditional statements to process the request object. A leaving exit is invoked on every action on the page.
- Validation exit
- This exit is invoked after performing any field level validation. This exit is used to perform any validation on the entire set of data, including relationships or dependencies between form fields. This exit is extendable in the PageSequenceAction class.
As a simple example, a user is asked to specify an email address in a company-specific form or as an Internet email address. If the user indicates that the email address is internal, a company-specific email address is expected in the next field. If the user indicates that it is not internal, a valid Internet email address is expected in the next field. A validation exit works well in cases where a back-end interaction may be required to validate an entire set of data.
- Guard exit
- This exit is used in conjunction with guarded actions as described earlier. This exit allows the application to determine at run-time whether to execute the configured action as is, or to execute one of the configured alternate actions instead. It does this by returning null to execute the regular action, or by returning one of the configured guarded action names. In this way, the application can choose from several possible actions after the user triggers an action by pressing a button on a form. This exit is extendable in the PageSequenceAction class.
- Access exit
- This exit gives the application the chance to determine if the user should be given access to a sequence or action. This is over and above the automatic role-based access rights checking that is done in normal page sequence processing. This exit is extendable in the PageSequenceAction class for actions and in the PageSequence class for sequences.
In some cases, a page might want to display some data that is collected in a previous page or multiple pages. Even though a request from the previous JSP is available in the next page, the parameters should not be read off the request directly in the second page. Instead a combination of done and entered exits should be used to read and set data from and into a request object. This procedure provides isolation from page to page in a future screen flow reconfiguration.
Configuring Page Sequences
Several modifications must be made to enable the Page Sequences extension in portlets. Configuration of Page Sequences is handled through two XML files.
Additions to struts-config.xml
Since Page Sequences support is an extension to the Struts Portlet Framework, it is necessary to do things to struts-config.xml to extend the basic Struts behavior to support Page Sequences.
To specify the Page Sequences Request Processor, the controller element is used.
<controller processorClass="com.ibm.wps.struts.sequence.base.PortalPageSequenceRequestProcessor"> </controller>The Page Sequences excecution relies on Struts Action-based processing. During processing of the Page Sequences configuration file, Struts action mappings are generated into a modified Struts configuration file that includes the generated Page Sequences action mappings along with the original Struts actions. The following sample illustrates what the path part of such a generated mapping for invoking a sequence using the default entry point looks like:
<action path="/NewRFQ ..." ... </action>The action path starts with a / symbol, as do all Struts action mappings. As with any Struts action mapping, the Struts extension (e.g. "*.do") is not included in the mapping. The names of the Page Sequence, pages, and action names must all be valid within a URL. It is recommended that simple names without any special characters be utilized. The current implementation builds action paths based on the sequence name, the page name, and the action name separated by two consecutive minus "-" signs. Thus, the path for the "Attach" action on the "Attachment" page of the "NewRFQ" page sequences is /NewRFQ--Attachments--Attach. The only time you would need to be aware of this detail is if the action mapping path in a validation rule needs to be referenced. See the Form data and validation for more information on this topic.
If the page and/or action name is empty, that is "", then it is excluded from the action path. Note that it is possible that the exact format of the generated paths could change in the future. Also, Page Sequences does not execute based solely on the generated Struts action mappings. Thus, it would not be possible for developers to generate their own action mappings and add them to a struts-config file and expect it to behave as a Page Sequence. There are additional required objects created from the page-sequence.xml file that are not added to the configuration objects in the struts-config.xml file.
To invoke a Page Sequence, you would reference the PageSequence's action mapping similar to any Struts action. That is, it would specify the path, including the Struts extension mapping, in one of two ways, depending on whether the default entry point was used.
- To invoke the beginning of a Page Sequence shown above above within a JSP, using the default entry point, you would specify the following:
<html:link page="/NewRFQ.do">New RFQ</html:link>- To invoke the same Page Sequence using a different entry point, you specify the entry name via the entryAction parameter:
<html:link page="/NewRFQ.do?entryAction=entry2">New RFQ</html:link>The validation plugin and the two XML files containing validation rules must also be specified. Generic rules for validation are contained in validator-rules.xml, while validation.xml typically contains rules specific to a particular application. Application-specific rules can exist in a differently named file. The following lines specify a validation plugin and XML files:
<!-- Add multiple validator resource files by setting the pathname property --> <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/> </plug-in>Page Sequences configuration file
A given page sequence is defined in page-sequence.xml. Only one page-sequence.xml can be associated with each struts-config.xml and it is placed in the same directory. However, multiple page sequences can be configured in one page-sequence.xml.
There is a single page-sequences element in the configuration file. This element contains the definition of one or more page sequences. A sub-element of the page-sequences element is the config element, which provides some basic configuration information. Below is the beginning part of a page-sequence configuration including the page-sequence element and its config element:
<?xml version="1.0"?> <page-sequences> <config> <solution>MyTesters</solution> <error-page> <uri> <default-uri>/ErrorPages/RFQErrorPage.jsp</default-uri> </uri> </error-page> </config> <!-- Page sequences --> ...... </page-sequences>The tags used in the page-sequences element are explained below:
Element name Purpose solution This element is a title for the page-sequence(s) included in the configuration. error-page This element provides the name of the JSP that should be used when page sequence exceptions are thrown. One or more page sequences definitions come after the config in page-sequences. Each definition should be inside its own page-sequence element. For example, the following is an example of a page-sequence element.
<page-sequence name="NewRFQ" context="child" class="com.ibm.testers.rfq.exits.NewRFQPageSequence">
Attribute Value name Required. A unique name should be assigned for the particular page sequence. context Optional. This attribute indicates which data context the page sequence uses. Default is child, which means a new data context is created for the page sequence. Other options are root, solution, parent, and none. class Optional. This attributes provides the name of a PageSequence subclass that has exit implementations. The exits that can be overridden are start and stop, as well as the access exit to check accessibility. Within a page sequence, one or more entry points, or sequence actions that get executed at the beginning of a page sequence, can be defined.
<entry-point> <action-list> <sequence-action name="" resulting-page="BasicInformation"/> <sequence-action name="restart" resulting-page="BasicInformationRestart"/> </sequence-action> </action-list> </entry-point>Note that the default action is specified with an empty string for the name. It is possible to have additional entry points, each having a unique name. The action specifies what page is rendered via the resulting-page attribute. However, the done exit of this initial action will be invoked prior to entering the resulting-page.
The page-list element has no attributes, but it contains one or more sequence-page elements, as indicated below:
<page-list> <sequence-page....> </sequence-page> .... </page-list>The following example illustrates a simple sequence-page element:
<sequence-page name="BasicInformation"> <uri> <default-uri>/NewRFQ/BasicInformation.jsp</default-uri> </uri> <action-list> <sequence-action name="Next" resulting-page="QnA" form="basicInformationForm"/> </action-list> </sequence-page>The example above defines a sequence page named BasicInformation that is rendered via /NewRFQ/BasicInformation.jsp. It has a single action named Next, which results in the next page, called "QnA".
The following example is a Page Sequence page definition containing guarded exits:
<sequence-page name="QnA"> <uri> <default-uri>/NewRFQ/QnA.jsp</default-uri> </uri> <action-list> <sequence-action name="Submit" resulting-page="QnA" class="com.ibm.testers.rfq.exits.QnaPageSubmitAction"> <guarded-actions> <action-list> <sequence-action name="Next" resulting-page="Attachments"/> <sequence-action name="Review" resulting-page="Summary"/> </action-list> </guarded-actions> </sequence-action> </action-list> </sequence-page>In the above example, the page is named QnA, and its rendering JSP is /NewRFQ/Qna.jsp. It has a single action named Submit, which takes it back to the same page. It would remain on the same page forever, except that it has guarded actions, which are selected via a guard exit. The guard exit will be executed in com.ibm.testers.rfq.exits.QnaPageSubmitAction, and one of three things will occur.
- If the guard exit returns Next, control passes to the Next action.
- If the guard exit returns Review, control passes to the Review action.
- otherwise, control is returned to the defined resulting-page of the action, which in this case is the same page, Qna.
Note that a guard exit returns null to indicate that the defined resulting-page should be used.
The sink page of a Page Sequence is a page which has no actions. This ends the execution of the page sequence. The following is an example of this:
<sequence-page name="Status"> <uri> <default-uri>/NewRFQ/Status.jsp</default-uri> </uri> </sequence-page>Advanced topics in page sequences
- Building on the Struts Framework
- Data handling
- Form data and validation
- Nested Page Sequences
- Runtime control flow
- Access Control in Page Sequences
- Error/exception handling
- DTD
Building on the Struts Framework
The Struts framework has evolved over time and has been used to implement thousands of servlet-based applications. Because of this, the Page Sequences support tries to leverage the Struts Framework capabilities. This section describes how this is done, as well as explaining the differences that the developer needs to understand.
Struts Actions vs. Page Sequences Actions in forms
Actions associated with HTML forms in Struts are treated somewhat differently from Actions associated with HTML forms in Page Sequences. In a Page Sequences configuration, each event, such as a button press, is treated as a separate action. In a Struts application, the target of the HTML FORM tag is the single action and parameters are added to the target to represent the actual event, for example, which button was pressed. This distinction becomes important when one uses the Page Sequences form tag, which extends the Struts HTML form tag.
The Struts form tag uses part of the Struts configuration to simplify the code developers must supply in the JSP. Based on the target of the form, the corresponding Struts action mapping is located, and the associated ActionForm bean is located or created and initialized if it did not exist already. Validation of the form fields occurs automatically, as does population of the ActionForm bean from the values entered by the user following submission of the form by the user. It is, of course, desirable to allow the Page Sequences application developer to utilize these same capabilities rather than requiring the use of a totally different approach. To support this, the Page Sequences functionality provides its own form tag, which extends the behavior of the regular Struts form tag.
For Page Sequences, you should use the the Page Sequences version of the form tag for all forms. In order to use an ActionForm bean with the form tag, you should specify the name and type of the ActionForm. The name must match the name of the form bean configuration in the Struts configuration. This is required because, unlike in the normal Struts case, the target of the form you specify does not have to match a configured Struts action name. The processing of the PageSequence determines the action mapping to use. If you do not need to use an ActionForm bean with your form, you should still use the Page Sequences form tag so that the proper Page Sequences state information is sent with the request.
JSP tagging
This section describes the JSP custom tags that are used in the page sequence framework. There are some special tags for use with Page Sequences that aid in the development of JSPs used in Page Sequences. In addition, they hide some of the details of the Page Sequences implementation from the developer, allowing for the possibility of future changes in the implementation without impacting the developer's Page Sequences. It is, therefore, strongly recommended that these tags be used rather than performing the equivalent function in Java code within the JSP.
The following table lists the custom JSP tags for page sequences. For more information about these tags and their attributes, see Detailed descriptions of the page sequence tags.
Tag Description <pseq:actionlist/> Iterates through the list of actions on the current sequence page <pseq:applycurrentstate/> Applies the client side state of the page sequence as hidden parameters in the form <pseq:bean/> Retrieves and saves page sequence or action page specific data beans <pseq:cleanup/> Attempts to clean up page sequence following unrecoverable error <pseq:currentstate/> Creates a page-scoped variable pointing to the current state object <pseq:exception/> Create a page-scoped variable pointing to a SequenceException, if present <pseq:form/> Define an input form <pseq:getinvalidfields/> Get the list of fields that are not valid <pseq:invalidfields/> Tests if there are any fields on the current action page that are not valid <pseq:link/> Render an HTML anchor or hyperlink <pseq:nextstate/> Get the next page sequence state <pseq:statehistory/> Iterates through the list of states in the history of visited states in the current page sequence <pseq:submit/> Render an input button of type "submit" <pseq:testaction/> Tests if a specified action is possible on the current sequence page given the active role in that particular state of application <pseq:testfield/> Tests whether field with given name is valid Data handling
The Page Sequences controller handles the data management in a screen flow. Various screens in a screen flow collect and/or generate data that needs to be stored or retrieved for further processing in the screen flow. A page sequence should make sure that this data is not available outside the scope of the screen flow. A page sequence runs in a context, called the page sequence context. When the screen flow starts, a context object is created which is available to the developer as long as the page sequence is alive. As soon as the page sequence ends, that is, when the page sequence reaches a sink page, the context and any data contained in the context object is destroyed. The page sequence controller provides an API to access data within the page sequence context, thereby hiding the complexities of context management from the developer.
A context object can be viewed as a container of data for the specific page sequence for which it is created. The context data is a set of name-value pairs. There are two types of data that can be stored in and retrieved from the context: global data and page specific data. Global data is available to all the pages participating in the page sequence, and page specific data is available only for the page. There might be cases where a developer might want to protect some data from other pages, in which case, the page-specific data can be used. Typically, this data can be view beans that are specific to a page. A data name should be unique across the page sequence, if it is used as global data, and should be unique across the page if it is used as page-specific data. The context object is not available to the sink page because a page sequence destroys the context before it renders the sink page.
A solution context, which is a singleton-per-solution, hosts an area for system beans and runtime page sequence contexts. A page sequence context hosts an area to save page sequence specific system beans (for internal use only), page sequence scoped beans, and an area to save page-scoped beans. The data for different page sequences is saved in different areas tagged with the context id within the solution context. Similarly, page-scoped data is saved in different areas tagged with the page id within the same page sequence context.
Form data and validation
The Page Sequence extension uses the Struts validation extension to support validation of form data. The Struts validation provides validation expressed as regular expressions, as well as providing custom classes to do validation. In order to use the validation support, the following conditions are required.
- The Page Sequences version of the form tag, pseq:form, must be used, and it must specify the name under which the form bean was configured in the struts-config.xml file.
- The Bean representing the form must subclass one of the special validation form classes rather than just ActionForm.
- The name of the configured form Bean should be specified via the form attribute on either the sequence-page element or the sequence-action element. If it is specified on the sequence-page element, it will automatically be copied to all actions defined under this page unless overridden by a different value on a particular sequence-action element.
The particular class that the form Bean should subclass depends on whether validation is the same for all actions associated with a page or particular to the action chosen.
- If all fields being validated should be validated the same way, no matter which action is taken, the Bean representing the form should subclass either ValidatorForm or DynaValidatorForm, and the validation rules will be located by looking up the rules based on the configured form bean name.
- For fields that need to be validated only when a particular action is chosen, the Bean representing the form should subclass either ValidatorActionForm or DynaValidatorActionForm, and the validation rules will be located by looking up the rules based on the action path.
- For situations where some fields should be validated no matter which action is taken and others that are specific to a particular action, the Bean representing the form should subclass the ValidatorPageActionForm or DynaValidatorPageActionForm classes, which were added for use with Page Sequences. In this case, validation rules will be located based both on the configured form bean name and the action name.
The classes that have names starting with Dyna are dynamic forms where the developer does not actually write code for the Bean but instead specifies the name and types of the fields in the form as part of the configuration of the form bean in the struts-config.xml.
It is strongly recommended that developers utilize the Struts HTML tags within the forms in the JSPs. For example, if the html:text tag is used for text input fields within the pseq:form tag, which also specified the configured form bean name, the following steps occur automatically:
- The form bean will be retrieved if it exists or is created otherwise.
- The rendered form fields will get initial values, if any, from the form bean, after which the user will enter or change valies and hit some submit action.
- The values from the form, either entered or changed by the user or initial values, will be set back into the form, and the form validation logic is invoked.
- If the validation of any values fail, an ActionErrors object will be generated containing the errors, and the html:errors tag can be used within the JSP to display them. Control is passed back to the same JSP.
- If no validation errors occurred, control is given to the JSP that was specified as the resulting-page of the chosen action.
Nested Page Sequences
A page sequence can invoke another page sequence, which makes the second sequence a nested sequence. In this case, assuming the sequence was configured with the default context="child", a new data context is created for the new page sequence and will be available as long as the sub-context is alive. Whenever the parent page sequence is invoked, a context is being created as a sub-context of the solution context. The created screen flow runs under this new context. If this screen flow hits a sub screen flow, a sub-context, or child context, is created and attached to this parent context, and the sub-screen flow runs under this sub-context. Once the sub-screen flow ends, the child context is destroyed and the control returns to the parent screen flow, which is running under the parent context. The context tree grows and shrinks as long as the user is working with the application, screen flows, and sub-screen flows.
The child contexts can use the global data available in the parent context, and its parent contexts, and so on. Hence, the global data names that are redefined in the child context will cover the data names defined in the parent node, its parent, and so on. Note that the ancestor nodes will retain the data, but it is not visible in the child node. It is left to developers to transfer the scratch data in the child node to the parent node, if they desire to do so, before the child context is destroyed.
Runtime control flow
There are three major cases of control flow at run time. All three cases are discussed below and refer to the example discussed in the Page Sequence Scenario:
- A page sequence is just invoked.
- A request comes to the Struts Portlet Framework, which forwards the request to the controller based on the fact that a pseudo-Struts action representing a page sequence is specified.
- As the screen flow state machine is being invoked for the first time, it is initialized and a context is created as child context of the parent context, if the request contains any parent context ID. Otherwise, the solution context is used as the parent context. The ID of the created context is saved in the request object. The parent context ID, if available in the request object, is saved, or pushed on to the context stack, in the child context object so that when the sub screen flow is halted, the parent screen flow can be reentered.
- The start exit is invoked if configured. If the exit method returns false (an error occurred in the initialization), an error page is rendered (the error page is configured in the page sequence configuration). Any time the error page is invoked because of an exception, the exception is set in the request as an attribute, so the error page can make use of the exception to provide better feedback to the user. See the Error/exception handling section for more information.
- If the start exit returns true, a done exit on the entry point transition is invoked. If the exit method returns false or throws an exception, stating that there is an error while invoking the exit, the configured error page is rendered.
- The entered exit, if any is configured, on the resulting page, BasicInformation page, is invoked. If this exit returns false or throws up an exception, the error page is invoked.
- If the entered exit is successful, the resulting-page, BasicInformation page, of the action is rendered.
- Transition from the BasicInformation sequence page to Qna sequence page as a result of Next action.
- A request comes to Struts, which forwards the request to the controller, based on the fact that a page sequence is in progress.
- The leaving exit on the current page, BasicInformation page, is invoked. If the exit method returns false, or throws an exception, it is considered to be failure, and the error page will be rendered.
- If the leaving exit returns true, the form fields are read from the request, and the basic validation is applied.
- validation exit, if configured, is invoked. If the exit throws an exception, the error page is invoked. A return value of false from the validation exit is also considered to be successful invocation of the exit, but it says that the set of data is invalid.
- Irrespective of the return values from the field-level validation and data-set level validation exit, the done exit, if configured on the action, is invoked. This allows the developer to perform any processing on the submitted data, even if some or all of the data fields are invalid. The done exit might or might not check to see if the data is valid before processing. If the done exit returns false or throws an exception, the error page is invoked.
- If any of the field-level validations or the data-set validation exit returns false, the same entered exit, if any is configured on the same sequence page BasicInformation page, is invoked. If this method returns false or throws an exception, the error page is invoked. If the exit method returns true, the same sequence page is re-rendered.
- If all the field level validations and the data-set level validation exit returns true, entered exit, if any is configured on the resulting page, Qna page, is invoked. If this method returns false or throws an exception, the error page is invoked.
- If the entered exit is successful, the resulting-page of the action, Qna page, is rendered.
- Transition from Summary sequence page to Result sequence page as a result of Submit action.
- All the steps, except the last one of the above case, are performed.
- If the entered exit on the resulting page returns true, stop exit, if configured in the page sequences configuration file, is invoked. If the exit method returns false or throws an exception (an error occurred in the destruction), the error page is rendered.
- As the screen flow state machine is being halted, the context is destroyed. The parent context ID, if any, is retrieved from the context stack and set in the request object. It is expected that the developer will transfer any child context scratch data to the parent context data in the previous step (the stop exit method) as the child context is being destroyed in this step.
- The resulting page, Result page, is rendered if the stop exit returns true. Note that the context object is not available to the sink or end page in the screen flow state machine.
Access Control in Page Sequences
You may want to limit access to certain page sequences, or certain actions within page sequences, to users having particular roles. Page Sequences supports this in the configuration by allowing an acl element to be associated with a page-sequence element and a sequence-action element. When configuring the acl element, you can specify one or more roles. WebSphere Portal currently supports groups, so the role must be a group name. To use the element under which the acl element is placed, the user must belong to one of those groups. If the acl is configured as a child of a page-sequence element, the user will not have access to the entire page sequence. If the acl element is configured as a child of a sequence-action element, the user will not have access to that particular action. In this case, when using the actionlist tag, the actions to which the user does not have access rights will not even be in the enumeration list. By using the actionlist tag to enumerate the actions on a page, you can automatical ly limit the actions displayed to only those that the user has permission to access.
The following example shows a sequence-action element with access limited to users in the admin group.
<sequence-action name="configure" resulting-page="AdminConfigure"> <acl> <role>admin</role> </acl> </sequence-action>Error/Exception handling
An error page must be configured in the configuration file, which will be invoked if any error occurs in the controller execution or any exception occurs in the exit methods. The exception is made available to the error page through a request attribute. When an exception occurs in the normal execution of a screen flow, the context is not destroyed. This facilitates the developer in providing any exception recovery. This error page URI can point to another page sequence. A typical example is to create a page sequence in which exception information and the contact information of the user can be collected and send an email to the administrator(s) who can respond to the exception.
A configuration file may host multiple page sequences. So, if there is any special error page required for a particular page sequence, then one can incorporate an error page as part of the screen flow itself and send all the errors/exceptions to that particular page, where a specialized processing can be performed with the error/exception.
Page Sequence DTD
The structure of the page sequence configuration is defined in the file page-sequence.dtd.
Note: The <ml-mapping/>, <ml-name/>, <roles-var/>, <alt-uri/>, and <locale-var/> tags do not apply to the portal environment.
The following shows the structure of the page sequence configuration. Click a link to a description of each element.
<?xml version="1.0"?> <page-sequences> <config> <solution>page-sequences_solution</solution> <error-page> <uri type="relative|web-app|host"> <request-parameter name="parameter_name" value="parameter_value"/> <default-uri>uri</default-uri> </uri> </error-page> <log name="log_object_name"/> </config> <page-sequence name="name" context="root|solution|parent|child|none" context-timeout="milliseconds" class="class_name"> <exit-class> <class>class_name</class> </exit-class> <acl> <role>role_name </role> </acl> <exit name="start|stop|entered|leaving|done|validation|guard|access"> <class>class_name</class> <method>exit_method_name</method> </exit> <entry-point> <action-list> <sequence-action name="action_name" resulting-page="page_ name" sys-defined="true|false" form="action-form_name" formScope="form_scope" actionClass="PageSequenceAction_class"> <acl> <role>role_name </role> </acl> <exit name="start|stop|entered|leaving|done|validation|guard|access"> <class>class_name</class> <method>exit_method_name</method> </exit> <guarded-action> <exit name="start|stop|entered|leaving|done|validation|guard|access"> <class>class_name</class> <method>exit_method_name</method> </exit> <action-list> ... </action-list> </guarded-action> </sequence-action > </action-list> </entry-point> <page-list> <sequence-page name="page_name" form="action-form_name" formScope="form_scope" class="PageSequencePage_class"> <uri> <default-uri>/Catalog/Filter.jsp</default-uri> </uri> <action-list> ... </action-list> </sequence-page> </page-list> </page-sequence> </page-sequences>
<page-sequences/>
describes one or more Page Sequences. This is the top level element. It contains a single <config/> element and one or more <page-sequence/> elements.
- <acl/>
- defines an Access Control list for a given page sequence or sequence action. This element is optional and multiples are not allowed. It has one or more child <role/> elements which define the list of possible roles to which a user must belong to access the parent <page-sequence/> or <sequence-action/>.
- <action-list/>
- defines a list of one or more sequence actions. Exactly one is required within an <entry-point/> tag. Within a <sequence-page/> element, this element is optional and multiples are not allowed.
- <class/>
- The "class" element defines the name of a class and has no attributes or child elements. Its text child simply provides the full classname of a Java class.
- <config/>
- contains configuration information for the entire set of page sequences. Exactly one <config/> element is required in the <page-sequences/> element.
- <default-uri/>
- The "default-uri" is the main (default) URI. It defines a URI and has no child elements (other than the text value of the URI itself) or attributes.
- <entry-point/>
- defines one or more entry points for the page sequence. It has no attributes and contains a single action-list element which contains one or more entry point sequence actions.
- <error-page/>
- defines the page which is to display exceptions from Page Sequence execution. It has no attributes and its only child element is a URI of the error page.
- <exit/>
- The <exit/> defines an exit method with an com.ibm.wps.struts.sequence.Exit subclass. It has a single child element which is a text element providing the name of the exit method in the Exit class.
Note: The exit element is supported for migration purposes only (for earlier implementations) and its use is not recommended. Instead please use the "class" attribute on the "page-sequence", "sequence-page", or "sequence-action" elements as appropriate to define classes which override exits with predefined names.
The following required attributes are defined:
name The type of the exit (e.g. "start")- <exit-class/>
- The "exit-class" element defines the name of a class used to specify a subclass of the com.ibm.wps.struts.sequence.Exit class which defines exits for a page sequence. In such a class the methods can be named anything you want and you configure an association between the name of the method and a particular type of exit. The <exit-class/> element has no attributes and contains a single child element, class.
NOTE: The exit-class element is supported for migration purposes only (for earlier implementations) and its use is not recommended. Instead please use the "class" attribute on the "page-sequence", "sequence-page", or "sequence-action" elements as appropriate to define classes which override exits with predefined names.
- <guarded-action/>
- defines a list of guarded actions, which are possible actions which are determined at runtime via the guard exit. The element can contain zero or more "exit" elements and an "action-list" element. The use of the "class" attribute rather than the "exit" element is strongly recommended. There are no attributes defined for this element.
- <log/>
- The "log" element defines a logging object. It has the following defined attributes:
name The name assigned to the logging object.- <method/>
- The name of the exit method in a subclass of
com.ibm.wps.struts.sequence.Exit
.- <nested-sequence-uri/>
- describes a Nested Sequence to be invoked rather than a regular URI as the URI associated with a sequence page. It has no child elements. The following attributes are defined:
sequence The name of the nested sequence to be invoked. entryAction The name of the action entry point. Defaults to "", the default entry point uri The uri value used on the action. Defaults to "/continue.do" which in almost all cases should be sufficient.- <page-list/>
- defines one or more sequence pages in the page sequence. It has no attributes and contains one or more "sequence-page" elements.
- <page-sequence/>
- defines the configuration for a Page Sequence. It can contain an "acl" child element, an "exit-class" child element, zero or more exit elements, and must contain an "entry-point" element and a "page-list" element. The use of the "class" attribute rather than the "exit-class" and "exit" elements is strongly recommended. The following attributes are defined.
name The name of the Page Sequence. This is required. context This is where the data context is defined. The default is "child" which means a new data context is created for the Page Sequence. context-timeout Amount of ms with no activity which will cause the context to be automatically timed out. The default is no timeout (note that on Portal the Portlet session has its own timeout value). class The full classname of a subclass of PageSequence which provides one or more of the exits. This is optional.- <request-parameter/>
- allows configured request parameters to be included with the URI when it is invoked. The "request-parameter" element has no children elements. The following attributes are defined:
name The name of the request parameter. value The value of the above named request parameter- <role/>
- defines the String name of a role. It has no attributes and its only child is text data providing the role.
- <sequence-action/>
- defines an action. It can contain a single "acl" child element, zero or more "exit" elements, zero or one guarded-action elements. The use of the "class" attribute rather than the "exit" element is strongly recommended. The following attributes are defined:
name The name of the action. This is required. resulting-page The name of the resulting page element. This is required. sys-defined Can be "true" or "false". "true" means it is not a normally used action, but one use for special situations such as error recovery. The default is "false". form The name of the associated action-form definition in the struts-config.xml file to be used with this action. This is optional. formScope The scope the form bean, if specified above, will be stored in. class The full classname of a subclass of PageSequenceAction which provides one or more of the exits. This is optional.- <sequence-page/>
- defines a page in the page sequence. It has a single "uri" child element, zero or more "exit" elements, and a single "action-list" element unless it is a sink page (last page in the sequence). The use of the "class" attribute rather than the "exit" element is strongly recommended. The following attributes are defined:
name The name of the page. This is required. form The name of the associated action-form definition in the struts-config.xml file to be used with this page. This is optional. If specified, this form will be used on all actions under this page unless overridden by the form property on the sequence-action configuration itself. formScope The scope the form bean, if specified above, will be stored in. class The full classname of a subclass of PageSequencePage which provides one or more of the exits. This is optional.- <solution/>
- defines the String name of an entire page-sequences solution. It has no attributes and its only child is text data providing the solution name.
- <uri/>
- describes a Uniform Resource Identifier used within a page sequence. The child elements are "request-parameter" and a single "default-uri". The following attributes are defined:
type How the URI is to be accessed. A "relative" URI is accessed within the same servlet (portlet). A "webapp" URI is accessed with the same web application server. A "host" URI is accessed on another host. "relative" is the default and is the only supported value in the Portal environment.Struts and Page Sequences Javadoc
Javadoc for classes that may be useful in extending the function of the Struts Portlet Framework are included in the Struts Portlet Framework Javadoc Two sets of Javadoc exist for Page Sequences. Normally, you should use Page Sequences Javadoc. However, customers who are migrating from WebSphere Business Integrator Action Sequences should use the Javadoc for the migration API at Page Sequences Migration Javadoc. Some or all of these migration interfaces may not be supported in the future.
The Javadoc is located in the wp_root/dev/StrutsPortletFramework directory.
Related information