Skip Headers
Oracle® Application Development Framework Developer's Guide For Forms/4GL Developers
10g (10.1.3.1.0)

Part Number B25947-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

25.9 Creating Extended Components Using Inheritance

Whenever you create a new business component, if necessary, you can extend an existing one to create a customized version of the original. For example, in the SRDemo application, as shown in Figure 25-9, the ServiceRequestsByStatus view object extends the ServiceRequests view object to add a named bind variable named TheStatus and to customize the WHERE clause to reference that bind variable.

Figure 25-9 ADF Business Components Can Extend Another Component

Image shows how business components can extend others

While the figure shows a view object example, this component inheritance facility is available for all component types. When one component extends another, the extended component inherits all of the metadata and behavior from the parent it extends. In the extended component, you can add new features or customize existing features of its parent component both through metadata and Java code.


Note:

The examples in this section refer to the BaseProject project in the AdvancedExamples workspace. See the note at the beginning of this chapter for download instructions.

25.9.1 How To Create a Component That Extends Another

To create an extended component, use the component wizard in the New Gallery for the type of component you want to create. For example, to create an extended view object, you use the Create View Object wizard. On the Name page of the wizard — in addition to specifying a name and a package for the new component — provide the fully-qualified name of the component that you want to extend in the Extends field. To pick the component name from a list, use the Browse button next to the Extends field. Then, continue to create the extended component in the normal way using the remaining panels of the wizard.

25.9.2 What Happens When You Create a Component That Extends Another

As you've learned, the ADF business components you create are comprised of an XML component definition and an optional Java class. When you create a component that extends another, JDeveloper reflects this component inheritance in both the XML component definition and in any generated Java code for the extended component.

25.9.2.1 Understanding an Extended Component's XML Descriptor

JDeveloper notes the name of the parent component in the new component's XML component definition by adding an Extends attribute to the root component element. Any new declarative features you add or any aspects of the parent component's definition you've overridden appear in the extended component's XML component definition. In contrast, metadata that is purely inherited from the parent component is not repeated for the extended component.

Example 25-15 shows what the ServiceRequstsByStatus.xml XML component definition for the ServiceRequstsByStatus view object looks like. Notice the Extends attribute on the ViewObject element, Variable element related to the additional bind variable added in the extended view object, and the overridden value of the Where attribute for the WHERE clause that was modified to reference the StatusCode bind variable.

Example 25-15 Extended Component Reflects Parent in Its XML Descriptor

<ViewObject
   Name="ServiceRequestsByStatus"
   Extends="oracle.srdemo.model.queries.ServiceRequests"
   Where="((ServiceRequest.CREATED_BY = CreatedByUser.USER_ID)
          AND (ServiceRequest.ASSIGNED_TO = AssignedToUser.USER_ID(+)))
          AND (ServiceRequest.PROD_ID = Product.PROD_ID)
          AND STATUS LIKE NVL(:StatusCode,&#39;%&#39;)"
   OrderBy="REQUEST_DATE DESC"
   BindingStyle="OracleName"
   CustomQuery="false"
   ComponentClass="oracle.srdemo.model.queries.ServiceRequestsByStatusImpl"
   FetchMode="FETCH_AS_NEEDED"
   UseGlueCode="false" >
   <Variable
      Name="StatusCode"
      Kind="where"
      Type="java.lang.String"
      DefaultValue="%" >
   </Variable>
</ViewObject>

25.9.2.2 Understanding Java Code Generation for an Extended Component

If you enable custom Java code for an extended component, JDeveloper automatically generates the Java classes to extend the respective Java classes of its parent component. In this way, the extended component can override any aspect of the parent component's programmatic behavior as necessary. If the parent component is an XML-only component with no custom Java class of its own, the extended component's Java class extends whatever base Java class the parent would use at runtime. This could be the default ADF Business Components framework class in the oracle.jbo.server package, or could be your own framework extension class if you have specified that in the Extends dialog of the parent component.

In addition, if the extended component is an application module or view object and you enable client interfaces on it, JDeveloper automatically generates the extended component's client interfaces to extend the respective client interfaces of the parent component. If the respective client interface of the parent component does not exist, then the extended component's client interface directly extends the appropriate base ADF Business Components interface in the oracle.jbo package.

25.9.3 What You May Need to Know

{para}?>

25.9.3.1 You Can Use Parent Classes and Interfaces to Work with Extended Components

Since an extended component is a customized version of its parent, code you write that works with the parent component's Java classes or its client interfaces works without incident for either the parent component or any customized version of that parent component.

For example, assume you have a base Products view object with custom Java classes and client interfaces like:

  • class ProductsImpl

  • row class ProductsRowImpl

  • interface Products

  • row interface ProductsRow

If you create a ProductsByName view object that extends Products, then you can use the base component's classes and interface to work both with Products and ProductsByName.

Example 25-16 illustrates a test client program that works with the Products, ProductsRow, ProductsByName, and ProductsByNameRow client interfaces. A few interesting things to note about the example are the following:

  1. You can use parent Products interface for working with the ProductsByName view object that extends it.

  2. Alternatively, you can cast an instance of the ProductsByName view object to its own more specific ProductsByName client interface.

  3. You can test if row ProductsRow is actually an instance of the more specific ProductsByNameRow before casting it and invoking a method specific to the ProductsByNameRow interface.

Example 25-16 Working with Parent and Extended Components

package devguide.advanced.extsub;
/* imports omitted */
public class TestClient {
  public static void main(String[] args) {
    String        amDef = "devguide.advanced.extsub.ProductModule";
    String        config = "ProductModuleLocal";
    ApplicationModule am =
    Configuration.createRootApplicationModule(amDef,config);
    Products products = (Products)am.findViewObject("Products");
    products.executeQuery();
    ProductsRow product = (ProductsRow)products.first();
    printAllAttributes(products,product);
    testSomethingOnProductsRow(product);
    // 1. You can use parent Products interface for ProductsByName
    products = (Products)am.findViewObject("ProductsById");
    // 2. Or cast it to its more specific ProductsByName interface
    ProductsByName productsById = (ProductsByName)products;
    productsById.setProductName("Ice");
    productsById.executeQuery();
    product = (ProductsRow)productsById.first();
    printAllAttributes(productsById,product);
    testSomethingOnProductsRow(product);
    am.getTransaction().rollback();
    Configuration.releaseRootApplicationModule(am,true);
  }
  private static void testSomethingOnProductsRow(ProductsRow product) {
    try {
      // 3. Test if row is a ProductsByNameRow before casting
      if (product instanceof ProductsByNameRow) {
        ProductsByNameRow productByName = (ProductsByNameRow)product;
        productByName.someExtraFeature("Test");        
      }
      product.setName("Q");
      System.out.println("Setting the Name attribute to 'Q' succeeded.");
    }
    catch (ValidationException v) {
      System.out.println(v.getLocalizedMessage());      
    }    
  }
  private static void printAllAttributes(ViewObject vo, Row r) {
    String viewObjName = vo.getName();
    System.out.println("Printing attribute for a row in VO '"+
                       viewObjName+"'");
    StructureDef def = r.getStructureDef();
    StringBuilder sb = new StringBuilder();
    int numAttrs = def.getAttributeCount();
    AttributeDef[] attrDefs = def.getAttributeDefs();
    for (int z = 0; z < numAttrs; z++) {
      Object value = r.getAttribute(z);
      sb.append(z > 0 ? "  " : "")
        .append(attrDefs[z].getName())
        .append("=")
        .append(value == null ? "<null>" : value)
        .append(z < numAttrs - 1 ? "\n" : "");
    }
    System.out.println(sb.toString());
  }
}

Running the test client above produces the following results:

Printing attribute for a row in VO 'Products'
ProdId=100
  Name=Washing Machine W001
  Checksum=I am the Product Class
Setting the Name attribute to 'Q' succeeded.
Printing attribute for a row in VO 'ProductsById'
ProdId=119
  Name=Ice Maker I012
  Checksum=I am the Product Class
  SomeExtraAttr=SomeExtraAttrValue
## Called someExtraFeature of ProductsByNameRowImpl
Setting the Name attribute to 'Q' succeeded.

Note:

In this example, Products is an entity-based view object based on the Product entity object. The Product entity object includes a transient Checksum attribute that returns the string "I am the Product class". You'll learn more about why this was included in the example in Section 25.10, "Substituting Extended Components In a Delivered Application".

25.9.3.2 Class Extends is Disabled for Extended Components

When you create an extended component, the Class Extends button on the Java page of the extended component is disabled. This is due to the fact that JDeveloper automatically extends the appropriate class of its parent component, so it does not make sense to allow you to select a different class.

25.9.3.3 Interesting Aspects You Can Extend for Key Component Types

Entity Objects

When you create an extended entity object, you can introduce new attributes, new associations, new validators, and new custom code. You can override certain declarative aspects of existing attributes as well as overriding any method from the parent component's class.

View Objects

When you create an extended view object, you can introduce new attributes, new view links, new bind variables, and new custom code. You can override certain declarative aspects of existing attributes as well as overriding any method from the parent component's class.

Application Modules

When you create an extended application module, you can introduce new view object instances or new nested application module instance and new custom code. You can also override any method from the parent component's class.

25.9.3.4 Extended Components Have Attribute Indices Relative to Parent

If you add new attributes in an extended entity object or view object, the attribute index numbers are computed relative to the parent component. For example, consider the Products view object mentioned above. If you enable a custom view row class, it might have attribute index constants defined in the ProductsRowImpl.java class like this:

public class ProductsRowImpl extends ViewRowImpl
                             implements ProductsRow {
  public static final int PRODID = 0;
  public static final int NAME = 1;
  public static final int CHECKSUM = 2;
  //etc.
}

When you create an extended view object like ProductsByName, if that view object adds an addition attribute like SomeExtraAttr and has a custom view row class enabled, then its attribute constants will be computed relative to the maximum value of the attribute constants in the parent component:

public class ProductsByNameRowImpl extends ProductsRowImpl
                                   implements ProductsByNameRow {
  public static final int MAXATTRCONST =
    ViewDefImpl.getMaxAttrConst("devguide.advanced.extsub.Products");
  public static final int SOMEEXTRAATTR = MAXATTRCONST;

Additional attributes would have index values of MAXATTRCONST+1, MAXATTRCONST+2, etc.

25.9.3.5 Design Time Limitations for Changing Extends After Creation

After defining an extended component, JDeveloper allows you to change the parent component from which an extended component inherits. You can accomplish by:

  • Selecting the extended component in the Application Navigator

  • Using the Property Inspector to change the Extends property

However, you cannot currently use this technique to change the extended component to not inherit from any parent. The one exception to this limitation is the entity object, whose component editor offers an Extends field on the Name page that you can blank out if necessary. For all other extended components, to make them no longer extend from a parent component you need to delete and recreate them to accomplish this.