Oracle® SOA Suite Developer's Guide 10g (10.1.3.1.0) Part Number B28764-01 |
|
|
View PDF |
When you need to display data on a Web page, ADF data binding allows you to easily and declaratively create a table bound to data using ADF Faces components. By default, users will be able to scroll through row sets, and select a row. You then can create a new page that shows the details of the selected row, and add the navigation between the two pages. ADF data binding will automatically display the details of the selected row, without need for any additional code.
For example, Figure 9-9 shows the BrowseItems
page in the SOADEMO-CLIENT application. Users can select a product then click the View Details button to navigate to the SelectItem
page, where they can view details for the selected item.
Figure 9-10 shows the SelectItem
page for the selected product.
To create a page that displays a collection of data, and then link to a page that displays the details of the selected item, you need to:
Create a navigation diagram for the two pages.
On the page that will display the collection of items (the browse page), create an ADF Faces table to display the collection and add a button to navigate to the details page.
On the details page, create a form that displays the details.
Creating a navigation diagram allows you to both create pages and create the navigation between them.
To create a navigation diagram:
Follow the steps for creating a web page, as documented in Section 9.3.1, "How to Create a JSF Web Page" to create both the browse page and the detail page.
For example, for the SOADEMO-CLIENT, you would create a JSP for the BrowseItems
page and the SelectItem
page, as shown in Figure 9-11.
From the Component Palette click the JSF Navigation Case component (as shown in Figure 9-12), click on the browseItems.jsp icon and then the selectItem.jsp icon, to create a new navigation case between the two pages.
By default, the outcome value is set to success, as shown in Figure 9-13.
Double-click the success
outcome text, and change it something more meaningful, such as details
.
Create another navigation case that goes from the selectItem
page back to the browseItems
page. Rename this outcome value to something more meaningful, such as back
.
Tip: You can easily create more readable diagrams by dragging the JSF Navigation Case line to create angles. |
Now that the navigation cases are created, you can place a command component on the first page, set the action attribute to the value of the outcome, and the user will navigate to the second page. For example, if you place a command button on the browseItems
page and set its action attribute to details
, the user will navigate to the selectItem
page.
When you create a navigation rule using the JSF Navigation Modeler or the JSF Configuration Editor, JDeveloper automatically adds the navigation rule elements to the faces-config.xml
file for you.
Example 9-4 shows two navigation rules defined in the faces-config.xml
file. The first rule navigates from the browseItems
page to the selectItem
page when the outcome specified in the action
attribute of an activated navigation component is details
. The second rule navigates from the selectItem
page back to the browseItems
page when the action
attribute of an activated navigation component is return
.
Example 9-4 Navigation Rules in the faces-config.xml File
<navigation-rule> <from-view-id>/retailclient/browseItems.jsp</from-view-id> <navigation-case> <from-outcome>details</from-outcome> <to-view-id>/retailclient/selectItem.jsp</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/retailclient/selectItem.jsp</from-view-id> <navigation-case> <from-outcome>return</from-outcome> <to-view-id>/retailclient/browseItems.jsp</to-view-id> </navigation-case> </navigation-rule>
The Sun JSF Reference Implementation reads the navigation rules in the faces-config.xml
file and calls the NavigationHandler
class, which evaluates the navigation rules and determines which page to display. The handler first finds all rules for the page from which the navigation is originating. It then checks the outcome either returned by an action method or set as the outcome string for the action property of the component, to determine the correct rule to use.
When using the navigation modeler to create and maintain page navigation, be aware of the following features:
Changes to navigation rules made directly in the faces-config.xml
file using the XML editor or made in the configuration editor usually refresh the navigation modeler. Each JSF configuration file has its own navigation modeler diagram. If the information in a navigation diagram does not match the information in its faces-config.xml
file, you can manually refresh the diagram by right-clicking within the diagram and choosing Diagram > Refresh diagram from faces-config.
When you delete a navigation case on the diagram, the associated navigation-case
element is removed from the faces-config.xml
file. If you remove all the cases in a rule, the navigation-rule
element remains in the faces-config.xml
file. You can remove the rule directly in the faces-config.xml
file.
When you edit the label for the navigation case on the diagram, the associated navigation-case
element is updated in the faces-config.xml
file. You cannot change the destination of the navigation case in the diagram. You can, however, change the destination of a navigation case in the JSF Configuration Editor or directly in the faces-config.xml
file itself.
When you delete a page icon from the navigation diagram, the associated page file is not deleted the from the Web Content folder in the ViewController
project in the Application Navigator.
When you edit pages manually, JDeveloper does not automatically update the navigation diagram or the associated faces-config.xml
file. Conversely, when you make changes to a page flow that affect the behavior of an existing page, JDeveloper does not automatically update the code in the page. To coordinate the navigation diagram with web page changes, right-click within the page in the navigation diagram and choose Diagram > Refresh Diagram from All Pages.
The navigation modeler diagram is the default editor for the faces-config.xml
file. If you have a large or complex application, loading the diagram may be slow, because the file may be large. If you do not want JSF diagram files to be created for your JSF configuration files, use the Tools > Preferences > File Types > Default Editor > JSF Configuration File option to change the default editor. If you change the default editor before opening the faces-config.xml
file for the first time, no diagram file is created unless you specifically request one.
You can display an entire collection of data by dragging the returned collection of a method represented on a data control onto a JSF page as a table.
To add collection data to a page:
Open a JSF page in the visual editor.
From the Data Control Palette, select a method return that returns a collection.
For example, to create a table that displays all products, you drag the returned Product
collection of the findAllProduct
method. Figure 9-14 shows the Product
collection in the Data Control Palette.
Drag the method return onto the JSF page, and from the context menu, choose the appropriate table.
When you drag the collection, you can choose from the following types of tables:
ADF Table: Allows you to select the specific attributes you wish your editable table columns to display, and what UI components to use to display the data. By default, each attribute on the collection object is displayed in an inputText
component, thus enabling the table to be editable.
ADF Read-Only Table: Same as the ADF Table; however, each attribute is displayed in an outputText
component.
ADF Read-Only Dynamic Table: The attributes returned and displayed are determined dynamically. This component is helpful when the attributes for the corresponding object are not known until runtime, or you do not wish to hardcode the column names in the JSF page. For example, if you have a method that returns a polymorphic collection (i.e. getAnimals()
can return a collection of mammals or a collection of birds), the dynamic table can display the different attributes accordingly.
Note: You can also drop a collection as an ADF Master Table, Inline Detail Table. For more information, see Oracle Application Development Framework Developer's Guide. |
From the ensuing Edit Table Columns dialog, you can do the following:
Change the display label for a column. By default, the label is bound to the label
property of the table binding. This binding to the property allows you to change the value of the label text once and have it appear the same on all pages that display the label. In this dialog, you can instead enter text or an EL expression to bind the label value to something else, for example, a key in a resource file.
For example, the heading for the description column in the table on the browseItems
page is bound to the label property of the corresponding attribute binding:
#{bindings.findAllProduct1.labels.description}
Change the attribute binding for a column.
For example, you can change the description column to instead be bound to the listPrice
attribute. Note the following:
If you change the binding, the label for the column also changes.
If you change the binding to an attribute currently bound to another column, the UI component changes to a component different from that used for the column currently bound to that attribute.
If you simply want to rearrange the columns, you should use the order buttons. See the fourth bullet point below for more information.
Change the UI component used to display an attribute. The UI components are either inputText
or outputText
and are set based on the table you selected when you dropped the collection onto the page. You can change to the other component using the dropdown menu. If you want to use a different component, such as a command link or button, you need to use this dialog to select the outputText
component, and then in the Structure window, add that other UI component (such as a command link) as a parent to this component.
Change the order of the columns using the order buttons.
Add a column using the New button. Doing so adds a new column at the bottom of the dialog and populates it by default with values from the next sequential attribute in the collection. You then need to edit the values. You can only select an attribute associated with the object to which the table is bound.
Delete a column using the Delete button. Doing so deletes the column from the table.
Add a tableSelectOne
component to the table's selection
facet by selecting Enable selection. In order to navigate to a page that displays details for a selected row in the table, you must select this option.
Allow sorting for all columns by selecting Enable sorting.
Note: If you choose to enable sorting, the table can only sort through the number of objects returned by the iterator, as determined by the iteratorsrangeSize attribute. For more information about iterators and the rangeSize attribute, refer to the Oracle Application Development Framework Developer's Guide. |
To add a command button that will navigate to the details page, in the Structure window, select the commandButton
for the tableSelectOne
component, as shown in Figure 9-15.
Note: This component will only be present if you selected the Enable Selection option when you created the table in the previous step. |
In the Property Inspector, use the Action
attribute's dropdown menu to choose the outcome created in the navigation diagram in the previous set of steps. For example, if you created an outcome named details
between the two pages, you would select details. Figure 9-16 shows the Property Inspector with this outcome selected for the Action attribute.
Now when users click this button, they will navigate to the page defined in the navigation case, in this case, the selectItem
page.
When you create an ADF web application by dragging and dropping items from the Data Control Palette, JDeveloper creates and registers all the files needed to run the application. Specifically, JDeveloper:
Creates a DataBindings.cpx
file in the view package in the Application Sources directory (if one does not already exist), and adds an entry for any pages.
The DataBindings.cpx
file defines the binding context for the application. It maps individual pages to their corresponding page definition files and registers the data controls used by those pages. The data controls are defined in the DataControls.dcx
file.
Registers the ADF binding filter in the web.xml
file.
The ADF binding filter preprocesses any HTTP requests that may require access to the binding context.
Registers the ADF phase listener in the faces-config.xml
file.
Adds the following ADF runtime libraries to the project properties of the view project:
ADF Model Runtime (adfm.jar
)
ADF Controller (adf-controller.jar
)
Adds a page definition file (if one does not already exist for the page) to the page definition subpackage, the name of which is defined in the ADFm settings of the project properties. The default subpackage is view.pageDefs
in the Application Sources
directory.
The page definition file (<
pageName
>
PageDef.xml
) defines the ADF binding container for each page in an application's view layer. The binding container provides runtime access to all the ADF binding objects.
Configures the page definition file, which includes adding definitions of the binding objects referenced by the page.
Example 9-5 shows the page definition file created when you drop the Product
collection. The method iterator references the return of the findAllProduct
method. This is what allows the page to access data for every instance returned. The method action binding is what actually invokes the method. The table binding references the results in the iterator, and allows the data for each attribute to be displayed.
Example 9-5 Page Definition Code
<executables> <methodIterator id="findAllProductIter" Binds="findAllProduct.result" DataControl="ProductsFacadeLocal" RangeSize="10" BeanClass="oracle.soademo.clientmodel.Product"/> </executables> <bindings> <methodAction id="findAllProduct" InstanceName="ProductsFacadeLocal.dataProvider" DataControl="ProductsFacadeLocal" MethodName="findAllProduct" RequiresUpdateModel="true" Action="999" ReturnName="ProductsFacadeLocal.methodResults.ProductsFacadeLocal_ dataProvider_findAllProduct_result"/> <table id="findAllProduct1" IterBinding="findAllProductIter"> <AttrNames> <Item Value="category"/> <Item Value="description"/> <Item Value="id"/> <Item Value="listPrice"/> <Item Value="name"/> <Item Value="prodid"/> <Item Value="producer"/> </AttrNames> </table> </bindings>
Adds prebuilt components to the JSF page.
When you drop a table onto a JSF page, JDeveloper creates a table that contains a column for each attribute on the object to which it is bound. To do this, JDeveloper inserts an ADF Faces table
component. This component contains an ADF Faces column
component for each attribute named in the table binding. Each column then contains either an input
or outputText
component bound to the attribute's value. Each column's heading attribute is bound to the label
property for each attribute on the table binding. Example 9-6 shows some of the code generated when you drop the Product
return as a table.
Example 9-6 JSF Page Code
<af:table value="#{bindings.findAllProduct1.collectionModel}" var="row"
rows="#{bindings.findAllProduct1.rangeSize}"
first="#{bindings.findAllProduct1.rangeStart}"
emptyText="#{bindings.findAllProduct1.viewable ? \
'No rows yet.\' : \'Access Denied.\'}">
<af:column headerText="#{bindings.findAllProduct1.labels.category}"
sortProperty="category" sortable="false">
<af:outputText value="#{row.category}"/>
</af:column>
<af:column headerText="#{bindings.findAllProduct1.labels.description}"
sortProperty="description" sortable="false">
<af:outputText value="#{row.description}"/>
</af:column>
...
</af:table>
An ADF Faces table itself iterates over the data accessed by the iterator binding. In order to do this, the table wraps the result set from the iterator binding in an oracle.adf.view.faces.model.CollectionModel
object. As the table iterates, it makes each item in the collection available within the table
component using the var
attribute.
In Example 9-6, the table iterates over the collection from the findAllProduct1
table binding, which in turn references the findAllProductIter
iterator binding. The iterator binding is what determines the current data object. When you set the var
attribute on the table to row
, each column then accesses the current data object for the current row presented to the table tag using the row
variable, as shown for the value of the outputText
tag:
<af:outputText value="#{row.category}"/>
Adds all the libraries, files, and configuration elements required by ADF Faces components, if ADF Faces components are used.
When a page contains ADF bindings, at runtime the interaction with the business services initiated from the client or controller is managed by the application through a single object known as the Oracle ADF binding context. The ADF binding context is a container object that contains a list of data controls and data binding objects derived from the Oracle ADF Model layer.
The ADF life cycle creates the Oracle ADF binding context from the DataControls.dcx
, DataBindings.cpx
, and page definition files, as shown in Figure 9-17. The DataControls.dcx
file defines all the data controls available to the application. The DataBindings.cpx
file references the data controls that are currently being used by pages in the application and maps the binding containers, which contain the binding objects defined in the page definition files, to web page URLs. The page definition files define the binding objects used by the application pages. There is one page definition for each page.
Using the table created from the Product
return as an example, the binding container invokes the findAllProductIter
method iterator, which in turn invokes the findAllProduct
method that returns the Product
collection. The iterator then iterates over the data and makes the data for the first found record available to the UI component by placing it in the binding container. Because there is a binding for the findAllProduct1
table in the page definition that can access the value from the iterator (see Example 9-5), and since the UI component is bound to the findAllProduct1
binding using an EL expression (#{bindings.findAllProduct1.collectionModel}
), that data is displayed by that component.
For more information about what specifically happens at runtime with ADF tables, refer to the Oracle Application Development Framework Developer's Guide.
You can display the detailed data of an item returned by a method by dragging the returned collection as a form. By using a read-only form, only the currently selected data will be displayed.
To add a form to display details of an item:
Open a JSF page in the visual editor.
From the Data Control Palette, select a method return that returns a collection.
For example, to create a form that displays information about a product, you drag the product return form the findAllProduct
method, as shown in Figure 9-18. This method creates a form with data already populated in the text fields.
Drag the collection onto the page, and from the context menu choose the type of form to display data for the object. For a form, you are given the following choices:
ADF Form: Launches the Edit Form Fields dialog that allows you to select individual attributes instead of creating a field for every attribute by default. It also allows you to select the label and UI component used for each attribute. By default, ADF inputText
components are used, except for dates, which use the selectInputDate
component. Each inputText
component contains a validator tag that allows you to set up validation for the attribute.
You can elect to include navigational controls that allow users to navigate through all the data objects in the collection. For additional help in using the dialog, click Help. All UI components are placed inside a panelForm
component.
ADF Read-Only Form: Same as the ADF Form, but by default, outputText
components are used. Since the form is meant to display data, no validator
tags are added. The label
attribute is populated for each component. Attributes of type Date
also use the outputText
component. All components are placed inside panelLabelAndMessage
components, which are in turn placed inside a panelForm
component.
Note: You can also drop a collection as an ADF Creation Form. For more information, see Oracle Application Development Framework Developer's Guide. |
The form will now display the data for the item selected in the table.
Dropping a form from the Data Control Palette has the same effect as dropping a table. For more information, see Section 9.5.6, "What Happens When You Add a Collection to a Page". Briefly, JDeveloper does the following:
Creates the bindings for the form and adds the bindings to the page definition file. Example 9-7 shows the page definition code created when you drop the Product
return as a form.
Example 9-7 Page Definition Code for a Form
<executables> <methodIterator id="findAllProductIter" Binds="findAllProduct.result" DataControl="ProductsFacadeLocal" RangeSize="10" BeanClass="oracle.soademo.clientmodel.Product"/> </executables> <bindings> <methodAction id="findAllProduct" InstanceName="ProductsFacadeLocal.dataProvider" DataControl="ProductsFacadeLocal" MethodName="findAllProduct" RequiresUpdateModel="true" Action="999" IsViewObjectMethod="false" ReturnName="ProductsFacadeLocal.methodResults.ProductsFacadeLocal_ dataProvider_findAllProduct_result"/> <attributeValues id="category" IterBinding="findAllProductIter"> <AttrNames> <Item Value="category"/> </AttrNames> </attributeValues> <attributeValues id="description" IterBinding="findAllProductIter"> <AttrNames> <Item Value="description"/> </AttrNames> </attributeValues> ... </bindings>
Note that the method iterator and the method binding are the same for the table as for the form. However, instead of using a table binding, each attribute has its own binding.
Adds the necessary code for the UI components to the JSF page.
The attributes on the UI components (such as value
) are bound to properties on that attribute's binding object (such as inputValue
). Example 9-8 shows the code generated on the JSF page when you drop the Product
collection for the findAllProduct
method as a default ADF Form.
Example 9-8 JSF Code for an ADF Form
<af:panelForm> <af:panelLabelAndMessage label="#{bindings.category.label}"> f:outputText value="#{bindings.category.inputValue}"/> </af:panelLabelAndMessage> <af:panelLabelAndMessage label="#{bindings.description.label}"> <af:outputText value="#{bindings.description.inputValue}"/> </af:panelLabelAndMessage> <af:panelLabelAndMessage label="#{bindings.id.label}"> <af:outputText value="#{bindings.id.inputValue}"> <f:convertNumber groupingUsed="false" pattern="#{bindings.id.format}"/> </af:outputText> </af:panelLabelAndMessage> ... </af:panelForm>