Skip Headers

Oracle® Application Development Framework Development Guidelines Manual 10g Release 2 (10.1.2) Part No. B14362-02 |
| Library | Product | Contents

Previous | Next |

# 5 Overview of Oracle ADF Integration with Struts

The Oracle Application Development Framework (Oracle ADF) extends the Struts framework to integrate with the Oracle ADF model layer. Oracle ADF provides a pure Struts integration, completely consistent with the Struts specification, that simplifies and speeds up web application development. JDeveloper fully supports the use of Struts, providing both visual and XML editors for the Struts configuration file, as well as other features that simplify building applications that use either plain Struts or Struts integrated with the Oracle ADF.

When you start a project using Struts technology, JDeveloper creates all of the basic Struts components for you, including the required definitions in the `web.xml` file, the Struts configuration file itself, and a resource file for use by Struts internationalization features.

This chapter provides an overview of the integration of Oracle ADF and Struts.

## 5.1 Summary

- Highlights of the Struts Framework

- Oracle ADF Extensions to Struts

  - Oracle ADF Data Action and Data Forward Action Classes

  - Oracle ADF Lifecycle

  - Named Events in Oracle ADF

  - Oracle ADF Data Action Mapping Class

  - Oracle ADF Data Form Bean

  - Oracle ADF Binding Filter

- Struts Design Time Integration with Oracle ADF

  - Struts Page Flow Diagram

  - Source View Tab

  - Property Inspector Integration with the Struts Configuration File

  - Design Time Rendering of Struts Tag Libraries

  - Interactive Code Insight for JSP Code Editing

- Struts Runtime Integration with the Oracle ADF Model Layer

- Data Pages and Data Actions in the Databound Struts Page Flow

  - Working with Data Pages

  - Working with Data Actions

- Best Practices

  - When to Use a Data Page or Data Action

  - Adding Business Service Methods to a Data Action

  - When to Subclass the DataAction or DataForwardAction Class

  - When to Use an Oracle ADF Lifecycle Plugin

  - Summary of Best Practices in Working with Oracle ADF/Struts Integration

## 5.2 Highlights of the Struts Framework

The Apache Software Foundation's Struts framework helps web application developers create applications that implement the Model-View-Controller (MVC) design pattern. This design pattern allows web application developers to cleanly separate the display code (for example, HTML and tag libraries) from flow control logic (the Struts controller and action classes) from the data model to be displayed and updated by the application.

The model is the repository for the application data and business logic. Part of the model's function is to retrieve data from, and persist data to, the enterprise information system, but it is also responsible both for exposing the data in such a way that the view can access it and for implementing a business logic layer to validate and consume the data entered through the view. At the application level, the model acts as a validation and abstraction layer between the user interface and the business data that is displayed. For more information about working with the model layer using Oracle ADF, see Overview of the Oracle ADF Model Layer.

The view is responsible for rendering the model data. The view code itself does not hard-code application or navigation logic, although it may contain some logic to carry out tasks like conditional data display based on a user's role. When an end user carries out an action within the HTML page that is eventually rendered from the view, an event is submitted to the controller, and it is up to the controller to work out what to do next. Struts applications typically use JSP pages for the view layer, but you can also use other technologies. For information about working with the view layer in Oracle ADF, see Overview of Oracle ADF Data Binding in View Technologies.

Every user action carried out in the view is submitted through the controller, which, based on the contents of the request from the browser and the controller's own programming or metadata, decides what to do next. In Struts, the base controller functionality is implemented in the action servlet. The integration of Oracle ADF and Struts includes extensions to several other controller components that provide major benefits to developers. Here is a brief description of their base functionality:

Action class

The `org.apache.struts.action.Action` class is an extension of the `ActionServlet` class that performs one or more operations in response to a client request. The action class processes a request using its `execute()` method and returns an action forward object that identifies where control should be forwarded (a web page or another action, for example) to supply the appropriate response. By default, the `execute()` method returns `null`, so you must always subclass the base `Action` class in a plain Struts application.

Action mapping class

An action mapping provides the information the Struts controller servlet needs to know about what action class to call when the controller receives a request. Struts developers define this information as `<action>` elements in the Struts configuration file, an XML file. The Struts framework parses this file and creates the appropriate objects initialized to the correct default values. The `org.apache.struts.action.ActionMapping` class represents the information specified in the `<action>` elements.

Action forward class

The `org.apache.struts.action.ActionForward` class is the destination to which the controller sends control when an action class is executed. Like action mappings, action forwards are defined in the Struts configuration file, typically as `<forward>` elements within an `<action>` element.

For detailed information about the Struts architecture and base classes, see `http://struts.apache.org/index.html`.

## 5.3 Oracle ADF Extensions to Struts

The integration of Oracle ADF and Struts comprises the following key elements:

- Oracle ADF Data Action and Data Forward Action Classes

- Oracle ADF Lifecycle

- Named Events in Oracle ADF

- Oracle ADF Data Action Mapping Class

- Oracle ADF Data Form Bean

- Oracle ADF Binding Filter

### 5.3.1 Oracle ADF Data Action and Data Forward Action Classes

The `DataAction` and `DataForwardAction` classes are core components of the integration of Oracle ADF and Struts. They are subclasses of the base Struts `Action` class that prepare the Oracle ADF model binding context for databound web pages. Your databound web application works with these classes through entries in the Struts configuration file.

Unlike the base Struts `Action` class, these classes offer a set of functionality that often makes it possible to use them without further subclassing. When you do need to subclass, using these classes simplifies the coding process. They implement a pluggable request-handling lifecycle that is Oracle ADF binding container–aware and fully customizable.

The fully qualified classnames are `oracle.adf.controller.struts.actions.DataAction` and `oracle.adf.controller.struts.actions.DataForwardAction` (represented in the Page Flow Diagram as a data page) to prepare the binding context for databound web pages. The `DataForwardAction` and `DataAction` classes extend `org.apache.struts.action.Action`.

Note: `DataForwardAction` is a subclass of `DataAction` and is different only in that it is used with the data page component, rather than with the data action component, in the Page Flow Diagram. For more information about these components, see Data Pages and Data Actions in the Databound Struts Page Flow.

### 5.3.2 Oracle ADF Lifecycle

In the integration of Oracle ADF with Struts, the `DataAction` and `DataForwardAction` classes implement the Oracle ADF lifecycle interface. This interface provides the code necessary to connect the action of a web page to the ADF model data bindings. At runtime, the lifecycle object calls the correct binding container needed for a web page and tells it to prepare the data to be rendered. The binding container pools the data and stores it locally before rendering the page. By avoiding additional round trips to the database before a web page is rendered, the lifecycle object improves application performance during the rendering process.

The `handleLifecycle()` method does most of the work in the lifecycle by calling a series of operations in a set order. The following diagram shows the steps performed by the method in the `oracle.adf.controller.lifecycle.PageLifecycle` class. Following the diagram is a table that describes what happens in each step.

The following table describes the `handleLifecycle()` method diagram in detail:

Step | Description
--- | ---
Initialize context. | The first step that the method `handleLifecycle()` performs is to initialize the lifecycle context. The context object holds the value of the associated request, binding container, and lifecycle objects. In a Struts application, the context is an instance of `oracle.adf.controller.struts.actions.DataActionContext`, a subclass of `LifecycleContext`. The method `handleLifecycle()` calls the lifecycle context `initialize()` method.
Build event list. | Next, `handleLifecycle()` builds the list of events to be performed by retrieving them from the request object with the lifecycle method `buildEventList()`.
Prepare model data bindings if they exist. | At this point, the method `handleLifecycle()` checks for model data bindings by calling `getAttribute("bindings")` on the binding container retrieved in step 1. If model data bindings do exist, this phase of the lifecycle prepares the data model to receive possible updates from the request. This phase also validates the state token. Note that a lifecycle instance may not have associated model bindings. Instead, the lifecycle can call events that operate only in the user interface. You may want to call custom page navigation events that do not use data bindings. For example, you might want to create an event associated with a help button that would take the user to an HTML page for the web application. If there are no associated model bindings, `handleLifecycle()` skips to step 7.
Check to see if model updates are allowed. | Some events should not be allowed to update the model. If the event is performing a rollback on data changes, for example, you do not allow model updates. The method `handleLifecycle()` calls `shouldAllowModelUpdate()` on the lifecycle instance to see whether model updates are allowed. If the user is allowed to update model data from the user interface, the method `handleLifecycle()` goes to the next step. If model updates are not allowed, `handleLifecycle()` skips to step 7.
Process model updates. | At this point, `handleLifecycle()` collects the new data values from the request and updates the model with them.
Validate model updates. | At this point, `handleLifecycle()` validates updates to the model by calling `validateInputValues()` on the binding container associated with the current lifecycle instance.
Handle model and UI events | Next, `handleLifecycle()` calls `processComponentEvents()` on the lifecycle instance. This method handles both named events, which you create and name yourself, and events tied to the data bindings you drop on a page (action bindings). For more information about creating your own named events, see Named Events in Oracle ADF.
Invoke custom methods | You can drag and drop methods onto a data action or data page without having to subclass the parent class, as described in Adding Business Service Methods to a Data Action. The method `handleLifecycle()`calls `invokeCustomMethod()` on the lifecycle instance to execute these custom methods at this point.
Refresh binding controls | This step notifies the binding container associated with the current lifecycle instance that all model updates for the action or page are complete. At this point, the method `handleLifecycle()` calls `refreshControl()` on the binding container instance.
Dispatch to forward | At this point, the method `handleLifecycle()` calls `findForward()` on the lifecycle instance. For Struts applications, `findForward()` looks for the value of the `<forward>` element in the `struts-config.xml` file, which it passes to the `execute()` method of the data action class or subclass.

You can override lifecycle methods to customize the behavior of your Oracle ADF application. For a Struts-based application, you can override the main lifecycle methods by subclassing the `DataAction` or `DataForwardAction` class. When you want to modify the lifecycle to perform certain behaviors across the application, or if you want to change the behavior of a method that may be called repeatedly by a step in the lifecycle, you must subclass the lifecycle itself. For more information, see When to Use an Oracle ADF Lifecycle Plugin.

Note: You cannot change the order of the lifecycle phases listed in the preceding table.

### 5.3.3 Named Events in Oracle ADF

An event is a specific operation that is executed for a specific command. An event is typically executed by a button or link in a web page. For example, when a user clicks the Next button, that click triggers the Next event. Next is the event name: naming an event simplifies the process of calling events and creating event handlers. When a command on a web page triggers an event, an event handler performs the work. Oracle ADF provides an easy way to build commands and event handlers for working with events in your web applications. For example, you can:

- Use events to execute action binding model operations. When you create and register business services for an application, the Data Control Palette displays the operations available from the business service. If you create or customize an operation in the business service, you do not have to do any work in the controller layer. You simply have to drag the operation to the web page or data action.

- Write a custom method that overrides an existing method in the action bindings. For example, if you want to override the next operation to behave differently, then you add code to the data action. The data action looks for a custom method first, then looks to see whether the method exists in the action bindings. This way, if a customized method exists, the data action finds it first.

- Develop actions that are independent of the model layer, that is, data actions that do not need to call an action binding to perform their operations. For example, if you want to include a help button in your web pages that takes the user to a help topic for your web application, you can do this with a named event.

- Use events to forward to a new page without subclassing the `DataAction` or `DataForwardAction` class. You can use a named event to define the forward for a data action or data forward action in a web page by making the the value of the forward `name` attribute for the action identical to the name of the associated event in the web page. When Oracle ADF action subclasses encounter an event that is defined neither in the action subclass nor in the action bindings, they assume that the event is the name of a forward.

  Note: Both the Oracle ADF data action classes and Oracle ADF UIX use events. In general, when you combine Oracle ADF UIX and Struts in a single application, the data action class takes precedence over the UIX servlet in managing events. If the data action class does not recognize the event as one it knows how to handle, the UIX servlet handles the event.

### 5.3.4 Oracle ADF Data Action Mapping Class

The Struts action mapping class represents the information configured in the `<action>` element in the Struts configuration file. The `DataActionMapping` class extends the basic Struts data action mapping class to support a number of custom action properties related to ADF data binding. The `DataActionMapping` class determines which lifecycle class should be used based on the type of page (JSP or UIX, for example) to be rendered by the action. It also defines and handles the following additional properties for the `DataAction` and `DataForwardAction` classes:

- `modelReference` is the name of the binding container the data action should use.

- `methodName` is the name of an action binding with a custom method that is to be executed in the data action during the `invokeCustomMethod()` lifecycle phase.

- `numParams` is the number of parameters for a custom method.

- `paramNames` is the EL expressions that retrieve the value for each method parameter.

- `resultLocation` is the EL expression representing the location where the method result is to be stored.

If you want to add additional `<set-property>` elements to the `<action>` element metadata, you need to subclass the `DataActionMapping` class to handle the additional elements.

The `DataActionMapping` class is in the `oracle.adf.controller.struts.actions` package. This class extends the `org.apache.struts.action.ActionMapping` class.

### 5.3.5 Oracle ADF Data Form Bean

By default, Struts forms in an Oracle ADF web application use a data form bean. The data form bean dynamically makes the attributes for any binding container available to the form and saves you the work of creating the `ActionForm` beans required by your applications.

When you drag and drop a data binding from the Data Control Palette to a JSP page, at runtime Oracle ADF automatically refers to the data form bean for the application. For each value binding in the associated binding container, JDeveloper dynamically creates the `get` and `set` methods for each binding.

Note: JDeveloper does not populate the `<form-property>` element in the `struts-config.xml` file when it uses the data form bean. Your application retrieves the necessary values from the associated binding container.

At runtime, the associated action class, either a `DataAction` or `DataForwardAction` instance or subclass, uses the data form bean to populate the form and submit updates, if any.

Here is a code snippet showing the `<html:form>` tag to illustrate the data form bean behavior:

    <html:form action="MyDataAction.do">
         <html:text property="dname">
    </html:form>

At runtime, the `MyDataAction` class needs to resolve the `dname` property. In Oracle ADF, the HTML form is associated with a data action, which is tied to the data form bean. The form goes to the data form bean to resolve the property. The data form bean in turn asks the binding container if it has a binding with that name. The binding container returns the binding if it exists, and the data form bean populates the HTML form with that binding's value.

Warning: Do not modify, rename, or remove the `DataForm` class or the `DataForm` entries in the `struts-config.xml` file. To work correctly throughout the application, this bean name must not be changed in any way. DataForm is a reserved form bean name in Oracle ADF.

The data form bean is an instance of `oracle.adf.controller.struts.forms.BindingContainerActionForm` (a subclass of `org.apache.struts.action.ActionForm` that implements the `apache.commons.beanutils.DynaBean` interface).

### 5.3.6 Oracle ADF Binding Filter

Oracle ADF web applications use the Oracle ADF binding filter to preprocess any HTTP requests that may require access to the binding context. The binding filter is a servlet filter that does the following:

- Overrides the character encoding at filter initialization time with the name specified as a filter parameter in the `web.xml` file. The parameter name of the filter `<init-param>` is `encoding`.

- Initializes the Oracle ADF model binding context for a user's HTTP session (for more information about the binding context, see Struts Runtime Integration with the Oracle ADF Model Layer).

- Serializes incoming HTTP requests from the same browser (from framesets, for example) to prevent multithreading problems.

- Notifies data control instances that they are about to receive a request, allowing them to do any necessary pre-request setup.

- Notifies data control instances after the response has been sent to the client, allowing them to do any necessary post-request cleanup.

JDeveloper creates the ADF binding filter and automatically configures it in the application's `web.xml` file the first time you add a control binding to a web page or drag a business service method to a data action in the Page Flow Diagram.

Here is an example of the elements added when you create a data page in a Struts-based Oracle ADF application for JSP pages and drag a control binding to its associated web page.

Note: This configuration file is included for information only. In most cases you do not need to modify this file.

    .
    .
    <!--
    Servlet context parameter, which determines which CPX file the filter reads at runtime to define the application binding context.
    -->
    <context-param>
       <param-name>CpxFileName</param-name>
       <param-value>DataBindings</param-value>
    </context-param><!-- ADF Binding Filter Class Setup -->
    <filter>
         <filter-name>ADFBindingFilter</filter-name>
         <filter-class>oracle.adf.model.servlet.ADFBindingFilter</filter-class>
         <!-- Default language encoding, which can be set in
              Tools>Preferences dialog -->
         <init-param>
             <param-name>encoding</param-name>
             <param-value>windows-1252</param-value>
         </init-param></filter>
    <!--
    A filter mapping links the filter to a static resource or servlet in the
    web application. When a mapped resource is requested, the filter is invoked.
    -->
    <filter-mapping>
       <filter-name>ADFBindingFilter</filter-name>
       <url-pattern>*.jsp</url-pattern>
    </filter-mapping>.
    .
    <filter-mapping>
       <filter-name>ADFBindingFilter</filter-name>
       <servlet-name>action</servlet-name>
    </filter-mapping>
    <filter-mapping>   <filter-name>ADFBindingFilter</filter-name>
       <servlet-name>jsp</servlet-name>
    </filter-mapping>

Note: If you have multiple filters for your application, make sure they are listed in `web.xml` in the order in which you want to run them. At runtime, the filters are called in the sequence listed in that file.

The Oracle ADF binding filter implements the `javax.servlet.Filter` interface and is an example of an intercepting filter.

Where to find additional information:

- For more information about servlet filters, see `http://java.sun.com/products/servlet/docs.html`.

- For more information about intercepting filters, see `http://java.sun.com/blueprints/patterns/InterceptingFilter.html`.

## 5.4 Struts Design Time Integration with Oracle ADF

Oracle ADF provides a rich set of features that help you build Struts-based applications quickly and easily.

### 5.4.1 Struts Page Flow Diagram

The main working environment you use when building Struts-based applications in JDeveloper is the Struts Page Flow Diagram. This is a visual representation of the Struts configuration file. Changes you make in the Page Flow Diagram are synchronized with the file; changes you make by editing the Struts configuration file manually are also reflected in the page flow. The Page Flow Diagram is your workbench for:

- Creating the application's page flow

- Selecting web pages and Struts actions to edit

- Running and debugging the application

The standard objects that you require for a Struts page flow are available in the Component Palette, along with the specialized data action and data page used to handle databound pages that use the Oracle ADF model. The data action component represents an Oracle ADF subclass of the Struts action class. The data page represents a data action subclass combined with an action forward and a destination web page. These components are described in more detail in Oracle ADF Data Action and Data Forward Action Classes.

The Component Palette also includes the specialized page forward element to represent a Struts forward action that always performs a simple forward to a specified destination web page. Using the page forward allows you a level of indirection and flexibility in working with web pages: you can change the name of the underlying web page in the Struts configuration file action mapping without having to change all of the components that forward to the page.

By dragging components from the Component Palette onto the Page Flow Diagram, you can create the Struts action mapping elements and action forwards required by the application without needing to edit the file directly. You can also annotate diagrams for documentation purposes. The following diagram shows a simple page flow with two data pages and two data actions with page links (dashed arrows, here representing explicit links between pages and actions) and action forwards (solid arrows).

The Page Flow Diagram also provides:

- Aids for creating and navigating around large page flows

- Tools to organize the layout of your flow

- Customization of diagram fonts and colors

### 5.4.2 Source View Tab

The Source view tab gives you access to the underlying XML in the Struts configuration file. This XML text editor is useful for drilling down to the XML information in the file and making more detailed additions and edits than is possible with the Page Flow Diagram. The XML Editor also allows developers familiar with the structure of the `struts-config.xml` file to update the file rapidly

The XML Editor is fully validated and synchronized with the Page Flow Diagram. You can edit the Struts configuration file in either mode.

### 5.4.3 Property Inspector Integration with the Struts Configuration File

The Property Inspector is synchronized with the underlying Struts configuration file. You can edit the XML metadata directly in the Property Inspector. You can also use the Property Inspector to display the possible values for Struts tags that take a cue from the contents of the Struts configuration file. For example, when you add an `<html:form>` tag to a web page, you can display a dropdown list of all actions currently defined in the Struts configuration file.

### 5.4.4 Design Time Rendering of Struts Tag Libraries

You can create web pages with HTML, JSTL, Struts, and other custom tag libraries to implement the view of the data. You can enhance your JSP pages using a large set of custom JSP tag libraries that work with the Struts framework. All of the Struts tag libraries are accessible from the JDeveloper Component Palette when you open a JSP page in the editor.

### 5.4.5 Interactive Code Insight for JSP Code Editing

If you prefer to hand-code your JSP pages instead of using the visual editor and the Property Inspector, the source view of the JSP editor is still Struts-aware and provides Code Insight to assist you. For example, if you are creating a `<bean:message>` tag to display a value from the Struts resource bundle and enter `key="`, JDeveloper displays a list of all valid keys in the resource bundle.

## 5.5 Struts Runtime Integration with the Oracle ADF Model Layer

In a Struts-based application integrated with the Oracle ADF model layer, data control objects implemented for each type of business service expose model data to the controller layer, as shown in the following diagram.

1. At runtime, the HTTP request goes through a servlet filter, the Oracle ADF Binding Filter, for preprocessing. The binding filter initializes the Oracle ADF model binding context and notifies data control instances that they are about to receive a request, allowing them to do any necessary pre-request setup.

   The binding context contains a series of binding containers and data controls. The binding container is a group of related control and iterator bindings used together for a single page in a web application. A data control abstracts the implementation of a business service, allowing the binding layer to access the data from all services in a consistent way.

2. Next, control passes to the data action class, most of whose functionality is encapsulated in an implementation of the Oracle ADF lifecycle. In a Struts-based application, the lifecycle used is a subclass of `StrutsLifecycle`.

3. The Oracle ADF lifecycle:

   - Calls the correct binding container needed for a web page and tells it to prepare the data to be rendered

   - Processes and validates any model updates submitted by the user

   - Notifies the binding container when all model updates are complete

For more information about working with the model layer using Oracle ADF, see Overview of the Oracle ADF Model Layer.

## 5.6 Data Pages and Data Actions in the Databound Struts Page Flow

If you use ADF data controls in a page or page forward, the web page must either be associated with a data action or it must be part of a data page. If you drag an ADF data control from the Component Palette to a web page before associating it with an action class, a dialog prompts you to choose a data page or data action in the current context. You can also use the dialog to set a default choice for converting any page that needs to be databound.

### 5.6.1 Working with Data Pages

When you use the Struts Page Flow Diagram to create a data page, JDeveloper updates the `struts-config.xml` file. For example, if you drag the data page icon to an empty Page Flow Diagram and rename it `/myPage`, you get a data page icon with a warning icon overlaid to show that the associated web page has not been created:

At the same time JDeveloper creates the following entry in the `struts-config.xml` file:

    <action-mappings>
        <action path="/myPage"
             className="oracle.adf.controller.struts.actions.DataActionMapping"
             type="oracle.adf.controller.struts.actions.DataForwardAction"
             name="DataForm"parameter=unknown">
         </action>
    </action-mappings>

The following table describes the attributes and subelements of the action mapping:

Attribute or Element | Description
--- | ---
`action` | The `<action>` element describes a mapping from a request path to the corresponding action class that is used to process the request.
`path` | The name of the data page.
`className` | The fully qualified Java classname of the action mapping subclass to use for this action mapping object. For an Oracle ADF Struts application, the default is `oracle.adf.controller.struts.actions.DataActionMapping`. This class determines which lifecycle class should be used, based on the type of page to which the action forwards. For more information, see Oracle ADF Data Action Mapping Class.
`type` | Fully qualified Java classname of the action subclass that processes requests for this action mapping. When you use a data page, the default class name is `oracle.adf.controller.struts.actions.DataForwardAction`
`name` | Unique name of the form bean, if any, that is associated with this action mapping. For a data page, the default form bean is `DataForm`. By default, all data actions and data pages share a single form bean. For more information, see Oracle ADF Data Form Bean.
`parameter` | General-purpose configuration parameter used to pass extra information to the action object selected by this action mapping. When you specify the associated web page, the value of this attribute changes from `unknown` to the page name.

When you create the associated web page (`myPage.jsp`, in this example) in a Struts application, the warning overlay disappears and the data page icon appears normal:

At the same time, JDeveloper updates the action mapping in the `struts-config.xml` file as shown in bold:

    <action-mappings>
     <action path="/myPage"
       className="oracle.adf.controller.struts.actions.DataActionMapping"
       type="oracle.adf.controller.struts.actions.DataForwardAction"
       name="DataForm" parameter="/myPage.jsp">
       <set-property property="modelReference" value="myPageUIModel"/>
     </action>
    </action-mappings>

JDeveloper updates the value of the `parameter` attribute in the action mapping to the name of the associated web page file. In addition, JDeveloper adds a `<set-property>` definition in the action with the property set to `modelReference` and the value set to the name of the binding definition (`pageNameUIModel`). When you add the first data control to the associated web page, JDeveloper also creates these project files:

- A client binding definition file (`myPageUIModel.xml`), which is specific to the web page. JDeveloper creates a client binding definition file for each web page in the project.

- A client project definition file (`DataBindings.cpx`), which creates the Oracle data controls registered with your application's business services. JDeveloper creates only one client project definition file per project.

### 5.6.2 Working with Data Actions

When you use the Struts Page Flow Diagram to create a data action, JDeveloper updates the `struts-config.xml` file. For example, if you drag the data action icon to an empty Page Flow Diagram and rename it as shown here:

JDeveloper creates the following entries in the `struts-config.xml` file:

    <form-beans>
       <form-bean name="DataForm"
         type="oracle.adf.controller.struts.forms.BindingContainerActionForm"/>
       </form-beans>
      <action-mappings>
        <action path="/myAction"
         className="oracle.adf.controller.struts.actions.DataActionMapping"
         type="oracle.adf.controller.struts.actions.DataAction"
         name="DataForm"/>
      </action-mappings>

There are two main differences between this entry and the entry for the previously described data page:

- The action type is `oracle.adf.controller.struts.actions.DataAction`.

- The action mapping for a data action does not use the `parameter` attribute.

The data action does not have an associated web page, so you need to create a forward that will redirect to the next page to be displayed. You can define the `<forward>` element by dragging the Forward icon to the Page Flow Diagram. You can forward to a data page, a page forward, a web page, or another data action. In this example, the forward is to a web page, `myPage.jsp`:

When you add the forward to the web page, JDeveloper updates the action mapping for the data action as shown in bold:

    <action path="/myAction"
       className="oracle.adf.controller.struts.actions.DataActionMapping"
       type="oracle.adf.controller.struts.actions.DataAction"
       name="DataForm">
         <set-property property="modelReference" value="myPageUIModel"/>
         <forward name="success" path="/myPage.jsp"/>
    </action>

The following table describes the attributes and subelements of the complete action mapping:

Attribute or Element | Description
--- | ---
`action` | The `<action>` element describes a mapping from a request path to the corresponding action class that is used to process the request.
`Path` | The name of the data action.
`className` | The fully qualified Java clasname of the action mapping subclass to use for this action mapping object. For an Oracle ADF Struts application, the default is `oracle.adf.controller.struts.actions.DataActionMapping`. This class determines which lifecycle class should be used, based on the type of page to which the action forwards. For more information, see Oracle ADF Data Action Mapping Class.
`Type` | Fully qualified Java classname of the action subclass that processes requests for this action mapping. When you use a data action, the default classname is `oracle.adf.controller.struts.actions.DataAction`.
`Name` | Specifies the method name and initial value of an additional JavaBean configuration property. When the object representing the surrounding element is instantiated, the accessor for the indicated property is called and passed the indicated value. In this case the property is set to `modelReference` and the value set to the name of the binding definition (pageName `UIModel`).
`set-property` | Specifies the method name and initial value of an additional JavaBean configuration property. When the object representing the surrounding element is instantiated, the accessor for the indicated property is called and passed the indicated value. In this case the property is set to `modelReference` and the value set to the name of the binding definition (pageName `UIModel`)
`forward` | The page or other resource to which the action forwards. In this case, the resource is a JSP page, `myPage.jsp`.

For information about when to use a data page or data action, see When to Use a Data Page or Data Action.

## 5.7 Best Practices

The integration of Oracle ADF with Struts provides you with several options for simplifying application development, from working with individual events to modifying behavior across a web application.

### 5.7.1 When to Use a Data Page or Data Action

The data page is the recommended component for adding an action that forwards to a databound web page. Use a data page when:

- You have a data action that is forwarding directly to a web page. In the Page Flow Diagram, a data page represents the combination of a data forward action class instance, a forward transition, and a web page.

- You want to simplify a complex page flow diagram. Using the data page reduces the number of elements in your page flow and makes complex application diagrams easier to read.

Use a data action when:

- You need to perform multiple operations before rendering a web page (this process is called chaining data actions). Use the data action to perform any operations that do not forward directly to a web page. For example, the data action in the following diagram sets the current row before forwarding to a data page that prepares the data for the edit form on the next web page. In this example, setting the current row requires a separate data action:

Depending on the design of your application, you may also want to use a data action that forwards to a separate page forward or page instead of using a data page. You may consider this approach to be appropriate, for example, when you are forwarding to a single page from multiple data actions. The page forward performs a simple forward to a destination web page.

### 5.7.2 Adding Business Service Methods to a Data Action

You can use the Data Control Palette to drag methods onto data actions in your databound Struts page flow. This option provides another way to add functionality to your web application without subclassing the data action class. The design time updates the action mapping for the data action like this:

    <set-property property="methodName" value="MyPageUIModel.ActionName"/>
    <set-property property="resultLocation" value="${requestScope.methodResult}"/>
    <set-property property="numParams" value="1"/>
    <set-property property="paramNames[0]" value="${param.paramName0}"/>

At runtime, the lifecycle implemented in the data action executes the method defined by the business service through the Oracle ADF data controls. For more information, see step 8 in the lifecycle-handling table earlier in this chapter.

Note: There is a `paramNames[]` property for each method parameter. If the method has no parameters, the value of `numParams` is set to 0 and there are no `paramNames` properties set. If you are using a custom method that requires parameters, you must add the `paramNames` properties using the Struts Configuration Editor.

### 5.7.3 When to Subclass the DataAction or DataForwardAction Class

The integration of Oracle ADF with Struts is designed to minimize the need to subclass the `DataAction` and `DataForwardAction` classes. The `execute()` method is final in both classes. However, you may need to subclass when:

- You want to develop named events that are independent of the model layer, as described in Named Events in Oracle ADF

- You want to override the behavior of an existing action binding

- You want to change the behavior of one of the steps in the lifecycle (as described in Oracle ADF Lifecycle) for a single action

The data action follows a general pattern of exposing the lifecycle methods and delegates most of its functionality to the lifecycle class.

### 5.7.4 When to Use an Oracle ADF Lifecycle Plugin

For a Struts-based application, you can override the main lifecycle methods by subclassing the `DataAction` or `DataForwardAction` class. You must subclass the lifecycle itself and register a lifecycle plugin when:

- You want to modify the lifecycle to perform certain behaviors across the application

- You want to change the behavior of a method in the lifecycle subclass that cannot be overwritten in the `DataAction` or `DataForwardAction` class

The data action follows a general pattern of exposing the lifecycle methods and delegating most of its functionality to the lifecycle class (also known as the Decorator Design Pattern). For example, `handleError()` follows this pattern, as do the lifecycle methods described in Oracle ADF Lifecycle. However, some methods, such as `handleEvent()`, do not follow this pattern. When a method is not a step of the lifecycle that is executed only once, you must subclass the lifecycle to change it. There is a difference between the phases of the lifecycle and the individual operations that each phase executes. `handleEvent()` is in the second category because the lifecycle calls it for each event, which means it may be called more than once. You may want to customize the basic `handleEvent()` logic for all events in your application, to do something before, after, or instead of the default. You can override the `handleEvent()` method on the lifecycle class but not on the data action class. You must create and register your own lifecycle implementation.

Modifying code once for all data actions in your application instead of overriding each data action may also be an effective development strategy. JDeveloper includes a Struts plugin implementation that allows you to specify a new `LifecycleFactory` class so that you can create and use a lifecycle subclass. A `LifecycleFactory` class implements `StrutsPageLifecycleFactory`, which is an abstract class.

To override the Struts lifecycle you need to specify the new `Lifecycle` class during the data action configuration, because some of the lifecycle methods are used during configuration. To specify the new class, you add a `<plug-in>` element to the `struts-config.xml` file. The plugin is a Struts mechanism that allows you to load components dynamically at application startup.

The entry in the configuration file has the following syntax:

    <plug-in
      className="oracle.adf.controller.struts.actions.PageLifecycleFactoryPlugin">
       <set-property property="lifecycleFactory"
         value="mypackage1.myStrutsLifecycleFactory"/>
    </plug-in>

The property is used to pass the name of the new `LifecycleFactory` class to the application. A `LifecycleFactory` class implements the abstract class `StrutsPageLifecycleFactory` class. You must define the following method in the class:

    public StrutsPageLifecycle getPageLifecycle(String path)

See the javadoc for `DefaultStrutsPageLifecycleFactory` for an example.

### 5.7.5 Summary of Best Practices in Working with Oracle ADF/Struts Integration

If you want to... | Then...
--- | ---
Create a custom method that accesses the ADF model layer. | Create a custom method in the business services layer.
Create an action that prepares model data for display, forwards to a specific databound page, and manages any submissions from that page. | Use a data page
Create an action that executes a custom method exposed by the business service. | Use a data action.
Override an existing method in the action bindings. | Subclass the data action.
Create a custom event that does not access the ADF model layer | Subclass the data action to create a named event.
Use events to forward to a new page without subclassing the data action. | Use an event to define an action forward.
Create an operation that is called every time a data action or data page is called | Subclass the data action or data forward action.
Modify lifecycle behavior across an entire application (for example, to modify how individual events are handled globally). | Create a lifecycle plugin and register it
Add extra properties to an action mapping. | Subclass the data action mapping class.