Oracle® Fusion Middleware - Google Groups

0 downloads 55 Views 11MB Size Report
Sep 1, 2008 - What Happens When You Add Attribute Control Hints ........................................... 4-21. 4.7. W
Oracle® Fusion Middleware Fusion Developer’s Guide for Oracle Application Development Framework 11g Release 1 (11.1.1) B31974-01

September 2008

Oracle Fusion Middleware Fusion Developer’s Guide for Oracle Application Development Framework 11g Release 1 (11.1.1) B31974-01 Copyright © 2008 Oracle. All rights reserved. Primary Authors: Ralph Gordon (Lead), Peter Jew, Dave Mathews, Landon Ott, and Robin Whitmore Contributing Authors: Walter Egan, Catherine Pickersgill, and Odile Sullivan-Tarazi Contributors: Steve Muench, Lynn Munsinger The Programs (which include both the software and documentation) contain proprietary information; they are provided under a license agreement containing restrictions on use and disclosure and are also protected by copyright, patent, and other intellectual and industrial property laws. Reverse engineering, disassembly, or decompilation of the Programs, except to the extent required to obtain interoperability with other independently created software or as specified by law, is prohibited. The information contained in this document is subject to change without notice. If you find any problems in the documentation, please report them to us in writing. This document is not warranted to be error-free. Except as may be expressly permitted in your license agreement for these Programs, no part of these Programs may be reproduced or transmitted in any form or by any means, electronic or mechanical, for any purpose. If the Programs are delivered to the United States Government or anyone licensing or using the Programs on behalf of the United States Government, the following notice is applicable: U.S. GOVERNMENT RIGHTS Programs, software, > // In the attribute identified as the start date // In the attribute identified as the end date // The SysEffectiveDate transient attribute

4.2.10 What You May Need to Know About Creating Entities from Tables The Business Components from Tables wizard makes it easy to quickly generate many business components at the same time. In practice, this does not mean that you should use it to immediately create entity objects for every table in your ... > < Value ="FALSE" />

When you create a business logic unit, JDeveloper generates an XML file similar to that of an entity object. Example 4–6 shows XML code for a business logic unit. The package for the business logic unit does not need to be the same as the package for the base entity or the business logic group. This allows you to develop and deliver business logic units separately from the core application.

Note:

Example 4–6 XML Code for a Business Logic Unit

4.8.5 What Happens at Runtime: Invoking a Business Logic Group When a row is loaded in the application at runtime, the entity object decides which business logic units to apply to it. The base entity maintains a list of business logic groups. Each group references the value of an attribute on the entity, and this value determines which business logic unit to load for that group. This evaluation is performed for each row that is loaded. If the logic for determining which business logic unit to load is more complex than just a simple attribute value, you can create a transient attribute on the entity object, and use a groovy expression to determine the value of the transient attribute.

4.9 Configuring Runtime Behavior Declaratively Entity objects offer numerous declarative features to simplify implementing typical enterprise business applications. Depending on the task, sometimes the declarative facilities alone may satisfy your needs. The declarative runtime features that describe the basic persistence features of an entity object are covered in this section, while declarative validation and business rules are covered in Chapter 7, "Defining Validation and Business Rules Declaratively"

Creating a Business Domain Layer Using Entity Objects

4-27

Configuring Runtime Behavior Declaratively

It is possible to go beyond the declarative behavior to implement more complex business logic or validation rules for your business domain layer when needed. In Chapter 8, "Implementing Validation and Business Rules Programmatically", you'll see some of the most typical ways that you extend entity objects with custom code.

Note:

Also, it is important to note as you develop your application that the business logic you implement, either programmatically or declaratively, should not assume that the attributes of an entity object or view row will be set in a particular order. This will cause problems if the end user enters values for the attributes in an order other than the assumed one.

4.9.1 How to Configure Declarative Runtime Behavior To configure the declarative runtime behavior of an entity object, use the overview editor. To configure the declarative runtime behavior of an entity object: 1. In the Application Navigator, double-click the entity object to open the editor. 2.

In the overview editor, click the General tab to view the name and package of the entity object, and configure aspects of the object at the entity level, such as its associated schema, validation rules, custom properties, and security. ■







3.

The Entity Validation Rules node allows you to declare validation rules, which can optionally use Groovy scripts. For information on how to use the declarative validation features, see Chapter 7, "Defining Validation and Business Rules Declaratively". The Tuning node allows you to set options to make IsUpdateable="false" IsQueriable="false" IsPersistent="false" ColumnName="$none$" Type="java.lang.String" ColumnType="$none$" SQLType="VARCHAR" >

In contrast, a persistent entity attribute has both a TableName and a ColumnName, as shown in Example 4–20. Example 4–20

XML Code for a Persistent



4.13.3 How to Base a Transient Attribute On a Groovy Expression When creating a transient attribute, you can use a Groovy expression to provide the default value. To create a transient attribute based on a Groovy expression: 1. Create a new attribute, as described in the first four steps of Section 4.13.1, "How to Add a Transient Attribute". 2.

In the New Entity Attribute dialog box, click the Edit button next to the Value field. Expressions that you define are evaluated using the Groovy Expression Language, as described in Section 3.6, "Overview of Groovy Support". Groovy lets you insert expressions and variables into strings. The expression is saved as part of the entity object definition

3.

In the Edit Expression dialog, enter an expression in the field provided, as shown in Figure 4–14.

4-52 Fusion Developer’s Guide for Oracle Application Development Framework

Adding Transient and Calculated Attributes to an Entity Object

Attributes that you reference can include any attribute that the entity object define. Do not reference attributes in the expression that are not defined by the entity object. Figure 4–14 Edit Expression Dialog

4.

Select the appropriate recalculate setting. If you select Always (default), the expression is evaluated each time any attribute in the row changes. If you select Never, the expression is evaluated only when the row is created.

5.

You can optionally provide a condition for when to recalculate the expression. For example, the following expression in the Based on the following expression field causes the attribute to be recalculated when either the Quantity attribute or the UnitPrice attribute are changed: return (adf.object.isAttributeChanged("Quantity") || adf.object.isAttributeChanged("UnitPrice"));

6.

Click OK to save the expression.

7.

Then click OK to create the attribute.

Creating a Business Domain Layer Using Entity Objects

4-53

Adding Transient and Calculated Attributes to an Entity Object

If either the value expression or the optional recalculate expression that you define references an attribute from the base entity object, you must define this as a dependency on the Dependencies page of the Edit Attribute dialog. In the Dependency page, locate the attributes in the Available list and shuttle each to the Selected list.

Note:

4.13.4 What Happens When You Base a Transient Attribute on Groovy Expression When you base a transient attribute on a Groovy expression, a tag is added to the entity object’s XML file within the appropriate attribute, as shown in Example 4–21. Example 4–21

Calculating a transient attribute using a Groovy expression

// Transient attribute for second column // Transient attribute for third column // Reference to file that contains static />

Because the > // Attribute identified as the start date // Attribute identified as the end date // The SysEffectiveDate transient attribute

5.4.6 What You May Need to Know About Date-Effective View Objects and View LInks Effective dated associations and view links allow queries to be generated that take the effective date into account. The effective date of the driving row is passed in as a bind parameter during the query execution. While it is possible to create a noneffective dated association between two entities when using the Create Association wizard or Create View Link wizard, JDeveloper will by default make the association or link effective dated if one of the ends is effective dated. However, when the association or view link exists between an effective dated and a noneffective dated object, then at runtime ADF Business Components will inspect the effective dated nature of the view object or entity object before generating the query clause and binding the effective date. The effective date is first obtained from the driving row. If it is not available, then it is obtained from the property EFF_ DT_PROPERTY_STR of the root application module. If you do not set EFF_DT_ PROPERTY_STR for the application module, the current date is used in the query filter on the driving row and applied to the other side of the association or view link.

5.5 Working with Multiple Tables in Join Query Results Many queries you will work with will involve multiple tables that are related by foreign keys. In this scenario, you join the tables in a single view object query to show additional descriptive information in each row of the main query result. You use the Create View Object wizard to define the query using declarative options. Whether your view object is read-only or entity-based determines how you can define the join: ■



When you work with entity-based view objects, the Create View Object wizard uses an existing association defined between the entities to automatically build the view object's join WHERE clause. You can declaratively specify the type of join you want to result from the entity objects. Inner join (equijoin) and outer joins are both supported. When you work with read-only view objects, you will use the SQL Builder dialog to build the view object’s join WHERE clause. In this case, you must select the columns from the tables that you want to join.

Figure 5–17 illustrates the rows resulting from two tables queried by a view object that defines a join query. The join is a single flattened result.

5-24 Fusion Developer’s Guide for Oracle Application Development Framework

Working with Multiple Tables in Join Query Results

Figure 5–17 Join Query Result

5.5.1 How to Create Joins for Entity-Based View Objects It is extremely common in business applications to supplement information from a primary business domain object with secondary reference information to help the end user understand what foreign key attributes represent. Take the example of the OrderItems entity object. It contains foreign key attribute of type Number like: ■

ProductId, representing the product to which the order item pertains

From experience, you know that showing an end user exclusively these "raw" numerical values won't be very helpful. Ideally, reference information from the view object’s related entity objects should be displayed to improve the application's usability. One typical solution involves performing a join query that retrieves the combination of the primary and reference information. This is equivalent to populating "dummy" fields in each queried row with reference information based on extra queries against the lookup tables. When the end user can change the foreign key values by editing the Entity="oracle.fodemo.storefront.entities.ShippingOptionBaseEO"/>

The secondary reference entity usages will have a slightly different entry, including information about the association that relates it to the primary entity usage, like the entity usage shown in Example 5–5. Example 5–5 Secondary Reference Entity Usage

Each attribute entry in the XML file indicates which entity usage it references. For example, the entry for the ShippingOptionId attribute in Example 5–6 shows that it's related to the ShippingOptionBaseEO entity usage, while the ShippingMethod attribute is related to the ShippingOptionTranslationEO entity usage. Example 5–6 Entity Usage Reference of View Object Attribute ...

The Create View Object wizard uses this association information at design time to automatically build the view object's join WHERE clause. It uses the information at runtime to enable keeping the reference information up to date when the end user changes foreign key attribute values.

5.5.7 How to Create Joins for Read-Only View Objects To create a read-only view object joining two tables, use the Create View Object wizard.

Defining SQL Queries Using View Objects 5-31

Working with Multiple Tables in Join Query Results

To create a read-only view object joining two tables: 1. In the Application Navigator, right-click the project in which you want to create the view object and choose New. 2.

In the New Gallery, expand Business Tier, select ADF Business Components, then View Object, and click OK.

3.

In the Initialize Business Components Project dialog, select the Name="CustomerCardStatus" SelectListFlags="1" FromListFlags="1" WhereFlags="1" ...

Similar to view objects that you create in either normal or expert mode, the view object meta ViewObjectName="oracle.fodemo.storefront.store.queries.CustomerCardStatus" Conjunction="AND" Mode="3" AppliedIfJoinSatisfied="false">

Defining SQL Queries Using View Objects 5-49

Working with View Objects in Declarative SQL Mode

5.7.6 What Happens at Runtime At runtime, when a declarative SQL mode query is generated, ADF Business Components determines which attributes were defined from the meta/> definition determines the component that JDeveloper will add to the web page. When the component type definition in the points to the Coupons view accessor, which accesses the view object CouponsVO. The element maps the list LOVName="LOV_TypedCouponCode" . . . . . . . . .

5.11.6 What Happens at Runtime: When an LOV Queries the List ) most likely will not provide the user with the desired selection choices. Performance Tip: To limit the set of values a LOV displays use a view accessor to filter the LOV binding, as described in Section 5.11.1, "How to Define a Single LOV-Enabled View Object Attribute". Additionally, in the case of component types that display a choice list, you can change the Most Recently Used Count setting to limit the list to display the user’s previous selections, as described in Section 5.11.3, "How to Set User Interface Hints on a View Object LOV-Enabled Attribute".

Note, a runtime exception will occur when a web page displays a UI component for an LOV-enabled attribute that does not match the view object’s CONTROLTYPE definition. When the user interface designer creates the page in JDeveloper using the IsNotNull="true" EntityAttrName="LastName" EntityUsage="User1" AliasName="LAST_NAME" >

Whereas, in contrast, a SQL-calculated attribute's tag looks like sample shown in Example 5–38. As expected, the tag has no EntityUsage or EntityAttrName property, and includes IsUp IsPersistent="false" Precision="62" Type="java.lang.String" ColumnType="VARCHAR2"

5-96 Fusion Developer’s Guide for Oracle Application Development Framework

Adding Calculated and Transient Attributes to a View Object

AliasName="FULL_NAME" Expression="LAST_NAME||', '||FIRST_NAME" SQLType="VARCHAR" >

Note: The ' is the XML character reference for the apostrophe. You reference it by its numerical ASCII code of 39 (decimal). Other characters in literal text that require similar construction in XML are the less-than, greater-than, and ampersand characters.

5.13.3 How to Add a Transient Attribute Transient attributes are often used to provide subtotals or other calculated expressions that are not stored in the ) or All at Once (FetchMode="FETCH_ALL"), depending on which option is desired. The As Needed option ensures that an executeQuery() operation on the view object initially retrieves only as many rows as necessary to fill the first page of a display, whose number of rows is set based on the view object's range size.

Fetch Size

In conjunction with the Fetch Mode option, the in Batches of field controls the number of records fetched at one time from the to the JVM upon startup.

Additionally, you have some options to tune the view objects’ associated SQL for better IsUpdateable="true" AttrLoad="Each" IsNotNull="true" ColumnName="DISCOUNT_AMOUNT" Type="oracle.jbo.domain.Number" ColumnType="NUMBER" SQLType="NUMERIC" TableName="DISCOUNTS_BASE" HistoryColumn="NonHistory">

At runtime, the rule is enforced by the entity object based on this declarative information.

7.3.4 What You May Need to Know About Entity and Attribute Validation Rules Declarative validation enforces both entity-level and attribute-level validation, depending on where you place the rules. Entity-level validation rules are enforced when a user tries to commit pending changes or navigates between rows. Attribute-level validation rules are enforced when the user changes the value of the related attribute. The Unique Key validator (described in Section 7.4.1, "How to Ensure That Key Values Are Unique") can be used only at the entity level. Internally the Unique Key validator behaves like an attribute-level validator. This means that users see the validation error when they tab out of the key attribute for the key that the validator is validating. This is done because the internal cache of entities can never contain a duplicate, so it is not allowed for an attribute value to be set that would violate that. This check needs to be performed when the attribute value is being set because the cache consistency check is done during the setting of the attribute value.

Defining Validation and Business Rules Declaratively 7-7

Using the Built-in Declarative Validation Rules

If the validity of one attribute is dependent on one or more other attributes, enforce this rule using entity validation, not attribute validation. Examples of when you would want to do this include the following:

Best Practice:







You have a Compare validator that compares one attribute to another. You have an attribute with an expression validator that examines the value in another attribute to control branching in the expression to validate the attribute differently depending on the value in this other attribute. You make use of conditional execution, and your precondition expression involves an attribute other than the one that you are validating.

Entity object validators are triggered whenever the entity, as a whole, is dirty. To improve performance, you can indicate which attributes play a role in your rule and thus the rule should be triggered only if one or more of these attributes are dirty. For more information on triggering attributes, see, Section 7.6, "Triggering Validation Execution".

7.4 Using the Built-in Declarative Validation Rules The built-in declarative validation rules can satisfy many, if not all, of your business needs. These rules are easy to implement because you don’t write any code. You use the user-interface tools to choose the type of validation and how it is used. Built-in declarative validation rules can be used to: ■

Ensure that key values are unique (primary key or other unique keys)



Determine the existence of a key value







■ ■



Make a comparison between an attribute and anything from a literal value to a SQL query Validate against a list of values that might be a literal list, a SQL query, or a view attribute Make sure that a value falls within a certain range, or that it is limited by a certain number of bytes or characters Validate using a regular expression or evaluate a Groovy expression Make sure that a value satisfies a relationship defined by an aggregate on a child entity available through an accessor Validate using a validation condition defined in a Java method on the entity

7.4.1 How to Ensure That Key Values Are Unique The Unique Key validator ensures that primary key values for an entity object are always unique. The Unique Key validator can also be used for a non-primary-key attribute, as long as the attribute is defined as an alternate key. For information on how to define alternate keys, see Section 4.10.15, "How to Define Alternate Key Values". Whenever any of the key attribute values change, this rule validates that the new key does not belong to any other entity object instance of this entity object class. (It is the business-logic tier equivalent of a unique constraint in the ResId="PersonEO_Rule_1" KeyName="AltKey"/>

7.4.3 How to Validate Based on a Comparison The Compare validator performs a logical comparison between an entity attribute and a value. When you add a Compare validator, you specify an operator and something to compare with. You can compare the following: ■

Literal value When you use a Compare validator with a literal value, the value in the attribute is compared against the specified literal value. When using this kind of comparison, it is important to consider ResId="Quantity_Rule_0" Severity="Warning" OnAttribute="Quantity" OperandType="VO_USAGE"

Defining Validation and Business Rules Declaratively 7-11

Using the Built-in Declarative Validation Rules

Inverse="false" CompareType="LESSTHANEQUALTO" ViewAccAttrName="Quantity" ViewAccName="ProductQuantitiesVO"/>

7.4.5 How to Validate Using a List of Values The List validator compares an attribute against a list of values (LOV). When you add a List validator, you specify the type of list to choose from: ■







Literal values - The validator ensures that the entity attribute is in (or not in, if specified) the list of values. Query result - The validator ensures that the entity attribute is in (or not in, if specified) the first column of the query's result set. The SQL query validator cannot use a bind variable, so it should be used only on a fixed, small list that you have to query from a table. All rows of the query are retrieved into memory. View object attribute - The validator ensures that the entity attribute is in (or not in, if specified) the view attribute. The View attribute validator cannot use a bind variable, so it should be used only on a fixed, small list that you have to query from a table. All rows of the query are retrieved into memory. View accessor attribute - The validator ensures that the entity attribute is in (or not in) the view accessor attribute. The view accessor is probably the most useful option, because it can take bind variables and after you’ve created the LOV on the user interface, a view accessor is required.

To validate using a list of values: 1. In the Application Navigator, double-click the desired entity object. 2.

On the Validators page of the overview editor, select where you want to add the validator. ■ ■

To add an entity-level validator, select the Entity folder. To add an attribute-level validator, expand the Attributes folder and select the appropriate attribute.

3.

Click the Add icon.

4.

In the Add Validation Rule dialog, in the Rule Type dropdown list, select List.

5.

In the Attribute list, choose the appropriate attribute.

6.

In the Operator field, select In or NotIn, depending on whether you want an inclusive list or exclusive.

7.

In the List Type field, select the appropriate type of list.

8.

Depending on the type of list you selected, you can either enter a list of values (each value on a new line) or an SQL query, or select a view object attribute or view accessor attribute.

9.

You can optionally click the Validation Execution tab and enter criteria for the execution of the rule, such as dependent attributes and a precondition expression. For more information, see Section 7.6, "Triggering Validation Execution".

10. Click the Failure Handling tab and enter or select the error message that will be

shown to the user if the validation rule fails. For more information, see Section 7.7, "Creating Validation Error Messages". 11. Click OK.

7-12 Fusion Developer’s Guide for Oracle Application Development Framework

Using the Built-in Declarative Validation Rules

Figure 7–3 shows what the dialog looks like when you use a List validator with a query. Figure 7–3 Using a Query in a List Validator

7.4.6 What Happens When You Validate Using a List of Values When you validate using a list of values, a tag is added to an entity object’s XML file. Example 7–4 shows the PersonEO.MaritalStatusCode attribute, which uses a query for the List validator. Example 7–4 List Validator XML Code

7.4.7 What You May Need to Know About the List Validator The List validator is designed for validating an attribute against a relatively small set of values. If you select the Query Result or View Object Attribute type of list validation, keep in mind that the validator retrieves all of the rows from the query before performing an in-memory scan to validate whether the attribute value in question matches an attribute in the list. The query performed by the validator’s SQL

Defining Validation and Business Rules Declaratively 7-13

Using the Built-in Declarative Validation Rules

or view object query does not reference the value being validated in the WHERE clause of the query. It is inefficient to use a validation rule when you need to determine whether a user-entered product code exists in a table of a large number of products. Instead, Section 8.5, "Using View Objects for Validation" explains the technique you can use to efficiently perform SQL-based validations by using a view object to perform a targeted validation query against the ResId="CreditLimit_Rule_0" OnAttribute="CreditLimit" OperandType="LITERAL" Inverse="false" MinValue="0" MaxValue="10000"/>

7.4.10 How to Validate Against a Number of Bytes or Characters The Length validator validates whether the string length (in characters or bytes) of an attribute's value is less than, equal to, or greater than a specified number, or whether it lies between a pair of numbers. To validate against a number of bytes or characters: 1. In the Application Navigator, double-click the desired entity object. 2.

On the Validators page of the overview editor, select where you want to add the validator. ■ ■

To add an entity-level validator, select the Entity folder. To add an attribute-level validator, expand the Attributes folder and select the appropriate attribute.

3.

Click the Add icon.

4.

In the Add Validation Rule dialog, in the Rule Type dropdown list, select Length.

5.

In the Attribute list, select the appropriate attribute.

6.

In the Operator field, select how to evaluate the value.

7.

In the Comparison Type field, select Byte or Character and enter a length.

8.

You can optionally click the Validation Execution tab and enter criteria for the execution of the rule, such as dependent attributes and a precondition expression. For more information, see Section 7.6, "Triggering Validation Execution".

9.

Click the Failure Handling tab and enter or select the error message that will be shown to the user if the validation rule fails. For more information, see Section 7.7, "Creating Validation Error Messages".

10. Click OK.

7.4.11 What Happens When You Validate Against a Number of Bytes or Characters When you validate using length, a tag is added to the entity object’s XML file, as shown in Example 7–6. For example, you might have a field where the user enters a password or PIN and the application wants to validate that it is at least 6 characters long, but not longer than 10. You would use the Length validator with the Between operator and set the minimum and maximum values accordingly. Example 7–6 Validating the Length Between Two Values

7.4.12 How to Validate Using a Regular Expression The Regular Expression validator compares attribute values against a mask specified by a Java regular expression. If you want to create expressions that can be personalized in meta OnAttribute="Email" Pattern="[A-Za-z0-9.!#$%&'*+-/=?^_`{|}~]+@[A-Z0-9-]+.[A-Z]{2,4}" Flags="CaseInsensitive" Inverse="false"/>

7.4.14 How to Use the Average, Count, or Sum to Validate a Collection You can use collection validation on the average, count, sum, min, or max of a collection. This validator is available only at the entity level. It is useful for validating the aggregate calculation over a collection of associated entities by way of an entity accessor to a child entity (on the many end of the association). You must select the association accessor to define the Collection validator. To validate using the average, count, or sum: 1. In the Application Navigator, double-click the desired entity object. 2.

On the Validators page of the overview editor, select the Entity folder and click the Add icon.

Defining Validation and Business Rules Declaratively 7-17

Using the Built-in Declarative Validation Rules

3.

In the Add Validation Rule dialog, in the Rule Type dropdown list, select Collection.

4.

In the Operation field, specify the operation (sum, average, count, min, or max) to perform on the collection for comparison.

5.

Select the appropriate accessor and attribute for the validation.

6.

Specify the operator and the comparison type and value.

7.

You can optionally click the Validation Execution tab and enter criteria for the execution of the rule, such as dependent attributes and a precondition expression. For more information, see Section 7.6, "Triggering Validation Execution".

8.

Click the Failure Handling tab and enter or select the error message that will be shown to the user if the validation rule fails. For more information, see Section 7.7, "Creating Validation Error Messages".

9.

Click OK.

7.4.15 What Happens When You Use Collection Validation When you validate using a Collection validator, a tag is added to the entity object’s XML file, as in Example 7–8. Example 7–8 Collection Validator XML Code

7.4.16 How to Determine Whether a Key Exists The Key Exists validator is used to determine whether a key value (primary, foreign, or alternate key) exists. There are a couple of benefits to using the Key Exists validator: ■



The Key Exists validator has better performance because it first checks the cache and only goes to the ResId="MembershipId_Rule_0" OperandType="EO" AssocName= "oracle.fodemo.storefront.entities.associations.PersonsMembershipsBaseFkAssoc"/>

7.4.18 What You May Need to Know About Declarative Validators and View Accessors When using declarative validators you must consider how your validation will interact with expected input. The combination of declarative validators and view accessors provides a simple yet powerful alternative to coding. But, as powerful as the combination is, you still need to consider how OperandType="EXPR" Inverse="false">

9.2.5 How to Edit an Existing Application Module After you've created a new application module, you can edit any of its settings by using the Edit Application Module dialog. To launch the editor, choose Open from the context menu in the Application Navigator, or double-click the application module. By visiting the different pages of the editor, you can adjust the > . . .

Using Oracle ADF Model in a Fusion Web Application

11-19

Working with the path="oracle.fodemo.storefront.pageDefs.loginPageDef"/> . . . < path="orderbookingservice.FusionOrderDemoBookingService"/>

The value of the filedBy parameter is defined by a binding on the userID version="11.1.1.44.61" id="myOrdersPageDef" Package="oracle.fodemo.storefront.pageDefs" EnableTokenValidation="false"> . . .

The binding object defined in the action element encapsulates the information needed to invoke the built-in commit operation on the StoreServiceAM id="pageTemplateBinding"/>

The invokeAction object invokes the executeMyOrdersForCustomerVO method, which is named in the Binds attribute. In the bindings wrapper element, the methodAction binding object encapsulates the details about how to invoke the method. The iterator binding named MyOrderItemsIterator was created by dropping the MyOrderItem collection on the page as a table. The iterator binding named MyOrdersIterator was created by dropping the MyOrders collection, which has a master-detail relationship with the MyOrderItems collection. For more information, see Chapter 22, "Displaying Master-Detail RangeSize="25" id="Products2Iterator"/>

11.8 Using Simple UI First Development While the > . . . view1 toView2 view2 toView3 view3 . . .

Use the task flow diagram as a starting point for creating basic control flows between activities. Later, you can edit control flow properties in the Structure window, Property Inspector or overview editor for the task flow diagram. To define a control flow case directly in the task flow diagram: 1. In the Application Navigator, double-click a task flow source file, for example, adfc-config.xml, to display the task flow diagram. 2.

In the ADF Task Flow page of the Component Palette, select Control Flow Case.

3.

On the diagram, click a source activity, for example a view, and then click the destination activity, as shown in Figure 13–12.

Getting Started with ADF Task Flows

13-13

Creating Task Flows

Figure 13–12 Control Flow Case

JDeveloper adds the control flow case to the diagram. Each line that JDeveloper adds between activities represents a control flow case. The arrow indicates the direction of the control flow case. JDeveloper automatically adds a default wildcard (*) from-outcome value as the control flow label. The from-outcome contains a value that can be matched against values specified in the action attribute of UI components. 4.

To change the from-outcome, select the text next to the control flow in the diagram. By default, this text is the wildcard * character as shown in Figure 13–12. You can overwrite the text with a new from-outcome, for example, toView2.

5.

To change the from-activity-id (identifies the source activity) or to-activity-id (identifies the target activity), drag either end of the arrow in the diagram to a new activity. Tips: After you select the control flow in the task flow diagram, you can also change its properties in the Property Inspector or the Structure window. The Structure window is helpful for displaying the relationship between control rules and cases.

You can also click Control Flows on the Overview tab for the task flow diagram to add cases, as shown in Figure 13–13. To add a case, make sure that the From Activity (source activity) and the To Activity (target activity) for the rule have already been added to the task flow. Figure 13–13 Control Flows on Task Flow Editor Overview Tab

13.2.4 How to Add a Wildcard Control Flow Rule You can add a wildcard control flow rule to an unbounded or bounded task flow. The steps for adding it are similar to those for adding any activity to a task flow diagram. To add a wildcard control flow rule: 1. In the Application Navigator, double-click a task flow source file, for example, adfc-config.xml, to display the task flow diagram. 2.

Drag Wildcard Control Flow Rule from the ADF Task Flow page of the Component Palette and drop it on the task flow diagram.

3.

Select Control Flow Case from the ADF Task Flow page list of the Component Palette.

13-14 Fusion Developer’s Guide for Oracle Application Development Framework

Creating Task Flows

4.

In the task flow diagram, drag the control flow case from the wildcard control flow rule to the target activity. The target can be any activity type.

5.

By default, the label below the wildcard control flow rule is *, which corresponds to a single * character in its from-activity-id value. To change this value, select the wildcard control flow rule in the diagram. In the Property Inspector for the wildcard control flow rule, enter a new value in the from_activity_id_field, for example, project*. The wildcard must be a trailing character in the new label. Tip: You can also change the from-activity-id value in the Overview editor for the task flow diagram.

13.2.5 What Happens When You Create a Control Flow Rule Understanding the elements that define the rules in the source file for the task flow helps when creating control flow rules directly in the ADF task flow diagram, ADF task flow overview editor, or Structure window, or when adding them directly in the XML source file. Example 13–2 shows the general syntax of a control flow rule element in the task flow source file. Example 13–2

Control Flow Rule Syntax in the Source File

from-view-activity actionmethod outcome destinationActivity . . .

Control flow rules can consist of the following meta encoding="windows-1252" ?> /SurveyPrompt.jspx

Getting Started with ADF Task Flows

13-21

Running ADF Task Flows

13.5 Running ADF Task Flows The procedure for running and debugging task flows differs depending on whether the task flow is bounded or unbounded, whether it contains pages or page fragments, or whether it accepts input parameters.

13.5.1 How to Run a Task Flow Definition That Contains Pages You can run or debug an ADF bounded task flow that contains view activities that are pages. For information on how to run a task flow definition that contains view activities that are page fragments, see Section 13.5.2, "How to Run a Task Flow Definition That Uses Page Fragments". You can select a view activity inside an ADF task flow diagram or the Application Navigator and choose Run to run an ADF bounded task flow. Note:

In an ADF unbounded task flow, you must designate the view as a default activity and run the ADF unbounded task flow from the Application Navigator. For more information, see Section 13.4, "Designating a Default Activity in an ADF Bounded Task Flow". If the first activity that runs in the ADF task flow is an activity type other than view, you must use an ADF bounded task flow. To run or debug a task flow definition that uses pages: In the task flow diagram, right-click the task flow and choose either Run or Debug.







You can also run the task flow directly by entering its URL in the browser, for example. http://mymachine:8988/StoreFrontModule-StoreFrontUI-context-r oot/faces/home You can right-click the task flow definition in the Application Navigator and choose either Run or Debug.

13.5.2 How to Run a Task Flow Definition That Uses Page Fragments ADF bounded task flows that use page fragments are intended to run only within an ADF region. A page fragment is a JSF JSP document that is rendered as content in another JSF page. For more information, see Section 16.1.9, "What You May Need to Know About Page Fragments". To run or debug a task flow definition that uses page fragments: 1. Create a JSF page containing a region that is bound to the task flow definition. When you drop a bounded task flow containing page fragments onto a JSF page, JDeveloper does this automatically for you. 2.

Create a view activity in the project's unbounded task flow that refers to the page. See Section 13.2.2, "How to Add an Activity to an ADF Task Flow" for more information.

3.

Right-click the view activity in the Application Navigator or in the task flow diagram and choose Run.

13-22 Fusion Developer’s Guide for Oracle Application Development Framework

Running ADF Task Flows

13.5.3 How to Run a Task Flow Definition That Has Parameters Before you run a task flow definition with parameters, you must first run a task flow definition containing pages.For more information about bounded task flow input parameters, see Chapter 15, "Using Parameters in Task Flows". To run a task flow definition that has input parameter definitions: If the task flow definition has defined input parameters, the Set Run Configuration dialog displays after you select either Run or Debug, as shown in Figure 13–17.

1.

Figure 13–17

2.

Set Run Configuration dialog

In the Input Parameters list, enter values that you want to be passed as input parameters to the task flow. If you do not specify a value, the input parameter is not used when calling the bounded task flow. Each required input parameter in the list displays with an asterisk, as shown in Figure 13–17. You must specify the parameter value as a literal string. You cannot specify an EL expression.

3.

Click OK.

13.5.4 How to Run a JSF Page You can run a JSF page by right-clicking the page in the Application Navigator and choosing Run. However, if the page contains navigation UI components such as a button or link, navigation is not guaranteed to work. To run a JSF Page with fully functioning navigation: 1. Create a bounded or unbounded task flow. See Section 13.2.1, "How to Create an ADF Task Flow" for more information. 2.

Add a view activity to the task flow. See Section 13.2.2, "How to Add an Activity to an ADF Task Flow" for more information

3.

In the Application Navigator, select the JSF page you want to run and drop it on top of the view activity in the task flow diagram. This associates the view activity with the JSF page.

4.

In the diagram, right-click the view activity and choose Run.

13.5.5 How to Run an ADF Unbounded Task Flow To run or debug an unbounded task flow, you must select a specific view activity with which to start.

Getting Started with ADF Task Flows

13-23

Running ADF Task Flows

To run a view activity in an ADF unbounded task flow: ■ In the task flow diagram, right-click the view activity and choose either Run or Debug. The unbounded task flow runs beginning with the selected view activity. ■

If you have selected something other than a single view activity (or have nothing selected), you are prompted to select one in the Set Run Configuration dialog.

13.5.6 How to Set a Run Configuration for a Project A run configuration contains settings that determine how projects run, such as specifying the first activity to run in a task flow. You can define one or more run configurations for a project. Within a run configuration, you can designate an ADFc source file as the default run target. When you run the project, the source file is the first to run. To define a default task flow run target: 1. Select the project in the Application Navigator. 2.

From the main menu, choose Run > Choose Active Run Configuration > Manage Run Configurations.

3.

Choose Run/Debug/Profile and choose New.

4.

Enter a name for the new run configuration.

5.

If you want to base the new configuration on an existing one, choose a configuration in the Copy Configuration Settings dropdown list.

6.

Click OK to exit the dialog.

7.

Click Edit.

8.

In the Default Run Target dropdown list, select a source file for the ADF task flow that should run first when you run the project. Once you choose a task flow, you can set a view activity (for an unbounded task flow) or input parameters (for task flow definitions).

9.

In the left panel of the Edit Configuration dialog, click ADF Task Flow.

10. In the Task Flow drop-down list, located on the right panel, select the ADF task

flow containing the run target. 11. If you are running an unbounded task flow, the Edit Run Configuration dialog

displays the Run Target Activity list. Select the view activity that will run first in the application. 12. Click Open.

The next time you run the project, the saved run configuration will be available in the Run > Choose Active Run Configuration menu. If you are running a bounded task flow that has been set up to accept input parameters, a dialog will display a section for specifying values for all input parameters defined for the bounded task flow (For more information, see Chapter 13.5.3, "How to Run a Task Flow Definition That Has Parameters".

13-24 Fusion Developer’s Guide for Oracle Application Development Framework

Refactoring to Create New ADF Task Flows and Templates

13.6 Setting Project Properties for ADF Task Flows You can set a project property to change the default source directory for ADF task flows created within a project. The task flow definition for any ADF task flow you create within the project will be located in this directory. This source directory for a new project is, by default, C:\JDeveloper\mywork\Application46\Project1\public_html\WEB-INF To change the default source directory for task flow definitions: 1. In the Application Navigator, right-click on the project and choose Project Properties. 2.

In the left panel of the Project Properties dialog, click ADF Task Flows.

3.

Select Use Project Settings.

4.

In the default ADF Task Flow Source Directory field enter a new default directory for task flow definitions created within the project.

13.7 Refactoring to Create New ADF Task Flows and Templates You can convert existing activities, JSF page flows, and JSF pages into new ADF Controller components such as ADF bounded task flows and task flow templates.

13.7.1 How to Create an ADF Bounded Task Flow from Selected Activities You can create a new ADF bounded task flow based on activities you select in an existing ADF bounded or unbounded task flow. To create a new ADF bounded task flow from selected activities: 1. Open the ADF unbounded or bounded task flow containing the activities you want to use in the new task flow. 2.

In the task flow diagram, select one or more activities. Tip: To select multiple activities in a diagram, click the left mouse button and drag the cursor over the activities.

You can also press the Ctrl key while selecting each activity. 3.

Right-click your selection and choose Extract Task Flow. The Create Task Flow dialog displays, which allows you to create a new ADF bounded task flow. For more information, see Section 13.2, "Creating Task Flows".

When you are done, the new ADF bounded task flow displays in the editor. The properties shown in Table 13–4 are automatically set for the new task flow. Table 13–4

Properties Updated in the New ADF Bounded Task Flow

Property

Value

Task flow definition ID

Value you entered in the Task Flow ID field in the Create ADF Task Flow dialog.

Default activity

Determined as the destination of all incoming control flow cases. If more than one destination exists, an error is flagged and the entire operation is rolled back.

Getting Started with ADF Task Flows

13-25

Refactoring to Create New ADF Task Flows and Templates

Table 13–4 (Cont.) Properties Updated in the New ADF Bounded Task Flow Property

Value

Control flow rules

Control flow cases with selected source activities are included in the new ADF bounded task. A source activity is an activity from which a control flow leads. The new ADF bounded task flow includes the following types of control flow cases: ■



Both the source and target activities in the control flow case were selected to create the new task flow. Only the source activity was selected to create the new task flow. Destinations are changed to the corresponding new task flow return activities added for each outcome.

The following changes automatically occur in the originating task flow (the task flow containing the activities you selected as the basis for the new task flow): ■

■ ■

A new task flow call activity is added to the originating task flow. The task flow call activity calls the new ADF bounded task flow. The selected activities are removed from the originating task flow. Existing control flow cases associated with the activities you selected are removed from the originating task flow. They are replaced with new control flow cases: –

An incoming control flow case to the old activity is redirected to the new task flow call activity.



An outgoing control flow cases from the old activity is redirected from the new task flow call activity.

13.7.2 How to Create a Task Flow from JSF Pages You can create a new ADF bounded task flow based on selected pages in a JSF page flow. Only pages that are part of a flow (that is, those that are linked by JSF navigation cases) are converted to view activities in the new task flow. To create a new task flow from selected JSF pages in a page flow. 1. In the task flow editor, open the page flow containing the pages you want to use in the new bounded task flow. 2.

In the task flow diagram, select one or more JSF pages. Tip: To select multiple elements in a diagram, click the left mouse button and drag the cursor over the elements.

You can also press the Ctrl key while selecting each element. 3.

Right-click your selection and choose Generate ADF Task Flow. The Create Task Flow dialog displays, which allows you to create a new ADF unbounded or bounded task flow. For more information, see Section 13.2, "Creating Task Flows".

13.7.3 How to Convert ADF Bounded Task Flows You can convert an existing ADF bounded task flow to an unbounded task flow or change whether the views it contains are pages or page fragments. Table 13–5 describes the results of each conversion.

13-26 Fusion Developer’s Guide for Oracle Application Development Framework

What You Should Know About Task Flow Constraints

Table 13–5

Converting ADF Bounded Task Flows

Conversion

Result

ADF bounded task flow to unbounded task flow

ADF bounded task flow loses all meta> /Home.jspx

The view activity ID and page name do not have to be the same. The file extension for a page fragment is.jsff: WEB-INF/Home.jsff

14.2.1 Adding a View Activity The steps for adding a view activity are similar to those for adding any activity to a task flow diagram (see Section 13.2.2, "How to Add an Activity to an ADF Task Flow". After you add the view activity, you can double-click it to display the Create JSF JSP Page wizard, which enables you to create a new page or page fragment. You also use the wizard to define characteristics for the page or page fragment. JDeveloper automatically associates the completed page or page fragment with the view activity. You can also drag an existing page or page fragment from the Application Navigator and drop it on top of a view activity. If you drag a page or page fragment to any other location on the diagram, a new view activity associated with the page or page fragment is automatically created. During creation, a default id for the view activity is automatically generated (for example Home) based on the name of the page or page fragment.

14.2.2 Transitioning Between View Activities Transitioning refers to one view activity passing control to another view activity.For example, control flow can be initiated at runtime by selecting a UI component on a page, such as a button or link. The Action attribute of the UI component should be set to the corresponding control flow case from-outcome leading to the next task flow activity. You can navigate from a view activity to another activity using either a constant or dynamic value on the Action attribute of the UI component.

14-4 Fusion Developer’s Guide for Oracle Application Development Framework

Using View Activities

Figure 14–3 Edit Property dialog





Constant: value of the Action attribute of the component is an Action Outcome, as shown in Figure 14–3. Action Outcome is a constant value that always triggers the same control flow case. When an end user clicks the component, the activity specified in the control flow case is performed. There are no alternative control flows. Dynamic: value of the Action attribute of the component is bound to a managed bean or a method. The value of the method binding determines the next control flow case that should be performed. For example, the method might verify user input on a page and return one value if the input is valid and another value if the input is invalid. Each of these different action values could trigger different navigation cases, causing the application to navigate to one of two possible target pages.

For more information about components that are bound to action="toOffices">

14.2.3 Bookmarking View Activities Bookmarking is available only for view activities within ADF unbounded task flows. When an end user bookmarks a page associated with a view activity, the URL that displays in the browser’s address field for the view is saved as the bookmark. In most cases, this URL cannot be used to redisplay the page associated with the view. For example the URL may contain Windows state information that cannot be used to redisplay the page. The bookmark URL should contain information that enables dynamic content on the page to be reproduced. For example, if an end user bookmarks a page displaying a customer's contact information, the bookmark URL needs to contain not only the page but also some identifier for the customer. This will enable contact information for the same customer to display when he returns to the page using the bookmark. To ensure that the URL for a page displayed in a browser can be used as a bookmark, identify the view activity associated with the page as bookmarkable. At runtime, you can identify if a view activity within an unbounded task flow has been designated as bookmarkable using the ViewBookmarkable() method. The method is located off the ViewPortContext. After you designate a view activity as bookmarkable, you can optionally specify one or more URL Parameters. The value of url-parameter is an EL expression. The EL expression specifies where the parameters that will be included in the URL are retrieved when the bookmarkable URL is generated. The EL expression also stores a

14-6 Fusion Developer’s Guide for Oracle Application Development Framework

Using View Activities

value from the URL when the bookmarkable URL is dereferenced. The converter option identifies a method that performs conversion and validation when parameters are passed via bookmarkable view activity URLs. In addition, you can specify an optional method that is invoked after updating the application model with submitted URL parameter values and before rendering the view activity. You can use this method to retrieve additional information based on URL parameter key values. Instead of designating the view activity as bookmarkable, you can specify the redirect option. redirect causes the ADF Controller to create a new browser URL for the view activity. The original URL for the view activity is no longer used. For more information, see Section 14.2.3.2, "How to Specify HTTP Redirect" for more information. Example 14–3 contains the URL syntax for a bookmarked view activity. Example 14–3

ADF Unbounded Task Flow View Activity URL Syntax

//faces/?=&...

The syntax of the URL for the bookmarked view activity is: ■











: Provided by customization at site or admin level, for example, http://mycompany.com/internalApp. : The web application context root, for example, myapp. The context root is the base path of a web application. For example, maps to the physical location of the WEB-INF node on the server. faces: The faces servlet mapping. The value in faces points to the node containing the faces-config.xml configuration file. : The identifier for the bookmarked view activity, for example, edit-customers. : The name of the bookmarked view activity URL parameter, for example, customer-id. : The parameter value, derived from an EL expression, for example, #{pageFlowScope.employee.id}. The value of the EL expression must be capable of being represented as a string.

Example 14–4 contains a sample URL for a bookmarkable view activity in an ADF unbounded task flow. Example 14–4

Sample URL for Bookmarkable View Activity

http://mycompany.com/internalApp/MyApp/faces/edit-customers?customer-id=1234&...

14.2.3.1 How to Create a Bookmarkable View Activity To create a bookmarkable view activity, designate a view activity as bookmarkable, specify a URL parameter in the bookmark, and specify a method that is executed after the bookmark is dereferenced. To designate a view activity as bookmarkable: 1. In the unbounded task flow diagram, select the view activity. 2.

In the Property Inspector, click Bookmark.

Working with Task Flow Activities 14-7

Using View Activities

3.

In the bookmark dropdown list, select true.

4.

Expand the URL Parameters section to add optional URL parameters that will be included in the URL for the bookmarked view activity: ■ ■



name: A name for the parameter. value: A settable EL expression that, when evaluated, specifies the parameter value, for example, #{pageFlowScope.employeeID}. The value must be capable of being represented as a string. converter: (optional): An EL expression to an object that implements oracle.adf.controller.URLParameterConverter.

The value is where the parameters that will be included in the URL are retrieved from when the bookmarkable URL is generated. In addition, parameters are stored here when the bookmarkable URL is dereferenced. If the EL expression entered in value returns NULL, the parameter is omitted from the bookmarked view activity URL. The name and value are used to append a bookmark parameter to the view activity URL, as shown in Example 14–4. 5.

In the converter field, you can enter an optional value binding to use for each bookmark URL parameter value, for example, #{pageFlowScope.employee.idConverter}. A URL parameter converter’s getAsObject() method takes a single string value as its input parameter and returns an object of the appropriate type. ADF Controller invokes the converter method on the URL parameters before applying the parameter value to the application's model objects. Similarly, the converter's getAsString() method takes an object as its input parameter and returns a string representation that is used on the URL. In a JSF application, > This technique could adversely affect back button behavior. If an end user clicks a browser Back button, the refresh occurs again, and navigation is forward, not backward as expected. In this situation, use HTTP redirect instead. To specify HTTP redirect for a view activity: 1. In the unbounded task flow diagram, select the view activity. 2.

In the Property Inspector, click Common.

3.

In the redirect dropdown list, select true.

14.2.3.3 What Happens When You Designate a View as Bookmarkable When you designate a view activity as bookmarkable, a bookmark element is added to the meta> /folderA/folderB/display-employee-info.jspx employee-id #{pageFlowScope.employee.id} #{pageFlowScope.employee.validateId} #{pageFlowScope.employee.query> #{binding.Region.InputValue='1'} toRegion1 #{binding.Region.InputValue='2'} toRegion2 #{binding.Region.InputValue='3'} toRegion3 toRegion3

14.5 Using Method Call Activities In a standard JSF application, application logic can be invoked only from actions specified within the JSF page markup. A method call activity allows you to call a custom or built-in method that invokes application logic from anywhere within an application's control flow. You can specify methods to perform tasks such as initialization before displaying a page, cleanup after exiting a page, exception handling, and so forth. As shown in Figure 14–5, the Fusion Order Demo application uses a method call activity in the Employee Registration bounded task flow. The activity calls userRegistrationCreate, a method exposed on the StoreServiceAM > #{pageFlowScope.taxService.calculateSalesTax} #{pageFlowScope.result} gotoError #{bindings.userRegistrationCreate.execute}

Working with Task Flow Activities

14-17

Using Task Flow Call Activities

editBasicInfo

14.6 Using Task Flow Call Activities You can use the task flow call activity to call an ADF bounded task flow from either an ADF unbounded or bounded task flow. Options on the task flow call activity allow you to call a bounded task flow located within the same application or a different application. The called bounded task flow executes beginning with its default activity. There is no depth limit to the number of ADF bounded task flow calls. A called ADF bounded task flow can call another ADF bounded task flow, which can call another and so on. To pass parameters into task flows, you must specify input parameter values on the task flow call activity. These values must correspond to the input parameter definitions on the called task flow definition (see Section 14.6.2, "How to Specify Input Parameters on a Task Flow Call Activity" for more information). ■



The value on the task flow call activity Input Parameter specifies where the value will be taken from within the calling task flow. The value on the Input Parameter Definition for the called task flow specifies where the value will be stored within the called task flow definition once it is passed. Tip: When a task flow definition is associated with a task flow call activity, input parameters are automatically inserted on the task flow call activity based on the input parameter definitions defined on the task flow definition. Therefore, the application developer only needs to assign values to the task flow call activity input parameters.

By default, all objects are passed by reference. Primitive types (for example, int, long, or boolean) are always passed by value. The technique for passing return values out of the ADF bounded task flow to the caller is similar to the way that input parameters are passed. See Section 15.4, "Specifying Return Values" for more information.

14.6.1 How to Call an ADF Bounded Task Flow To call an ADF bounded task flow, add a task flow call activity to the diagram for the calling bounded or unbounded task flow. To call an ADF bounded task flow: 1. In the editor, open the task flow diagram for the calling ADF task flow. 2.

In the ADF Task Flow dropdown list of the Component Palette, select a task flow call activity and drop it on the diagram.

3.

Identify the called task flow using one of the following techniques: ■

In the task flow diagram, double-click the task flow call activity. The Create ADF Task Flow dialog displays, where you specify options for creating a new bounded task flow.

14-18 Fusion Developer’s Guide for Oracle Application Development Framework

Using Task Flow Call Activities



Drag an existing ADF bounded task flow from either the Application Navigator or the Resource Palette and drop it on the task flow call activity in the task flow diagram. Tips: You can also drag an ADF bounded task flow from the Application Navigator and drop it directly on the task flow diagram. This automatically adds to the diagram a task flow call activity that calls the ADF bounded task flow.

You can drop an ADF bounded task flow on a page or page fragment. If the ADF bounded task flow consists of pages (not page fragments), you can choose whether to add a Go Link or Go Button UI component on the page where you drop the task flow. An end user can click the button or link to call the task flow definition. This may in turn automatically generate the task flow call activity if the page is already associated with an existing view activity in an ADF task flow. You cannot drop an ADF bounded task flow contained in one application to a diagram contained in another application using the Application Navigator, even though both applications appear in the navigator. In addition, you cannot drop a bounded task flow contained in one project onto a task flow diagram contained in another project. Instead, you can package the bounded task flow in an ADF Library, then reuse it in your current application or project. You can then drag the bounded task flow from the Resource Catalog or from the Component Palette page that is created when you import the library. See Section 31.1.2, "Using the Resource Palette" for more information.



Associate the task flow call activity to the called task flow definition by following these steps:

a.

In the task flow diagram, select the task flow call activity.

b.

On the Common page of the Property Inspector, expand the Task Flow Reference node.

c.

Enter a document name. This is the name of the source file containing the id of the called ADF bounded task flow, for example, called-task-flow-definition.xml.

d.

Enter an id. This is the task flow definition id contained in the XML source file for the called ADF bounded task flow, for example, targetTaskFlow.

14.6.2 How to Specify Input Parameters on a Task Flow Call Activity The suggested method for mapping parameters between a task flow call activity and its called bounded task flow is to first specify input parameter definitions for the called task flow definition. Then you can drag the task flow definition from the Application Navigator and drop it on the task flow call activity. The task flow call activity input parameters will be created automatically based on the task flow definition’s input parameter definition. For more information, see Section 15.2, "Passing Parameters to an ADF Bounded Task Flow".

Working with Task Flow Activities

14-19

Using Task Flow Call Activities

You can, of course, first specify input parameters on the task flow call activity. Even if you have defined them first, they will automatically be replaced based on the input parameter definitions of the called task flow definition, once it is associated with the task flow call activity. If you haven’t yet created the called task flow definition, you may still find it useful to specify input parameters on the task flow call activity. Doing so at this point allows you to identify any input parameters you expect the task flow call activity to eventually map when calling a task flow definition. To specify input parameters on the task flow call activity Select the task flow call activity in the task flow diagram and open the Property Inspector.

1. 2.

Click Parameters.

3.

Click the + icon and enter a name for the parameter, for example, empno. Tip: Dropping an ADF bounded task flow on a task flow call activity in a diagram automatically populates the name field.

4.

Enter a parameter value, for example, #{pageFlowScope.callingTaskflowParm}. The value specifies where the parameter value will be taken from within the calling task flow. By default, all objects are passed by reference. Primitive types (for example, int, long, or boolean) are always passed by value.

5.

After you have specified an input parameter, you can specify a corresponding input parameter definition for the called ADF bounded task flow. For more information, see Section 15.2, "Passing Parameters to an ADF Bounded Task Flow".

14.6.3 How to Call an ADF Bounded Task Flow Located in Another Web Application You can use the remote-app-url option on a task flow call activity to call an ADF bounded task flow located in a different web application. You specify in remote-app-url an EL expression that, when evaluated, returns the remote web application's URL. Using an EL expression allows you to configure the remote application's URL in any manner, including using context initialization parameters in web.xml, for example #{initParam.remoteAppUrl}. In addition to the remote-app-url, you must also specify a task flow reference in the task flow call activity meta> . . . view1 /WEB-INF/called-task-flow-definition.xml called-task-flow-definition . . .

14.6.8 What Happens at Runtime: Using a Task Flow Call Activity The ADF Controller performs the following steps when an ADF bounded task flow is called using a task flow call activity: 1.

Verifies that the user is authorized to call the ADF bounded task flow.

Working with Task Flow Activities

14-23

Using Task Flow Return Activities

2.

Invokes task flow call activity before listener or listeners, if specified (see Section 14.6.6, "How to Specify Before and After Listeners").

3.

Evaluates the input parameter values on the ADF bounded task flow.

4.

Pushes the called ADF bounded task flow onto the stack and initializes its pageFlow scope

5.

Sets input parameter values in the called ADF bounded task flow's context

6.

Invokes an ADF bounded task flow initializer method, if one is specified (see Section 17.1, "Using Initializers and Finalizers" for more information).

7.

Executes the ADF bounded task flow's default activity.

14.7 Using Task Flow Return Activities The task flow return activity identifies the point in the application control flow where an ADF bounded task flow completes and sends control flow back to the caller. You can use the task flow return activity only within an ADF bounded task flow. A gray circle around an activity icon indicates that the activity is an exit point for an ADF bounded task flow. Each ADF bounded task flow can have zero to many task flow return activities. In Figure 14–8, the ADF bounded task flow contains two task flow return activities. Figure 14–8 Multiple Task Flow Return Activities

Each task flow return activity specifies an outcome that is returned to the calling task flow. For example, the outcome for the AddNewCust task flow return activity is registerCustomer. As shown in Figure 14–9, the calling task flow can match this outcome with a control flow case from-outcome. This handles control flow upon return from the called task flow.

14-24 Fusion Developer’s Guide for Oracle Application Development Framework

Using Task Flow Return Activities

Figure 14–9 Control Flow Case Specified on Calling Task Flow

The restore-save-point option specifies whether model changes made within an ADF bounded task flow should be discarded when exiting using a task flow return activity. If set to true, transactions are rolled back to the ADFm save point that was created when the ADF bounded task flow was originally entered. You can specify this option only if the bounded task flow on which the task flow return activity is located was entered without starting a new transaction. For more information, see Section 17.2.1, "How to Enable Transactions in an ADF Bounded Task Flow" To add a task flow return activity to an ADF bounded task flow: 1. Drag a task flow return activity from the ADF Task Flow dropdown list in the Component Palette to the diagram for the ADF bounded task flow. 2.

In the task flow diagram, select the task flow return activity.

3.

On the Common page of the Property Inspector, expand the Outcome section.

4.

In the name field, enter an outcome, for example, preferredCustomer. Specifying this will return an outcome to the caller when the ADF bounded task flow exits. You can specify only one outcome per task flow return activity. The calling ADF task flow should define control flow rules to handle control flow upon return. See Section 13.2.3, "How to Add Control Flows" for more information.

5.

In Property Inspector, click Behavior.

6.

In the Reentry dropdown list, choose either reentry-allowed or reentry-not-allowed. ■



reentry-allowed: Reentry is allowed on any view activity within the ADF bounded task flow. reentry-not-allowed: Reentry of the ADF bounded task flow is not allowed. If you specify reentry-not-allowed on a task flow definition, an end user can still click the browser back button and return to a page within the bounded task flow. However, if the user does anything on the page such as clicking a button, an exception (for example, InvalidTaskFlowReentry) is thrown indicating the bounded task flow was reentered improperly. The actual reentry condition is identified upon the submit of the reentered page.

Working with Task Flow Activities

14-25

Using Save Point Restore Activities

Your selection defines the default behavior when the ADF bounded task flow is reentered by an end user clicking a browser back button. This selection applies only if reentry-outcome-dependent has been set on the ADF bounded task flow where the task flow return activity is located. For more information, see Section 17.3, "Reentering an ADF Bounded Task Flow". 7.

In the End Transaction dropdown, list choose either commit or rollback. ■ ■

commit: commits the existing transaction to the > . . . inputParameter1 #{pageFlowScope.parmValue1} java.lang.String . . .

Example 15–2 shows the input parameter meta> . . . inputParameter1 #{pageFlowScope.newCustomer} . . Using Parameters in Task Flows 15-3

Passing Parameters to an ADF Bounded Task Flow

.

Best Practice:

You can set parameters for a page using an ADF task flow as opposed to dropping a parameterized form from the taskFlowId="/WEB-INF/Department.xml#Department" xmlns="http://xmlns.oracle.com/adf/Controller/binding" Refresh="ifNeeded">

Appending inputValue to the parameter value binding EL expression, ensures that the parameter is assigned the value of the binding rather than the actual binding object. If you use the above syntax without appending inputValue #{bindings.bindingId}, the binding object (not the value of the binding) is passed. Therefore, the binding will end up being evaluated within the wrong context (the context of the Task Flow Call, ADF Region, or ADF Dynamic Region instead of the context of the page) and multiple taskFlowId="/WEB-INF/region-task-flow-definition.xml#region-task-flowdefinition" xmlns="http://xmlns.oracle.com/adf/controller/binding"/>

taskFlowId can also contain an EL expression that evaluates to a String or to the public class TaskFlowId (oracle.adf.Controller.TaskFlowId). See Section 16.2, "Creating ADF Dynamic Regions" for more information. An ADF region is comprised of the following: ■

The task flow binding



An ADF bounded task flow

16-8 Fusion Developer’s Guide for Oracle Application Development Framework

Introduction to ADF Regions



An ADF region tag (af:region)



A UI component called Region

A task flow binding is added to the page definition each time you add a region to the JSF page. The task flow binding is the bridge between the region UI component and the ADF bounded task flow. It binds a specific region instance to its associated task flow, and maintains all information specific to the ADF bounded task flow. When you drop the an ADF bounded task flow onto a JSF page, all of the The ADF region is refreshed a single time when its RefreshCondition evaluates true. The RefreshCondition must evaluate to a boolean value. At the time the RefreshCondition is evaluated, if the variable bindings is used within the EL Expression, the context refers to the binding container of the parent page, not the page fragment displayed within the ADF Region. RefreshCondition is independent of the change of value of binding parameters. If the task flow binding parameters do not change, nothing within the ADF region will change.



Refresh="ifNeeded" Any change to a task flow binding parameter values causes the ADF region to refresh. There are no values other than ifNeeded for the Refresh attribute. If the ADF region task flow binding doesn't have parameters, Refresh="ifNeeded" is equivalent to not specifying the Refresh attribute. If you set Refresh to ifNeeded, the RefreshCondition attribute should not be specified.

16-10 Fusion Developer’s Guide for Oracle Application Development Framework

Introduction to ADF Regions

Refresh="ifNeeded" is not supported when passing parameters to the task flow binding using a dynamic parameter map. You must instead use the RefreshCondition="#{EL.Expression}". RefreshCondition and Refresh are mutually exclusive. Refresh="ifNeeded" takes precedence over RefreshCondition. If the bindings variable bindings is used within the EL expression at the time RefreshCondition is evaluated, the context refers to the binding container of the parent page, not the page fragment displayed within the ADF region. The expression is evaluated during the PrepareRender phase of the ADF page lifecycle (for more information, see Chapter 19, "Understanding the Fusion Page Lifecycle"). Example 16–2 contains a sample task flow binding located within the page definition of a page on which an ADF region has been added. Example 16–2

Refresh Option Specified in ADF region binding



If the variable, bindings, is used within the EL expression, the context refers to the binding container of the parent page, not the page fragment displayed within the ADF region. You do not need to refresh an ADF region to refresh the version="2.0" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">

Using ADF Task Flows as Regions 16-11

Creating ADF Dynamic Regions

The file extension for a page fragment is.jsff. An ADF bounded task flow that is added to a JSF JSP page as an ADF region must use page fragments, not pages (see Section 16.1, "Introduction to ADF Regions" for more information).

16.1.10 What You May Need to Know about ViewPorts A ViewPort is a display area that has its own viewId and is capable of navigating independently of other ViewPorts. A browser window and a region are both examples of a ViewPort. The RootViewPort displays the main page in a browser window. The RootViewPort may have child ViewPorts, for example, regions on the page, but does not have a parent ViewPort.

16.1.11 What You May Need to Know about Securing ADF Regions You can set security on the ADF bounded taskflow that is displayed in an ADF region as well as on the page definition for the page containing the region (see Chapter 28, "Adding Security to a Fusion Web Application" for more information). If an end user displays a page that contains an ADF region he is not authorized to view, the contents of the ADF region will not display. No method for logging into the ADF region will be provided.

16.2 Creating ADF Dynamic Regions An ADF dynamic region is similar to an ADF region, except that its task flow ID in the task flow binding is determined dynamically at runtime. This enables the application to determine at runtime which ADF bounded task flow to execute within the dynamic region. For example, a page displays employee information. A dynamic region added to the page displays a form for updating employee address information when the user clicks a button. Then the same region switches to a different form for updating the social security number when the employee clicks another button on the page. Or, you could create a dynamic region that first displays a customer's street address. The end user might click a link or button to display forms for changing the billing address or the shipping address. The page fragment that displays the customer address and the two forms are all within the same ADF dynamic region, which saves space on the main page where the region is located. As shown in Example 16–4, the task flow binding for the ADF dynamic region contains an EL expression that returns the current taskFlowId. When the taskFlow id value changes, the dynamic region refreshes automatically. New input parameter values are automatically passed to it. Example 16–4

Dynamic Task Flow Binding for ADF Dynamic Region

When an ADF dynamic region is reinitialized, the application must reinitialize the task flow binding associated the region. This includes evaluating whether there are new input parameters and input parameter values to be passed to the ADF dynamic region. When you drop an ADF bounded task flow onto a page to create an ADF dynamic region, you also specify any input parameters defined for the region in the task flow

16-12 Fusion Developer’s Guide for Oracle Application Development Framework

Creating ADF Dynamic Regions

binding in the page definition file. See Section 16.1.3, "How to Specify Parameters for an ADF Region"

16.2.1 How to Create an ADF Dynamic Region The steps for adding an ADF bounded task flow to a page as an ADF dynamic region are similar to adding it as an ADF region. In the following example, you might have an order page that displays products and services. If the user selects a product on a page, a details ADF dynamic region might show product details. If a service is selected, the same details region should show service details. Before you begin: ■





Create two page fragments that display product details and service details, for example, ProductDetails.jsff and ServiceDetails.jsff (see Chapter 20, "Creating a Basic , parameters are not supported in the . The only condition that determines if the region need to be refreshed is the boolean value returned by the evaluation of RefreshCondition (see Section 16.1.7, "What You May Need to Know About Refreshing an ADF Region" for more information).

Note:

In Example 16–5, a parameter named regionParm1 in the parameter map overrides the first parameter value specified. The parameters named regionParm2 and regionParm3 in the parameter map are overridden by the last two parameter values specified in the example. Example 16–5

task flow binding for ADF Dynamic Region



Parameter binding objects declare the parameters that the page evaluates at the beginning of a request (for more information about binding objects and the ADF lifecycle, see Chapter 11, "Using Oracle ADF Model in a Fusion Web Application"). However, since a template itself is never executed, the page that uses the template (the calling page) must access the binding objects created for the template (including parameters or any other type of binding objects created by dragging and dropping objects from the id="pageTemplateBinding"/>

In this example, the calling page was built using the MyTemplate template. By placing the page definition file for the MyTemplate template as an executable for the

18-4 Fusion Developer’s Guide for Oracle Application Development Framework

Creating a Web Page

calling page, when the calling page’s binding container is instantiated, it will in turn instantiate the MyTemplatePageDef’s binding container, thus allowing access to the parameter values, or any other value="#{bindings.pageTemplateBinding}".../>

18.2.3 What Happens at Runtime: How Pages Use Templates When a page is created using a template that contains ADF .

Note:

Because the only job of the taskFlow binding is to refresh its parameters, Refresh="always" doesn't apply. If the taskFlow binding’s parameters don’t change, there is no reason to refresh the ADF Region. The Refresh attribute does not need to be specified: the RefreshCondition and Refresh attributes are mutually exclusive. Note that setting the Refresh attribute to ifNeeded takes precedence over any value for the RefreshCondition attribute. Note that the child page fragment’s page definition still handles the refresh of the bindings of the child page fragments.

19.3 Object Scope Lifecycles At runtime, ADF objects such as the binding container and managed beans are instantiated. Each of these objects has a defined lifespan set by its scope attribute. You can access a scope as a java.util.Map from the RequestContext API. For example, to access an object named foo in the request scope, you would use the expression #{requestScope.foo}. There are six types of scopes in a Fusion web application: ■

Application scope: The object is available for the duration of the application.



Session scope: The object is available for the duration of the session. There's no window uniqueness for session scope, all windows in the session share the same session scope instance. If you are concerned about multiple windows being able to access the same object (for example to ensure that managed beans do not conflict across windows), you should use a scope that is window-specific, such as page flow or view scope.

Note:



Page flow scope: The object is available for the duration of a bounded task flow. Because these are not standard JSF scopes, you cannot register a managed bean to these scopes. However, the value of a managed bean property can refer to values in these scopes.

Note:

Also, EL expressions must explicitly include the scope to retrieve values. For example, to retrieve foo from the pageFlowScope scope, your expression would be #{pageFlowScope.foo}.

Understanding the Fusion Page Lifecycle

19-9

Object Scope Lifecycles





Request scope: The object is available from the time an HTTP request is made until a response is sent back to the client. Backing bean scope: Used for managed beans for page fragments and declarative components only, the object is available from the time an HTTP request is made until a response is sent back to the client. This scope is needed for fragments and declarative components because there may be more than one page fragment or declarative component on a page, and to prevent collisions, any values must be kept in separate scope instances. Therefore, any managed bean for a page fragment or declarative component must use backing bean scope. Because these are not standard JSF scopes, you cannot register a managed bean to these scopes. However, the value of a managed bean property can refer to values in these scopes.

Note:

Also, EL expressions must explicitly include the scope to retrieve values. For example, to retrieve foo from the backing bean scope, your expression would be #{backingBeanScope.foo}. ■

View scope: The object is available until the view ID for the current view activity changes. You can use view scope to hold values for a given page. While request scope can be used to store a value needed from one page to the next, anything stored in view scope will be lost once the view ID changes. Because these are not standard JSF scopes, you cannot register a managed bean to these scopes. However, the value of a managed bean property can refer to values in these scopes.

Note:

Also, EL expressions must explicitly include the scope to retrieve values. For example, to retrieve foo from the view scope, your expression would be #{viewScope.foo}.

When you create objects (such as a managed bean) that require you to define a scope, you can set the scope to none, meaning that it will not live within any particular scope, but will instead be instantiated each time it is referenced.

Note:

Object scopes are analogous to global and local variable scopes in programming languages. The wider the scope, the higher availability of an object. During their life, these objects may expose certain interfaces, hold information, or pass variables and parameters to other objects. For example, a managed bean defined in session scope will be available for use during multiple page requests. However, a managed bean defined in request scope will only be available for the duration of one page request. By default, the binding container and the binding objects it contains are defined in session scope. However, the values referenced by value bindings and iterator bindings are undefined between requests and for scalability reasons do not remain in session scope. Therefore, the values that binding objects refer to are valid only during a request in which that binding container has been prepared by the ADF lifecycle. What stays in session scope are only the binding container and binding objects themselves. Figure 19–3 shows the time period during which each type of scope is valid.

19-10 Fusion Developer’s Guide for Oracle Application Development Framework

Object Scope Lifecycles

Figure 19–3 Relationship Between Scopes and Page Flow

When determining what scope to register a managed bean with, always try to use the narrowest scope possible. Only use the session scope for information that is relevant to the whole session, such as user or context information. Avoid using session scope to pass values from one task flow to another. When creating a managed bean for a page fragment or a declarative component, you must use backing bean scope.

19.3.1 What You May Need to Know About Object Scopes and Task Flows When determining what scope to use for variables within a task flow, you should use any of the scope options other than application or session scope. These two scopes will persist objects in memory beyond the life of the task flow and therefore compromise the encapsulation and reusable aspects of a task flow. In addition, application and session scopes may keep objects in memory longer than needed, causing unneeded overhead. When you need to pass encoding="US-ASCII" ?> . . . MyPagePhaseListener mypackage.MyPagePhaseListener . . . 2.

Enter the remaining elements shown in italics in Example 19–2.

3.

Add values for the following elements: ■



A unique identifier for the listener (you can use the fully qualified class name) The class name of the listener

19.4.3 What You May Need to Know About Listener Order You can specify multiple phase listeners in the adf-settings.xml and, optionally, the relative order in which they are called. When registering a new listener in the file, the position in the list of listeners is determined using two parameters: ■



beforeIdSet: The listener is called before any of the listeners specified in beforeIdSet afterIdSet: The listener is called after any of the listeners specified in afterIdSet

Example 19–3 contains an example configuration file in which multiple listeners have been registered for an application. Example 19–3

adf-settings.xml Configuration File with Multiple Listener Registration

MyPhaseListener view.myPhaseListener

Understanding the Fusion Page Lifecycle 19-13

Customizing the ADF Page Lifecycle

ListenerA

20.4.2.2 Iterator RangeSize Attribute Iterator bindings have a rangeSize attribute that the binding uses to determine the number of RangeSize="25" id="CustomerInfoVOIterator" ChangeEventPolicy="ppr"/>

20-10 Fusion Developer’s Guide for Oracle Application Development Framework

Incorporating Range Navigation into Forms

This rangeSize attribute is not the same as the rows attribute on a table component. For more information, see Table 21–1, " ADF Faces Table Attributes and Populated Values".

Note:

By default, the rangeSize attribute is set to 25. This means that a user can view 25 objects, navigating back and forth between them, without needing to access the > 20-12 Fusion Developer’s Guide for Oracle Application Development Framework

Incorporating Range Navigation into Forms



20.4.2.4 Using Automatic Partial Page Rendering When you create a form with navigational controls, JDeveloper configures the iterator binding to automatically use partial page rendering (PPR). PPR allows only certain components on a page to be rerendered without the need to refresh the entire page. For example, a command link or button can cause another component on the page to be rerendered, without the whole page refreshing. You can configure components to use PPR by setting one component as a target for another component’s event, for example a value change or action event. For more information about partial page rendering, see the "Rerendering Partial Page Content" chapter of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework. When you create a form, setting up PPR to work for all the components in the form can be time consuming and error prone. To alleviate this, you can set the changeEventPolicy attribute to ppr on value bindings. Doing so means that anytime the associated component’s value changes as a result of backend business logic, the component will be automatically rerendered. You can also set an iterator binding’s changeEventPolicy to ppr. When you do this, any action or value binding associated with the iterator will act as though its changeEventPolicy is set to PPR. This allows entire forms to use PPR without your having to configure each component separately. When you drop a form and elect to include navigation controls, JDeveloper automatically sets the changeEventPolicy attribute on the associated iterator to ppr. JDeveloper also sets each of the navigation buttons’ partialSubmit attribute to true. This is how command components notify the framework that PPR should occur. When you set the navigation command components’ partialSubmit attribute to true and you set the iterator’s changeEventPolicy to ppr, each time a navigation button is clicked, all the components in the form that use the iterator binding are rerendered. Example 20–9 shows the page definition code for the iterator created when dropping the CustomerInfoVO collection from the RangeSize="25" id="CustomerInfoVOIterator" ChangeEventPolicy="ppr"/>

20.4.3 What Happens at Runtime: How Action Events and Action Listeners Work An action event occurs when a command component is activated. For example, when a user clicks a Submit button, the form is submitted, and subsequently, an action event is fired. Action events might affect only the user interface (for example, a link to change the locale, causing different field prompts to display), or they might involve some logic processing in the back end (for example, a button to navigate to the next record). An action listener is a class that wants to be notified when a command component fires an action event. An action listener contains an action listener method that processes the action event object passed to it by the command component.

Creating a Basic RequiresUpdateModel="true" Action="commitTransaction" />

Table 20–2 shows the built-in non-navigation operations provided on RangeSize="25" Binds="CustomerAddress" />

24.5.4 What You May Need to Know About Adding Custom Point Style Items to a Map Point Theme If you want to provide custom HTML as well as custom images for map points, then you can use the customPointCallback attribute of the dvt:mapPointTheme tag to accomplish this customization. If you set the customPointCallback attribute for a map point theme, the map ignores any dvt:mapPointStyleItem child tags because the callback overrides these tags.

Important:

To use a callback to customize the style of map points: 1. Write a method in Java to perform the desired point customization. 2.

Store this method in a managed bean for the map. For more information about managed beans, see the "Creating and Using Managed Beans" section in the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.

3.

After you finish id="ProductPopularity1" xmlns="http://xmlns.oracle.com/adfm/dvt">

24.6 Creating id="OrderShippingSummary2" xmlns="http://xmlns.oracle.com/adfm/dvt">

24-42 Fusion Developer’s Guide for Oracle Application Development Framework

Creating type="startTime"/>

Creating sortable="false" headerText="#{bindings.OrderShippingSummary2.hints.TaskType.label}">

24.6.3 What You May Need to Know About Summary Tasks in a Project Gantt A summary task shows start time and end time for a group of tasks (which are usually subtasks). A summary task cannot be moved or extended. However, your application should recalculate the summary task times when the dates of any subtask changes. To detect a change in task duration, register an event handler by specifying a method binding expression on the type="percentComplete"/>. Example 24–19 shows the percent complete attribute mapping added to the type="Tasks">

Another attribute (completedThrough) exists that allows you to specify a date rather than a percentage. The gantt type="completedThrough"/>.

24.6.5 What You May Need to Know About Variance in a Project Gantt Variance can be rendered within two horizontal bars. One bar represents the base (or original) start and end time for the task. The second bar represents the actual start and end time for the task. You enter the binding information for the base start time and end time in the type="actualStart"/>

Example 24–21 shows the actual start and actual end attribute mappings added to the type="Tasks">

24.6.6 How to Create a id="GanttRugResourcesView2" xmlns="http://xmlns.oracle.com/adfm/dvt"> 24-48 Fusion Developer’s Guide for Oracle Application Development Framework

Creating />

24.6.8 How to Create a id="Persons" xmlns="http://xmlns.oracle.com/adfm/dvt">

24-52 Fusion Developer’s Guide for Oracle Application Development Framework

Creating > ...

Creating )

Creating ADF )

If the view criteria for the query has mixed AND and OR conjunctions between the criteria items, then neither Match All nor Match Any will be selected when the component first renders. However, the user can select Match All or Match Any to override the conjunctions defined as the initial state in the view criteria. Advanced mode query forms allow users to dynamically add search criteria fields to the query panel to perform more complicated queries. These user-created search criteria fields can be deleted, but the user cannot delete existing fields. Figure 25–4 shows how the Add Fields dropdown list is used to add the CategoryId criteria field to the search form. Figure 25–4 Dynamically Adding Search Criteria Fields at Runtime

Figure 25–5 show a user-added search criteria with the delete icon to its right. Users can click the delete icon to remove the criteria. Figure 25–5 User-Added Search Criteria with Delete icon

If you intend for a query search form to have both a basic and an advanced mode, you can define each search criteria field to appear only for basic, only for advanced, or for both. When the user switches from one mode to the other, only the search criteria fields defined for that mode will appear. For example, three search fields for basic mode (A, B, C), and three search fields for advanced mode (A, B, D) were defined for a query. When the query search form is in basic mode, search criteria fields A, B, and C will appear. When it is in advanced mode, then field A, B, and D will appear. Any search

queryPerformed is a method on the FacesCtrlSearchBinding class that returns true if the query has already been executed. In this expression, the query will refresh if queryPerformed returns true. Example 25–3 shows how RefreshCondition and queryPerformed are used in a page definition file. Example 25–3

Page Definition Entries for Query Search Region



You can set how long the value of queryPerformed is valid using the TrackingQueryPerformed property in the searchRegion. TrackingQueryPerformed indicates the duration for which the FacesCtrlSearchBinding should remember whether a query has been performed. When an af:query and its corresponding searchRegion binding are used in a region, you should set the value of queryPerformed to Page. When set to Page, queryPerformed will stay valid only for viewScope. If TrackingQueryPerformed is set to PageFlow, then queryPerformed is valid for pageFlowScope. The isQueryPerformed() method on FacesCtrlSearchBinding uses TrackingQueryPerformed to check for the appropriate scope and to return a boolean true or false.

25.2.4 What Happens When You Create a Query Form When you drop a query search form onto a page, JDeveloper creates an af:query tag on the page. If you drop a query with table or tree table, then an af:table tag or af:treeTable tag will follow the af:query tag. Under the af:query tag are several attributes that define the query properties. They include: ■ ■

The id attribute, which uniquely identifies the query. The resultsComponentId attribute, which identifies the component that will display the results of the query. Typically, this will be the table or tree table that was dropped onto the page together with the query. You can change this value to be the id of a different results component. For more information, see Section 25.2.2, "How to Create a Query Search Form and Add a Results Component Later".

25.2.5 What Happens at Runtime: Creating a Search Form At runtime, the search form displays as a search panel on the page. The search panel will display in either basic mode or advanced mode, depending on the mode control hint when its corresponding view criteria was created. The Saved Search dropdown list will contain all the view criteria that are enabled (Show in List control hint enabled). The Match All/Any conjunction radio button may be enabled. A search criteria field will be rendered for each search criteria defined in the view criteria. If the Default List Type control hint in the view object has been declared as an LOV or a selection list component, the search criteria field component is as shown in Table 25–3. After the user enters the search criteria and clicks Search, a query against the view criteria is executed and the results are displayed in the associated table, tree table, or component.

25.3 Setting Up Search Form Properties A query search form is based on a view criteria defined in a view object. When you create the view criteria, you also specify some of the search form properties. Later on,

25-16 Fusion Developer’s Guide for Oracle Application Development Framework

Setting Up Search Form Properties

when you drop the named criteria onto the page to create a query component, you can specify other search form properties. Search form properties that can be set when the view criteria is being created include: ■

Default mode in basic or advanced mode



Automatic query execution when the page loads



Rendering of the search criteria field

Search form properties that can be set after the query component has been added to the JSF page include: ■

id of the results table or results component



Show or hide of the basic/advanced button



Position of the mode button



Default, Simple, or Compact mode for display

25.3.1 How to Set Search Form Properties on the View Criteria When you are creating a view criteria, you can declaratively set the initial state of several properties. Figure 25–22 shows the Edit View Criteria dialog for setting default options. For more information about view criteria, see Section 5.10, "Working with Named View Criteria". Figure 25–22

Edit View Criteria Dialog

You must select the default mode of the query search form as either basic or advanced. The default is basic. You also must declare whether each individual search criteria field will be available only in basic mode, only in advanced mode, available in both modes, or never displayed. If a search criteria field is declared only for basic mode, it will not appear when the user switches to advanced mode, and the reverse is true. If the field is Creating ADF UpperColumns="1"> (that is, the ID is missing a closing angle bracket). Example 29–1

Sample Page Definition File with Two Errors

Structure to open the Structure window or View > Log to open the Log Window. 2.

In either window, double-click the error message to open the file in the XML editor.

3.

In the XML editor, locate the highlighted lines. The highlighted lines will be lines with errors.

4.

Correct any errors. After an error has been corrected, the corresponding error message will be automatically removed from the Structure window.

5.

Optionally, you can recompile the project by choosing Run > Make and checking to see whether the compiler still produces the error message.

29.3 Correcting Simple Oracle ADF Runtime Errors Failures of the Oracle ADF Model layer cannot be detected by the JDeveloper compiler, in part because the page’s for detailed logging diagnostics. 29-6 Fusion Developer’s Guide for Oracle Application Development Framework

Using the ADF Logger and Business Component Browser

For the Oracle ADF view layer packages oracle.adf.view.faces and oracle.adfinternal.view.faces, edit: For the Oracle ADF Model layer packages, edit these elements: For the Oracle ADF Controller layer packages, edit these elements: Alternatively, you can create a debug configuration in JDeveloper that you can choose when you start a debugging session. Example 29–2 shows the portion of the logging.xml file where you can change the granularity of the log messages. Note in the example that the log for oracle.adf.faces has been changed to FINE to display more messages. Example 29–2

Sample Section of the logging.xml Configuration File

...

For the latest information about the different levels of the Java Logging system, go to the Sun Java website. Normally, the Java logging systems supports the following levels: ■

SEVERE



WARNING



INFO



CONFIG



FINE



FINER



FINEST

To create an Oracle ADF Model debugging configuration: In the Application Navigator, double-click the user interface project.

1. 2.

In the Project Properties dialog, click the Run/Debug/Profile node and create a new run configuration.

Testing and Debugging ADF Components 29-7

Using the ADF Logger and Business Component Browser

3.

In the Run Configurations list, double-click the new run configuration to edit its properties.

4.

In the Edit Run Configuration dialog, for Launch Settings, enter the following Java options for the default virtual machine: -Djbo.debugoutput=adflogger -Djbo.adflogger.level=FINE Set the level=FINE for detailed diagnostic messages.

To create an Oracle ADF view Javascript logging configuration: In the Application Navigator, open the application or project web.xml file using the source editor.

1. 2.

Add the following elements to the file: oracle.adf.view.rich.LOGGER_LEVEL FINE

To create a core JSF Reference Implementation logging configuration: 1. Open the logging.properites file. 2.

Set the following line to FINE:

The junit tag contains a nested test tag that identifies the test suite class to execute and specifies a directory in which to report the results. The junitreport tag allows you to format the test results into a collection of HTML pages that resemble the format of Javadoc. To try running the JUnit test from Ant, select the build.xml file in the Application Navigator, and choose Run Ant Target > tests from the context menu.

29-42 Fusion Developer’s Guide for Oracle Application Development Framework

30 Refactoring a Fusion Web Application This chapter describes considerations for renaming, moving, and deleting files, configuration files, objects, attributes, and elements. In most cases, JDeveloper automatically performs refactoring. However, you may need to complete some manual steps to refactor. This chapter includes the following sections: ■

Section 30.1, "Introduction to Refactoring a Fusion Web Application"



Section 30.2, "Renaming Files"



Section 30.3, "Moving JSF Pages"



Section 30.4, "Refactoring pagedef.xml Bindings Objects"



Section 30.5, "Refactoring ADF Business Components"



Section 30.6, "Refactoring Attributes"



Section 30.7, "Refactoring Named Elements"



Section 30.8, "Refactoring ADF Task Flows"



Section 30.9, "Refactoring the in the source code, for example:

A named element is not an object or attribute. 6.

To rename the element, right-click the element and choose Rename.

7.

To delete the element, choose Delete Safely. If the element is used elsewhere in the application, a dialog displays with the following options: ■ ■

Ignore: Unresolved usages will remain in the code as undefined references. View Usages: Display a preview of the usages of the element in the Compiler log. You can use the log to inspect and resolve the remaining usages.

30.8 Refactoring ADF Task Flows For more information, see Section 13.7, "Refactoring to Create New ADF Task Flows and Templates".

30.9 Refactoring the encoding="UTF-8" ?>

30.10 Refactoring Across Abstraction Layers Refactoring does not cross abstraction layers. For example, when a view object is created based on the entity Dept, it is named DeptView by default. Renaming Dept updates the entity usage in DeptView, but does not change the name of the view object.

30.11 Refactoring Limitations Table 30–4 summarizes the limitations of JDeveloper’s refactoring support. Table 30–4

Refactoring Limitations

Area

Limitation

.

3.

Change the jbo.project attributes in all common/bc4j.xcfg files that contain elements referred to in the.jpx file to include the new package name. For example:

4.

Change the JDeveloper project file (the.jpr file) contents: ■

Set the new.jpx package location. If you later change the default package in the project properties, you will again raise a NotFound error for the.jpx file. For example:



Fix any ownerURL elements in the ownerMap that contain references to the old location of the.jpx file. For example:

Refactoring a Fusion Web Application

30-7

Refactoring the .jpx Project File

30-8 Fusion Developer’s Guide for Oracle Application Development Framework

31 Reusing Application Components This chapter describes how to package certain ADF components into the ADF Library for reuse in applications. Reusable ADF components are application modules, Business Components, Component >

JDeveloper also updates the component's custom Java class to modify its extends clause to reflect the new custom framework base class, as shown in Example 33–3. Example 33–3

Component's Custom Java Class Updates to Reflect New Base Class

package com.yourcompany.yourapp; import com.yourcompany.fwkext.CustomAppModuleImpl; // --------------------------------------------------------------------// --File generated by Oracle ADF Business Components Design Time. // --Custom code may be added to this class. // --Warning: Do not modify method signatures of generated methods. // --------------------------------------------------------------------public class YourServiceImpl extends CustomAppModuleImpl { /**This is the default constructor (do not remove) */ public YourServiceImpl() {} // etc. }

Figure 33–4 illustrates how the YourService application module with its custom YourServiceImpl class is related to your framework extension class. At runtime, it

Advanced Business Components Techniques 33-5

Globally Extending ADF Business Components Functionality

uses the YourServiceImpl class which inherits its base behavior from the CustomAppModuleImpl framework extension class which, in turn, extends the base ApplicationModuleImpl class. Figure 33–4 Component with Custom Java Extending Customized Framework Base Class

33.1.6 What You May Need to Know 33.1.6.1 Don't Update the Extends Clause in Custom Component Java Files By Hand If you have an ADF component with a custom Java class and later decide to base the component on a framework extension class, use the Class Extends button on the Java page of the component editor to change the component's base class. Doing this updates the component's XML component definition to reflect the new base class, and also modifies the extends clause in the component's custom Java class. If you manually update the extends clause without using the component editor, the component's XML component definition will not reflect the new inheritance and the next time you open the editor, your manually modified extends clause will be overwritten with what the component editor believes is the correct component base class.

33.1.6.2 You Can Have Multiple Levels of Framework Extension Classes In the examples above, you've seen a single CustomAppModuleImpl class that extends the base ApplicationModuleImpl class. However, there is no fixed limit on how many levels of framework extension classes you create. After creating a company-level CustomAppModuleImpl to use for all application modules in all Fusion web applications your company creates, some later project team might encounter the need to further customize that framework extension class. That team could create a SomeProjectCustomAppModuleImpl class that extends the CustomAppModuleImpl and then include the project-specific custom application module code in there: public class SomeProjectCustomAppModuleImpl extends CustomAppModuleImpl { /* * Custom application module code specific to the * "SomeProject" project goes here.

33-6 Fusion Developer’s Guide for Oracle Application Development Framework

Creating a Layer of Framework Extensions

*/ }

Then, any application modules created as part of the implementation of this specific project can use the SomeProjectCustomAppModuleImpl as their base class instead of the CustomAppModuleImpl.

33.1.6.3 Setting up Project-Level Preferences for Framework Extension Classes If you decide to use a specific set of framework extension classes as a standard for a given project, you can open the Business Components > Base Classes page in the Project Properties dialog, as shown in Figure 33–5, to define your preferred base classes for each component type. For example, to indicate that any new application modules created in the project should use the CustomAppModuleImpl class by default, enter the fully-qualified name of that class in the Application Module Object class name field as shown. Setting these preferences for base classes does not affect any existing components in the project, but the component wizards will use the preferences for any new components created. Figure 33–5 Setting Project-Level Preferences for ADF Component Base Classes

33.1.6.4 Setting Up Framework Extension Class Preferences at the IDE Level When you want to apply the same base class preferences to each new project that you create in JDeveloper, you can define the preferences at a global level. Choose the Tools | Preferences main menu item in JDeveloper and display the Business Components > Base Classes page. The page displays the same options for specifying the preferred base classes for each component type as shown in Figure 33–5. Base classes that you specify at the global level will not alter your existing projects containing ADF components.

33.2 Creating a Layer of Framework Extensions Before you begin to develop application-specific business components, Oracle recommends that you consider creating a complete layer of framework extension classes and setting up your project-level preferences to use that layer by default. You might not have any custom code in mind to put in these framework extension classes yet, but you will be glad you heeded this recommendation the first time you encounter a need to: ■

Add a generic feature that all your company's application modules require

Advanced Business Components Techniques 33-7

Creating a Layer of Framework Extensions



Augment a built-in feature with some custom, generic processing



Workaround a bug you encounter in a generic way

Failure to set up these preferences at the outset can present your team with a substantial inconvenience if you discover mid-project that all of your entity objects, for example, require a new generic feature, augmented built-in feature, or a generic bug workaround. Putting a complete layer of framework classes in place at the start of your project is an insurance policy against this inconvenience and the wasted time related to dealing with it later in the project. JDeveloper will automatically use framework classes when you create them.

33.2.1 How to Create Your Layer of Framework Extension Layer Classes A common set of customized framework base classes in a package name of your own choosing like com.yourcompany.adfextensions, each importing the oracle.jbo.server.* package, would consist of the following classes: ■

public class CustomEntityImpl extends EntityImpl



public class CustomEntityDefImpl extends EntityDefImpl



public class CustomViewObjectImpl extends ViewObjectImpl



public class CustomViewRowImpl extends ViewRowImpl



public class CustomApplicationModuleImpl extends ApplicationModuleImpl



public class CustomDBTransactionImpl extends DBTransactionImpl2



public class Custom Name="ProductsByName" Extends="devguide.advanced.baseproject.extsub.Products" Where="UPPER(PRODUCT_NAME) LIKE UPPER(:theProductName)||'%'" BindingStyle="OracleName" CustomQuery="false" Row Component ... ...

33.9.3.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.

33.9.4 What You May Need to Know

Advanced Business Components Techniques 33-31

Creating Extended Components Using Inheritance

33.9.4.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 33–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 33–16 Working with Parent and Extended Components package devguide.advanced.baseproject.extsub; /* imports omitted */ public class TestClient { public static void main(String[] args) { String amDef = "devguide.advanced.baseproject.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);

33-32 Fusion Developer’s Guide for Oracle Application Development Framework

Creating Extended Components Using Inheritance

} 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 ? "" : 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=1 ProductName=Plasma HD Television Checksum=I am the Product Class Setting the Name attribute to 'Q' succeeded. Printing attribute for a row in VO 'ProductsByName' ProdId=15 ProductName=Ipod Speakers Checksum=I am the Product Class SomeExtraAttr= ## Called someExtraFeature of ProductsByNameRowImpl Setting the Name attribute to 'Q' succeeded.

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 33.10, "Substituting Extended Components In a Delivered Application".

Note:

Advanced Business Components Techniques 33-33

Creating Extended Components Using Inheritance

33.9.4.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’s wizard is disabled. Additionally, in the application module editor’s Java page, when you click Edit java options, the Class Extends button in the Java dialog appears 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.

33.9.4.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.

33.9.4.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.baseproject.extsub.Products"); public static final int SOMEEXTRAATTR = MAXATTRCONST;

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

33-34 Fusion Developer’s Guide for Oracle Application Development Framework

Substituting Extended Components In a Delivered Application

33.10 Substituting Extended Components In a Delivered Application If you deliver packaged applications that can require on-site customization for each potential client of your solution, ADF Business Components offers a useful feature to simplify that task.

33.10.1 Extending and Substituting Components Is Superior to Modifying Code All too often, on-site application customization is performed by making direct changes to the source code of the delivered application. This approach demonstrates its weaknesses whenever you deliver patches or new feature releases of your original application to your clients. Any customizations they had been applied to the base application's source code need to be painstakingly re-applied to the patched or updated version of the base application. Not only does this render the application customization a costly, ongoing maintenance expense, it can introduce subtle bugs due to human errors that occur when reapplying previous customizations to new releases. ADF Business Components offers a superior, component-based approach to support application customization that doesn't require changing — or even having access to — the base application's source code. To customize your delivered application, your customers can: 1.

Import one or more packages of components from the base application into a new project.

2.

Create new components to effect the application customization, extending appropriate parent components from the base application as necessary.

3.

Define a list of global component substitutions, naming their customized components to substitute for your base application's appropriate parent components.

When the customer runs your delivered application with a global component substitution list defined, their customized application components are used by your delivered application without changing any of its code. When you deliver a patched or updated version of the original application, their component customizations apply to the updated version the next time they restart the application without needing to re-apply any customizations.

33.10.2 How To Substitute an Extended Component To define global component substitutions, use the Business Components > Substitutions page of the Project Properties dialog in the project where you've created extended components based on the imported components from the base application. As shown in Figure 33–13, to define each component substitution: 1.

Select the base application's component in the Available list.

2.

Select the customized, extended component to substitute in the Substitute list.

3.

Click Add. You can only substitute a component in the base application with an extended component that inherits directly or indirectly from the base one.

Note:

Advanced Business Components Techniques 33-35

Substituting Extended Components In a Delivered Application

Figure 33–13 Defining Business Components Substitutions

33.10.3 What Happens When You Substitute When you define a list of global component substitutions in a project named YourExtendsAndSubstitutesProject, the substitution list is saved in the YourExtendsAndSubstitutesProject.jpx in the root directory of the source path. The file will contain elements as shown in Example 33–17, one for each component to be substituted. Example 33–17 Component Substitution List Saved in the Project's JPX File

33.10.4 Enabling the Substituted Components in the Base Application To have the original application use the set of substituted components, define the Java system property Factory-Substitution-List and set its value to the name of the

33-36 Fusion Developer’s Guide for Oracle Application Development Framework

Substituting Extended Components In a Delivered Application

project whose *.jpx file contains the substitution list. The value should be just the project name without any *.jpr or *.jpx extension. Consider a simple example that customizes the Product entity object and the Products view object described in Section 33.9.4.1, "You Can Use Parent Classes and Interfaces to Work with Extended Components". To perform the customization, assume you create new project named ExtendsAndSubstitutes that: ■

Defines a library for the JAR file containing the base components



Imports the package containing Product and Products





Creates new extended components in a distinct package name called CustomizedProduct and CustomizedProducts Defines a component substitution list to use the extended components.

When creating the extended components, assume that you: ■





Added an extra view attribute named ExtraViewAttribute to the CustomizedProducts view object. Added a new validation rule to the CustomizedProduct entity object to enforce that the product name cannot be the letter "Q". Overrode the getChecksum() method in the CustomizedProduct.java class to return "I am the CustomizedProduct Class".

If you define the Factory-Substitution-List Java system property set to the value ExtendsAndSubstitutes, then when you run the exact same test client class shown above in Example 33–16 the output of the sample will change to reflect the use of the substituted components: Printing attribute for a row in VO 'Products' ProdId=1 ProductName=Plasma HD Television Checksum=I am the CustomizedProduct Class ExtraViewAttribute=Extra Attr Value The name cannot be Q! Printing attribute for a row in VO 'ProductsByName' ProdId=15 ProductName=IPod Speakers Checksum=I am the CustomizedProduct Class SomeExtraAttr=SomeExtraAttrValue ## Called someExtraFeature of ProductsByNameRowImpl The name cannot be Q!

Compared to the output from Example 33–16, notice that in the presence of the factory substitution list, the Products view object in the original test program now has the additional ExtraViewAttribute, now reports a Checksum attribute value of "I am the CustomizedProduct Class", and now disallows the assignment of the product name to have the value "Q". These component behavior changes were performed without needing to modify the original Java or XML source code of the delivered components.

Advanced Business Components Techniques 33-37

Substituting Extended Components In a Delivered Application

33-38 Fusion Developer’s Guide for Oracle Application Development Framework

34 Advanced Entity Object Techniques This chapter describes advanced techniques for use in the entity objects in your business domain layer. This chapter includes the following sections: ■

Section 34.1, "Creating Custom, Validated Cardinality="1" Owner="devguide.advanced.multiplemasters.Orders"

Advanced View Object Techniques 35-5

Advanced View Object Concepts and Features

Source="true">

Assuming you've named your accessor attribute AccessorAttrName, you can access the detail row set using the generic getAttribute() API like: RowSet detail = (RowSet)currentRow.getAttribute("AccessorAttrName");

If you've generated a custom view row class for the master view object and exposed the getter method for the view link accessor attribute on the client view row interface, you can write strongly-typed code to access the detail row set like this: RowSet detail = (RowSet)currentRow.getAccessorAttrName();

Unlike the ... > ... Padova 110 Expert 112

Example 35–29 shows the interesting lines of code from a TestClientReadXML class that applies this XML xmlns="http://xmlns.oracle.com/bc4j/configuration">

Note that attributes of the tag appear with names matching their ADF Business Component properties (for example, the attribute jbo.locking.mode corresponds to the property jbo.locking.mode). It's also important to understand that if a property is currently set to its runtime default value, then the Configuration Manager does not write the entry to the bc4j.xcfg file.

37.3.2 Setting Configuration Properties as System Parameters As an alternative to specifying configuration properties in the bc4j.xcfg file, you can also set Java VM system parameters with the same property names. These system parameters will be used only if a corresponding property does not exist in the relevant bc4j.xcfg file for the application module in question. In other words, configuration parameters that appear in the application module configuration take precedence over parameters of the same name supplied as Java system parameters. You typically set Java system parameters using the -D command line flag to the Java VM like this: java -Dproperty=value -jar yourserver.jar

Alternatively, your Java EE container probably has a section in its own configuration files where Java system parameters can be specified for use at Java EE container startup time. If you adopt the technique of specifying site-specific default values for Oracle ADF configuration parameters as Java system parameters, you should make sure that your application’s bc4j.xcfg files do not include references to these parameters unless you want to define an application-module-specific exception to these global default values.

Caution: The values of Idle Instance Timeout, Pool Polling Interval settings for both the Application Pool and the Name="StoreFrontService" Version="11.1.1.49.73" SeparateXMLFiles="true" PackageName="">

A.5 bc4j.xcfg The bc4j.xcfg file contains meta xmlns="http://xmlns.oracle.com/bc4j/configuration">

A.6 xmlns="http://xmlns.oracle.com/bc4j/configuration">

where the XML namespace attribute (xmlns) specifies the URI to which the version="11.1.1.44.61" id=" Package="oracle.fodemo.storefront" ClientType="Generic" ErrorHandler>

Oracle ADF XML Files A-9

pageNamePageDef.xml

... ... < Package="oracle.fodemo.storefront.store.service" Factory SupportsTransactions="true" SupportsFindMode="true" SupportsRangesize="true" SupportsResetState="true" SupportsSortCollection="true" Configuration="StoreServiceAMLocalWeb" syncMode="Immediate" xmlns="http://xmlns.oracle.com/adfm/ version="10.1.3.35.83" id="PageDef" Package="oracle.fod.view.pageDefs">

where the XML namespace attribute (xmlns) specifies the URI to which the ADF binding container binds at runtime. Only the package name is editable; all other attributes should have the values shown. Example A–4 displays the child element hierarchy of the element. Note that each business service for which you have created a encoding="UTF-8" ?> ... ... ...

The child elements have the following usages: ■



defines page-level parameters that are EL accessible. These parameters store information local to the web page request and may be accessed in the binding expressions. defines the list of items (methods, view objects, and accessors) to execute during the prepareModel phase of the ADF page lifecycle. Methods to be executed are defined by . The lifecycle performs the execute in the sequence listed in the section. Whether or not the method or operation is executed depends on its refresh or refreshCondition attribute value. Built-in operations on the xmlns:wap="http://xmlns.oracle.com/adf/share/http/config" >

A.12 web.xml Oracle ADF has specific configuration settings for the standard web.xml deployment descriptor file. When you create a project in JDeveloper that uses JSF technology, a starter web.xml file with default settings is created for you in the /WEB-INF folder. To edit the file, double-click web.xml in the Application Navigator to open it in the XML editor. The following must be configured in web.xml for all applications that use JSF and ADF Faces: ■





JSF servlet and mapping: The servlet javax.faces.webapp.FacesServlet that manages the request-processing lifecycle for web applications utilizing JSF to construct the user interface. ADF Faces filter and mapping: A servlet filter to ensure that ADF Faces is properly initialized by establishing a AdfFacesContext object. This filter also processes file uploads. ADF resource servlet and mapping: A servlet to serve up web application resources (images, style sheets, JavaScript libraries) by delegating to a ResourceLoader.

The JSF servlet and mapping configuration settings are automatically added to the starter web.xml file when you first create a JSF project. When you insert an ADF Faces component into a JSF page for the first time, JDeveloper automatically inserts the configuration settings for ADF Faces filter and mapping, and resource servlet and mapping.

A-24 Fusion Developer’s Guide for Oracle Application Development Framework

logging.xml

For more information, see the "Configuration in web.xml" section in the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.

A.13 logging.xml ADF Faces leverages the Java Logging API (java.util.logging.Logger) to provide logging functionality when you run a debugging session. Java Logging is a standard API that is available in the Java Platform, starting with JDK 1.4. For the key elements, see the section "Java Logging Overview" at http://java.sun.com/j2se/1.4.2/docs/guide/util/logging/overview. html. The logging.xml configuration file can be used to configure the following: ■ ■



The logging level for Oracle ADF packages. Log output location. In addition to the default Log window in JDeveloper, you can redirect the log output to a file. The directory path that determines where your log file resides.

For more information, see Section 29.4, "Using the ADF Logger and Business Component Browser".

Oracle ADF XML Files A-25

logging.xml

A-26 Fusion Developer’s Guide for Oracle Application Development Framework

B Oracle ADF Binding Properties This appendix provides a reference for the properties of the ADF bindings. This appendix contains the following section: ■

Section B.1, "EL Properties of Oracle ADF Bindings"

B.1 EL Properties of Oracle ADF Bindings Table B–1 shows the properties that you can use in EL expressions to access values of the ADF binding objects at runtime. The properties appear in alphabetical order. Table B–1

EL Properties of Oracle ADF Bindings

Runtime Property

Description

Iterator Action Attribute Button List Table Tree

actionEnabled

Use operationEnabled instead.

n/a

yes

n/a

n/a

n/a

n/a

n/a

allRowsInRange

Returns an array of current set of rows from the associated collection. Calls getAllRowsInRange() on the RowSetIterator.

yes

n/a

n/a

n/a

n/a

n/a

n/a

attributeDef

Returns the attribute definition n/a for the first attribute to which the binding is associated.

n/a

yes

yes

yes

n/a

n/a

attributeDefs

Returns the attribute n/a definitions for all the attributes to which the binding is associated.

n/a

yes

yes

yes

n/a

n/a

attributeValue

n/a Returns an unformatted and typed (appropriate Java type) value in the current row, for the attribute to which the control binding is bound. Note this property is not visible in the EL expression builder dialog.

n/a

yes

yes

yes

n/a

n/a

Oracle ADF Binding Properties B-1

EL Properties of Oracle ADF Bindings

Table B–1 (Cont.) EL Properties of Oracle ADF Bindings Runtime Property

Description

attributeValues

n/a Returns the value of all the attributes to which the binding is associated in an ordered array.Returns an array of an unformatted and typed (appropriate Java type) values in the current row for all the attributes to which the control binding is bound. Note this property is not visible in the EL expression builder dialog.

n/a

yes

yes

yes

n/a

n/a

bindings

Returns a new binding for each cell or attribute exposed under the rows of a tree node binding.

no

no

no

no

no

no

yes

children

Returns the child nodes of a tree node binding.

n/a

n/a

n/a

n/a

n/a

n/a

yes

currentRow

Returns the current row on an action binding bound to an iterator (for example, built-in navigation actions).

n/a

yes

n/a

n/a

n/a

n/a

n/a

dataControl

Returns the iterator’s associated data provider.

yes

n/a

n/a

n/a

n/a

n/a

n/a

displayData

Returns a list of map elements. n/a Each map entry contains the following elements:

n/a

n/a

n/a

yes

n/a

n/a

n/a

n/a

n/a

yes

n/a

n/a









Iterator Action Attribute Button List Table Tree

selected: A boolean true if current entry should be selected. index: The index value of the current entry. prompt: A string value that may be used to render the entry in the UI. displayValues: An ordered list of display attribute values for all display attributes in the list binding.

Note this property is not visible in the EL expression builder dialog. displayHint

Returns the display hint for the n/a first attribute to which the binding is associated. The hint identifies whether the attribute should be displayed or not. For more information, see oracle.jbo.AttributeHin ts.displayHint. Note this property is not visible in the EL expression builder dialog.

B-2 Fusion Developer’s Guide for Oracle Application Development Framework

EL Properties of Oracle ADF Bindings

Table B–1 (Cont.) EL Properties of Oracle ADF Bindings Runtime Property

Description

displayHints

n/a Returns a list of name-value pairs for UI hints for all display attributes to which the binding is associated. The map contains the following elements: ■













Iterator Action Attribute Button List Table Tree n/a

n/a

yes

yes

n/a

n/a

label: The label to display for the current attribute. tooltip: The tooltip to display for the current attribute. displayHint: The display hint for the current attribute. displayHeight: The height in lines for the current attribute. displayWidth: The width in characters for the current attribute. controlType: The control type hint for the current attribute. format: The format to be used for the current attribute.

Note this property is not visible in the EL expression builder dialog. enabled

Use operationEnabled.

n/a

n/a

n/a

n/a

n/a

n/a

n/a

enabledString

Returns disabled if the n/a action binding is not ready to be invoked. Otherwise, returns "".

yes

n/a

n/a

n/a

n/a

n/a

error

yes Returns any exception that was cached while updating the associated attribute value for a a value binding or when invoking an operation bound by an operation binding.

yes

yes

yes

yes

yes

yes

estimatedRowCount Returns the maximum row count of the rows in the collection with which this iterator binding is associated

yes

n/a

n/a

n/a

n/a

yes

yes

findMode

Return true if the iterator is currently operating in find mode. Otherwise, returns false.

yes

n/a

n/a

n/a

n/a

n/a

n/a

fullName

Returns the fully qualified name of the binding object in the Oracle ADF binding context.

yes

yes

yes

yes

yes

yes

yes

Oracle ADF Binding Properties B-3

EL Properties of Oracle ADF Bindings

Table B–1 (Cont.) EL Properties of Oracle ADF Bindings Runtime Property

Description

Iterator Action Attribute Button List Table Tree

hints

Returns the value of the UI hint indicated for the binding. See displayHints for the list of UI hint keywords.

yes

yes

yes

yes

yes

yes

yes

inputValue

Returns the value of the first attribute to which the binding is associated. If the binding was used to set the value on the attribute and the set operation failed, this method returns the invalid value that was being set.

n/a

n/a

yes

yes

yes

yes

yes

iteratorBinding

Returns the iterator binding n/a that provides access to the data collection.

yes

yes

yes

yes

yes

yes

label

Returns the label (if supplied by Control Hints) for the first attribute of the binding.

n/a

n/a

yes

yes

yes

n/a

n/a

labels

n/a Returns a map of labels (if supplied by Control Hints) keyed by attribute name for all attributes to which the binding is associated. Note this property is not visible in the EL expression builder dialog.

n/a

yes

yes

yes

yes

n/a

labelSet

Returns an ordered set of labels for all the attributes to which the binding is associated. Note this property is not visible in the EL expression builder dialog.

n/a

n/a

yes

yes

yes

yes

n/a

mandatory

Returns whether the first attribute to which the binding is associated is required.

n/a

n/a

yes

yes

yes

n/a

n/a

name

Returns the name of the yes binding object in the context of the binding container to which it is registered. Note this property is not visible in the EL expression builder dialog.

yes

yes

yes

yes

yes

yes

operationEnabled

n/a Returns true or false depending on the state of the action binding. For example, the action binding may be enabled (true) or disabled (false) based on the currency (as determined, for example, when the user clicks the First, Next, Previous, Last navigation buttons.

yes

n/a

n/a

n/a

n/a

n/a

B-4 Fusion Developer’s Guide for Oracle Application Development Framework

EL Properties of Oracle ADF Bindings

Table B–1 (Cont.) EL Properties of Oracle ADF Bindings Runtime Property

Description

rangeSet

Returns a list of map elements n/a over the range of rows from the associated iterator binding. The elements in this list are wrapper objects over the indexed row in the range that restricts access to only the attributes to which the binding is bound. The properties returned on the reference object are: ■









Iterator Action Attribute Button List Table Tree n/a

n/a

n/a

n/a

yes

yes

index — The range index of the row this reference is pointing to. key — The key of the row this reference is pointing to. keyStr — The String format of the key of the row this reference is pointing to. currencyString — The current indexed row as a String. Returns "*" if the current entry belongs to the current row; otherwise, returns " ". This property is useful in JSP applications to display the current row. attributeValues — The array of applicable attribute values from the row.

And you may also access an attribute value by name on a range set like rangeSet.dname if dname is a bound attribute in the range binding. rangeSize

yes Returns the range size of the ADF iterator binding’s row set. This allows you to determine the number or data objects to bind from the data source.

n/a

n/a

n/a

n/a

yes

yes

rangeStart

Returns the absolute index in a yes collection of the first row in range. See javadoc for oracle.jbo.RowSetIterat or.getRangeStart().

n/a

n/a

n/a

n/a

yes

yes

result

Returns the result of a method n/a that is bound and invoked by a method action binding.

yes

n/a

n/a

n/a

n/a

n/a

rootNodeBinding

Returns the root node of a tree binding.

n/a

n/a

n/a

n/a

n/a

yes

n/a

Oracle ADF Binding Properties B-5

EL Properties of Oracle ADF Bindings

Table B–1 (Cont.) EL Properties of Oracle ADF Bindings Runtime Property

Description

Iterator Action Attribute Button List Table Tree

selectedValue

Returns the value corresponding to the current selected index in the list or button binding.

n/a

n/a

n/a

yes

yes

n/a

n/a

tooltip

Returns the tooltip hint for the first attribute to which the binding is associated.

n/a

n/a

yes

yes

yes

n/a

n/a

updateable

Returns true if the first attribute to which the binding is associated is updateable. Otherwise, returns false.

n/a

n/a

yes

yes

yes

n/a

n/a

B-6 Fusion Developer’s Guide for Oracle Application Development Framework

C Oracle ADF Permission Grants This appendix lists the security-aware ADF components and the actions that their Permission implementation classes define. This appendix contains the following section: ■

Appendix C.1, "Grantable Actions of ADF Components"

C.1 Grantable Actions of ADF Components You can create security policies for the ADF components shown in Table C–1 by defining permission information in the overview editor for ADF security policies. Permissions that you add to the policy store, specify the fully-qualified permission class name, the fully-qualified resource name, the action that can be performed against the resource, and the application role target of the grant. When you enable ADF security to enforce permission checking, the operations supported by ADF components will be inaccessible to users who do not possess sufficient access rights as defined by grants to their application role. For complete details about defining ADF security policies, see Chapter 28, "Adding Security to a Fusion Web Application".

Note:

Table C–1

Oracle ADF Security Permissions Grants

ADF Component

Grantable Action

Corresponding Implementation

ADF Bounded Task Flow

View

Read and execute a bounded task flow. This is the only operation that the task flow supports in this release.

ADF page definition View

View the page. This is the only operation that the page definition supports in this release.

ADF Business Components entity objects

read

View a row of the bound collection.

update

Update any attribute of the bound collection.

removeCurrentRow Delete a row from the bound collection. /delete ADF Business Component attributes of entity objects

update

Update a specific attribute of the bound collection.

Oracle ADF Permission Grants C-1

Grantable Actions of ADF Components

C-2 Fusion Developer’s Guide for Oracle Application Development Framework

D ADF Equivalents of Common Oracle Forms Triggers This appendix provides a quick summary of how basic tasks performed with the most common Oracle Forms triggers are accomplished using Oracle ADF. This appendix contains the following sections: ■

Section D.1, "Validation & Defaulting (Business Logic)"



Section D.2, "Query Processing"



Section D.3, "Database Connection"



Section D.4, "Transaction "Post" Processing (Record Cache)"



Section D.5, "Error Handling"

D.1 Validation & Defaulting (Business Logic) Table D–1

ADF Equivalents for Oracle Forms Validation and Defaulting Triggers

Forms Trigger

ADF Equivalent

WHEN-VALIDATE-RECORD

In the custom EntityImpl class for your entity object, write a public method returning a boolean type with a method name like validateXXXX() and have it return true if the validation succeeds or false if the validation fails. Then, add a Method validator for this validation method to your entity object at the entity level. When doing that, you can associate a validation failure message with the rule.

Execute validation code at the record level

WHEN-VALIDATE-ITEM Execute validation code at the field level

WHEN-DATABASE-RECORD Execute code when a row in the data block is marked for insert or update

In the custom EntityImpl class for your entity object, write a public method returning a boolean type and accepting a single argument of the same data type as your attribute, having a method name like validateXXXX(). Have it return true if the validation succeeds or false if the validation fails. Then, add a Method validator for this validation method to the entity object at the attribute level for the appropriate attribute. When doing that, you can associate a validation failure message with the rule. Override the addToTransactionManager() method of your entity object. Write code after calling the super.

ADF Equivalents of Common Oracle Forms Triggers

D-1

Query Processing

Table D–1 (Cont.) ADF Equivalents for Oracle Forms Validation and Defaulting Triggers Forms Trigger

ADF Equivalent

WHEN-CREATE-RECORD

Override the create() method of your entity object and after calling the super, use appropriate setAttrName() methods to set default values for attributes as necessary.

Execute code to populate complex default values when a new record in the data block is created, without changing the modification status of the record

To immediately set a primary key attribute to the value of a sequence, construct an instance of the SequenceImpl helper class and call its getSequenceNumber() method to get the next sequence number. Assign this value to your primary key attribute. If you want to wait to assign the sequence number until the new record is saved, but still without using a database trigger, you can use this technique in an overridden prepareForDML() method in your entity object. If instead you want to assign the primary key from a sequence using your own BEFOREINSERTFOREACHROW database trigger, then use the special data type called DBSequence for your primary key attribute instead of the regular Number type.

WHEN-REMOVE-RECORD Execute code whenever a row is removed from the data block

Override the remove() method of your entity object and write code either before or after calling the super.

D.2 Query Processing Table D–2

ADF Equivalents for Oracle Forms Query Processing Triggers

Forms Trigger

ADF Equivalent

PRE-QUERY

Override the executeQueryForCollection() method on your view object class and write code before calling the super.

Execute logic before executing a query in a data block, typically to set up values for Query-by-Example criteria in the "example record" ON-COUNT Override default behavior to count the query hits for a data block POST-QUERY Execute logic after retrieving each row from the data source for a data block.

ON-LOCK Override default behavior to attempt to acquire a lock on the current row in the data block

Override the getQueryHitCount() method in your view object and do something instead of calling the super. Generally instead of using a POST-QUERY style technique to fetch descriptions from other tables based on foreign key values in the current row, in ADF it's more efficient to build a view object that has multiple participating entity objects, joining in all the information you need in the query from the main table, as well as any auxiliary/lookup-value tables. This way, in a single roundtrip to the database you get all the information you need. If you still need a per-fetched-row trigger like POST-QUERY, override the createInstanceFromResultSet() method in your view object class. Override the lock() method in your entity object class and do something instead of calling the super.

D-2 Fusion Developer’s Guide for Oracle Application Development Framework

Transaction "Post" Processing (Record Cache)

D.3 Database Connection Table D–3

ADF Equivalents for Oracle Forms Database Connection Triggers

Forms Trigger

ADF Equivalent

POST-LOGON

Override the afterConnect() method on your custom application module. Since application module instances can stay connected while serving different logical client sessions, you can override the prepareSession() method, which is fired after initial login, as well as after any time the application module is accessed by a user that was different from the one that accessed it last time.

Execute logic after logging into the database

PRE-LOGOUT Execute logic before logging out of the database

Override the beforeDisconnect() method on your custom application module class.

D.4 Transaction "Post" Processing (Record Cache) Table D–4

ADF Equivalents for Oracle Forms Transactional Triggers

Forms Trigger

ADF Equivalent

PRE-COMMIT

Override the commit() method in a custom DBTransactionImpl class and write code before calling the super.

Execute code before commencing processing of the changed rows in all data blocks in the transaction

Note: For an overview of creating and using a custom DBTransaction implementation, see Section 33.8.4.1, "Creating a Custom Database Transaction Framework Extension Class".

PRE-INSERT Execute code before a new row in the data block is inserted into the database during "post" processing ON-INSERT Override default processing for inserting a new row into the database during "post" processing POST-INSERT Execute code after new row in the data block is inserted into the database during "post" processing

Override the doDML() method in your entity class, and if the operation equals DML_ INSERT, then write code before calling the super. Override the doDML() method in your entity class, and if the operation equals DML_ INSERT, then write code instead of calling the super. Override the doDML() method in your entity class, and if the operation equals DML_ INSERT, then write code after calling the super.

Override the doDML() method in your entity class, and if the operation equals DML_ Execute code before a row removed from the DELETE, then write code before calling the data block is deleted from the database during super. "post" processing PRE-DELETE

Override the doDML() method in your entity class, and if the operation equals DML_ Override default processing for deleting a row DELETE, then write code instead of calling the removed from the data block from the super. database during "post" processing ON-DELETE

ADF Equivalents of Common Oracle Forms Triggers

D-3

Error Handling

Table D–4 (Cont.) ADF Equivalents for Oracle Forms Transactional Triggers Forms Trigger

ADF Equivalent

Override the doDML() method in your entity class, and if the operation equals DML_ Execute code after a row removed from the DELETE, then write code after calling the data block is deleted from the database during super. "post" processing POST-DELETE

Override the doDML() method in your entity class, and if the operation equals DML_ Execute code before a row changed in the data UPDATE, then write code before calling the block is updated in the database during "post" super. processing PRE-UPDATE

ON-UPDATE Override default processing for updating a row changed in the data block from the database during "post" processing

Override the doDML() method in your entity class, and if the operation equals DML_ UPDATE, then write code instead of calling the super.

Override the doDML() method in your entity class, and if the operation equals DML_ Execute code after a row changed in the data UPDATE, then write code after calling the block is updated in the database during "post" super. processing POST-UPDATE

If you want a single block of code for the whole transaction, you can override the Execute code after Forms has "posted" all doCommit() method in a custom necessary rows to the database, but before DBTransactionImpl object and write code issuing the data commit to end the transaction before calling the super. POST-FORMS-COMMIT

To execute entity-specific code before commit for each affected entity in the transaction, override the beforeCommit() method on your entity object, and write code there. POST-DATABASE-COMMIT Execute code after database transaction has been committed

Override the commit() method in a custom DBTransactionImpl class, and write code after calling the super.

D.5 Error Handling Table D–5

ADF Equivalents for Oracle Forms Error Handling Triggers

Forms Trigger

ADF Equivalent

ON-ERROR

Install a custom error handler (DCErrorHandler) on the ADF BindingContext For details, see Section 26.8, "Customizing Error Handling".

Override default behavior for handling an error

D-4 Fusion Developer’s Guide for Oracle Application Development Framework

E Most Commonly Used ADF Business Components Methods This appendix highlights the most commonly used methods in the interfaces and classes of the ADF Business Components layer of Oracle ADF. This appendix contains the following sections: ■

Section E, "Most Commonly Used ADF Business Components Methods"



Section E.2, "Most Commonly Used Methods In the Business Service Tier"

E.1 Most Commonly Used Methods in the Client Tier All of the interfaces described in this section are designed for use by client-layer code and are part of the oracle.jbo.* package. The corresponding implementation classes for these oracle.jbo.* interfaces are consciously designed to not be directly accessed by client code. As you'll see in the Section E.2, "Most Commonly Used Methods In the Business Service Tier" section below, the implementation classes live in the oracle.jbo.server.* package and generally have the suffix Impl in their name to help remind you not to using them in your client-layer code. Note:

E.1.1 ApplicationModule Interface The ApplicationModule is a business service component that acts as a transactional container for other ADF components and coordinates with them to implement a number of Java EE design patterns important to business application developers. These design pattern implementations enable your client code to work easily with updatable collections of value objects, based on fast-lane reader SQL queries that retrieve only the data needed by the client, in the way the client wants to view it. Changes made to these value objects are automatically coordinated with your persistent business domain objects in the business service tier to enforce business rules consistently and save changes back to the database. For the complete list of design patterns ADF Business Components implements, see Appendix F, "ADF Business Components Java EE Design Pattern Catalog".

Note:

Most Commonly Used ADF Business Components Methods

E-1

Most Commonly Used Methods in the Client Tier

Table E–1

ApplicationModule Interface

If you want to...

Call this ApplicationModule interface method...

Access an existing view object instance using the assigned instance name (for example, MyVOInstanceName)

findViewObject()

Creating a new view object instance from an existing definition

createViewObject()

Creating a new view object instance from a SQL Statement

createViewObjectFromQueryStmt() Note: This incurs runtime overhead to describe the "shape" of the dynamic query's SELECT list. Oracle recommends using this only when you cannot know the SELECT list for the query at design-time. Furthermore, if you are creating the dynamic query based on some kind of custom runtime repository, you can follow the steps to create (both read-only and updatable) dynamic view objects without the runtime-describe overhead, as described in Section 35.10, "Creating a View Object with Multiple Updatable Entities". If only the WHERE needs to be dynamic, create the view object at design time, then set the where clause dynamically as needed using ViewObject API's.

Access a nested application module instance by name

findApplicationModule()

Create a new nested application module instance from an existing definition

createApplicationModule()

Find a view object instance in a nested application module using a dot-notated name (for example, MyNestedAMInstanceName.OneOfItsVON ames)

findViewObject()

Accessing the current transaction object

getTransaction()

Note: You can use the above method to find an instance of a view object belonging to a nested application module in a single method call. This way you do not need to first call findApplicationModule() to find the nested application module, then call findViewObject() on that nested application module.

In addition to generic ApplicationModule access, Oracle JDeveloper can generate you a custom YourApplicationModuleName interface containing service-level custom methods that you've chosen to expose to the client. You do this by visiting the Client Interface tab of the Application Module editor, and shuttling the methods you'd like to appear in your client interface into the Selected list.

E.1.2 Transaction Interface The Transaction interface exposes methods allowing the client to manage pending changes in the current transaction.

E-2 Fusion Developer’s Guide for Oracle Application Development Framework

Most Commonly Used Methods in the Client Tier

Table E–2

Transaction Interface

If you want to...

Call this Transaction interface method...

Commit pending changes

commit()

Rollback pending changes

rollback()

Execute a one-time database command or block of PL/SQL

executeCommand() Note: Commands that require retrieving OUT parameters, that will be executed more than once, or that could benefit by using bind variables should not use this method. Instead, expose a custom method on your application module.

Validate all pending invalid changes in the transaction

validate()

Change the default locking mode

setLockingMode() Note: You can set the locking mode in your configuration by setting the property jbo.locking.mode to one of the four supported values: none, optimistic, pessimistic, optupdate. If you don't explicitly set it, it will default to pessimistic. For Fusion web applications, Oracle recommends using optimistic or optupdate modes.

Decide whether to use bundled exception reporting mode or not.

setBundledExceptionMode() Note: ADF controller layer support sets this parameter to true automatically for Fusion web applications.

Decide whether entity caches will be cleared upon a successful commit of the transaction.

setClearCacheOnCommit() Note: Default is false

Decide whether entity caches will be cleared upon a rollback of the transaction.

setClearCacheOnRollback() Note: Default is true

Clear the entity cache for a specific entity object.

clearEntityCache()

E.1.3 ViewObject Interface A ViewObject encapsulates a database query and simplifies working with the RowSet of results it produces. You use view objects to project, filter, join, or sort business data using SQL from one or more tables into exactly the format that the user should see it on the page or panel. You can create "master/detail" hierarchies of any level of depth or complexity by connecting view objects together using view links. View objects can produce read-only query results, or by associating them with one ore more entity objects at design time, can be fully updatable. Updatable view objects can support insertion, modification, and deletion of rows in the result collection, with automatic delegation to the correct business domain objects.

Most Commonly Used ADF Business Components Methods

E-3

Most Commonly Used Methods in the Client Tier

Every ViewObject aggregates a "default rowset" for simplifying the 90% of use cases where you work with a single RowSet of results for the ViewObject's query. A ViewObject implements all the methods on the RowSet interface by delegating them to this default RowSet. That means you can invoke any RowSet methods on any ViewObject as well. Every ViewObject implements the StructureDef interface to provide information about the number and types of attributes in a row of its row sets. So you can call StructureDef methods right on any view object. Table E–3

ViewObject Interface

If you want to...

Call this ViewObject interface method...

Set an additional runtime WHERE clause on the rowset

setWhereClause() Note: This WHERE clause augments any WHERE clause specified at design time in the base view object. It does not replace it.

Set a dynamic ORDER BY clause

setOrderByClause()

Create a Query-by-Example criteria collection

createViewCriteria() Note: You then create one or more ViewCriteriaRow objects using the createViewCriteriaRow() method on the ViewCriteria object you created. Then, you add() these view criteria rows to the view criteria collection and apply the criteria using the method below.

Apply a Query-by-Example criteria collection

applyViewCriteria()

Set a query optimizer hint

setQueryOptimizerHint()

Access the attribute definitions for the key attributes in the view object

getKeyAttributeDefs()

Add a dynamic attribute to rows in this view object's row sets

addDynamicAttribute()

Clear all row sets produced by a view object

clearCache()

Remove view object instance an its resources

remove()

Set an upper limit on the number of rows that the view object will attempt to fetch from the database.

setMaxFetchSize() Note: Default is -1 which means to impose no limit on how many rows would be retrieved from the database if you iterate through them all. By default they are fetched lazily as you iterate through them.

In addition to generic ViewObject access, JDeveloper can generate you a custom YourViewObjectName interface containing view-object level custom methods that you've chosen to expose to the client. You do this by visiting the Client Interface tab of the View Object editor, and shuttling the methods you'd like to appear in your client interface into the Selected list.

E.1.4 RowSet Interface A RowSet is a set of rows, typically produced by executing a ViewObject's query. E-4 Fusion Developer’s Guide for Oracle Application Development Framework

Most Commonly Used Methods in the Client Tier

Every RowSet aggregates a "default rowset iterator" for simplifying the 90% of use cases where you only need a single iterator over the rowset. A RowSet implements all the methods on the RowSetIterator interface by delegating them to this default RowSetIterator. This means you can invoke any RowSetIterator method on any RowSet (or ViewObject, since it implements RowSet as well for its default RowSet). Table E–4

RowSet Interface

If you want to...

Call this RowSet interface method...

Set a where clause bind variable value

setWhereClauseParam() Note: Bind variable ordinal positions are zero-based

Avoid view object row caching if data is being read only once

setForwardOnly()

Force a row set's query to be (re)executed

executeQuery()

Estimate the number of rows in a view object's getEstimatedRowCount() query result Produce XML document for rows in View Object rowset

writeXML()

Process all rows from an incoming XML document

readXML()

Set whether rowset will automatically see new setAssociationConsistent() rows based on the same entity object created through other rowsets Create secondary iterator to use for programmatic iteration

createRowSetIterator() Note: If you plan to find and use the secondary iterator by name later, then pass in a string name as the argument, otherwise pass null for the name and make sure to close the iterator when done iterating by calling its closeRowSetIterator() method.

E.1.5 RowSetIterator Interface A RowSetIterator is an iterator over the rows in a RowSet. By default it allows you to iterate both forward and backward through the rows. Table E–5

RowSetIterator Interface

If you want to...

Call this RowSetIterator interface method...

Get the first row of the iterator's rowset

first()

Test whether there are more rows to iterate

hasNext()

Get the next row of iterator's rowset

next()

Find row in this iterator's rowset with a given Key value

findByKey() Note: It's important that the Key object that you pass to findByKey be created using the exact same datatypes as the attributes that comprise the key of the rows in the view object you're working with.

Most Commonly Used ADF Business Components Methods

E-5

Most Commonly Used Methods in the Client Tier

Table E–5

(Cont.) RowSetIterator Interface

If you want to...

Call this RowSetIterator interface method...

Create a new row to populate for insertion

createRow() Note: The new row will already have default values set for attributes which either have a static default value supplied at the entity object or view object level, or if the values have been populated in an overridden create() method of the underlying entity object(s).

Create a view row with an initial set of foreign createAndInitRow() key and/or discriminator attribute values Note: You use this method when working with view objects that can return one of a "family" of entity object subtypes. By passing in the correct discriminator attribute value in the call to create the row, the framework can create you the correct matching entity object subtype underneath. Insert a new row into the iterator's rowset

insertRow() Note: It's a good habit to always immediately insert a newly created row into the rowset. That way you will avoid a common gotcha of creating the row but forgetting to insert it into the rowset.

Get the last row of the iterator's rowset

last()

Get the previous row of the iterator's rowset

previous()

Reset the current row pointer to the slot before reset() the first row Close an iterator when done iterating

closeRowSetIterator()

Set a given row to be the current row

setCurrentRow()

Remove the current row

removeCurrentRow()

Remove the current row to later insert it at a different location in the same iterator.

removeCurrentRowAndRetain()

Remove the current row from the current collection but do not remove it from the transaction.

removeCurrentRowFromCollection()

Set/change the number of rows in the range (a setRangeSize() "page" of rows the user can see) Scroll to view the Nth page of rows (1-based)

scrollToRangePage()

Scroll to view the range of rows starting with row number N

scrollRangeTo()

Set row number N in the range to be the current row

setCurrentRowAtRangeIndex()

Get all rows in the range as a Row array

getAllRowsInRange()

E-6 Fusion Developer’s Guide for Oracle Application Development Framework

Most Commonly Used Methods in the Client Tier

E.1.6 Row Interface A Row is generic value object. It contains attributes appropriate in name and Java type for the ViewObject that it's related to. Table E–6

Row Interface

If you want to...

Call this Row interface method...

Get the value of an attribute by name

getAttribute()

Set the value of an attribute by name

setAttribute()

Produce an XML document for a single row

writeXML()

Eagerly validate a row

validate()

Read row attribute values from XML

readXML()

Remove the row

remove()

Flag a newly created row as temporary (until updated again)

setNewRowState(Row.STATUS_ INITIALIZED)

Retrieve the attribute structure definition information for a row

getStructureDef()

Get the Key object for a row

getKey()

In addition to generic Row access, JDeveloper can generate you a custom YourViewObjectNameRow interface containing your type-safe attribute getter and setter methods, as well as any desired row-level custom methods that you've chosen to expose to the client. You do this by visiting the Client Row Interface tab of the View Object editor, and shuttling the methods you'd like to appear in your client interface into the Selected list.

E.1.7 StructureDef Interface A StructureDef is an interface that provides access to runtime metadata about the structure of a Row. In addition, for convenience every ViewObject implements the StructureDef interface as well, providing access to metadata about the attributes in the resulting view rows that its query will produce. Table E–7

StructureDef Interface

If you want to...

Call this StructureDef interface method...

Access attribute definitions for all attributes in getAttributeDefs() the view object row Find an attribute definition by name

findAttributeDef()

Get attribute definition by index

getAttributeDef()

Get number of attributes in a row

getAttributeCount()

E.1.8 AttributeDef Interface An AttributeDef provides attribute definition information for any attribute of a View Object row or Entity Object instance like attribute name, Java type, and SQL type. It also provides access to custom attribute-specific metadata properties that can be inspected by generic code you write, as well as UI hints that can assist in rendering an appropriate user interface display for the attribute and its value.

Most Commonly Used ADF Business Components Methods

E-7

Most Commonly Used Methods in the Client Tier

Table E–8

AttributeDef Interface

If you want to...

Call this AttributeDef interface method...

Get the Java type of the attribute

getJavaType()

Get the SQL type of the attribute

getSQLType() Note: The int value corresponds to constants in the JDBC class java.sql.Types

Determine the kind of attribute

getAttributeKind() Note: If it's a simple attribute, it returns one of the constants ATTR_PERSISTENT, ATTR_SQL_ DERIVED, ATTR_TRANSIENT, ATTR_ DYNAMIC, ATTR_ENTITY_DERIVED. If it is an 1-to-1 or many-to-1 association/viewlink accessor it returns ATTR_ASSOCIATED_ROW. If it is an 1-to-many or many-to-many association/viewlink accessor it returns ATTR_ASSOCIATED_ROWITERATOR

Get the Java type of elements contained in an Array-valued attribute

getElemJavaType()

Get the SQL type of elements contained in an Array-valued attribute

getElemSQLType()

Get the name of the attribute

getName()

Get the index position of the attribute

getIndex()

Get the precision of a numeric attribute or the maximum length of a String attribute

getPrecision()

Get the scale of a numeric attribute

getScale()

Get the underlying column name corresponding to the attribute

getColumnNameForQuery()

Get attribute-specific custom property values

getProperty(), getProperties()

Get the UI AttributeHints object for the attribute

getUIHelper()

Test whether the attribute is mandatory

isMandatory()

Test whether the attribute is queriable

isQueriable()

Test whether the attribute is part of the primary key for the row

isPrimaryKey()

E.1.9 AttributeHints Interface The AttributeHints interface related to an attribute exposes UI hint information that attribute that you can use to render an appropriate user interface display for the attribute and its value. Table E–9

AttributeHints Interface

If you want to...

Call this AttributeHints interface method...

Get the UI label for the attribute

getLabel()

Get the tool tip for the attribute

getTooltip()

E-8 Fusion Developer’s Guide for Oracle Application Development Framework

Most Commonly Used Methods In the Business Service Tier

Table E–9

(Cont.) AttributeHints Interface

If you want to...

Call this AttributeHints interface method...

Get the formatted value of the attribute, using any format mask supplied

getFormattedAttribute()

Get the display hint for the attribute

getDisplayHint() Note: Will have a String value of either Display or Hide.

Get the preferred control type for the attribute getControlType() Parse a formatted string value using any format mask supplied for the attribute

parseFormattedAttribute()

E.2 Most Commonly Used Methods In the Business Service Tier The implementation classes corresponding to the oracle.jbo.* interfaces, as described in Section E.1, "Most Commonly Used Methods in the Client Tier", are consciously designed to not be directly accessed by client code. They live in a different package named oracle.jbo.server.* and have the Impl suffix in their name to help remind you not to using them in your client-layer code. In your business service tier implementation code, you can use any of the same methods that are available to clients, but in addition you can also: ■



Safely cast any oracle.jbo.* interface to its oracle.jbo.server.* package implementation class and use any methods on that Impl class as well. Override any of the base framework implementation class' public or protected methods to augment or change its default functionality by writing custom code in your component subclass before or after calling super.methodName().

This section provides a summary of the most frequently called, written, and overridden methods for the key ADF Business Components classes.

E.2.1 Controlling Custom Java Files For Your Components Before examining the specifics of individual classes, it's important to understand how you can control which custom Java files each of your components will use. When you don't need a customized subclass for a given component, you can just let the base framework class handle the implementation at runtime. Each business component you create comprises a single XML component descriptor, and zero or more related custom Java implementation files. Each component that supports Java customization has a Java tab in its component editor in the JDeveloper IDE. By checking or unchecking the different Java classes, you control which ones get created for your component. If none of the boxes is checked, then your component will be an XML-only component, which simply uses the base framework class as its Java implementation. Otherwise, tick the checkbox of the related Java classes for the current component that you need to customize. JDeveloper will create you a custom subclass of the framework base class in which you can add your code. You can setup global IDE preferences for which Java classes should be generated by default for each ADF business component type by selecting Tools | Preferences... | Business Components and ticking the checkboxes to indicate what you want your defaults to be. Note:

Most Commonly Used ADF Business Components Methods

E-9

Most Commonly Used Methods In the Business Service Tier

A best practice is to always generate Entity Object and View Row classes, even if you don't require any custom code in them other than the automatically-generated getter and setter methods. These getter and setter methods offer you compile-time type checking that avoids discovering errors at runtime when you accidentally set an attribute to an incorrect kind of value.

E.2.2 ApplicationModuleImpl Class The ApplicationModuleImpl class is the base class for application module components. Since the application module is the ADF component used to implement a business service, think of the application module class as the place where you can write your service-level application logic. The application module coordinates with view object instances to support updatable collections of value objects that are automatically "wired" to business domain objects. The business domain objects are implemented as ADF entity objects.

E.2.2.1 Methods You Typically Call on ApplicationModuleImpl

Table E–10

Methods You Typically Call on ApplicationModuleImpl

If you want to...

Call this method of the ApplicationModuleImpl class

Perform any of the common application module operations from inside your class, which can also be done from the client

For more information, see Section E.1.1, "ApplicationModule Interface".

Access a view object instance that you added to the application module's data model at design time

getViewObjectInstanceName() Note: JDeveloper generates this type-safe view object instance getter method for you to reflect each view object instance in the application module's design-time data-model.

Access the current DBTransaction object

getDBTransaction()

Access a nested application module instance that you added to the application module at design time

getAppModuleInstanceName() Note: JDeveloper generates this type-safe application module instance getter method for you to reflect each nested application module instance added to the current application module at design time.

E.2.2.2 Methods You Typically Write in Your Custom ApplicationModuleImpl Subclass

E-10 Fusion Developer’s Guide for Oracle Application Development Framework

Most Commonly Used Methods In the Business Service Tier

Table E–11 Subclass

Methods You Typically Write in Your Custom ApplicationModuleImpl

If you want to...

Write a method like this in your custom ApplicationModuleImpl class

Invoke a database stored procedure

someCustomMethod() Note: Use appropriate method on the DBTransaction interface to create a JDBC PreparedStatement. If the stored procedure has OUT parameters, then create a CallableStatement instead. For sample code that demonstrates encapsulating a call to a PL/SQL stored procedure inside your application module, see Section 33.5, "Invoking Stored Procedures and Functions".

Expose custom business service methods on your application module

someCustomMethod() Note: Select the method name on the Client Interface panel of the application module editor to expose it for client access if required.

JDeveloper can generate you a custom YourApplicationModuleName interface containing service-level custom methods that you've chosen to expose to the client. You do this by visiting the Client Interface tab of the Application Module editor, and shuttling the methods you'd like to appear in your client interface into the Selected list.

E.2.2.3 Methods You Typically Override in Your Custom ApplicationModuleImpl Subclass

Most Commonly Used ADF Business Components Methods E-11

Most Commonly Used Methods In the Business Service Tier

Table E–12 Subclass

Methods You Typically Override in Your Custom ApplicationModuleImpl

If you want to... Perform custom setup code the first time an application module is created and each subsequent time it gets used by a different client session.

Override this method of the ApplicationModuleImpl class prepareSession() Note: This is the method you'd use to setup per-client context info for the current user in order to use database Oracle's Virtual Private Database (VPD) features. It can also be used to set other kinds of PL/SQL package global variables, whose values might be client-specific, on which other stored procedures might rely. This method is also useful to perform setup code that is specific to a given view object instance in the application module. If instead of being instance-specific you want the view object setup code to be initialized for every instance ever created of that view object component, then put the setup logic in an overridden create() method in your ViewObjectImpl subclass instead.

Perform custom setup code after the application module's transaction is associated with a database connection from the connection pool.

afterConnect() Note: Can be a useful place to write a line of code that uses getDBTransaction().executeCommand( ) to perform an ALTER SESSION SET SQL TRACE TRUE to enable database SQL Trace logging for the current application connection. These logs can then be processed with the TKPROF utility to study the SQL statements being performed and the query optimizer plans that are getting used. For details about the TKPROF utility, see section "Understanding SQL Trace and TKPROF" in the Oracle Database Performance Tuning Guide.

Perform custom setup code before the application module's transaction releases its database connection back to the database connection pool.

beforeDisconnect()

Write custom application module state to the state management XML snapshot

passivateState()

Read and restore custom application module state from the state management XML snapshot

activateState()

Note: If you have set jbo.doconnectionpooling to true, then the connection is released to the database connection pool each time the application module is returned to the application module pool.

E.2.3 DBTransactionImpl2 Class The DBTransactionImpl2 class — which extends the base DBTransactionImpl class, and is constructed by the DatabaseTransactionFactory class — is the base class that

E-12 Fusion Developer’s Guide for Oracle Application Development Framework

Most Commonly Used Methods In the Business Service Tier

implements the DBTransaction interface, representing the unit of pending work in the current transaction.

E.2.3.1 Methods You Typically Call on DBTransaction

Table E–13

Methods You Typically Call on DBTransaction

If you want to...

Call this method on the DBTransaction object

Commit the transaction

commit()

Rollback the transaction

rollback()

Eagerly validate any pending invalid changes in the transaction

validate()

Create a JDBC PreparedStatement using the transaction's Connection object

createPreparedStatement()

Create a JDBC CallableStatement using the transaction's Connection object

createCallableStatement()

Create a JDBC Statement using the transaction's Connection object

createStatement()

Add a warning to the transaction's warning list.

addWarning()

E.2.3.2 Methods You Typically Override in Your Custom DBTransactionImpl2 Subclass

Table E–14 Subclass

Methods You Typically Override in Your Custom DBTransactionImpl2 Override this method in your custom DBTransactionImpl2 class

If you want to... Perform custom code before or after the transaction commit operation

commit()

Perform custom code before or after the transaction rollback operation

rollback()

In order to have your custom DBTransactionImpl2 subclass get used at runtime, there are two steps you must follow: 1.

Create a custom subclass of DatabaseTransactionFactory that overrides the create method to return an instance of your custom DBTransactionImpl2 subclass like this: package com.yourcompany.adfextensions; import oracle.jbo.server.DBTransactionImpl2; import oracle.jbo.server.DatabaseTransactionFactory; import com.yourcompany.adfextensions.CustomDBTransactionImpl; public class CustomDatabaseTransactionFactory extends DatabaseTransactionFactory { /** * Return an instance of our custom CustomDBTransactionImpl class * instead of the default implementation. *

Most Commonly Used ADF Business Components Methods E-13

Most Commonly Used Methods In the Business Service Tier

* @return An instance of our custom DBTransactionImpl2 implementation. */ public DBTransactionImpl2 create() { return new CustomDBTransactionImpl(); } } 2.

Tell the framework to use your custom transaction factory class by setting the value of the TransactionFactory configuration property to the fully-qualified class name of your custom transaction factory. As with other configuration properties, if not supplied in the configuration XML file, it can be provided alternatively as a Java system parameter of the same name.

E.2.4 EntityImpl Class The EntityImpl class is the base class for entity objects, which encapsulate the data, validation rules, and business behavior for your business domain objects.

E.2.4.1 Methods You Typically Call on EntityImpl

Table E–15

Methods You Typically Call on EntityImpl

If you want to...

Call this method in your EntityImpl subclass

Get the value of an attribute

getAttributeName() Note: Code-generated getter method calls getAttributeInternal() but provides compile-time type checking.

Set the value of an attribute

setAttributeName() Note: Code-generated setter method calls setAttributeInternal() but provides compile-time type checking.

Get the value of an attribute by name

getAttributeInternal()

Set the value of an attribute by name

setAttributeInternal()

Eagerly perform entity object validation

validate()

Refresh the entity from the database

refresh()

Populate the value of an attribute without marking it as being changed, but sending notification of its being changed so UI's refresh the value on the screen/page.

populateAttributeAsChanged()

Access the definition object for an entity

getDefinitionObject()

Get the Key object for an entity

getKey()

Determine the state of the entity instance, irrespective of whether it has already been posted in the current transaction (but not yet committed)

getEntityState() Note: Will return one of the constants STATUS_ UNMODIFIED, STATUS_INITIALIZED, STATUS_NEW, STATUS_MODIFIED, STATUS_ DELETED, or STATUS_DEAD indicating the status of the entity instance in the current transaction.

E-14 Fusion Developer’s Guide for Oracle Application Development Framework

Most Commonly Used Methods In the Business Service Tier

Table E–15 (Cont.) Methods You Typically Call on EntityImpl If you want to...

Call this method in your EntityImpl subclass

Determine the state of the entity instance

getPostState() Note: This method is typically only relevant if you are programmatically using the postChanges() method to post but not yet commit entity changes to the database and need to detect the state of an entity with regard to its posting state

Get the value originally read from the database for a given attribute

getPostedAttribute()

Eagerly lock the database row for an entity instance

lock()

E.2.4.2 Methods You Typically Write in Your Custom EntityImpl Subclass

Table E–16

Methods You Typically Write in Your Custom EntityImpl Subclass Write a method like this in your EntityImpl subclass

If you want to... Perform attribute-specific validation

public boolean validateSomething(AttrTypevalue) Note: Register the attribute validator method by adding a "MethodValidator" on correct attribute in the Validation panel of the Entity Object editor.

Perform entity-level validation

public boolean validateSomething() Note: Register the entity-level validator method by adding a "MethodValidator" on the entity in the Validation panel of the Entity Object editor.

Calculate the value of a transient attribute

Add your calculation code to the generated getAttributeName() method.

E.2.4.3 Methods You Typically Override on EntityImpl

Table E–17

Methods You Typically Override on EntityImpl Override this method in your custom EntityImpl subclass...

If you want to... Set calculated default attribute values, including programmatically populating thbe primary key attribute value of a new entity instance.

create() Note: After calling super.create(), call the appropriate setAttrName() method(s) to set the default values for that(/those) attributes.

Most Commonly Used ADF Business Components Methods E-15

Most Commonly Used Methods In the Business Service Tier

Table E–17 (Cont.) Methods You Typically Override on EntityImpl If you want to...

Override this method in your custom EntityImpl subclass...

Modify attribute values before changes are posted to the database

prepareForDML()

Augment/change the standard INSERT, UPDATE, or DELETE DML operation that the framework will perform on your entity object's behalf to the database

doDML() Note: Check the value of the operation flag to the constants DML_INSERT, DML_UPDATE, or DML_DELETE to test what DML operation is being performed.

Perform complex, SQL-based validation after all entity instances have been posted to the database but before those changes are committed.

beforeCommit()

Insure that a related, newly-created, parent entity gets posted to the database before the current child entity on which it depends

postChanges() Note: If the parent entity is related to this child entity via a composition association, then the framework already handles this automatically. If they are only associated (but not composed) then you need to override postChanges() method to force a newly-created parent entity to post before the current, dependent child entity. For an example of the code you typically write in your overridden postChanges() method to accomplish this, see Section 34.8.3, "Overriding postChanges() to Control Post Order".

It is possible to write attribute-level validation code directly inside the appropriate setAttributeName method of your EntityImpl class, however adopting the MethodValidator approach suggested in Table E–16 results in having a single place on the Validation Rules panel of the overview editor for the attributes of the entity object to look in order to understand all of the validations in effect for your entity object.

Note:

WARNING: It is also possible to override the validateEntity() method to write entity-level validation code, however if you want to maintain the benefits of the ADF bundled exception mode — where the framework collects and reports a maximal set of validation errors back to the client user interface — it is recommended to adopt the MethodValidator approach suggested in Table E–16. This allows the framework to automatically collect all of your exceptions that your validation methods throw without your having to understand the bundled exception implementation mechanism. Overriding the validateEntity() method directly shifts the responsibility on your own code to correctly catch and bundle the exceptions like Oracle ADF would have done by default, which is non-trivial and a chore to remember and hand-code each time.

E-16 Fusion Developer’s Guide for Oracle Application Development Framework

Most Commonly Used Methods In the Business Service Tier

E.2.5 EntityDefImpl Class The EntityDefImpl class is a singleton, shared metadata object for all entity objects of a given type in a single Java VM. It defines the structure of the entity instances and provides methods to create new entity instances and find existing instances by their primary key.

E.2.5.1 Methods You Typically Call on EntityDefImpl

Table E–18

Methods You Typically Call on EntityDefImpl

If you want to...

Call the EntityDefImpl method

Find an entity object of a this type by its primary key

findByPrimaryKey() Note: For a tip about getting findByPrimaryKey() to find entity instances of subtype entities as well, see Section 34.7.4.2, "Finding Subtype Entities by Primary Key".

Access the current DBTransaction object

getDBTransaction()

Find any EntityDefImpl object by its fully-qualified name

findDefObject() (static method)

Retrieve the value of an entity object's custom property

getProperty(), getProperties()

Set the value of an entity object's custom property

setProperty()

Create a new instance of an entity object

createInstance2() Note: Alternatively, you can expose custom createXXX() methods with your own expected signatures in that same custom EntityDefImpl subclass. See the next section for details.

Iterate over the entity instances in the cache of getAllEntityInstancesIterator() this entity type. Access ArrayList of entity definition objects getExtendedDefObjects() for entities that extend the current one.

E.2.5.2 Methods You Typically Write on EntityDefImpl

Most Commonly Used ADF Business Components Methods E-17

Most Commonly Used Methods In the Business Service Tier

Table E–19

Methods You Typically Write on EntityDefImpl

If you want to...

Write a method like this in your custom EntityDefImpl class

Allow other classes to create an entity instance createXXXX(Type1arg1,..., with an initial type-safe set of attribute values TypeNargN) or setup information. Note: Internally, this would create and populate an instance of a NameValuePairs object (which implements AttributeList) and call the protected method createInstance(), passing that NameValuePairs object. Make sure the method is public if other classes need to be able to call it.

E.2.5.3 Methods You Typically Override on EntityDefImpl

Table E–20

Methods You Typically Override on EntityDefImpl

If you want to...

Call the EntityDefImpl method

Perform custom metadata initialization when this singleton metaobject is loaded.

createDef()

Avoid using the RETURNING INTO clause to isUseReturningClause() support refresh-on-insert or refresh-on-update Note: attributes Return false to disable the use of RETURNING INTO, necessary sometimes when your entity object is based on a view with INSTEAD OF triggers that doesn't support RETURNING INTO at the database level. Control whether the UPDATE statements issued for this entity update only changed columns, or all columns

isUpdateChangedColumns() Note: Defaults to true.

Find any EntityDefImpl object by its fully-qualified name

findDefObject() Note: Static method.

Set the value of an entity object's custom property

setProperty()

Allow other classes to create a new instance an createInstance() entity object without doing so implicitly via a Note: view object. If you don't write a custom create method as noted in the previous section, you'll need to override this method and widen the visibility from protected to public to allow other classes to construct an entity instance.

E.2.6 ViewObjectImpl Class The ViewObjectImpl class the base class for view objects.

E.2.6.1 Methods You Typically Call on ViewObjectImpl

E-18 Fusion Developer’s Guide for Oracle Application Development Framework

Most Commonly Used Methods In the Business Service Tier

Table E–21

Methods You Typically Call on ViewObjectImpl

If you want to...

Call this ViewObjectImpl method

Perform any of the common view object, rowset, or rowset iterator operations from inside your class, which can also be done from the client

For more information, see Section E.1.3, "ViewObject Interface", Section E.1.4, "RowSet Interface", and Section E.1.5, "RowSetIterator Interface".

Set an additional runtime WHERE clause on the default rowset

setWhereClause()

Defines a named bind parameter.

defineNamedWhereClauseParam()

Removes a named bind parameter.

removeNamedWhereClauseParam()

Set bind variable values on the default rowset setNamedWhereClauseParam() by name. Only works when you have formally defined named bind variables on your view object. Set bind variable values on the default rowset. setWhereClauseParam() Use this method for view objects with binding style of "Oracle Positional" or "JDBC Positional" when you have not formally defined named bind variables. Retrieved a subset of rows in a view object's row set based on evaluating an in-memory filter expression.

getFilteredRows()

Retrieved a subset of rows in the current range getFilteredRowsInRange() of a view object's row set based on evaluating an in-memory filter expression. Set the number of rows that will be fetched setFetchSize() from the database per round-trip for this view Note: object. The default fetch size is a single row at a time. This is definitely not optimal if your view object intends to retrieve many rows, so you should either set the fetch size higher at design time on the Tuning tab of the View Object editor, or set it at runtime using this API.

E.2.6.2 Methods You Typically Write in Your Custom ViewObjectImpl Subclass

Table E–22

Methods You Typically Write in Your Custom ViewObjectImpl Subclass Write a method like this in your ViewObjectImpl subclass

If you want to... Provide clients with type-safe methods to set bind variable values without exposing positional details of the bind variables themselves

someMethodName(Type1arg1,..., TypeNargN) Note: Internally, this method would call the setWhereClauseParam() API to set the correct bind variables with the values provided in the type-safe method arguments.

JDeveloper can generate you a custom YourViewObjectName interface containing view object custom methods that you've chosen to expose to the client. You can accomplish this by visiting the Client Interface tab of the View Object editor, and

Most Commonly Used ADF Business Components Methods E-19

Most Commonly Used Methods In the Business Service Tier

shuttling the methods you'd like to appear in your client interface into the Selected list.

E.2.6.3 Methods You Typically Override in Your Custom ViewObjectImpl Subclass

Table E–23

Methods You Typically Override in Your Custom ViewObjectImpl Subclass

If you want to...

Override this ViewObjectImpl method

Initialize custom view object class members (not row attributes!) when the view object instance is created for the first time.

create() Note: This method is useful to perform setup logic that is applicable to every instance of a view object that will ever get created, in the context of any application module. If instead of generic view object setup logic, you need to perform logic specific to a given view object instance in an application module, then override the prepareSession() method of your application module's ApplicationModuleImpl subclass and perform the logic there after calling findViewObject() to find the view object instance whose properties you want to set.

Write custom view object instance state to the state management XML snapshot.

passivateState()

Read and restore custom view object instance state from the state management XML snapshot.

activateState()

Customize the behavior of view object query execution, independent of whether the query was executed explicitly by calling executeQuery() or implicitly, for example, by navigating to the first() row when the query hadn't yet been executed.

executeQueryForCollection()

Change/augment the way that the ViewCriteria collection of ViewCriteriaRows is converted into a Query-by-Example WHERE clause.

getViewCriteriaClause()

E.2.7 ViewRowImpl Class The ViewRowImpl class is the base class for view row objects.

E.2.7.1 Methods You Typically Call on ViewRowImpl Table E–24

Methods You Typically Call on ViewRowImpl

If you want to...

Write a method like this in your custom ViewRowImpl class

Perform any of the common view row operations from inside your class, which can also be done from the client.

For more information, see Section E.1.6, "Row Interface".

Get the value of an attribute.

getAttrName()

Set the value of an attribute.

setAttrName()

E-20 Fusion Developer’s Guide for Oracle Application Development Framework

Most Commonly Used Methods In the Business Service Tier

Table E–24 (Cont.) Methods You Typically Call on ViewRowImpl Write a method like this in your custom ViewRowImpl class

If you want to...

Access the underlying entity instance to which getEntityUsageAliasName() this view row is delegating attribute storage. Note: You can change the name of the entity usage alias name on the Entity Objects tab of the View Object Editor

E.2.7.2 Methods You Typically Write on ViewRowImpl

Table E–25

Methods You Typically Write on ViewRowImpl Write a method like this in your custom ViewRowImpl class

If you want to... Calculate the value of a view object level transient attribute

getAttrName() Note: JDeveloper generates the skeleton of the method for you, but you need to write the custom calculation logic inside the method body.

Perform custom processing of the setting of a view row attribute

setAttrName() Note: JDeveloper generates the skeleton of the method for you, but you need to write the custom logic inside the method body if required.

Determine the updateability of an attribute in a conditional way.

isAttributeUpdateable()

Custom methods that expose logical operations on the current row, optionally callable by clients

doSomething() Note: Often these view-row level custom methods simply turn around and delegate to a method call on the underlying entity object related to the current row.

JDeveloper can generate you a custom YourViewObjectNameRow interface containing view row custom methods that you've chosen to expose to the client. You can accomplish this by visiting the Client Row Interface tab of the View Object editor, and shuttling the methods you'd like to appear in your client interface into the Selected list.

E.2.7.3 Methods You Typically Override in Your Custom ViewRowImpl Subclass

Table E–26

Methods You Typically Override in Your Custom ViewRowImpl Subclass Write a method like this in your custom ViewRowImpl class

If you want to... Determine the updateability of an attribute in a conditional way.

isAttributeUpdateable()

Most Commonly Used ADF Business Components Methods E-21

Most Commonly Used Methods In the Business Service Tier

E.2.8 Setting Up Your Own Layer of Framework Base Classes Before you begin to develop application specific business components, Oracle recommends creating yourself a layer of classes that extend all of the ADF Business Components framework base implementation classes described in this paper. An example of a customized framework base class for application module components might look like this: package com.yourcompany.adfextensions; import oracle.jbo.server.ApplicationModuleImpl; public class CustomApplicationModuleImpl extends ApplicationModuleImpl { /* * We might not yet have any custom code to put here yet, but * the first time we need to add a generic feature that all of * our company's application modules need, we will be very happy * that we thought ahead to leave ourselves a convenient place * in our class hierarchy to add it so that all of the application * modules we have created will instantly benefit by that new feature, * behavior change, or even perhaps, bug workaround. */ }

A common set of customized framework base classes in a package name of your own choosing like com.yourcompany.adfextensions, each importing the oracle.jbo.server.* package, would consist of the following classes. ■

public class CustomEntityImpl extends EntityImpl



public class CustomEntityDefImpl extends EntityDefImpl



public class CustomViewObjectImpl extends ViewObjectImpl



public class CustomViewRowImpl extends ViewRowImpl



public class CustomApplicationModuleImpl extends ApplicationModuleImpl



public class CustomDBTransactionImpl extends DBTransactionImpl2



public class CustomDatabaseTransactionFactory extends DatabaseTransactionFactory

For completeness, you may also want to create customized framework classes for the following classes as well, but overriding anything in these classes would be a fairly rare requirement. ■

public class CustomViewDefImpl extends ViewDefImpl



public class CustomEntityCache extends EntityCache



public class CustomApplicationModuleDefImpl extends ApplicationModuleDefImpl

E-22 Fusion Developer’s Guide for Oracle Application Development Framework

F ADF Business Components Java EE Design Pattern Catalog This appendix provides a brief summary of the Java Platform, Enterprise Edition (Java EE) design patterns that the ADF Business Components layer implements for you. This appendix contains the following section: ■

Section F, "ADF Business Components Java EE Design Pattern Catalog"

F.1 Java EE Design Patterns Implemented by ADF Business Components By using the Oracle Application Development Framework's business components building-blocks and related design-time extensions to JDeveloper, you get a prescriptive architecture for building richly-functional and cleanly layered Java EE business services with great performance. Table F–1 provides a brief overview of the numerous design patterns that the ADF Business Components layer implements for you. Some are the familiar patterns from Sun’s Java EE BluePrints and some are design patterns that ADF Business Components adds to the list. For details about Java EE BluePrints, see the BluePrints page at the Sun Developer Network website at http://java.sun.com/reference/blueprints/. Table F–1

Java EE Design Patterns Implemented by ADF Business Components

Pattern Name and Description Model/View/Controller Cleanly separates the roles of data and presentation, allowing multiple types of client displays to work with the same business information.

Interface / Implementation Separation Cleanly separates the API or Interface for components from their implementation class.

How ADF Business Components Implements It The ADF Application Module provides a generic implementation of a Model/View/Controller "application object" that simplifies exposing the application data model for any application or service, and facilitates declaratively specifying the boundaries of a logical unit of work. Additional UI-centric frameworks and tag libraries provided in JDeveloper 10g help the developer implement the View and Controller layers. ADF Business Components enforce a logical separation of client-tier accessible functionality (via interfaces) and their business tier implementation. JDeveloper handles the creation of custom interfaces and client proxy classes automatically.

ADF Business Components Java EE Design Pattern Catalog F-1

Java EE Design Patterns Implemented by ADF Business Components

Table F–1 (Cont.) Java EE Design Patterns Implemented by ADF Business Components Pattern Name and Description Service Locator Abstracts the technical details of locating a service so the client and use it more easily.

Inversion of Control A containing component orchestrates the lifecycle of the components it contains, invoking specific methods that the developer can overrides at the appropriate times so the developer can focus more on what the code should do instead when it should get executed. Dependency Injection Simplifies application code, and increases configuration flexibility by deferring component configuration and assembly to the container.

Active Record Avoids the complexity of "anything to anything" object/relational mapping, by providing an object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data. Data Access Objects Avoids unnecessary marshalling overhead by implementing dependent objects as lightweight, persistent classes instead of each as an Enterprise Bean. Isolates persistence details into a single, easy to maintain class.

How ADF Business Components Implements It ADF application modules are looked up using a simple configuration object which hides the low-level details of finding the service instance behind the scenes. For Fusion web applications, it also hides the implementation of the application module pool usage, a lightweight pool of service components that improves application scalability. ADF components contain a number of easy-to-override methods that the framework invokes as needed during the course of application processing.

The ADF configures all its components from externalized XML metadata definition files. The framework automatically injects dependent objects like view object instances into your application module service component and entity objects into your view rows at runtime, implementing lazy loading. It supports runtime factory substitution of components by any customized subclass of that component to simplify on-site application customization scenarios. Much of the ADF functionality is implemented via dynamic injection of validator and listener subscriptions that coordinate the framework interactions depending on what declarative features have been configured for each component in their XML metadata. ADF entity objects handle the database mapping functionality you use most frequently, including inheritance, association, and composition support, without having to think about object/relational mapping. They also provide a place to encapsulate both declarative business rules and one-off programmatic business domain logic. ADF view objects automate the implementation of data access for reading data using SQL statements. ADF entity objects automate persistent storage of lightweight business entities. ADF view objects and entity objects cooperate to provide a sophisticated, performant data access objects layer where any data queried through a view object can optionally be made fully updatable without writing any "application plumbing" code.

ADF application modules are designed to implement a coarse-grained "service facade" Avoids inefficient client access of Entity Beans architecture in any of their supported and inadvertent exposure of sensitive business deployment modes. When deployed as EJB information by wrapping Entity Beans with a Session Beans or as a Service Interface, they Session Bean. provide an implementation of the Session Facade pattern automatically. Session Facade

F-2 Fusion Developer’s Guide for Oracle Application Development Framework

Java EE Design Patterns Implemented by ADF Business Components

Table F–1 (Cont.) Java EE Design Patterns Implemented by ADF Business Components Pattern Name and Description Value Object Avoids unnecessary network round-trips by creating one-off "transport" objects to group a set of related attributes needed by a client program.

Page-by-Page Iterator Avoids sending unnecessary data to the client by breaking a large collection into page-sized "chunks" for display.

How ADF Business Components Implements It ADF provides an implementation of a generic Row object, which is a metadata-driven container of any number and kind of attributes that need to be accessed by a client. The developer can work with the generic Row interface and do late-bound getAttribute("Price") and setAttribute("Quantity")calls, or optionally generate early-bound row interfaces like OverdueOrdersRow, to enable type-safe method calls like getPrice() and setQuantity(). Smarter than just a simple "bag 'o attributes" the ADF Row object can be introspected at runtime to describe the number, names, and types of the attributes in the row, enabling sophisticated, generic solutions to be implemented. ADF provides an implementation of a generic RowSet interface which manages result sets produced by executing View Object SQL queries. RowSet allows the developer to set a desired page-size, for example 10 rows, and page up and down through the query results in these page-sized chunks. Since data is retrieved lazily, only data the user actually visits will ever be retrieved from the database on the backend, and in the client tier the number of rows in the page can be returned over the network in a single roundtrip.

ADF View Objects read data directly from the database for best performance, however they Avoids unnecessary overhead for read-only give developers a choice regarding data data by accessing JDBC API's directly. This consistency. If updateability and/or allows an application to retrieve only the consistency with pending changes is desired, attributes that need to be displayed, instead of the developer need only associate his/hew finding all of the attributes by primary key View Object with the appropriate Entity when only a few attributes are required by the Objects whose business data is being client. Typically, implementations of this presented. If consistency is not a concern, pattern sacrifice data consistency for View Objects can simply perform the query performance, since queries performed at the with no additional overhead. In either case, raw JDBC level do not "see" pending changes the developer never has to write JDBC data made to business information represented by access code. They only provide appropriate Enterprise Beans. SQL statements in XML descriptors. Fast-Lane Reader

(Bean) Factory Allows runtime instantiation and configuration of an appropriate subclass of a given interface or superclass based on externally-configurable information. Entity Facade Provides a restricted view of data and behavior of one or more business entities.

All ADF component instantiation is done based on XML configuration metadata through factory classes allowing runtime substitution of specialized components to facilitate application customization. The ADF view object can surface any set of attributes and methods from any combination of one or more underlying entity objects to furnish the client with a single, logical value object to work with.

ADF Business Components Java EE Design Pattern Catalog F-3

Java EE Design Patterns Implemented by ADF Business Components

Table F–1 (Cont.) Java EE Design Patterns Implemented by ADF Business Components Pattern Name and Description Value Messenger Keeps client value object attributes in sync with the middle-tier business entity information that they represent in a bidirectional fashion.

How ADF Business Components Implements It ADF's value object implementation coordinates with a client-side value object cache to batch attribute changes to the EJB tier and receive batch attribute updates which occur as a result of middle-tier business logic. The ADF Value Messenger implementation is designed to not require any kind of asynchronous messaging to achieve this effect.

ADF's application module pooling and state management functionality combine to deliver Gives the developer the simplicity and this developer value-add. This avoids productivity of a stateful programming model dedicating application server tier resources to with the scalability of a stateless web solution. individual users, but supports a "stateless with user affinity" optimization that you can tune. Continuations

F-4 Fusion Developer’s Guide for Oracle Application Development Framework

G Performing Common Oracle Forms Tasks in Oracle ADF This appendix describes how some common Oracle Forms tasks are implemented in Oracle ADF. In Oracle Forms, you do some tasks in the data block, and others in the UI. For this reason, the appendix is divided into two sections: tasks that relate to data, and tasks that relate to the UI. This appendix contains the following sections: ■

Section G.1, "Performing Tasks Related to Data"



Section G.2, "Performing Tasks Related to the User Interface"

G.1 Performing Tasks Related to Data In Oracle Forms, tasks that relate solely to data are performed in the data block. In Oracle ADF, these tasks are done on the business components that persist data (entity objects) and the objects that query data (view objects).

G.1.1 How to Retrieve Lookup Display Values for Foreign Keys In Oracle Forms, an editable table often has foreign key lookup columns to other tables. The user-friendly display values corresponding to the foreign key column values exist in related tables. You often need to present these related display values to the user. In Oracle Forms, this was a complicated task that required adding nondatabase items to the data block, adding a block-level POST-QUERY trigger to the data block, and writing a SQL select statement for each foreign key attribute. Additionally, if the user changed the data, you needed to sync the foreign key values with an item-level WHEN-VALIDATE-ITEM trigger. This process is much easier in Oracle ADF. Implementation of the task in Oracle ADF 1. Create a view object that includes the main, editable entity object as the primary entity usage, and includes secondary "reference" entity usages for the one or more associated entities whose underlying tables contain the display text. For more information, see Section 5.5.1, "How to Create Joins for Entity-Based View Objects". 2.

Select the desired attributes (at least the display text) from the secondary entity usages as described in Section 5.5.2, "How to Select Additional Attributes from Reference Entity Usages".

Performing Common Oracle Forms Tasks in Oracle ADF G-1

Performing Tasks Related to Data

At runtime, the data for the main entity and all related lookup display fields are retrieved from the database in a single join. If the user can change the data, no additional steps are required. If the user changes the value of a foreign key attribute, the reference information is automatically retrieved for the new, related row in the associated table.

G.1.2 How to Get the Sysdate from the Database In Oracle Forms, when you wanted to get the current date and time, you got the sysdate from the database. In Oracle ADF, you also have the option of getting the system date using a Java method or a Groovy expression. Implementation of the task in Oracle ADF To get the system date from the database, you can use the following Groovy expression at the entity level: DBTransaction.currentDbTime

Note: The DBTransaction reference is for entity-level Groovy expressions only.

If you want to assign a default value to an attribute using this Groovy expression, see Section 4.10.7, "How to Define a Default Value Using a Groovy Expression". To get the system date from Java, you call the getCurrentDate() method. For more information, see Section 8.10, "Accessing the Current Date and Time".

G.1.3 How to Implement an Isolation Mode That Is Not Read Consistent In Oracle Forms, you might have been concerned with read consistency, that is, the ability of the database to deliver the state of the data at the time the SQL statement was issued. Implementation of the task in Oracle ADF If you use an entity-based view object, the query sees the changes currently in progress by the current user's session in the pending transaction. This is the default behavior, and the most accurate. If instead, you want a snapshot of the data on the database without considering the pending changes made by the current user, you can use a read-only view object and reexecute the query to see the latest committed database values. For more information on read-only view objects, see Section 5.2.3, "How to Create an Expert Mode, Read-Only View Object".

G.1.4 How to Implement Calculated Fields Calculated fields are often used to show the sum of two values, but could also be used for the concatenated value of two or more fields, or the result of a method call. Implementation of the task in Oracle ADF Calculated attributes are usually not stored in the database, as their values can easily be obtained programmatically. Attributes that are used in the middle tier, but that are

G-2 Fusion Developer’s Guide for Oracle Application Development Framework

Performing Tasks Related to the User Interface

not stored in the database are called transient attributes. Transient attributes can be defined at the entity object level or the view object level. If a transient attribute will be used by more than one view object that might be based on an entity object, then define the attribute at the entity object level. Otherwise, define the transient attribute at the view object level for a particular view object. To define transient attributes at the entity object level, see Section 4.13, "Adding Transient and Calculated Attributes to an Entity Object". To define transient attributes at the view object level, see Section 5.13, "Adding Calculated and Transient Attributes to a View Object".

G.1.5 How to Implement Mirrored Items In Oracle Forms, you may be used to using mirrored items to show two or more fields that share identical values. Implementation of the task in Oracle ADF There is no need to have mirrored items in Oracle ADF, because the UI and data are separated. The same view object can appear on any number of pages, so you don’t need to create mirrored items that have the same value. Likewise, a form could have the same field represented in more than one place and it would not have to be mirrored.

G.1.6 How to Use Database Columns of Type CLOB or BLOB If you are used to working with standard database types, you may be wondering how to use the CLOB and BLOB types in Oracle ADF. Implementation of the task in Oracle ADF In Oracle ADF, use the built-in data types ClobDomain or BlobDomain. These are automatically created when you reverse-engineer entity objects or view objects from existing tables with these column types. ADF Business Components also supports data types for Intermedia column types: OrdImage, OrdAudio, OrdDoc, and OrdVideo. For more information, see Section 4.10.1, "How to Set Database and Java Data Types for an Entity Object Attribute".

G.2 Performing Tasks Related to the User Interface This section describes how to perform some common Oracle Forms tasks that relate to the UI with Oracle ADF.

G.2.1 How to Lay Out a Page Oracle Forms is based on an absolute pixel or point-based layout, as compared to the container-based approach of JSF, and the Layout Manager approach in ADF Swing. Implementation of the task in Oracle ADF See the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework for information on how to lay out a page in Oracle ADF.

Performing Common Oracle Forms Tasks in Oracle ADF G-3

Performing Tasks Related to the User Interface

G.2.2 How to Stack Canvases In Oracle Forms, stacked canvases are often used to hide and display areas of the screen. Implementation of the task in Oracle ADF The analog of stacked canvases in Oracle ADF is panels (layout containers) with the rendered property set to true or false. See the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework for more information.

G.2.3 How to Implement a Master-Detail Screen Master-detail relationships in Oracle ADF are coordinated through a view link. A view link is conceptually similar to a Oracle Forms relation. Implementation of the task in Oracle ADF For information on how create view links, see Section 5.6, "Working with Multiple Tables in a Master-Detail Hierarchy". Once you have established a relationship between two view objects with a view link, see Section 5.6.4, "How to Enable Active Master-Detail Coordination in the Data Model".

G.2.4 How to Implement an Enter Query Screen In Oracle Forms, another common task is creating an enter query screen. That is, a screen that starts in Find mode. Implementation of the task in Oracle ADF Complete information on how to create a search form is covered in Chapter 25, "Creating ADF Databound Search Forms". In particular, you may want to look at Section 25.3.1, "How to Set Search Form Properties on the View Criteria".

G.2.5 How to Implement an Updatable Multi-Record Table In Oracle Forms, you may be used to creating tables where you can edit and insert many records at the same time. In Oracle ADF, this is slightly more complicated when using a JSF page, because the operations to edit an existing record and to create a new record are not the same. Implementation of the task in Oracle ADF In Oracle ADF, this is done using an input table. To create an input table, see Section 21.4, "Creating an Input Table".

G.2.6 How to Create a Popup List of Values In Oracle Forms, it is simple to create a list of values (LOV) object and then associate that object with a field in a declarative manner. This LOV would display a popup window and provide the following capabilities: ■

Selection of modal values



Query area at the top of the LOV dialog



Display of multiple columns



Automatic reduction of LOV contents, possibly based on the contents of the field that launched the LOV

G-4 Fusion Developer’s Guide for Oracle Application Development Framework

Performing Tasks Related to the User Interface



Automatic selection of the list value when only one value matches the value in the field when the LOV function is invoked



Validation of the field value based on the values cached by the LOV



Automatic popup of the LOV if the field contents are not valid

Implementation of the task in Oracle ADF To implement a popup list in Oracle ADF, you configure one of the view object’s attributes to be of LOV type, and select Input Text with List of Values as the style for its UI hint. For a description of how to do this, see Section 5.11, "Working with List of Values (LOV) in View Object Attributes".

G.2.7 How to Implement a Dropdown List as a List of Values In Oracle Forms, you can create a list of values (LOV) object and then associate that object with a field in a declarative manner. In Oracle ADF, you can implement an LOV (look-up-value) screen with a search item, usable for a look-up field with many possible values. Implementation of the task in Oracle ADF To implement a dropdown list in Oracle ADF, you configure one of the view object’s attributes to be of LOV type, and select Input Text with List of Values as the style for its UI hint. For a description of how to do this, see Section 5.11, "Working with List of Values (LOV) in View Object Attributes".

G.2.8 How to Implement a Dropdown List with Values from Another Table In Oracle Forms, you can create a list of values (LOV) object and then associate that object with a field in a declarative manner. In Oracle ADF, you can implement a dropdown list with string values from a different table that populates the field with an id code that is valid input in the table that the screen is based on. Implementation of the task in Oracle ADF To implement a dropdown list of this type in Oracle ADF, you configure one of the view object’s attributes to be of LOV type, and select Choice List as the style for its UI hint. For a description of how to do this, see Section 5.11, "Working with List of Values (LOV) in View Object Attributes".

G.2.9 How to Implement Immediate Locking In Oracle ADF, you can lock a record in the database at the first moment it is obvious that the user is going to change a specific record. Implementation of the task in Oracle ADF Immediate locking mode is the default in ADF Business Components, although it is not typically used in web application scenarios. For web applications, use jbo.locking.mode=optimistic. For more information, see Section 36.11.1, "How to Set Applications to Use Optimistic Locking".

G.2.10 How to Throw an Error When a Record Is Locked When a record has been locked by a user, it’s helpful to throw an error to let other users know that the record is not currently updatable.

Performing Common Oracle Forms Tasks in Oracle ADF G-5

Performing Tasks Related to the User Interface

Implementation of the task in Oracle ADF Locking rows and throwing an exception if the row is already locked is built-in ADF Business Components functionality. There are a couple of different ways that you can handle the error message, depending on whether you want a static error message or a custom message with information about the current row. ■



To throw a static message, register a custom message bundle in your ADF Business Components project to substitute the default RowAlreadyLockedException's error message, to something more meaningful or user-friendly. To throw a message that contains information about the row, override the lock() method on the entity object, using a try/catch block to catch the RowAlreadyLocked exception. After you catch the exception, you can throw an error message that might contain more specific information about the current row.

G-6 Fusion Developer’s Guide for Oracle Application Development Framework