Task flows are reusable building blocks in Oracle ADF. Oracle WebCenter provides task flows for you, or you can build your own task flows and add them to your WebCenter application pages. When you add task flows to customizable pages (that is, Oracle Composer-enabled pages), users can personalize, customize, and edit these task flows at runtime. It is imperative that you design your task flows according to the rules set forth in Oracle WebCenter publications. Failure to do so can result in problems when the task flows are consumed in WebCenter pages, such as too much white space, too many scroll bars, or slow, jerky, and unpredictable responses when displaying large data sets.
To prevent these issues and provide a consistent user experience in terms of look and feel, layout design, and interaction, follow the instructions in this document for:
Creating highly performant, cost-effective task flows
Consuming these task flows effectively in your application by implementing task flow parameters and customization and personalization options
This appendix contains the following topics:
Effective geometry management results in efficient sizing and placement of task flows on the page. If the task flows are not designed properly, you end up with pages that have a slow response time or lots of unnecessary scroll bars or white spaces between components. For example, if you include a task flow containing very little data inside a container that stretches it (for example, a Show Detail Frame
component), there is a lot of white space below the data in the task flow. Poor design can also cause scrolling to be slow and unpredictable in a task flow with a table displaying a large amount of data. To avoid such issues, be sure to design your task flows so that they flow and use a conventional pagination model when displaying large data sets.
Follow the guidelines in this section when designing new task flows for WebCenter applications. Also, be sure to adhere to these guidelines when you edit existing WebCenter application task flows.
To avoid unnecessary white spaces in your task flows, you must ensure that the task flow content flows and is not stretched by the task flow container. A stretching task flow is one that is stretched to the height of the container, whereas a flowing task flow is one whose height is determined by its content, rather than by a stretching container or by itself having a fixed height. A flowing task flow with a small amount of data is shorter than one with large amounts of data, as shown in Figure D-1.
Figure D-1 Difference Between a Task Flow that Stretches and One that Flows
To design a flowing task flow, you must ensure that:
The child component of the task flow does not have a fixed height.
The Show Detail Frame
component surrounding the task flow region does not have a fixed height (specified using its contentStyle
attribute).
The following two examples illustrate how you might include flowing components inside task flows.
Add an Oracle ADF Faces Table
component within the task flow and set the autoHeightRows
attribute on the Table
to a specific value. By defining this attribute, the table height is adjusted according to the content (flow behavior), rather than the table having a fixed height or being stretched into a container (stretch behavior). The autoHeightRows
attribute setting results in table data being displayed as follows:
If you provide a value H
for autoHeightRows
, the table grows to a maximum of H
rows.
If the number of records returned from the data source is less than H
, the table height wraps to that number.
If the number of records is more than H
, the table displays H
rows and provides a scrollbar to view the remaining rows.
If the autoHeightRows
attribute is not used, the table displays at a fixed default height irrespective of the amount of data displayed.
Instead of specifying a fixed value for the autoHeightRows
attribute, you can also provide an EL value so that the attribute is populated based on some logic you specify. You can enable customization and personalization on the task flow and provide an option for users to specify a value for this attribute. A value specified using the personalization option overrides a value specified using the customization option.
Example D-1 shows the attributes of a sample ADF Faces table
component that is included inside a task flow called recent-pages-task-flow-definition
. The autoHeightRows
attribute is set to an EL expression that references a Java bean, recentPagesBean
. This bean contains the logic to populate this attribute with a value provided by the end user (either as a personalization or a customization).
Example D-1 The autoHeightRows Attribute on a Sample ADF Faces Table
<af:table value="#{pageFlowScope.recentPagesBean.pages}"
var="row" rowBandingInterval="0" id="t1"
rowSelection="none" columnBandingInterval="0"
width="100%" inlineStyle="border:none;width:100%;"
columnStretching="last" horizontalGridVisible="true"
verticalGridVisible="false"
autoHeightRows="#{pageFlowScope.recentPagesBean.number_of_items_to_show_at_a_time}"
contentDelivery="immediate"
fetchSize="#{pageFlowScope.recentPagesBean.number_of_items_to_query}">
.
.
.
</af:table>
For a detailed description of the sample task flow displaying personalization and customization options for specifying the autoHeightRows
value, see Section D.3, "Example of a WebCenter Application Containing a Task Flow Created By Following the Guidelines."
To learn more about the autoHeightRows
attribute, including requirements such as setting the contentDelivery
attribute to immediate
, see the tag documentation for <af:table>
in the Oracle Fusion Middleware Tag Reference for Oracle ADF Faces.
Add a Panel Group Layout
component within the task flow and set its layout
attribute to scroll
. Then add an Iterator
inside the Panel Group Layout
. Add your content inside the Iterator
. The content from the Iterator
flows inside the Panel Group Layout
.
Since the height of the Panel Group Layout
depends on the content from the Iterator
, specify a minimum and maximum height for the component by using min-height
and max-height
in the Panel Group Layout
's inlineStyle
attribute.
To avoid a slow and jerky response when scrolling large data sets in your task flow, you must limit the number of records to be fetched from the data source at a time. For example, if you have included an ADF faces Table
component inside your task flow, limit the number of records to be displayed in the table. Use the fetchSize
attribute on the Table
to specify the number of records to be fetched from the data source in a single query. If you specify a fetch size of N
, only N
records are sent to the client from the data source.
The fetchSize
and autoHeightRows
attributes together control the number of rows displayed in the table. The relationship between these attributes is as follows:
If fetchSize
equals autoHeightRows
, all records are displayed in the table.
If fetchSize
is less than autoHeightRows
, the table is cropped at the fetchSize
value.
If fetchSize
is greater than autoHeightRows
, you can decide whether to display only as many records as the autoHeightRows
value or provide pagination controls to display the remaining records. For example, you might include a More link at the bottom of the task flow or include pagination using Previous and Next links. For more information, see Section D.3, "Example of a WebCenter Application Containing a Task Flow Created By Following the Guidelines."
Figure D-2 shows the difference between two task flows containing tables with equal autoHeightRows
and fetchSize
values of 10 and 5. The task flows wrap to the number of records displayed.
Instead of specifying a fixed value for fetchSize
, you can provide an EL value so that the attribute is populated based on some logic you specify. You can enable customization and personalization on the task flow and provide an option for users to specify a value for this attribute. A value specified using the personalization option overrides a value specified using the customization option.
The following example shows the attributes of a sample ADF Faces Table
component that is included inside a task flow called recent-pages-task-flow-definition
. The fetchSize
attribute is set to an EL expression that references a Java bean, recentPagesBean
. This bean contains the logic to populate this attribute with a customization value provided by the end user.
<af:table value="#{pageFlowScope.recentPagesBean.pages}"
var="row" rowBandingInterval="0" id="t1"
rowSelection="none" columnBandingInterval="0"
width="100%" inlineStyle="border:none;width:100%;"
columnStretching="last" horizontalGridVisible="true"
verticalGridVisible="false"
autoHeightRows="#{pageFlowScope.recentPagesBean.number_of_items_to_show_at_a_time}"
contentDelivery="immediate"
fetchSize="#{pageFlowScope.recentPagesBean.number_of_items_to_query}">
.
.
.
</af:table>
For a detailed description of the sample task flow displaying a customization option for specifying the fetchSize
value, see Section D.3, "Example of a WebCenter Application Containing a Task Flow Created By Following the Guidelines."
To learn more about the fetchSize
attribute, see the tag documentation for <af:table>
in the Oracle Fusion Middleware Tag Reference for Oracle ADF Faces.
You can ensure that the task flow wraps to the height of the content by adhering to the first guideline, described in Section D.1.1, "Guideline 1: Create Task Flows that Flow."
To prevent the task flow from collapsing completely when there are no records, or seeming too short when there are only one or two records, specify a minimum height for the content.
For example, if your task flow contains a table with an autoHeightRows
value specified, you can specify a min-height
value using the table's inlineStyle
attribute.
Figure D-3 shows a task flow displayed with a reasonable height even though it has only two rows.
If a task flow is showing ten records, but the data source contains 100 records, you can design the task flow to do one of the following depending on the nature of data in the task flow:
Display only ten records.
For example, a Popular Discussion Topics task flow may use this first option if it is considered sufficient to show the ten most popular topics and not necessary to let users see even the eleventh most popular topic.
Show a More link at the bottom of the task flow that opens a view with the ability to show more records.
For example, the People Connections task flow on a WebCenter Spaces page displays a More link at the bottom.
Show a pagination control with Previous and Next links.
For example, a Watched Discussion Topics task flow may display pagination controls, as users typically want to see all of their watched topics. Pagination is a common choice for task flows in which the data is not inherently ranked in order of importance or can be sorted in different ways, and where it is important to be able to access any record in the data set. The pagination control can be placed either above or below the content, depending on the nature of the content.
Figure D-4 shows the Watched Topics and Popular Topics task flows containing tables having a fetchSize
of 5 but both having more than five records in the data source. The Watched Topics task flow displays five records with pagination at the bottom, but the Popular Topics task flow displays only five records with no UI option to view other records.
Here are a few simple recommendations for creating a pagination control:
Add a pagination message in the format 1 to N of M [prev][next]
.
Align the pagination elements to the right so that the Previous and Next links do not move as you navigate pages.
Ensure that the Next or Previous option is grayed out when it is not required.
For an example of how to use pagination controls, see Section D.3, "Example of a WebCenter Application Containing a Task Flow Created By Following the Guidelines."
You can customize pagination controls using the following parameters:
Position of Previous and Next links
Labels for Previous and Next links, for example, Newer and Older
Icons used with Previous and Next links
The words or symbols used to represent to and of, for example, 1-5 of 100
Options for permitting random access, for example, Prev 1 2 3 ... Next Last
While creating a task flow, you can create parameters and provide options for users to customize and personalize the task flow. You can enable privileged users to customize the task flow for all users (customization) and edit the task flow's properties and parameters in Oracle Composer. You can enable all users viewing the page to customize their view of the page (personalization). This section provides guidelines for implementing task flow parameters and the customization and personalization options.
Table D-1 provides an overview of the various task flow editing options available to users.
Table D-1 Options Used to Define Task Flow Appearance and Behavior
Option | Description | When to Use | Who can See It |
---|---|---|---|
Parameters |
A small set of ideally scalar values, used to program a task flow or set its context.Each parameter must have a good display name and description (which must include possible values and examples). |
Use for a context like the city or pin code so that you can add multiple instances of the task flow, each showing different information or programmed to show information based on receiving a value from the page, programmatically or using the URL. In WebCenter Spaces, you can use a parameter for a context like group space name. Precedence: 3 This value overrides built-in values in the task flow. |
Power users (or users with Edit or Customize permission) can see parameters in Oracle Composer's Component Properties dialog while editing a page. In WebCenter Spaces, moderators can see and edit task flow parameters. When a WebCenter task flow is exposed as a portlet in Oracle Portal, page designers can see these parameters while setting up the portlet. |
Customization/Preferences |
These two are synonymous.Customizations are typically considered changes a business user makes to the task flow. These changes are available to all viewers of the page and are used to specify values for options defined in the task flow. For example, users can decide whether to display the author name or revision date for a document. Preferences are referred to as a definition of the content in the task. For example, a query definition in the Document Viewer task flow, or a query in OmniPortlet. |
Use these when the task flow must provide a user interface that assists the user in defining the task flow behavior. That is, when Lists of Values or specific UI components such as images or radio buttons guide the user better, or when the task flow setup is a multiple step wizard-style interface. Such assistance cannot be provided through parameters because they are strictly scalar values, with no assistance other than a description. Precedence: 2 If there is an identical parameter value (for example, group space name), customization overrides that value. |
Business users (or users with Edit or Customize permission) editing a page in Oracle Composer can see the customization or preferences options. Typically, customization or preferences options are available on the chrome surrounding the task flow in Edit mode. However, users with Edit or Customize permission can also see these options on the chrome in View mode of the page. When a WebCenter task flow is exposed as a portlet in Oracle Portal, the page designer sees these as Edit Defaults options while setting up the portlet. |
Personalization |
A subset of the customization and preferences options. You cannot have personalization options that are not also customization options. |
Use these to allow all viewers of the page to tweak and tune the visual aspects of the task flow or the amount of data shown to them. For example, to set the number of items to display. Precedence: 1 If there is an identical customization value (for example, number of items), personalization overrides that value. |
All end users with View permission can see these options. Personalization options are available on the chrome surrounding the task flow. When WebCenter task flows are exposed as portlets in Oracle Portal, the Personalization options allow end users to tweak the same visual aspects. |
Implicit Personalization |
Options that are persisted for end users from session to session. Implicit personalization options are not available on the chrome surrounding the task flow, but are actions that can be performed directly in the body of the task flow. For example, sorting and column resizing are implicit personalization options. |
Use these options sparingly and only for options that are frequently changing. Options like column resizing and sorting are available for free from Oracle ADF. |
All end users with View permission on the page can perform personalizations. |
To improve application performance, follow the guidelines in this section while implementing parameters and customization and personalization options in task flows.
At design time (in JDeveloper), you can create parameters by defining them in the task flow definition XML file. At runtime, users with Edit or Customize permission can edit task flow parameters in the Component Properties dialog in Oracle Composer. To provide a good user experience, you must adhere to the following guidelines when creating parameters:
Provide a display name that is meaningful.
Provide a description for each parameter, along with examples and the possible values it can take.
The following example shows the code to define a parameter called layoutStyle
in the task flow definition file:
<input-parameter-definition> <name>layoutStyle</name> <description> Used to control whether the documents must display as a list, with icons, or with document details. Allowed values are list, icon, and detail.</description> <display-name>Layout Style</display-name> </input-parameter-definition>
Users with Edit or Customize permission can access customization options from the chrome surrounding the task flow.
You must adhere to the following guidelines while implementing customization in your task flow:
Customization options must be a subset of the task flow's parameters.
Implement a view fragment within the task flow and expose an outcome to open this view in a separate dialog. For example, the control flow rule to invoke a view called advancedEditPopupView
in a dialog is as follows:
<control-flow-case> <from-outcome>dialog:advancedEditPopup</from-outcome> <to-activity-id>advancedEditPopupView</to-activity-id> </control-flow-case>
Adhering to this guideline is mandatory for new task flows.
Implement a view fragment within the task flow and expose an outcome to transition inline to this view. For example, the control flow rule to invoke a view called advancedEditView
within the same screen is as follows:
<control-flow-case> <from-outcome>advancedEdit</from-outcome> <to-activity-id>advancedEditView</to-activity-id> </control-flow-case>
Although you can implement a task flow in this way, it is recommended that you expose an outcome to open the view in a dialog.
Ensure that customizations are saved in the MDS level set up by the application. Unlike task flow parameters, which are stored in the task flow definition itself, customizations are saved in the Metadata Storage (MDS). If you do not explicitly specify the MDS layer to be used to save task flow customizations, customization metadata and the consuming application metadata may get stored in different layers.
To ensure that customizations are saved to the same layer as application metadata, you must clone the application's MDS session in the task flow's preference file and reference that while configuring customization. For an example of how this is implemented, see Section D.3, "Example of a WebCenter Application Containing a Task Flow Created By Following the Guidelines."
All users viewing the page can access personalization options from the chrome surrounding the task flow in View mode of the page.
You must adhere to the following guidelines while implementing personalization in your task flow:
Ensure that personalization options are a subset of the customization options you define on the task flow.
If a key aspect of the task flow is to show objects—for example, documents, users, or requests—then you must include a personalization option for users to set the maximum number of objects to display.
Implement a view fragment within the task flow, and expose an outcome to open this view in a dialog. For example, the control flow rule to invoke a view called simpleEditPopupView
in a dialog is as follows:
<control-flow-case> <from-outcome>dialog:simpleEditPopup</from-outcome> <to-activity-id>simpleEditPopupView</to-activity-id> </control-flow-case>
Adhering to this guideline is mandatory for new task flows.
Implement a view fragment within the task flow and expose an outcome to transition inline to the view. For example, the control flow rule to invoke a view called simpleEditView
within the same screen is as follows:
<control-flow-case> <from-outcome>simpleEdit</from-outcome> <to-activity-id>simpleEditView</to-activity-id> </control-flow-case>
Although you can implement a task flow in this way, it is recommended that you make a transition to bring this view up as a dialog.
Ensure that personalizations are written to the MDS level set up by the application. Unlike task flow parameters, which are stored in the task flow definition itself, personalizations are saved in MDS. If you do not explicitly specify the MDS layer to be used to save personalizations, personalization metadata and application metadata may get stored in different layers.
To ensure that personalizations are saved to the same layer as application metadata, you must clone the application's MDS session in the task flow's preference file and reference that while configuring personalization. For an example of how this is implemented, see "Example of a WebCenter Application Containing a Task Flow Created By Following the Guidelines"
Users perform implicit personalizations while using the task flow itself, by way of resizing, sorting table columns, and so on. Personalization options in this case are not invoked using dialogs and users may not even be aware that they are actually personalizing a page.
Adhere to the following guidelines while implementing implicit personalization:
Do not overload the task flow with implicit personalization attributes. Select a few key, frequently used attributes to expose as implicit. Infrequently used or complex attributes can be handled with explicit personalization.
Do not implement implicit personalization such that a dialog is invoked. Implicit personalization must be performed in the body of the task flow itself.
As a companion to this document, a sample application was developed using Oracle WebCenter Framework. This sample application, called RecentPages
, is used as an example to illustrate how you can build a near-perfect task flow by adhering to the guidelines in this document. The RecentPages
application contains a customizable page, Welcome.jspx
, which contains a task flow named recent-pages-taskflow-definition
created by following all the required guidelines.
This section only provides a high-level description of how the task flow was implemented. For detailed information about using task flows and Oracle Composer, see the following guides:
Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework, for information about creating task flows.
Oracle Fusion Middleware User's Guide for Oracle WebCenter, for information about editing, customizing, and personalizing task flows in Oracle Composer.
The RecentPages
sample application is available for download from the Oracle WebCenter Suite 11g Demonstrations and Samples page on OTN at:
The RecentPages
WebCenter application contains the following projects:
A Model project
A ViewController project named RecentPagesTaskFlow
that contains the recent-pages-task-flow-definition
task flow
Another ViewController project named WebPages
that contains the JSPX page in which the task flow is consumed
This project contains the task flow created by following the guidelines. The files of significance in this project are as follows:
The recent-pages-task-flow-definition.xml
file
The mainView.jsff
fragment
The simpleEditPopupView.jspx
page
The advancedEditPopupView.jspx
page
The recentPagesBean
Java bean
The Preference
Java bean
This is an Oracle ADF task flow definition containing three views: mainView
, simpleEditPopupView
, and advancedEditPopupView
. The task flow is designed such that mainView
displays a list of recently created pages in the application, simpleEditPopupView
displays a personalization option to all users, and advancedEditPopupView
displays customization options to users with Edit or Customize permission.
The following table breaks down the code in recent-pages-task-flow-definition.xml
and explains each snippet.
The outcomes from mainView
to simpleEditPopupView
and advancedEditPopupView
are called dialog:simpleEditPopupview
and dialog:advancedEditPopupView
respectively. This is to ensure that the views open in separate dialogs, not inline. In addition, this task flow provides Refresh, Previous, and Next outcomes on mainView
. The simpleEditPopupView
and advancedEditPopupView
views provide Save and Cancel outcomes.
The following table describes significant sections of code in the recent-pages-task-flow-definition.xml
file.
Table D-2 Sections Of Code in the Task Flow Definition File
Code | Description |
---|---|
<default-activity>mainView</default-activity> |
Defining the default view for the task flow: |
<managed-bean> <managed-bean-name>recentPagesBean</managed-bean-name> <managed-bean-class>view.RecentPangesBean</managed-bean-class> <managed-bean-scope>pageFlow</managed-bean-scope> </managed-bean> |
Referencing the |
<view id="mainView"> <page>/mainView.jsff</page> </view> <view id="simpleEditPopupView"> <page>/simpleEditPopupView.jspx</page> </view> <view id="advancedEditPopupView"> <page>/advancedEditPopupView.jspx</page> </view> |
Mapping task flow views to pages or page fragments. For example, |
<control-flow-rule> <from-activity-id>mainView</from-activity-id> <control-flow-case> <from-outcome>refresh</from-outcome> <to-activity-id>mainView</to-activity-id> </control-flow-case> <control-flow-case> <from-outcome>dialog:simpleEditPoup</from-outcome> <to-activity-id>simpleEditPopupView</to-activity-id> </control-flow-case> <control-flow-case> <from-outcome>next</from-outcome> <to-activity-id>mainView</to-activity-id> </control-flow-case> <control-flow-case> <from-outcome>previous</from-outcome> <to-activity-id>mainView</to-activity-id> </control-flow-case> <control-flow-case> <from-outcome>dialog:advancedEditPopup</from-outcome> <to-activity-id>advancedEditPopupView</to-activity-id> </control-flow-case> </control-flow-rule> |
Control flow rules from |
<control-flow-rule> <from-activity-id>simpleEditPopupView</from-activity-id> <control-flow-case> <from-outcome>save</from-outcome> <to-activity-id>mainView</to-activity-id> </control-flow-case> <control-flow-case> <from-outcome>cancel</from-outcome> <to-activity-id>mainView</to-activity-id> </control-flow-case> </control-flow-rule> |
Control flow rules from |
<control-flow-rule> <from-activity-id>advancedEditPopupView</from-activity-id> <control-flow-case> <from-outcome>save</from-outcome> <to-activity-id>mainView</to-activity-id> </control-flow-case> <control-flow-case> <from-outcome>cancel</from-outcome> <to-activity-id>mainView</to-activity-id> </control-flow-case> </control-flow-rule> |
Control flow rules from |
Figure D-5 displays a list of recently created pages in the application. At runtime, the list looks like this:
The design features of this view fragment are as follows:
The autoHeightRows
attribute is defined on the table to control the number of items displayed in the table. The task flow then wraps to the height of the items displayed.
The fetchSize
attribute is defined to control the number of items to be fetched from the data source and displayed in the table.
Pagination controls are included to display a message in the format "Items 1-4 of 25
" along with previous and next icons.
Table D-3 describes significant sections of code in the mainView.jsff
fragment.
Table D-3 The mainView Fragment Code
Code | Description |
---|---|
<af:panelGroupLayout id="pgl1" layout="vertical"> <af:outputText value="Shows recent pages in the application" id="ot1"/> |
A single top-level component- |
<af:table value="#{pageFlowScope.recentPagesBean.pages}" var="row" rowBandingInterval="0" id="t1" rowSelection="none" columnBandingInterval="0" width="100%" inlineStyle="border:none;width:100%;" columnStretching="last" horizontalGridVisible="true" verticalGridVisible="false" autoHeightRows="#{pageFlowScope.recentPagesBean.number_of_items_to_show_at_a_time}" contentDelivery="immediate" fetchSize="#{pageFlowScope.recentPagesBean.number_of_items_to_query}"> |
A table component that is a child of the Table attributes:
|
<af:column sortable="false" headerText="#{null}" align="start" id="c1"> <af:panelGroupLayout id="pgl11" styleClass="nowrap" inlineStyle="padding-top:2px; font-weight:bold;"> <af:outputText value="#{row.title}" id="ot4"/> <af:goLink destination="/faces#{row.contentMRef}" text=">>" targetFrame="_blank" id="gl1"/> </af:panelGroupLayout> <af:panelGroupLayout id="pgl10" styleClass="AFFieldTextDisabled nowrap" inlineStyle="padding-top:2px"> <af:outputText value="Created on " id="ot7"/> <af:outputText value="#{row.createDate}" id="ot8"/> <af:outputText value=" by #{row.createdBy}" id="ot9"/> </af:panelGroupLayout> </af:column> |
The table contains a single column that displays a list of pages in the application along with the creation date and author for each page. Implicit personalization capability to sort the table column is turned off. |
<af:panelGroupLayout id="pgl2" halign="end" layout="vertical" inlineStyle="margin:1px" rendered="#{pageFlowScope.recentPagesBean.showPageControl}"> <af:panelGroupLayout id="pgl3"> <af:outputText value="#{pageFlowScope.recentPagesBean.footerText}" id="ot2"/> <af:commandLink id="cl1" actionListener="#{pageFlowScope.recentPagesBean.previous}" disabled="#{not pageFlowScope.recentPagesBean.showPrevious}" action="previous"> <af:image source="#{pageFlowScope.recentPagesBean.showPrevious ? '/adf/webcenter/shuttleleft_ena.png' : '/adf/webcenter/shuttleleft_dis.png'}" id="i1" shortDesc="previous"/> </af:commandLink> <af:commandLink id="cl2" actionListener="#{pageFlowScope.recentPagesBean.next}" disabled="#{not pageFlowScope.recentPagesBean.showNext}" action="next"> <af:image source="#{pageFlowScope.recentPagesBean.showNext ? '/adf/webcenter/shuttleright_ena.png' : '/adf/webcenter/shuttleright_dis.png'}" id="i2" shortDesc="next"/> </af:commandLink> </af:panelGroupLayout> </af:panelGroupLayout> |
Pagination controls to display records beyond those that are displayed in the table. The |
Figure D-6 displays an option to select the number of items to be displayed in the task flow. All users viewing the page can personalize the task flow using this option. The value specified by a user is applicable only for that user's view of the page.
The following table describes significant sections of code in the simpleEditPopupView.jspx
page.
Table D-4 Code in the Personalization Page
Code | Description |
---|---|
<af:panelStretchLayout id="psl1"> <f:facet name="center"> <af:group id="group1"> <af:panelFormLayout id="pfl1"> <af:inputText label="Number of Items to show at a time" id="it1" value="#{pageFlowScope.recentPagesBean.number_of_items_to_show_at_a_time}" columns="3"/> </af:panelFormLayout> <af:panelGroupLayout id="pgl2" layout="horizontal" halign="right" inlineStyle="width:500px;"> <af:commandButton text="Save" id="cb1" action="#{pageFlowScope.recentPagesBean.saveSettings}"/> <af:commandButton text="Cancel" id="cb2" action="cancel" actionListener="#{pageFlowScope.recentPagesBean.cancel}"/> </af:panelGroupLayout> </af:group> </f:facet> </af:panelStretchLayout> |
A single top-level The The |
This page displays customization options to users with Edit or Customize permission. At runtime, this page opens in a separate dialog and displays options to select the number of items to be displayed and number of items to be queried, and a check box to show or hide pagination controls.
The following table describes significant sections of code in the advancedPopupView.jspx
page.
Table D-5 Code in the Customization Page
Code | Description |
---|---|
<af:panelStretchLayout id="psl1"> <f:facet name="center"> <af:group id="group1"> <af:panelFormLayout id="pfl1"> <af:inputText label="Number of Items to show at a time" id="it1" value="#{pageFlowScope.recentPagesBean.number_of_items_to_show_at_a_time}" columns="3"/> <af:inputText label="Number of Items to Query" id="it2" value="#{pageFlowScope.recentPagesBean.number_of_items_to_query}" columns="3"/> <af:selectBooleanCheckbox label="Show Page Control" id="sbc1" value="#{pageFlowScope.recentPagesBean.showPageControl}"/> </af:panelFormLayout> <af:panelGroupLayout id="pgl2" layout="horizontal" halign="right" inlineStyle="width:500px;"> <af:commandButton text="Save" id="cb1" action="#{pageFlowScope.recentPagesBean.saveSettings}"/> <af:commandButton text="Cancel" id="cb2" action="cancel" actionListener="#{pageFlowScope.recentPagesBean.cancel}"/> </af:panelGroupLayout> </af:group> </f:facet> </af:panelStretchLayout> |
A single top-level The The |
This Java bean contains the logic for the following:
Displaying a specific number of items in the table based on user input.
Handling the Save and Cancel events triggered from the simpleEditPopupView
and advancedEditPopupView
pages.
Rendering Previous and Next icons while implementing pagination.
Displaying the pagination message after retrieving the total number of pages.
Referencing the Preference
bean that defines where customizations and personalizations must be saved.
You can find the code for this bean in the RecentPages
application that is available for download from the Oracle WebCenter Suite 11g Demonstrations and Samples page on OTN at:
The following table describes significant sections of code in the recentPagesBean.java
file.
Table D-6 The recentPagesBean Java Bean Code
Code | Description |
---|---|
private String _getPreferenceFileName() { String taskflowId = ControllerContextFwk.getInstanceFwk().getCurrentViewPortFwk().getClientId(); if (taskflowId == null) { taskflowId = ControllerContextFwk.getInstanceFwk().getCurrentViewPortFwk().getParentViewPort().getClientId(); } String preferenceFileName = PREFERENCE_BASE + taskflowId.replace(".", "_") + ".xml"; return preferenceFileName; } private static PageServiceBean getPageServiceBean() { String beanName = "pageServiceBean"; Object bean = null; FacesContext ftx = FacesContext.getCurrentInstance(); bean = ftx.getExternalContext().getRequestMap().get(beanName); if (bean == null) { ELContext elContext = ftx.getELContext(); ExpressionFactory exFactory = ftx.getApplication().getExpressionFactory(); ValueExpression expr = exFactory.createValueExpression(elContext, "#{" + beanName + "}",PageServiceBean.class); bean = expr.getValue(elContext); } return (PageServiceBean) bean; } |
Logic for identifying the task flow and retrieving the instance-level preference file for the currently running task flow. |
public String saveSettings() throws Exception { if (number_of_items_to_query != null && !number_of_items_to_query.isEmpty()) { Preference.setNumberOfItemsToQuery(_getPreferenceFileName(), Integer.parseInt(number_of_items_to_query)); } if (this.number_of_items_to_show_at_a_time != null && !this.number_of_items_to_show_at_a_time.isEmpty()) { Preference.setNumberOfItemsToShow(_getPreferenceFileName(), Integer.parseInt(number_of_items_to_show_at_a_time)); } if (_showPageControl != null) { Preference.setShowPageControl(_getPreferenceFileName(),_showPageControl); } AdfFacesContext.getCurrentInstance().returnFromDialog(null, null); return "save"; } |
Logic to define behavior of Save button in the personalization or customization dialog. Settings are saved in the task flow preference file. |
public void setNumber_of_items_to_show_at_a_time(String number_of_items_to_show_at_a_time) { this.number_of_items_to_show_at_a_time = number_of_items_to_show_at_a_time; } public String getNumber_of_items_to_show_at_a_time() { String query = Integer.toString(Preference.getNumberOfItemsToShow(_getPreferenceFileName())); return query; } |
Logic to populate the |
public void setNumber_of_items_to_query(String number_of_items_to_query) { this.number_of_items_to_query = number_of_items_to_query; } public String getNumber_of_items_to_query() { String query = Integer.toString(Preference.getNumberOfItemsToQuery(_getPreferenceFileName())); return query; } |
Logic to populate the |
public boolean getShowPageControl() { boolean showPageControl = Preference.getShowPageControl(_getPreferenceFileName()); return showPageControl; } public void setShowPageControl(boolean showPageControl) { _showPageControl = showPageControl; } |
Logic to set the |
public List<PageDef> getPages() { PageServiceBean psb = getPageServiceBean(); List<PageDef> pages = psb.getPages(); int start = getStart(); int end = getEnd(); if (start < 0 || start > pages.size()) { start = 0; } if (end < 0 || end > pages.size()) { end = pages.size(); } List<PageDef> tempPages = pages.subList(start, end); return tempPages; } public int getEnd() { String items_to_query = this.getNumber_of_items_to_query(); int offset = Integer.parseInt(items_to_query); int end = getStart() + offset; if (end > this.getTableSize()) { end = getTableSize(); } return end; } |
Logic to retrieve the list of pages to display in the current view of the table. |
public int getTableSize() { int tableSize = -1; try { PageServiceBean psb = getPageServiceBean(); List<PageDef> pages = psb.getPages(); tableSize = pages.size(); } catch (Exception e) { System.out.println(e.toString()); } return tableSize; } |
Logic to set the table size to the number of records retrieved. |
public int getStart() { String items_to_query = this.getNumber_of_items_to_query(); int offset = Integer.parseInt(items_to_query); return (getPageNumber() - 1) * offset; } public int getPageNumber() { Object page_num = RequestContext.getCurrentInstance().getPageFlowScope().get("page_num"); int local_page_num = 1; if (page_num == null || (Integer) page_num <= 0) { local_page_num = 1; } else { local_page_num = (Integer) page_num; } return local_page_num; } |
|
public void cancel(ActionEvent actionEvent) { AdfFacesContext.getCurrentInstance().returnFromDialog(null, null); } |
Logic to define behavior of Cancel button in the personalization or customization dialog. |
public void previous(ActionEvent actionEvent) { int page_num = getPageNumber(); page_num--; if (page_num <= 0) { page_num = 1; } RequestContext.getCurrentInstance().getPageFlowScope().put("page_num", page_num); } |
Logic to define behavior of Previous action in the task flow's pagination control. |
public void next(ActionEvent actionEvent) { int page_num = getPageNumber(); page_num++; String items_to_query = this.getNumber_of_items_to_query(); int offset = Integer.parseInt(items_to_query); int total_page_num = getTotalPageNumber(); if (page_num > total_page_num) { page_num = this.getTableSize() / offset; } RequestContext.getCurrentInstance().getPageFlowScope().put("page_num", page_num); } |
Logic to define behavior of Next action in the task flow's pagination control. |
public boolean isShowPrevious() { int page_num = getPageNumber(); if (page_num <= 1) { return false; } else { return true; } } |
Logic to render Previous icon |
public boolean isShowNext() { int page_num = getPageNumber(); if (page_num >= getTotalPageNumber()) { return false; } else { return true; } } |
Logic to render Next icon. |
public int getTotalPageNumber() { String items_to_query = this.getNumber_of_items_to_query(); int offset = Integer.parseInt(items_to_query); int total_page_num = this.getTableSize() / offset; if (getTableSize() % offset > 0) { total_page_num++; } return total_page_num; } |
Logic to return the total number of pages. |
public String getFooterText() { return "Items " + (this.getStart() + 1) + "-" + this.getEnd() + " of " + " " + this.getTableSize() + " "; } |
Logic for returning pagination text in the format |
This Java bean is a wrapper that provides APIs to get and set attributes in the task flow preference file. It contains the logic for saving personalizations and customizations on this task flow instance in the same MDS layer as that used by the application. In this sample application, site-level customizations are stored in the mds/mdssys/cust/site/site
directory. Therefore, the code in the Preference
bean ensures that the application's MDS session is cloned and the task flow personalizations and customizations are stored in the same directory.
You can find the code for this bean in the RecentPages
application that is available for download from the Oracle WebCenter Suite 11g Demonstrations and Samples page on OTN at:
The following table describes significant sections of code in the Preference.java
file.
Table D-7 The Preference Java Bean Code
Code | Description |
---|---|
private static MDSSession _getClonedMDSSession() { MDSInstance instance = (MDSInstance) ADFContext.getCurrent().getMDSInstanceAsObject(); MDSSession mdsSession = (MDSSession) ADFContext.getCurrent().getMDSSessionAsObject(); mdsSession = instance.createSession(mdsSession.getSessionOptions(), mdsSession.getUserStateHandler()); return mdsSession; } |
Logic to clone the application's MDS session. |
private static MetadataObject _readPreference(MDSSession mdsSession, String preferenceFileName) { MetadataObject mo = null; try { mo = mdsSession.getMutableMO(MOReference.create(preferenceFileName)); } catch (MetadataNotFoundException mnfe) { _LOG.warning("Creating a new preference file " + preferenceFileName); } catch (ReferenceException re) { _LOG.warning("Creating a new preference file " + preferenceFileName); } catch (Exception e) { throw new RuntimeException(e); } // preference file is not available create a new one if (mo == null) { try { DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); builderFactory.setNamespaceAware(true); builderFactory.setValidating(false); DocumentBuilder builder = builderFactory.newDocumentBuilder(); Document document = builder.parse(new ByteArrayInputStream(CONTENTS.getBytes())); mo = mdsSession.createMetadataObject(preferenceFileName, document); mdsSession.flushChanges(); mo = mdsSession.getMutableMO(MOReference.create(preferenceFileName)); } catch (Exception e) { throw new RuntimeException(e); } } return mo; } |
Logic to read the preference file in the MDS session or create one, if required. |
public static void setNumberOfItemsToShow(String preferenceFileName, int numberOfItemsToShow) { MDSSession session = _getClonedMDSSession(); MetadataObject mo = _readPreference(session, preferenceFileName); mo.getDocument().getDocumentElement().setAttribute("numberOfItemsToShow", Integer.toString(numberOfItemsToShow)); _flushChanges(session); } public static int getNumberOfItemsToShow(String preferenceFileName) { MDSSession session = _getClonedMDSSession(); MetadataObject mo = _readPreference(session, preferenceFileName); String show = mo.getDocument().getDocumentElement().getAttribute("numberOfItemsToShow"); return Integer.parseInt(show); } |
Logic to get and set the number of items to show in the table at a time. |
public static void setNumberOfItemsToQuery(String preferenceFileName, int _numberOfItemsToQuery) { MDSSession session = _getClonedMDSSession(); MetadataObject mo = _readPreference(session, preferenceFileName); mo.getDocument().getDocumentElement().setAttribute("numberOfItemsToQuery", Integer.toString(_numberOfItemsToQuery)); _flushChanges(session); } public static int getNumberOfItemsToQuery(String preferenceFileName) { MDSSession session = _getClonedMDSSession(); MetadataObject mo = _readPreference(session, preferenceFileName); String query = mo.getDocument().getDocumentElement().getAttribute("numberOfItemsToQuery"); return Integer.parseInt(query); } |
Logic to get and set the number of items to query from the data source. |
public static void setShowPageControl(String preferenceFileName, boolean showPageControl) { MDSSession session = _getClonedMDSSession(); MetadataObject mo = _readPreference(session, preferenceFileName); mo.getDocument().getDocumentElement().setAttribute("showPageControl", Boolean.toString(showPageControl)); _flushChanges(session); } public static boolean getShowPageControl(String preferenceFileName) { MDSSession session = _getClonedMDSSession(); MetadataObject mo = _readPreference(session, preferenceFileName); String pageControl = mo.getDocument().getDocumentElement().getAttribute("showPageControl"); return Boolean.parseBoolean(pageControl); } |
Logic to get and set whether to show page control on the task flow. |
private static void _flushChanges(MDSSession session) { try { session.flushChanges(); } catch (Exception e) { throw new RuntimeException(e); } } |
Logic to save changes made to the task flow into the MDS session.If a sand box is set up in the MDS session, the changes are saved to the sand box. Else, they are permanently written to MDS. |
private static final String CONTENTS = "<preference numberOfItemsToShow='5' numberOfItemsToQuery='10' showPageControl='true' xmlns='http://xmlns.oracle.com/apps/preference'/>"; } |
Logic to display defaults in the Number of Items to show at a time and |
The RecentPages
project containing all these files is deployed to Oracle ADF and the task flow is then consumed in the customizable Welcome.jspx
page in the WebPages
project.
This project contains the Welcome.jspx
page in which the recent-pages-task-flow-definition
task flow is consumed.
Welcome.jspx
is a customizable page containing a Panel Stretch Layout
component. The top facet of the Panel Stretch Layout
contains a Change Mode Link
and a Page Create task flow. The center facet contains a Page Customizable
with a child Panel Customizable
, which in turn contains a Show Detail Frame
component with the recent-pages-task-flow-definition
task flow.
The stretchContent
and showResizer
attributes on the Show Detail Frame
are set to false
and never
respectively to ensure that this component does not stretch its child task flow.
Also, the refresh
attribute is set to ifNeeded
in the task flow binding. This is to ensure that customizations made to the page at runtime are reflected when users perform a refresh.
The Welcome.jspx
page contains the following code:
<?xml version='1.0' encoding='US-ASCII'?> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:af="http://xmlns.oracle.com/adf/faces/rich" xmlns:pe="http://xmlns.oracle.com/adf/pageeditor" xmlns:cust="http://xmlns.oracle.com/adf/faces/customizable"> <jsp:directive.page contentType="text/html;charset=US-ASCII"/> <f:view> <af:document id="d1"> <af:form id="f1"> <af:panelStretchLayout id="psl1"> <f:facet name="top"> <af:panelGroupLayout layout="horizontal" xmlns:af="http://xmlns.oracle.com/adf/faces/rich" id="pgl2"> <pe:changeModeLink id="cml1"/> <af:spacer width="10" height="10" id="s2"/> <af:region value="#{bindings.pagecreatepage1.regionModel}" id="r1"/> <af:panelGroupLayout id="pgl1"/> </af:panelGroupLayout> </f:facet> <f:facet name="center"> <pe:pageCustomizable id="pageCustomizable1"> <cust:panelCustomizable id="panelCustomizable1" layout="scroll"> <cust:showDetailFrame text="Recent Pages" id="sdf1" stretchContent= "never" showResizer="never"> <af:region value="#{bindings.recentpagestaskflowdefinition1.regionModel}" id="r2"/> </cust:showDetailFrame> </cust:panelCustomizable> <f:facet name="editor"> <pe:pageEditorPanel id="pep1"/> </f:facet> </pe:pageCustomizable> </f:facet> <f:facet name="start"/> <f:facet name="end"/> </af:panelStretchLayout> </af:form> </af:document> </f:view> </jsp:root>
At runtime, the page appears as shown in Figure D-7.
You can add a task flow inside a Show Detail Frame
component and display the task flow's outcomes as actions on the chrome of the parent Show Detail Frame
component. This is possible by defining custom actions on the parent Show Detail Frame
component. You can define custom actions at the instance level where Custom Action
components are added as child components of the Show Detail Frame
, or at the global level where Custom Action
elements are defined in the application's adf-config.xml
file. Global custom actions are enabled on all Show Detail Frame
instances in the application, but are displayed only when a Show Detail Frame
instance contains the task flow as its child.
In this application, custom actions corresponding to the task flow's outcomes, dialog:simpleEditPopupView
and dialog:advancedEditPopupView
, are defined globally in the adf-config.xml
file as follows:
<customizableComponentsSecurity xmlns="http://xmlns.oracle.com/adf/faces/customizable/config"> <enableSecurity value="true"/> <customActions> <customAction action="refresh" text="Refresh" shortDesc="Refresh" location="menu" rendered="true" icon="/adf/pe/images/refresh_ena.png"/> <customAction action="dialog:simpleEditPoup" text="Simple Edit" shortDesc="Simple Edit" location="menu" rendered="#{!changeModeBean.inEditMode}" icon="/adf/pe/images/editproperties_ena.png"/> <customAction action="dialog:advancedEditPopup" text="Advanced Edit" shortDesc="Advanced Edit" location="menu" rendered="#{changeModeBean.inEditMode}" icon="/adf/pe/images/editproperties_ena.png"/> </customActions> </customizableComponentsSecurity>
This configuration results in the following behavior at runtime:
All users see a Simple Edit action on the chrome surrounding the task flow while viewing the page.
Clicking this action displays the personalization option in a separate dialog.
Users with Edit or Customize permission see an Advanced Edit action on the chrome surrounding the task flow while editing the page.
Clicking this action displays customization options in a separate dialog.
In WebCenter application pages containing task flows, task flow design can have a significant impact on application performance. Also, slow response time and inconsistent UI can lead to an unpleasant experience for application users. To ensure better performance and a good user experience for WebCenter application users, follow the guidelines in this document while implementing task flows to be consumed in the application.