Skip Headers

Oracle® Application Development Framework Developer's Guide 10g Release 3 (10.1.3) B25386-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# 10.5 Overriding Declarative Methods

When you drop a method as a command button, JDeveloper binds the button to the `execute` method on the associated binding object. This binding allows you to create the JSF page declaratively, without needing to write the associated binding code. However, there may be occasions when you need to add logic before or after the method executes. For example, in order to delete multiple selected rows in a table, you must add code before the delete method executes that accesses each row and makes it current. For more information, see Section 7.6.4, "How to Use the tableSelectMany Component in the Selection Facet".

JDeveloper allows you to add logic to a declarative method by creating a new method on a managed bean that accesses the associated action binding, thereby injecting the binding container into the managed bean. By default, this generated code executes the method of the corresponding binding. You can then add logic before or after this code. JDeveloper automatically binds the command component to this new method instead of the `execute` property on the binding. Now when the user clicks the button, the new method is executed.

Following are some of the instances in the SRDemo application where backing beans contain methods that inject the binding container and then add logic before or after the declarative method is executed:

- `SRCreateConfirm.java`: The `createSR_action` method overrides the `createServiceRequest` method to add validation logic before the method is executed, and sets a parameter value after the method is executed.

- `SRMain.java`: The `deleteSR_action` method overrides the `removeServiceRequest` method to check whether a service request has associated histories before deleting. The `srDelete_action` method overrides the `removeServiceHistory` method in order to delete multiple rows in the Service History table.

## 10.5.1 How to Override a Declarative Method

In order to override a declarative method, you must have a managed bean to hold the new method. If your page has a backing bean associated with it, JDeveloper adds the code needed to access the binding object to this backing bean. If your page does not have a backing bean, JDeveloper asks you to create one.

Note: You cannot use the following procedure if the button currently has an EL expression as its value for the `Action` attribute, as JDeveloper will not overwrite an EL expression. You must remove this value before continuing.

To override a declarative method:

1. Drag the method to be overridden onto the JSF page and drop it as a UI command component.

   Doing so creates the component and binds it to the associated binding object in the ADF Model layer using the `ActionListener` attribute on the component. For more information about creating command components using the Data Control Palette, see Section 10.3, "Creating Command Components to Execute Methods".

2. On the JSF page, double-click on the component.

   In the Bind Action Property dialog, identify the backing bean and the method to which you want to bind the component using one of the following techniques:

   - If auto-binding has been enabled on the page, the backing bean is already selected for you, as shown in Figure 10-6.

     Figure 10-6 Bind Action Property Dialog for a Page with Auto-Binding Enabled

     - To create a new method, enter a name for the method in the Method field, which initially displays a default name.

       OR

     - To use an existing method, select a method from the dropdown list in the Method field.

     - Select Generate ADF Binding Code.

   - If the page is not using auto-binding, you can select from an existing backing bean or create a new one, as shown in Figure 10-7.

     Figure 10-7 Bind Action Property Dialog for a Page with Auto-Binding Disabled

     - Click New to create a new backing bean. The Create Managed Bean dialog is displayed. Use this dialog to name the bean and the class.

       OR

     - Select an existing backing bean and method from the dropdown lists.

   Note: If you are creating a new managed bean, then you must set the scope of the bean to `request`. Setting the scope to `request` is required because the data in the binding container object that will be referenced by the generated code is on the `request` scope, and therefore cannot "live" beyond a request.

3. After identifying the backing bean and method, click OK in the Bind Action Property dialog

   JDeveloper opens the managed bean in the source editor. Example 10-6 shows the code inserted into the bean. In this example, a command button is bound to the `mergeEntity` method.

   Tip: JDeveloper believes that the button is bound to the `execute` property of a binding whenever there is a value for the `ActionListener` attribute on the command component. Therefore, if you have removed that binding, you will not be given the choice to generate the ADF binding code. You need to either inject the code manually, or to set a dummy value for the `ActionListener` before double-clicking on the command component.

   Example 10-6 Generated Code in a Backing Bean to Access the Binding Object

         public BindingContainer getBindings() {

             return this.bindings;
         }

         public void setBindings(BindingContainer bindings) {
             this.bindings = bindings;
         }

         public String commandButton_action1() {
             BindingContainer bindings = getBindings();
             OperationBinding operationBinding =
                 bindings.getOperationBinding("mergeEntity");
             Object result = operationBinding.execute();
             if (!operationBinding.getErrors().isEmpty()) {
                 return null;
             }
             return null;
         }

4. You can now add logic either before or after the binding object is accessed.

   Tip: To get the result of an EL expression, you need to use the `ValueBinding` class, as shown in Example 10-7

   Example 10-7 Accessing the Result of an EL Expression in a Managed Bean

       FacesContext fc = FacesContext.getCurrentInstance();
         ValueBinding expr =
           fc.getApplication().
             createValueBinding("#{bindings.findAllEmployeesIter}");
       DCIteratorBinding ib = (DCIteratorBinding)
         expr.getValue(fc);

   In addition to any processing logic, you may also want to write conditional logic to return one of multiple outcomes depending on certain criteria. For example, you might want to return `null` if there is an error in the processing, or another outcome value if the processing was successful. A return value of `null` causes the navigation handler to forgo evaluating navigation cases and to immediately redisplay the current page.

   Tip: To trigger a specific navigation case, the outcome value returned by the method must exactly match the outcome value in the navigation rule, including uppercase and lowercase letters.

   The command button is now bound to this new method using the `Action` attribute instead of the `ActionListener` attribute. If a value had previously existed for the `Action` attribute (such as an outcome string), that value is added as the return for the new method. If there was no value, the return is kept as `null`.

## 10.5.2 What Happens When You Override a Declarative Method

When you ovrerride a declarative method, JDeveloper automatically rebinds the UI command component to the new method using the `Action` attribute, instead of the `ActionListener` attribute. For example, Example 10-8 shows the code on a JSF page for a command button created by dropping the `mergeEntity` method. Notice that the `actionListener` attribute is bound to the `mergeEntity` method, and the `action` attribute has a `String` outcome of `back`. If the user were to click the button, the method would simply execute, and navigate to the page defined as the `toViewId` for this navigation case.

Example 10-8 JSF Page Code for a Command Button Bound to a Declarative Method

    <af:commandButton actionListener="#{bindings.mergeEntity.execute}"
                      text="persistEntity"
                      disabled="#{!bindings.persistEntity.enabled}"
                      id="commandButton1"
                      action="back"/>

Example 10-9 shows the code after overriding the method on the page's backing bean. Note that the `action` attribute is now bound to the backing bean's method.

Example 10-9 JSF Page Code for a Command Button Bound to an Overridden Method

    <af:commandButton text="persistEntity"
                      disabled="#{!bindings.mergeEntity.enabled}"
                      binding="#{backing_create.commandButton1}"
                      id="commandButton1"
                      action="#{backing_create.commandButton1_action}"/>

Example 10-6 shows the code that JDeveloper adds to the chosen managed bean. Notice that the return `String` `"back`" was automatically added to the method.

Example 10-10 Generated Code in a Backing Bean to Access the Binding Object

    public String commandButton1_action() {
        BindingContainer bindings = getBindings();
        OperationBinding operationBinding =
                bindings.getOperationBinding("mergeEntity");
        Object result = operationBinding.execute();
        if (!operationBinding.getErrors().isEmpty()) {
            return null;
        }

        return "back";
    }

This code does the following:

- Accesses the binding container

- Finds the binding for the associated method, and executes it

- Adds a return for the method that can be used for navigation. By default the return is `null`, or if an outcome string had previously existed for the button's `Action` attribute, that attribute is used as the return value. You can change this code as needed. For more information about using return outcomes, see Section 9.4, "Creating Navigation Using Dynamic Outcome Values".

Tip: If when you click the button that uses the overridden method, you receive this error: `SEVERE: Managed bean main_bean could not be created The scope of the referenced object: '#{bindings}' is shorter than the referring object` it is because the managed bean that contains the overriding method has a scope that is greater than `request`, (that is, either `session` or `application`). Because the data in the binding container referenced in the method has a scope of `request`, the scope of this managed bean must be set to `request` scope or a lesser scope.