PK z$Doa,mimetypeapplication/epub+zipPKz$DiTunesMetadata.plist{ artistName Oracle Corporation book-info cover-image-hash 66519081 cover-image-path OEBPS/dcommon/oracle-logo.jpg package-file-hash 896792870 publisher-unique-id E23132-03 unique-id 24057165 genre Oracle Documentation itemName Oracle® Fusion Middleware Developing Fusion Web Applications with Oracle Application Development Framework, 12c (12.1.2) releaseDate 2014-04-01T19:29:09Z year 2014 PKPuPKz$DMETA-INF/container.xml PKYuPKz$DOEBPS/appendix_permissions.htmy ADF Security Permission Grants

C ADF Security Permission Grants

This appendix lists the security-aware components of Oracle ADF and the actions that their Permission implementation classes define.

Table C-1 shows the ADF components and their permission grants that you can define to create ADF security policies. You add grants to the policy store using the overview editor for ADF security policies. A permission grant specifies 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 authorization checking against the security policies of the policy store, 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 in Fusion web applications, see Chapter 41, "Enabling ADF Security in a Fusion Web Application."

Table C-1 ADF Security Permission Grants

ADF ComponentGrantable ActionCorresponding Implementation

ADF bounded task flow

View

The view action controls who can read and execute a bounded task flow. Pages that the user accesses within the process of executing a bounded task flow will not be individually security checked and will run under the permission of the task flow.


Customize

Reserved for future use. This action is not checked at runtime.


Grant

Reserved for future use. This action is not checked at runtime.


Personalize

Reserved for future use. This action is not checked at runtime.

ADF page definition

View

The view action controls who can view the page. Page-level security is checked for pages that have an associated page definition binding file only if the page is accessed in the process of an unbounded task flow. There is a one-to-one relationship between the page definition file and the web page it secures.

ADF Business Components entity objects

read

The read action controls who can view a row of the bound collection.


update

The update action controls who can update any attribute of the bound collection.


removeCurrentRow/delete

The delete action controls who can delete a row from the bound collection.

ADF Business Components attributes of entity objects

update

The update action controls who can update a specific attribute of the bound collection.


PK!PKz$DOEBPS/bcstatemgmt.htm Using State Management in a Fusion Web Application

49 Using State Management in a Fusion Web Application

This chapter describes the Fusion web application state management facilities and how to use them to specify the release level for ADF application modules to support stateful applications on the web.

This chapter includes the following sections:

49.1 Understanding Why State Management is Necessary

Most real-world business applications need to support multi-step user tasks. Modern sites tend to use a step-by-step style user interface to guide the end user through a logical sequence of pages to complete these tasks. When the task is done, the user can save or cancel everything as a unit. However, the HTTP protocol is built on the concept of individual, stateless requests, so the responsibility of grouping a sequence of user actions into a logical, stateful unit of work falls to the application developer.

49.1.1 Examples of Multi-Step Tasks

In a typical search-then-edit scenario, the end user searches to find an appropriate row to update, then may open several different pages of related master-detail information to make edits before deciding to save or cancel work. Consider another scenario where the end user wants to book a vacation online. The process may involve the end user's entering details about:

  • One or more flight segments that comprise the journey

  • One or more passengers taking the trip

  • Seat selections and meal preferences

  • One or more hotel rooms in different cities

  • Car they will rent

Along the way, the user might decide to complete the transaction, save the reservation for finishing later, or abandon the whole thing.

It's clear these scenarios involve a logical unit of work that spans multiple web pages. You've seen in previous chapters how to use JDeveloper's JSF page navigation diagram to design the page flow for these use cases, but that is only part of the puzzle. The pending changes the end user makes to business domain objects along the way — Trip, Flight, Passenger, Seat, HotelRoom, Auto, etc. — represent the in-progress state of the application for each end user. Along with this, other types of "bookkeeping" information about selections made in previous steps comprise the complete picture of the application state.

49.1.2 Stateless HTTP Protocol Complicates Stateful Applications

While it may be easy to imagine these multi-step scenarios, implementing them in web applications is complicated by the stateless nature of HTTP, the hypertext transfer protocol. Figure 49-1 illustrates how an end user's visit to a site comprises a series of HTTP request/response pairs. However, HTTP affords a web server no way to distinguish one user's request from another user's, or to differentiate between a single user's first request and any subsequent requests that user makes while interacting with the site. The server gets each request from any user always as if it were the first (and only) one they make.

Figure 49-1 Web Applications Use the Stateless HTTP Protocol

Web applications and stateless HTTP protocol

49.1.3 How Cookies Are Used to Track a User Session

As shown in Figure 49-2, the technique used to recognize an ongoing sequence of requests from the same end user over the stateless HTTP protocol involves a unique identifier called a cookie. A cookie is a name/value pair that is sent in the header information of each HTTP request the user makes to a site. On the initial request made by a user, the cookie is not part of the request. The server uses the absence of the cookie to detect the start of a user's session of interactions with the site, and it returns a unique identifier to the browser that represents this session for this user. In practice, the cookie value is a long string of letters and numbers, but for the simplicity of the illustration, assume that the unique identifier is a letter like "A" or "Z" that corresponds to different users using the site.

Web browsers support a standard way of recognizing the cookie returned by the server that allows the browser to identify the following:

  • the site that sent the cookie

  • how long it should remember the cookie value

On each subsequent request made by that user, until the cookie expires, the browser sends the cookie along in the header of the request. The server uses the value of the cookie to distinguish between requests made by different users.

Cookies can be set to live beyond a single browser session so that they might expire in a week, a month, or a year from when they were first created, while a session cookie expires when you close your browser.

Figure 49-2 Tracking State Using a Session Cookies and Server-Side Session

Tracking state cookies in server-side sessions flow

Java EE-compliant web servers provide a standard server-side facility called the HttpSession that allows a web application to store Java objects related to a particular user's session as named attribute/value pairs. An object placed in this session Map on one request can be retrieved by the application while handling a subsequent request during the same session.

The session remains active while the user continues to send new requests within the timeframe specified by the <session-timeout> element in the web.xml file. The default session length is typically around 30 minutes, depending on the container.

49.1.4 Performance and Reliability Impact of Using HttpSession

The HttpSession facility is an ingredient in most application state management strategies, but it can present performance and reliability problems if not used judiciously. First, because the session-scope Java objects you create are held in the memory of the Java EE web server, the objects in the HTTP session are lost if the server should fail.

As shown in Figure 49-3, one way to improve the reliability is to configure multiple Java EE servers in a cluster. By doing this, the Java EE application server replicates the objects in the HTTP session for each user across multiple servers in the cluster so that if one server goes down, the objects exist in the memory of the other servers in the cluster that can continue to handle the users requests. Since the cluster comprises separate servers, replicating the HTTP session contents among them involves broadcasting the changes made to HTTP session objects over the network.

Figure 49-3 Session Replication in a Server Cluster

Flow of session replication in server cluster

You can begin to see some of the performance implications of overusing the HTTP session:

  • The more active users, the more HTTP sessions will be created on the server.

  • The more objects stored in each HTTP session, the more memory you will need. Note that the memory is not reclaimed when the user becomes inactive; this only happens with a session timeout or an explicit session invalidation. Session invalidations don't always happen because users don't always logout.

  • In a cluster, the more objects in each HTTP session that change, the more network traffic will be generated to replicate the changed objects to other servers in the cluster.

At the outset, it would seem that keeping the number of objects stored in the session to a minimum addresses the problem. However, this implies leveraging an alternative mechanism for temporary storage for each user's pending application state. The most popular alternatives involve saving the application state to the database between requests or to a file of some kind on a shared file system.

Of course, this is easier said than done. A possible approach involves eagerly saving the pending changes to your underlying database tables and committing the transaction at the end of each HTTP request. But this idea has two key drawbacks:

  • Your database constraints might fail.

    At any given step of the multi-step process, the information may only be partially complete, and this could cause errors at the database level when trying to save the changes.

  • You complicate rolling back the changes.

    Cancelling the logical of unit of work would involve carefully deleting all of the eagerly committed rows in possible multiple tables.

These limitations have led developers in the past to invent solutions involving a "shadow" set of database tables with no constraints and with all of the column types defined as character-based. Using such a solution becomes very complex very quickly. Ultimately, you will conclude that you need some kind of generic application state management facility to address these issues in a more generic and workable way. The solution comes in the form of ADF Business Components, which implements this for you out of the box.

49.2 Introduction to Fusion Web Application State Management

State management enables you to easily create web applications that support multi-step use cases without falling prey to the memory, reliability, or implementation complexity problems described in Section 49.1, "Understanding Why State Management is Necessary."

Application state management is provided at two levels, by the Save For Later feature in a task flow, and application module state management in the model layer.

Save For Later is activated at the controller layer and automatically saves a "snapshot" of the current UI and controller states, and delegates to the model layer to passivate (save) its state as well.

If you are not using ADF data controls, you can still use application module state management alone, but since this will save only the model state, this is an outside case for most applications.

49.2.1 Basic Architecture of the Save for Later Facility

Save for Later saves an incomplete transaction without enforcing validation rules or submitting the data. The end user can resume working on the same transaction later with the same data that was originally saved when the application was exited.

49.2.2 Basic Architecture of the Application Module State Management Facility

Your ADF Business Components-based application automatically manages the application state of each user session. This provides the simplicity of a stateful programming model that you are accustomed to in previous 4GL tools, yet implemented in a way that delivers scalability nearing that of a purely stateless application. Understanding what happens behind the scenes is essential to make the most efficient use of this important feature.

You can use application module components to implement completely stateless applications or to support a unit of work that spans multiple browser pages. Figure 49-4 illustrates the basic architecture of the state management facility to support these multi-step scenarios. An application module supports passivating (storing) its pending transaction state to an XML document, which is stored in the database in a single, generic table, keyed by a unique passivation snapshot ID. It also supports the reverse operation of activating pending transaction state from one of these saved XML snapshots. This passivation and activation is performed automatically by the application module pool when needed.

Figure 49-4 ADF Provides Generic, Database-Backed State Management

ADF state management

The ADF binding context is the one object that lives in the HttpSession for each end user. It holds references to lightweight application module data control objects that manage acquiring an application module instance from the pool during the request (when the data control is accessed) and releasing it to the pool at the end of each request. The data control holds a reference to the ADF session cookie that identifies the user session. In particular, business domain objects created or modified in the pending transaction are not saved in the HttpSession using this approach. This minimizes both the session memory required per user and eliminates the network traffic related to session replication if the servers are configured in a cluster.

For improved reliability, serialize your session objects. Objects stored in distributed sessions need to implement the java.io.Serializable interface. Implementing this interface ensures the data can be transported over-the-wire to each server instance in the cluster. Use a custom method like the addObjectToSession(String key, Serializable value) method, instead of the default HttpSession.setAttribute (String key, Object value) method when adding session data. The distinction is, if you were to call the addObjectToSession() method with a nonserializable object, you would see a compile-time error. If you were to try to replicate a session object that had nonserializable objects placed into session with the put() method, you would see a runtime error and potentially, a broken user experience.

Additionally, if you have multiple application servers and you enable the optional ADF Business Components failover support (explained in Section 49.2.2.2, "How Passivation Changes When Optional Failover Mode is Enabled"), then subsequent end-user requests can be handled by any server in your server farm or cluster. The session cookie can reactivate the pending application state from the database-backed XML snapshot if required, regardless of which server handles the request.

49.2.2.1 Understanding When Passivation and Activation Occurs

To better understand when the automatic passivation and activation of application module state occurs, consider the following simple case:

  1. At the beginning of an HTTP request, the application module data control handles the beginrequest event by checking out an application module instance from the pool.

    The application module pool returns an unreferenced instance. An unreferenced application module is one that is not currently managing the pending state for any other user session.

  2. At the end of the request, the application module data control handles the endrequest event by checking the application module instance back into the pool in "managed state" mode.

    That application module instance is now referenced by the data control that just used it. And the application module instance is an object that still contains pending transaction state made by the data control (that is, entity object and view object caches; updates made but not committed; and cursor states), stored in memory. As you'll see below, it's not dedicated to this data control, just referenced by it.

  3. On a subsequent request, the same data control — identified by its SessionCookie — checks out an application module instance again.

    Due to the "stateless with user affinity" algorithm the pool uses, you might assume that the pool returns the exact same application module instance, with the state still there in memory. (To understand this algorithm, read Section 50.1, "About Application Module Pooling" and the discussion of Referenced Pool Size in Section 50.2.7.2, "Pool Sizing Parameters.")

Sometimes due to a high number of users simultaneously accessing the site, application module instances must be sequentially reused by different user sessions. In this case, the application pool must recycle a currently referenced application module instance for use by another session, as follows:

  1. The application module data control for User A's session checks an application module instance into the application pool at the end of a request. Assume this instance is named AM1.

  2. The application module data control for User Z's new session requests an application module instance from the pool for the first time, but there are no unreferenced instances available. The application module pool then:

    • Passivates the state of instance AM1 to the database.

    • Resets the state of AM1 in preparation to be used by another session.

    • Returns the AM1 instance to User Z's data control.

  3. On a subsequent request, the application module data control for User A's session requests an application module instance from the pool. The application module pool then:

    • Obtains an unreference instance.

      This could be instance AM1, obtained by following the same tasks as in Step 2, or another AM2 instance if it had become unreferenced in the meantime.

    • Activates the appropriate pending state for User A from the database.

    • Returns the application module instance to User A's data control.

The process of passivation, activation, and recycling allows the state referenced by the data control to be preserved across requests without requiring a dedicated application module instance for each data control. Both browser users in the above scenario are carrying on an application transaction that spans multiple HTTP requests, but the end users are unaware whether the passivation and activation is occurring in the background. They just continue to see the pending changes. In the process, the pending changes never need to be saved into the underlying application database tables until the end user is ready to commit the logical unit of work.

Note that this keeps the session memory footprint low because the only business component objects that are directly referenced by the session (and are replicable) are the data control and the session cookie.

The application module pool makes a best effort to keep an application module instance "sticky" to the current data control whose pending state it is managing. This is known as maintaining user session affinity. The best performance is achieved if a data control continues to use exactly the same application module instance on each request, since this avoids any overhead involved in reactivating the pending state from a persisted snapshot.

49.2.2.2 How Passivation Changes When Optional Failover Mode is Enabled

The jbo.dofailover parameter controls when and how often passivation occurs. You can set this parameter in your application module configuration on the Pooling and Scalability tab of the Edit Configuration dialog. When the failover feature is disabled, which it is by default, then application module pending state will only be passivated on demand when it must be. This occurs just before the pool determines it must hand out a currently referenced application module instance to a different data control.

The passivation activity (and the corresponding wait) occurs only if failover is disabled and session replication is disabled. If either failover or session replication is enabled, then the recycling thread will reuse the snapshot that was already acquired to support the failover.


Note:

Passivation can also occur when an application module is timed out. For more information about application pool removal algorithms (such as jbo.ampool.timetolive), see Section 50.2.7.3, "Pool Cleanup Parameters."


In contrast, with the failover feature turned on, the application module's pending state is passivated every time it is checked back into application module pool. This provides the most pessimistic protection against application server failure. The application module instances' state is always saved and may be activated by any application module instance at any time. Of course, this capability comes at expense of the additional overhead of eager passivation on each request.

When failover is turned on, a failure can occur when Oracle WebLogic Server is configured to forcibly release connections back into the pool. A failure of this type produces a SQLException (Connection has already been closed.) that is saved to the server log. The exception is not reported through the user interface. To ensure that state passivation occurs and users' changes are saved, the server administrator should set an appropriate value for the weblogic-application.xml deployment descriptor parameter inactive-connection-timeout-seconds on the <connection-check-params> pool params element. Setting the deployment descriptor parameter to several minutes, in most cases, should avoid forcing the inactive connection timeout and the resulting passivation failure. Adjust the setting as needed for your environment.


Best Practice:

By default, the failover feature is disabled (jbo.dofailover=false) as a performance optimization when there is only one web server instance configured, by reducing the need for passivation and activation. This allows for application module affinity to a specific user session.

For high availability, in a clustered server environment, the failover feature will auto-default to enabled (jbo.dofailover=true). This ensures that more application modules are readily available, thereby increasing scalability. In this mode, passivation occurs at the end of every request.

To understand application module pooling and the "stateless with affinity" algorithm, read Section 50.1, "About Application Module Pooling" and the discussion of Referenced Pool Size in Section 50.2.7.2, "Pool Sizing Parameters."



Note:

When running or debugging an application that uses failover support within the JDeveloper environment, you are frequently starting and stopping the application server. The ADF failover mechanism has no way of knowing whether you stopped the server to simulate an application server failure, or whether you stopped it because you want to retest something from scratch in a fresh server instance. If you intend to do the latter, exit out of your browser before restarting the application on the server. This eliminates the chance that you will be confused by the correct functioning of the failover mechanism when you didn't intend to be testing that aspect of your application.


49.2.2.3 About State Management Release Levels

When a data control handles the endrequest notification indicating the processing for the current HTTP request has completed, it releases the application module instance by checking it back into the application module pool. The application module pool manages instances and performs state management tasks (or not) based on the release level you use when returning the instance to the pool.

There are three release levels used for returning an instance of an application module to a pool:

  • Managed - This is the default level, where the application module pool prefers to keep the same application module instance for the same data control, but may release an instance if necessary.

  • Unmanaged - No state needs to be preserved beyond the current request.

  • Reserved - A one-to-one relationship is preserved between an application module instance and a data control.


    Caution:

    In general, it is strongly recommended never to use Reserved release level. You would normally avoid using this mode because the data control to application module correlation becomes one to one, the scalability of the application reduces very sharply, and so does reliability of the application.


49.2.2.3.1 About Managed Release Level

This is the default release level and implies that application module's state is relevant and has to be preserved for this data control to span over several HTTP requests. Managed level does not guarantee that for the next request this data control will receive the same physical application module instance, but it does guarantees that an application module with identical state will be provided so it is logically the same application module instance each time. It is important to note that the framework makes the best effort it can to provide the same instance of application module for the same data control if it is available at the moment. This is done for better performance since the same application module does not need to activate the previous state which it still has intact after servicing the same data control during previous request. However, the data control is not guaranteed to receive the same instance for all its requests and if the application module that serviced that data control during previous is busy or unavailable, then a different application module will activate this data control's state. For this reason, it is not valid to cache references to application module objects, view objects, or view rows across HTTP requests in controller-layer code.

To specify the managed release level for an application module, set the release mode to Stateful.


Note:

If the jbo.ampool.doampooling configuration property is false — corresponding to your unchecking the Enable Application Module Pooling option in the Pooling and Scalability tab of the Edit Configuration dialog — then there is effectively no pool. In this case, when the application module instance is released at the end of a request it is immediately removed. On subsequent requests made by the same user session, a new application module instance must be created to handle each user request, and pending state must be reactivated from the passivation store. Setting this property to false is useful to discover problems in your application logic that might occur when reactivation does occur due to unpredictable load on your system. However, the property jbo.ampool.doampooling set to false is not a supported configuration for production applications and must be set to true before you deploy your application. For further details, see Section 49.10, "Testing to Ensure Your Application Module is Activation-Safe."


49.2.2.3.2 About Unmanaged Release Level

This mode implies that no state associated with this data control has to be preserved to survive beyond the current HTTP request. This level is the most efficient in performance because there is no overhead related to state management. However, you should limit its use to applications that require no state management, or to cases when state no longer needs to be preserved at this point. Usually, you can programmatically release the application module with the unmanaged level when you want to signal that the user has ended a logical unit of work.


Performance Tip:

.The default release level is Managed, which implies that the application module's state is relevant and has to be preserved to allow the data control to span over several HTTP requests. Set release level to Unmanaged programmatically at runtime for particular pages to eliminate passivation and achieve better performance. A typical example is releasing the application module after servicing the HTTP request from a logout page.


To specify the unmanaged release level for an application module, set the release mode to Stateless.

49.2.2.3.3 About Reserved Release Level

This level guarantees that each data control will be assigned its own application module during its first request and for all subsequent requests coming from the HttpSession associated with this data control. This data control will always receive the same physical instance of application module. This mode exists for legacy compatibility reasons and for very rare special use cases.

An example of using Reserved level occurs when there is a pending database state across a request resulting from the postChanges() method or a PL/SQL stored procedure but not issuing a commit() or rollback() at the end of the request. In this case, if any other release level is used instead of Reserved, when the application module instance is recycled, a rollback is issued on the database connection associated with this application module instance and all uncommitted changes would be lost.


Performance Tip:

If you must use Reserved level, call setReleaseLevel() on the data control to keep its period as short as possible. For details about changing the release level programmatically, see Section 49.4, "Setting the Application Module Release Level at Runtime."


Consequences of Reserved mode can be adverse. Reliability suffers because if for whatever reason the application module is lost, the data control will not be able to receive any other application module in its place from the pool, and so HttpSession gets lost as well, which is not the case for managed level.

The failover option is ignored for an application module released with Reserved release level since its use implies your application absolutely requires working with the same application module instance on each request.

49.2.2.4 State Management and Subclassed Entity Objects

If your application employs subclassed entity objects, the key attribute of new entities must be prepopulated. If the key is not prepopulated, passivation and activation will fail. You can prepopulate the key attribute by overriding the create() method or by using the DBSequence type that will assign a temporary negative value to the key before the real value is fetched from the database after commit. For more information, see Section 4.10.10, "How to Get Trigger-Assigned Primary Key Values from a Database Sequence."

49.2.3 What You May Need to Know About Data Consistency and Application Module Affinity

When an entity object is updated concurrently by more than one user and one of those users loses affinity with their application module during the update, it is possible to experience data corruption if a change indicator has not been defined for the entity object.

Consider a scenario where two users (User A and User B) access the same entity object at the same time.

  • After querying, User B changes the value of an attribute (for example, changing the Dept attribute value from Accounting to Research) and then commits.

  • Meanwhile, User A has also queried and sees the same record where the value of the Dept attribute is Accounting.

  • User A loses affinity with the application module that was used to query, resulting in passivation.

  • User A then changes the Dept attribute value from Accounting to Sales and commits, resulting in activation.

  • When activation occurs, the new value of the Dept attribute is activated but the browser is unaware of the data change, and the commit proceeds without issue.

To avoid this type of scenario, define a change indicator attribute for all entity objects. For more information, see Section 4.10.11, "How to Protect Against Losing Simultaneously Updated Data."

49.2.4 What You May Need to Know About Using Application Scoped Managed Beans in a Clustered Environment

JSF Application Scope beans are backed by a servlet context which can only have one instance per cluster node. Therefore, for each design time configured bean, there will be a runtime instance of the bean for each node in a cluster. Because there is no synchronization across nodes, each instance of the application running on different nodes will have separate instances of that bean with separate values. Therefore, application scoped managed beans should not be used to carry application-wide values that can be updated to be shared across all nodes in a cluster. They can, however, be used to carry constants, read-only values, or values to reflect the state of a single node within the cluster (such as the number of users on a node).

49.3 Using Save For Later

To enable Save For Later, you must first add Save Points to the application at points where you would like application state and data to be preserved if the end user leaves the application. You can use it to save data and state information about a region, view port, or portlet. Later, you use the Save Point Restore activity to restore application state and data associated with a Save Point.

For more information on how create and restore Save Points, see Section 24.7, "Using Save Points in Task Flows."

Save For Later can also perform implicit saves. These occur when data is saved automatically without the end user performing an explicit Save action when the user session times out or closes the browser window, for example.

For more information on how to perform an implicit save, see Section 24.7, "Using Save Points in Task Flows."

49.4 Setting the Application Module Release Level at Runtime

If you do not want to use the default "Managed State" release level for application modules, you can set your desired level programmatically.

49.4.1 How to Set Unmanaged Level

To set a data control to release its application module using the unmanaged level, call the resetState() method on the DCDataControl class (in the oracle.adf.model.binding package).

You can call this method any time during the request. This will cause application module not to passivate its state at all when it is released to the pool at the end of the request. Note that this method only affects the current application module instance in the current request. After this, the application module is released in unmanaged level to the pool, it becomes unreferenced and gets reset. The next time the application module is used by a client, it will be used in the managed level again by default.


Note:

You can programmatically release the application module with the unmanaged level when you want to signal that the user has ended a logical unit of work. This will happen automatically when the HTTPSession times out, as described below.


49.4.2 How to Set Reserved Level

To set a data control to release its application module using the reserved level, call the setReleaseLevel() method of the DCJboDataControl class (in the oracle.adf.model.bc4j package), and pass the integer constant ApplicationModule.RELEASE_LEVEL_RESERVED.

When the release level for an application module has been changed to "Reserved" it will stay so for all subsequent requests until explicitly changed.

49.4.3 How to Set Managed Level

If you have set an application module to use reserved level, you can later set it back to use managed level by calling the setReleaseLevel() method of the DCJboDataControl class, and passing the integer constant ApplicationModule.RELEASE_LEVEL_MANAGED.

49.4.4 How to Set Release Level in a JSF Backing Bean

Example 49-1 shows calling the resetState() method on a data control named UserModuleDataControl from the action method of a JSF backing bean.

Example 49-1 Calling resetState() on Data Control in a JSF Backing Bean Action Method

package devguide.advanced.releasestateless.controller.backing;
import devguide.advanced.releasestateless.controller.JSFUtils;
import oracle.adf.model.BindingContext;
import oracle.adf.model.binding.DCDataControl;
/**
 * JSF Backing bean for the "Example.jspx" page
 */
public class Example {
  /**
   * In an action method, call resetState() on the data control to cause
   * it to release to the pool with the "unmanaged" release level.
   * In other words, as a stateless application module.
   */
  public String button_action() {
    // Add event code here...
    getDataControl("UserModuleDataControl").resetState();
    return null;
  }
  private DCDataControl getDataControl(String name) {
    BindingContext bc = 
      (BindingContext)JSFUtils.resolveExpression("#{data}");
    return bc.findDataControl(name);
  }
}

49.4.5 How to Set Release Level in an ADF PagePhaseListener

Example 49-2 shows calling the resetState() method on a data control named UserModuleDataControl from the after-prepareRender phase of the ADF lifecycle using a custom ADF page phase-listener class. You would associate this custom class to a particular page by setting the ControllerClass attribute on the page's page definition to the fully qualified name of this class.

Example 49-2 Calling resetState() on Data Control in a Custom PagePhaseListener

package devguide.advanced.releasestateless.controller;
import oracle.adf.controller.v2.lifecycle.Lifecycle;
import oracle.adf.controller.v2.lifecycle.PagePhaseEvent;
import oracle.adf.controller.v2.lifecycle.PagePhaseListener;
import oracle.adf.model.binding.DCDataControl;
public class ReleaseStatelessPagePhaseListener
       implements PagePhaseListener {
  /**
   * In the "after" phase of the final "prepareRender" ADF Lifecycle
   * phase, call resetState() on the data control to cause it to release
   * to the pool with the "unmanaged" release level. In other words,
   * as a stateless application module.
   * 
   * @param event ADF page phase event
   */
  public void afterPhase(PagePhaseEvent event) {
    if (event.getPhaseId() == Lifecycle.PREPARE_RENDER_ID) {
      getDataControl("UserModuleDataControl", event).resetState();
    }
  }
  // Required to implement the PagePhaseListener interface
  public void beforePhase(PagePhaseEvent event) {}
  private DCDataControl getDataControl(String name,
                                       PagePhaseEvent event) {
    return event.getLifecycleContext()
                .getBindingContext()
                .findDataControl(name);
  }
}

49.4.6 How to Set Release Level in an ADF PageController

Example 49-3 shows calling the resetState() method on a data control named UserModuleDataControl from an overridden prepareRender() method of a custom ADF page controller class. You would associate this custom class to a particular page by setting the ControllerClass attribute on the page's page definition to the fully qualified name of this class.


Note:

You can accomplish basically the same kinds of page-specific lifecycle customization tasks using a custom PagePhaseListener or a custom PageController class. The key difference is that the PagePhaseListener interface can be implemented on any class, while a custom PageController must extend the PageController class in the oracle.adf.controller.v2.lifecycle package.


Example 49-3 Calling resetState() on Data Control in a Custom ADF PageController

package devguide.advanced.releasestateless.controller;
import oracle.adf.controller.v2.context.LifecycleContext;
import oracle.adf.controller.v2.lifecycle.PageController;
import oracle.adf.controller.v2.lifecycle.PagePhaseEvent;
import oracle.adf.model.binding.DCDataControl;
public class ReleaseStatelessPageController extends PageController {
  /**
   * After calling the super in the final prepareRender() phase
   * of the ADF Lifecycle, call resetState() on the data control
   * to cause it to release to the pool with the "unmanaged"
   * release level. In other words, as a stateless application module.
   * 
   * @param lcCtx ADF lifecycle context
   */
  public void prepareRender(LifecycleContext lcCtx) {
    super.prepareRender(lcCtx);
    getDataControl("UserModuleDataControl", lcCtx).resetState();    
  }
  private DCDataControl getDataControl(String name,
                                       LifecycleContext lcCtx) {
    return lcCtx.getBindingContext().findDataControl(name);
  }  
}

49.4.7 How to Set Release Level in a Custom ADF PageLifecycle

If you wanted to build a Fusion web application where every request was handled in a completely stateless way, use a global custom PageLifecycle class as shown in Example 49-4. For details on how to configure your application to use your custom lifecycle see Section 27.2, "About the JSF and ADF Page Lifecycles."

Example 49-4 Calling resetState() on Data Control in a Custom ADF PageLifecycle

package devguide.advanced.releasestateless.controller;
import oracle.adf.controller.faces.lifecycle.FacesPageLifecycle;
import oracle.adf.controller.v2.context.LifecycleContext;
import oracle.adf.model.binding.DCDataControl;
public class ReleaseStatelessPageLifecycle extends FacesPageLifecycle {
  /**
   * After calling the super in the final prepareRender() phase
   * of the ADF Lifecycle, call resetState() on the data control
   * to cause it to release to the pool with the "unmanaged"
   * release level. In other words, as a stateless application module.
   * 
   * @param lcCtx ADF lifecycle context
   */  
  public void prepareRender(LifecycleContext lcCtx) {
    super.prepareRender(lcCtx);
    getDataControl("UserModuleDataControl", lcCtx).resetState();    
  }
  private DCDataControl getDataControl(String name,
                                       LifecycleContext lcCtx) {
    return lcCtx.getBindingContext().findDataControl(name);
  }    
}

49.5 What Model State Is Saved and When It Is Cleaned Up

The information saved by application model passivation is divided in two parts: transactional and nontransactional state. Transactional state is the set of updates made to entity object data – performed either directly on entity objects or on entities through view object rows – that are intended to be saved into the database. Nontransactional state comprises view object runtime settings, such as the current row index, WHERE clause, and ORDER BY clause.

49.5.1 State Information Saved During Passivation

The information saved as part of the application module passivation snapshot includes the following.

Transactional State
  • New, modified, and deleted entities in the entity caches of the root application module for this user session's (including old/new values for modified ones).

Nontransactional State
  • For each active view object (both statically and dynamically created):

    • Current row indicator for each row set (typically one)

    • New rows and their positions. (New rows are treated differently then updated ones. Their index in the view object is traced as well.)

    • ViewCriteria and all related parameters such as view criteria row, etc.

    • Flag indicating whether or not a row set has been executed

    • Range start and Range size

    • Access mode

    • Fetch mode and fetch size

    • Any view object-level custom data


      Note:

      Transient view object attributes can be saved if they are selected for passivation at design time. However, use this feature judiciously because this results in a snapshot that will grow in size with the number of rows that have been retrieved.


    • SELECT, FROM, WHERE, and ORDER BY clause if created dynamically or changed from the View definition


Note:

If you enable ADF Business Components runtime diagnostics, the contents of each XML state snapshot are also saved. See Section 8.3.10, "How to Enable ADF Business Components Debug Diagnostics" for information on how to enable diagnostics.


49.5.2 Where the Model State Is Saved

By default, passivation snapshots are saved in the database, but you can configure it to use the file system as an alternative.

49.5.2.1 How Database-Backed Passivation Works

The passivated XML snapshot is written to a BLOB column in a table named PS_TXN, using a connection specified by the jbo.server.internal_connection property. Each time a passivation record is saved, it is assigned a unique passivation snapshot ID based on the sequence number taken from the PS_TXN_SEQ sequence. The ADF session cookie held by the application module data control in the ADF binding context remembers the latest passivation snapshot ID that was created on its behalf and remembers the previous ID that was used.

49.5.2.2 Controlling the Schema Where the State Management Table Resides

The ADF runtime recognizes a configuration property named jbo.server.internal_connection that controls which database connection and schema should be used for the creation of the PS_TXN table and the PS_TXN_SEQ sequence. If you don't set the value of this configuration parameter explicitly, then the state management facility creates the temporary tables using the credentials of the current application database connection.

To keep the temporary information separate, the state management facility uses a different connection instance from the database connection pool, but the database credentials are the same as the current user. Since the framework creates temporary tables, and possibly a sequence if they don't already exist, the implication of not setting a value for the jbo.server.internal_connection is that the current database user must have CREATE TABLE, CREATE INDEX and CREATE SEQUENCE privileges. Since this is often not desirable, Oracle recommends always supplying an appropriate value for the jbo.server.internal_connection property, providing the credentials for a state management schema where table and schema be created. Valid values for the jbo.server.internal_connection property in your configuration are:

  • A fully qualified JDBC connection URL like:

    jdbc:oracle:thin:username/password@host:port:SID

  • A JDBC datasource name like:

    java:/comp/env/jdbc/YourJavaEEDataSourceName


Performance Tip:

When creating the PS_TXN table, use securefiles to store LOB data (the content column), and create a primary column index on the PS_TXN table as global, partitioned reverse key index. The securefile configuration delivers superior performance over the basicfile configuration when working with LOB data. The reverse key index helps by reducing contention that can happen when the rate of inserts is high.


49.5.2.3 Configuring the Type of Passivation Store

Passivated information can be stored in several places. You can control it programmatically or by configuring an option in the application module configuration. The choices are database or a file stored on local file system:

  • File

    This choice may be the fastest available, because access to the file is faster then access to the database. This choice is good if the entire middle tier is either installed on the same machine or has access to a commonly shared file system, so passivated information is accessible to all. Usually, this choice may be good for a small middle tier where one Oracle WebLogic Server domain is used. In other words this is a very suitable choice for small middle tier such as one Oracle WebLogic Server instance with all its components installed on one physical machine. The location and name of the persistent snapshot files are determined by jbo.tmpdir property if specified. It follows usual rules of ADF property precedence for a configuration property. If nothing else is specified, then the location is determined by user.dir if specified. This is a default property and the property is OS specific.

  • Database

    This is the default choice. While it may be a little slower than passivating to file, it is by far the most reliable choice. With passivation to file, the common problem might be that it is not accessible to Oracle WebLogic Server instances that are remotely installed. In this case, in a cluster environment, if one node goes down the other may not be able to access passivated information and then failover will not work. Another possible problem is that even if file is accessible to the remote node, the access time for the local and remote node may be very different and performance will be inconsistent. With database access, time should be about the same for all nodes.

To set the value of your choice in design time, set the property jbo.passivationstore to database or file. The value null will indicate that a connection-type-specific default should be used. This will use database passivation for Oracle or DB2, and file serialization for any others.

To set the storage programmatically use the method setStoreForPassiveState() of interface oracle.jbo.ApplicationModule. The parameter values that you can pass are:

  • PASSIVATE_TO_DATABASE

  • PASSIVATE_TO_FILE

49.5.3 Cleaning Up the Model State

Under normal circumstances, the ADF state management facility provides automatic cleanup of the passivation snapshot records.

49.5.3.1 Previous Snapshot Removed When Next One Taken

When a passivation record is saved to the database on behalf of a session cookie, as described above, this passivation record gets a new, unique snapshot ID. The passivation record with the previous snapshot ID used by that same session cookie is deleted as part of the same transaction. In this way, assuming no server failures, there will only ever be a single passivation snapshot record per active end-user session.

49.5.3.2 Passivation Snapshot Removed on Unmanaged Release

The passivation snapshot record related to a session cookie is removed when the application module is checked into the pool with the unmanaged state level. This can occur when:

  • Your code specifically calls resetState() on the application module data control.

  • Your code explicitly invalidates the HttpSession, for example, as part of implementing an explicit "Logout" functionality.

  • The HttpSession times out due to exceeding the session timeout threshold for idle time and failover mode is disabled (which is the default).

In each of these cases, the application module pool also resets the application module referenced by the session cookie to be "unreferenced" again. Since no changes were ever saved into the underlying database tables, once the pending session state snapshots are removed, there remains no trace of the unfinished work the user session had completed up to that point.

49.5.3.3 Passivation Snapshot Retained in Failover Mode

When the failover mode is enabled, if the HttpSession times out due to session inactivity, then the passivation snapshot is retained so that the end user can resume work upon returning to the browser.

After a break in the action, when the end user returns to the browser and continues to use the application, it continues working as if nothing had changed. The session cookie is used to reactivate any available application module instance with the user's last pending state snapshot before handling the request. So, even though the users next request will be processed in the context of a new HttpSession (perhaps even in a different application server instance), the user is unaware that this has occurred.


Note:

If an application module was released with reserved level then the HttpSession times out, the user will have to go through authentication process, and all unsaved changes are lost.


49.5.4 Cleaning Up Temporary Storage Tables

JDeveloper supplies the adfbc_purge_statesnapshots.sql script to help with periodically cleaning up the application module state management table. You can find this file in the oracle_common subdirectory of your Oracle Middleware installation directory (for example, ORACLE_HOME\oracle_common\common\sql).

Persistent snapshot records can accumulate over time if the server has been shutdown in an abnormal way, such as might occur during development or due to a server failure. Running the script in SQL*Plus will create the BC4J_CLEANUP PL/SQL package. The two relevant procedures in this package are:

  • PROCEDURE Session_State(olderThan DATE)

    This procedure cleans up application module session state storage for sessions older than a given date.

  • PROCEDURE Session_State(olderThan_minutes INTEGER)

    This procedure cleans up application module session state storage for sessions older than a given number of minutes.

You can schedule periodic cleanup of your ADF temporary persistence storage by submitting an invocation of the appropriate procedure in this package as a database job.

You can use an anonymous PL/SQL block like the one shown in Example 49-5 to schedule the execution of bc4j_cleanup.session_state() to run starting tomorrow at 2:00 am and each day thereafter to cleanup sessions whose state is over 1 day (1440 minutes) old.

Example 49-5 Scheduling Periodic Cleanup of the State Management Table

SET SERVEROUTPUT ON
DECLARE
  jobId    BINARY_INTEGER;
  firstRun DATE;
BEGIN
  -- Start the job tomorrow at 2am
  firstRun := TO_DATE(TO_CHAR(SYSDATE+1,'DD-MON-YYYY')||' 02:00',
              'DD-MON-YYYY HH24:MI');
   -- Submit the job, indicating it should repeat once a day
  dbms_job.submit(job       => jobId,
                  -- Run the ADF Purge Script for Session State
                  -- to cleanup sessions older than 1 day (1440 minutes)
                  what      => 'bc4j_cleanup.session_state(1440);',
                  next_date => firstRun,
                  -- When completed, automatically reschedule
                  -- for 1 day later
                  interval  => 'SYSDATE + 1'
                 );
  dbms_output.put_line('Successfully submitted job. Job Id is '||jobId);
END;
.
/

49.6 Timing Out the HttpSession

Since HTTP is a stateless protocol, the server receives no implicit notice that a client has closed the browser or gone away for the weekend. Therefore any Java EE-compliant server provides a standard, configurable session timeout mechanism to allow resources tied to the HTTP session to be freed when the user has stopped performing requests. You can also programmatically force a timeout.

49.6.1 How to Configure the Implicit Timeout Due to User Inactivity

You configure the session timeout threshold using the <session-timeout> tag in the web.xml file. The default value is typically around 30 minutes, depending on the container. When the HttpSession times out the BindingContext goes out of scope, and along with it, any data controls that might have referenced application modules released to the pool in the managed state level. The application module pool resets any of these referenced application modules and marks the instances unreferenced again.

49.6.2 How to Code an Explicit HttpSession Timeout

To end a user's session before the session timeout expires, you can call the invalidate() method on the HttpSession object from a backing bean in response to the user's click on a Logout button or link. This cleans up the HttpSession in the same way as if the session time had expired. Using JSF and ADF, after invalidating the session, you must perform a redirect to the next page you want to display, rather than just doing a forward. Example 49-6 shows sample code to perform this task from a Logout button.

Example 49-6 Programatically Terminating a Session

public String logoutButton_action() throws IOException{
  ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
  HttpServletResponse response = (HttpServletResponse)ectx.getResponse();
  HttpSession session = (HttpSession)ectx.getSession(false);
  session.invalidate();
  response.sendRedirect("Welcome.jspx");
  return null;
}

As with the implicit timeouts, when the HTTP session is cleaned up this way, it ends up causing any referenced application modules to be marked unreferenced.

49.7 Managing Custom User-Specific Information

It is fairly common practice to add custom user-defined information in the application module in the form of member variables or some custom information stored in oracle.jbo.Session user data hashtable. The ADF state management facility provides a mechanism to save this custom information to the passivation snapshot as well, by overriding the passivateState() method and the activateState() methods in the ApplicationModuleImpl class.


Note:

Similar methods are available on the ViewObjectImpl class and the EntityObjectImpl class to save custom state for those objects to the passivation snapshot as well.


49.7.1 How to Passivate Custom User-Specific Information

You can override passivateState() and activateState() to ensure that custom application module state information is included in the passivation/activation cycle. Example 49-7 shows how this is done.

In the example, jbo.counter contains custom values you want to preserve across passivation and activation of the application module state. Each application module has an oracle.jbo.Session object associated with it that stores application module-specific session-level state. The session contains a user data hashtable where you can store transient information. For the user-specific data to "survive" across application module passivation and reactivation, you need to write code to save and restore this custom value into the application module state passivation snapshot.

Example 49-7 Passivating and Activating Custom Information in the State Snapshot XML Document

/**
 * Overridden framework method to passivate custom XML elements
 * into the pending state snapshot document
 */
public void passivateState(Document doc, Element parent) {
  // 1. Retrieve the value of the value to save
  int counterValue = getCounterValue();
  // 2. Create an XML element to contain the value
  Node node = doc.createElement(COUNTER);
  // 3. Create an XML text node to represent the value
  Node cNode = doc.createTextNode(Integer.toString(counterValue));
  // 4. Append the text node as a child of the element
  node.appendChild(cNode);
  // 5. Append the element to the parent element passed in
  parent.appendChild(node);
}
/**
 * Overridden framework method to activate  custom XML elements
 * into the pending state snapshot document
 */
public void activateState(Element elem) {
  super.activateState(elem);
  if (elem != null) {
    // 1. Search the element for any <jbo.counter> elements
    NodeList nl = elem.getElementsByTagName(COUNTER);
    if (nl != null) {
      // 2. If any found, loop over the nodes found
      for (int i=0, length = nl.getLength(); i < length; i++) {
        // 3. Get first child node of the <jbo.counter> element 
        Node child = nl.item(i).getFirstChild();
        if (child != null) {
          // 4. Set the counter value to the activated value
          setCounterValue(new Integer(child.getNodeValue()).intValue()+1);
          break;
        }
      }
    }
  }
}
/*
 * Helper Methods
 */
private int getCounterValue() {
  String counterValue = (String)getSession().getUserData().get(COUNTER);
  return counterValue == null ? 0 : Integer.parseInt(counterValue);
}
private void setCounterValue(int i) {
  getSession().getUserData().put(COUNTER,Integer.toString(i));
}
private static final String COUNTER = "jbo.counter";

49.7.2 What Happens When You Passivate Custom Information

In Example 49-7, when activateState() is overridden, the following steps are performed:

  1. Search the element for any jbo.counter elements.

  2. If any are found, loop over the nodes found in the node list.

  3. Get first child node of the jbo.counter element.

    It should be a DOM Text node whose value is the string you saved when your passivateState() method above got called, representing the value of the jbo.counter attribute.

  4. Set the counter value to the activated value from the snapshot.

When passivateState() is overridden, it performs the reverse job by doing the following:

  1. Retrieve the value of the value to save.

  2. Create an XML element to contain the value.

  3. Create an XML text node to represent the value.

  4. Append the text node as a child of the element.

  5. Append the element to the parent element passed in.


Note:

The API's used to manipulate nodes in an XML document are provided by the Document Object Model (DOM) interfaces in the org.w3c.dom package. These are part of the Java API for XML Processing (JAXP). See the Javadoc for the Node, Element, Text, Document, and NodeList interfaces in this package for more details.


49.7.3 What You May Need to Know About Activating Custom Information

The activateState() method is called at the end of the activation process after the view objects have been activated. Most of the time this is where you want to place the application module state activation logic. However, if your application module activation logic needs to set up custom state information before the ADF state management facility activates the view objects (for example, you might need to write custom code to allow the view objects to internally reference custom values at execution time), then the prepareForActivation() method in the ApplicationModuleImpl class would be the right place because it fires at the beginning of the activation process.

49.8 Managing the State of View Objects

By default, all view objects are marked as passivation-enabled, so their state will be saved. However, view objects that have transient attributes do not have those attributes passivated by default. You can change how a view object is passivated, and even which attributes are passivated, using the Tuning page of the view object overview editor.

49.8.1 How to Manage the State of View Objects

Each view object can be declaratively configured to be passivation-enabled or not. If a view object is not passivation enabled, then no information about it gets written in the application module passivation snapshot.


Performance Tip:

There is no need to passivate read-only view objects since they are not intended to be updated and are easily re-created from the XML definition. This eliminates the performance overhead associated with passivation and activation and reduces the CPU usage needed to maintain the application module pool.


Before you begin:

It may be helpful to have an understanding of passivation in view objects. For more information, see Section 49.8, "Managing the State of View Objects."

You will also need to perform the following task:

  • Open the application in JDeveloper.

To set the passivation state of a view object:

  1. In the Applications window, double-click the view object for which you want to set the passivation state.

  2. In the overview editor, click the General navigation tab.

  3. On the General page, expand the Tuning section and select Passivate State to make sure the view object data is saved.

  4. Optionally, you can select Including All Transient Attributes to passivate all transient attributes at this time, but see Section 49.8.4, "What You May Need to Know About Passivating Transient View Objects" for additional information.

49.8.2 What You May Need to Know About Passivating View Objects

The activation mechanism is designed to return your view object to the state it was in when the last passivation occurred. To ensure that, Oracle ADF stores in the state snapshot the values of any bind variables that were used for the last query execution. These bind variables are in addition to those that are set on the row set at the time of passivation. The passivated state also stores the user-supplied WHERE clause on the view object related to the row set at the time of passivation.

49.8.3 How to Manage the State of Transient View Objects and Attributes

Because view objects are marked as passivated by default, a transient view object — one that contains only transient attributes — is marked to be passivation enabled, but only passivates its information related to the current row and other nontransactional state.


Performance Tip:

Transient view object attributes are not passivated by default. Due to their nature, they are usually intended to be read-only and are easily re-created. So, it often doesn't make sense to passivate their values as part of the XML snapshot. This also avoids the performance overhead associated with passivation and activation and reduces the CPU usage needed to maintain the application module pool.


Before you begin:

It may be helpful to have an understanding of passivation in view objects. For more information, see Section 49.8, "Managing the State of View Objects."

You will also need to perform the following task:

  • Open the application in JDeveloper.

To individually set the passivation state for transient view object attributes:

  1. In the Applications window, double-click the view object that contains the transient attributes for which you want to specify the passivation state.

  2. In the overview editor, click the Attributes navigation tab.

  3. On the Attributes page, select the transient attribute you want to passivate and click the Details tab.

  4. In the Details page, select the Passivate checkbox.

49.8.4 What You May Need to Know About Passivating Transient View Objects

Passivating transient view object attributes is more costly resource-wise and performance- wise, because transactional functionality is usually managed on the entity object level. Since transient view objects are not based on an entity object, this means that all updates are managed in the view object row cache and not in the entity cache. Therefore, passivating transient view objects or transient view object attributes requires special runtime handling.

Usually passivation only saves the values that have been changed, but with transient view objects passivation has to save entire row. The row will include only the view object attributes marked for passivation.

49.8.5 How to Use Transient View Objects to Store Session-level Global Variables

Using passivation, you can use a view object to store one or more global variables, each on a different transient attribute. When you mark a transient attribute as passivated, the ADF Business Components framework will remember the transient values across passivation and activation in high-throughput and failover scenarios. Therefore, it is an easy way to implement a session-level global value that is backed up by the state management mechanism, instead of the less-efficient HTTP Session replication. This also makes it easy to bind to controls in the UI if necessary.

There are two basic approaches to store values between invocations of different screens, one is controller-centric, and the other is model-centric.

To implement this task in the ADF controller layer using the controller-centric approach involves storing and referencing values using attributes in the pageFlow scope. This approach might be appropriate if the global values do not need to be referenced internally by any implementations of ADF Business Components. For more information about pageFlow scope, see Section 20.2.4, "What You May Need to Know About Memory Scope for Task Flows."

The model-centric approach involves creating a transient view object, which is conceptually equivalent to a nondatabase block in Oracle Forms.

Before you begin:

It may be helpful to have an understanding of passivation in view objects. For more information, see Section 49.8, "Managing the State of View Objects."

You will also need to perform the following tasks:

  1. Open the application in JDeveloper.

  2. Create a new view object using the View Object wizard, as described in Section 5.2.1, "How to Create an Entity-Based View Object."

    1. On Page 1 of the wizard, select the option for Data Source: Programmatic.

    2. On Page 2, click New to define the transient attribute names and types the view object should contain.

    3. On Page 3, set the Updatable option to Always for each attribute.

    4. Click Finish and the newly created view object appears in the overview editor.

To store session-level global variables using the model-centric approach:

  1. Disable any entries from being performed in the view object:

    1. In the overview editor, on the General page, expand the Tuning section.

    2. In the Retrieve from the Database group, select the No Rows option.

  2. Make sure data in the view object is not cleared out during a rollback operation. To implement this, you enable a custom Java class for the view object and override two rollback methods.

    1. In the overview editor, click the Java navigation tab, and click the Edit icon for the Java Classes section.

    2. In the Select Java Options dialog, select Generate View Object Class and click OK.

    3. In the overview editor, click the link next to View Object Class in the Java Classes section.

    4. From the main menu, choose Source > Override Methods.

    5. In the Override Methods dialog, select the beforeRollback() and afterRollback() methods to override, and click then OK.

    6. In both the beforeRollback() and afterRollback() methods, comment out the call to super in the Java code.

  3. Add an instance of the transient view object to your application module's data model, as described in Section 13.2.3.2, "Adding Master-Detail View Object Instances to an Application Module."

  4. Create an empty row in the view object when a new user begins using the application module:

    1. In the Applications window, double-click the application module.

    2. Generate an application module Java class if you don't have one yet, as described in Section 13.7.1, "How to Generate a Custom Class for an Application Module."

    3. Override the prepareSession() method of the application module, as described in Section 13.11.1, "How to Override a Built-in Framework Method."

    4. After the call to super.prepareSession(), add code to create a new row in the transient view object and insert it into the view object.

Now you can bind read-only and updatable UI elements to the "global" view object attributes just as with any other view object using the Data Controls panel.

49.9 Using State Management for Middle-Tier Savepoints

In the database server you are likely familiar with the savepoint feature that allows a developer to rollback to a certain point within a transaction instead of rolling back the entire transaction. An application module offers the same feature but implemented in the middle tier.


Best Practice:

Oracle ADF provides a declarative approach to working with savepoints, described in Section 24.7, "Using Save Points in Task Flows." Use the programmatic approach described in Section 49.9.1, "How to Use State Management for Savepoints" only if the declarative approach doesn't meet your needs.


49.9.1 How to Use State Management for Savepoints

To use state management for implementing middle-tier savepoints, you override three methods in the oracle.jbo.ApplicationModule interface

public String passivateStateForUndo(String id,byte[] clientData,int flags)
public byte[] activateStateForUndo(String id,int flags)
public boolean isValidIdForUndo(String id)

You can use these methods to create a stack of named snapshots and restore the pending transaction state from them by name. Keep in mind that those snapshots do not survive past duration of transaction (for example, events of commit or rollback). This feature could be used to develop complex capabilities of the application, such as the ability to undo and redo changes. Another ambitious goal that could exploit this functionality would be functionality to make the browser back and forward buttons behave in an application-specific way. Otherwise, simple uses of these methods can come in quite handy.

49.10 Testing to Ensure Your Application Module is Activation-Safe

If you have not explicitly tested that your application module functions when its pending state gets activated from a passivation snapshot, then you may encounter an unpleasant surprise in your production environment when heavy system load tests this aspect of your system for the first time.

49.10.1 Understanding the jbo.ampool.doampooling Configuration Parameter

The jbo.ampool.doampooling configuration property corresponds to the Enable Application Module Pooling option in the Pooling and Scalability tab of the Edit Configuration dialog. By default, this checkbox is checked so that application module pooling is enabled. Whenever you deploy your application in a production environment the default setting of jbo.ampool.doampooling to true is the way you will run your application. But, as long as you run your application in a test environment, setting the property to false can play an important role in your testing. When this property is false, there is effectively no application pool. When the application module instance is released at the end of a request it is immediately removed. On subsequent requests made by the same user session, a new application module instance must be created to handle it and the pending state of the application module must be reactivated from the passivation store.

49.10.2 How To Disable Application Module Pooling to Test Activation

As part of your overall testing plan, you should adopt the practice of testing your application modules with the jbo.ampool.doampooling configuration parameter set to false. This setting completely disables application module pooling and forces the system to activate your application module's pending state from a passivation snapshot on each page request. It is an excellent way to detect problems that might occur in your#) production environment due to assumptions made in your custom application code.


Caution:

It is important to reenable application module pooling after you conclude testing and are ready to deploy the application to a production environment. The configuration property jbo.ampool.doampooling set to false is not a supported configuration for production applications and must be set to true before deploying the application.


For example, if you have transient view object attributes you believe should be getting passivated, this technique allows you to test that they are working as you expect. In addition, consider situations where you might have introduced:

  • Private member fields in application modules, view objects, or entity objects

  • Custom user session state in the Session user data hashtable

Your custom code likely assumes that this custom state will be maintained across HTTP requests. As long as you test with a single user on the JDeveloper Integrated WebLogic Server, or test with a small number of users, things will appear to work fine. This is due to the "stateless with affinity" optimization of the ADF application module pool. If system load allows, the pool will continue to return the same application module instance to a user on subsequent requests. However, under heavier load, during real-world use, it may not be able to achieve this optimization and will need to resort to grabbing any available application module instance and reactivating its pending state from a passivation snapshot. If you have not correctly overridden passivateState() and activateState() (as described in Section 49.7, "Managing Custom User-Specific Information") to save and reload your custom component state to the passivation snapshot, then your custom state will be missing (i.e. null or back to your default values) after this reactivation step. Testing with jbo.ampool.doampooling set to false allows you to quickly isolate these kinds of situations in your code.

49.11 Keeping Pending Changes in the Middle Tier

The ADF state management mechanism relies on passivation and activation to manage the state of an application module instance. Implementing this feature in a robust way is only possible if all pending changes are managed by the application module transaction in the middle tier. The most scalable strategy is to keep pending changes in middle-tier objects and not perform operations that cause pending database state to exist across HTTP requests. This allows the highest leverage of the performance optimizations offered by the application module pool and the most robust runtime behavior for your application.


Caution:

When the jbo.doconnectionpooling configuration parameter is set to true — typically in order to share a common pool of database connections across multiple application module pools — upon releasing your application module to the application module pool, its JDBC connection is released back to the database connection pool and a ROLLBACK will be issued on that connection. This implies that all changes which were posted but not commited will be lost. On the next request, when the application module is used, it will receive a JDBC connection from the pool, which may be a different JDBC connection instance from the one it used previously. Those changes that were posted to the database but not commited during the previous request are lost.

The jbo.doconnectionpooling configuration parameter is set by checking the Disconnect Application Module Upon Release property on the Pooling and Scalability tab of the Edit Configuration dialog.


49.11.1 How to Confirm That Applications Use Optimistic Locking

Oracle recommends using optimistic locking, the default mode for web applications. Pessimistic locking should not be used for web applications as it creates pending transactional state in the database in the form of row-level locks. If pessimistic locking is set, state management will work, but the locking mode will not perform as expected. Behind the scenes, every time an application module is recycled, a rollback is issued in the JDBC connection. This releases all the locks that pessimistic locking had created.


Performance Tip:

Always use the default mode optimistic locking for web applications. Only optimistic locking is compatible with the application module unmanaged release level mode, which allows the application module instance to be immediately released when a web page terminates. This provides the best level of performance for web applications that expect many users to access the application simultaneously.


To ensure your configuration uses optimistic locking, open the Properties tab of the Edit Configuration dialog and confirm that the value of the jbo.locking.mode property is set to optimistic or optupdate.


Note:

To open the Edit Configuration dialog, double-click the application module in the Applications window, and select the Configurations navigation tab from the overview editor. Then, in the Configurations page of the overview editor, select the configuration and click Edit.


Optimistic locking (optimistic) issues a SELECT FOR UPDATE statement to lock the row, then detects whether the row has been changed by another user by comparing the change indicator attribute — or, if no change indicator is specified, the values of all the persistent attributes of the current entity as they existed when the entity object was fetched into the cache.

Optimistic update locking (optupdate) does not perform any locking. The UPDATE statement determines whether the row was updated by another user by including a WHERE clause that will match the existing row to update only if the attribute values are unchanged since the current entity object was fetched.

49.11.2 How to Avoid Clashes Using the postChanges() Method

The transaction-level postChanges() method exists to force the transaction to post unvalidated changes without committing them. This method is not recommended for use in web applications unless you can guarantee that the transaction will definitely be committed or rolled-back during the same HTTP request. Failure to heed this advice can lead to strange results in an environment where both application modules and database connections can be pooled and shared serially by multiple different clients.

49.11.3 How to Use the Reserved Level For Pending Database States

If for some reason you need to create a transactional state in the database in a particular request by invoking the postChanges() method or by calling a PL/SQL stored procedure, but you cannot issue a commit or rollback by the end of that same request, then you must release the application module instance with the reserved level from that request until a subsequent request when you either commit or rollback.


Performance Tip:

Use as short a period of time as possible between creation of transactional state in the database and performing the concluding commit or rollback. This ensures that reserved level doesn't have to be used for a long time, as it has adverse effects on application's scalability and reliability.


Once an application module has been released with reserved level, it remains at that release level for all subsequent requests until release level is explicitly changed back to managed or unmanaged level. So, it is your responsibility to set release level back to managed level once commit or rollback has been issued.

For more information, see Section 49.4, "Setting the Application Module Release Level at Runtime."

PKik7#PKz$DOEBPS/bcquerying.htm Defining SQL Queries Using View Objects

5 Defining SQL Queries Using View Objects

This chapter describes how to create ADF view objects to create SQL queries that join, filter, sort, and aggregate data for use in an Oracle ADF application. It describes how view objects map their SQL-derived attributes to database table columns and static data sources, such as a flat file.

This chapter includes the following sections:

5.1 About View Objects

A view object is an Oracle Application Development Framework (Oracle ADF) component that encapsulates a SQL query and simplifies working with its results. There are several types of view objects that you can create in your data model project:

An entity-based view object can be configured to support updatable rows when you create view objects that map their attributes to the attributes of one or more existing entity objects. The mapped entity object is saved as an entity usage in the view object definition. In this way, entity-based view objects cooperate automatically with entity objects to enable a fully updatable data model. The entity-based view object usage queries just the data needed for the client-facing task and relies on its mapped entity objects and their entity cache of rows to automatically validate and save changes made to its view rows. An entity-based view object encapsulates a SQL query, it can be linked into master-detail hierarchies, and it can be used in the data model of your application modules. The backing entity cache manages updates to the queried data so that every view object usage based on the same entity object points to the entity cache of rows rather than store duplicate data in the view object usage.

In contrast to entity-based view objects, entity-less view objects require you to write the query using the SQL query language. Non-entity backed view objects do not pick up entity-derived default values, they do not reflect pending changes, and they do not reflect updated reference information. The Create View Object wizard and overview editor for entity-based view objects, on the other hand, simplify this task by helping you to construct the SQL query declaratively. In addition, because entity-based view objects manage queried data using the entity cache, they have better performance over view objects with no entity usage which require special runtime handling of updates to their view object row cache. For these reasons, it is almost always preferable to create an entity-mapped view object, even when you want to create a view object just to read data.

There remain a few situations where it is still preferable to create a non-entity-mapped view object to read data, including SQL-based validation, Unions, and Group By queries.

As an alternative to creating view objects that specify a SQL statement at design time, you can create entity-based view objects that contain no SQL statements. This capability of the ADF Business Components design time and runtime is known as declarative SQL mode. The business component developer who works with the wizard or editor for a view object in declarative SQL mode, requires no knowledge of SQL. In declarative SQL mode, the runtime query statement is based solely on the usage of attributes in the databound UI component.

When a view object has one or more underlying entity usages, you can create new rows, and modify or remove queried rows. The entity-based view object coordinates with underlying entity objects to enforce business rules and to permanently save the changes to the database. In addition, entity-based view objects provide these capabilities that do not exist with entity-less view objects:

5.1.1 View Object Use Cases and Examples

This chapter helps you understand these view object concepts as illustrated in Figure 5-1:

  • You define a view object by providing a SQL query (either defined explicitly or declaratively).

  • You use view object instances in the context of an application module that provides the database transaction for their queries.

  • You can link a view object to one or more others to create master-detail hierarchies.

  • At runtime, the view object executes your query and produces a set of rows (represented by a RowSet object).

  • Each row is identified by a corresponding row key.

  • You iterate through the rows in a row set using a row set iterator.

  • You can filter the row set a view object produces by applying a set of Query-by-Example criteria rows.

Figure 5-1 A View Object Defines a Query and Produces a Row Set of Rows

Query produces a row set of rows

This chapter explains how instances of entity-based view objects contained in the data model of your application module enable clients to search for, update, insert, and delete business services layer information in a way that combines the full data shaping power of SQL with the clean, object-oriented encapsulation of reusable domain business objects. And all without requiring a line of code.This chapter helps you to understand these entity-based view object concepts as illustrated in Figure 5-2:

  • You define an updatable view object by referencing attributes from one or more entity objects.

  • You can use multiple, associated entity objects to simplify working with reference information.

  • You can define view links based on underlying entity associations.

  • You use your entity-based view objects in the context of an application module that provides the transaction.

  • At runtime, the view row delegates the storage and validation of its attributes to underlying entity objects.

Figure 5-2 View Objects and Entity Objects Collaborate to Enable an Updatable Data Model

Entity-based view objects

5.1.2 Additional Functionality for View Objects

You may find it helpful to understand other Oracle ADF features before you start working with view objects. Following are links to other functionality that may be of interest.

5.2 Populating View Object Rows from a Single Database Table

View objects provide the means to retrieve data from a data source. In the majority of cases, the data source will be a database and the mechanism to retrieve data is the SQL query. ADF Business Components can work with JDBC to pass this query to the database and retrieve the result.

When view objects use a SQL query, query columns map to view object attributes in the view object. The definition of these attributes, saved in the view object's XML definition file, reflect the properties of these columns, including data types and precision and scale specifications.


Performance Tip:

If the query associated with the view object contains query parameters whose values change from execution to execution, use bind variables. Using bind variables in the query allows the query to reexecute without needing to reparse the query on the database. You can add bind variables to the view object in the Query page of the overview editor for the view object. For more information, see Section 5.10, "Working with Bind Variables."


Using the same Create View Object wizard, you can create view objects that either map to the attributes of existing entity objects or not. Only entity-based view objects automatically coordinate with mapped entity objects to enforce business rules and to permanently save data model changes. Additionally, you can disable the Updatable feature for entity-based view objects and work entirely declaratively to query read-only data. Alternatively, you can use the wizard or editor's expert mode to work directly with the SQL query language, but the view object you create will not support the transaction features of the entity-based view object.

When you create entity-based view objects, you have the option to keep the view object definition entirely declarative and maintain a customizable view object. Or, you may switch to expert-mode query editing to create queries that entity objects alone cannot express, including Unions and Group By queries. Additionally, expert mode-based view objects are useful in SQL-based validation queries used by the view object-based Key Exists validator. It is worth noting that using expert mode to create a view object means the view object will be read-only unless custom code is used to specify the view object may be updatable.

For more information about the differences between entity-based view objects and entity-less view objects, see Section 5.1, "About View Objects."

5.2.1 How to Create an Entity-Based View Object

Creating an entity-based view object is the simplest way to create a view object. It is even easier than creating an expert-mode view object, since you don't have to type in the SQL statement yourself. An entity-based view object also offers significantly more runtime functionality than its expert-mode counterpart.

In an entity-based view object, the view object and entity object play cleanly separated roles:

  • The view object is the data source: it retrieves the data using SQL.

  • The entity object is the data sink: it handles validating and saving data changes.

Because view objects and entity objects have cleanly separated roles, you can build different view objects — projecting, filtering, joining, sorting the data in whatever way your user interfaces require, application after application — without any changes to the reusable entity object. In fact, it is possible that the development team responsible for the core business services layer of entity objects might be completely separate from another team responsible for the specific application modules and view objects needed to support the end-user environment. This relationship is enabled by metadata that the entity-based view object encapsulates. The metadata specifies how the SELECT list columns are related to the attributes of one or more underlying entity objects.

Your entity-based view object may be based on more than one database table. To use database joins to add multiple tables to the view object, see Section 5.6, "Working with Multiple Tables in Join Query Results."

5.2.1.1 Creating a View Object with All the Attributes of an Entity Object

When you want to allow the client to work with all of the attributes of an underlying entity object, you can use the Create Default View Object dialog to quickly create the view object from an entity object that you select in the Applications window. To create the default view object, select the entity object, right-click and choose New Default View Object. When you do not want the view object to contain all the attributes, you can use the Create View Object wizard and select only the attributes that you need, as described in Section 5.2.1.2, "Creating an Entity-Based View Object from a Single Table."

Before you begin: 

It may be helpful to have an understanding of entity-based view objects. For more information, see Section 5.2.1, "How to Create an Entity-Based View Object."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Either create the desired entity objects yourself, as described in Section 4.2.1, "How to Create Multiple Entity Objects and Associations from Existing Tables" or consult the developer responsible for creating entity objects and let them know the data that you expect to query.

To create a default entity-based view object: 

  1. In the Applications window, right-click the entity object and choose New Default View Object.

    This context menu option lets you create a view object based on a single entity object that you select. If you need to add additional entity objects to the view object definition, you can use the Entity Objects page of the view object overview editor after you create the view object.

  2. In the Create Default View Object dialog, provide a package and component name for the new view object.

    In the Create Default View Object dialog you can click Browse to select the package name from the list of existing packages. For example, in Figure 5-3, clicking Browse locates oracle.summit.model.entities package on the classpath for the Model project of the application.

Figure 5-3 Shortcut to Creating a Default View Object for an Entity Object

Create Default View Object dialog

The new entity-based view object created will be identical to one you could have created with the Create View Object wizard. By default, it will have a single entity usage referencing the entity object you selected in the Applications window, and will include all of its attributes. It will initially have neither a WHERE nor ORDER BY clause, and you may want to use the overview editor for the view object to:

  • Remove unneeded attributes

  • Refine its selection with a WHERE clause

  • Order its results with an ORDER BY clause

  • Customize any of the view object properties

5.2.1.2 Creating an Entity-Based View Object from a Single Table

To create an entity-based view object, use the Create View Object wizard, which is available from the New Gallery.

Before you begin: 

It may be helpful to have an understanding of entity-based view objects. For more information, see Section 5.2.1, "How to Create an Entity-Based View Object."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired entity objects, as described in Section 4.2.1, "How to Create Multiple Entity Objects and Associations from Existing Tables."

To create an entity-based view object from a single table: 

  1. In the Applications window, right-click the package of the data model project in which you want to create the view object and choose New and then View Object.

  2. In the Create View Object wizard, on the Name page, enter a package name and a view object name. Keep the default setting Entity object selected to indicate that you want this view object to manage data with its base entity object. Click Next.

  3. On the Entity Objects page, select an entity object whose data you want to use in the view object. Click Next.

    An entry in this list is known as an entity usage, since it records the entity objects that the view object will be using. Each entry could also be thought of as an entity reference, since the view object references attributes from that entity. For information about working table joins to create additional entity usages, see Section 5.6, "Working with Multiple Tables in Join Query Results."

    For example, Figure 5-4 shows the result after shuttling the ProductEO entity object into the Selected list.

    Figure 5-4 Create View Object Wizard, Entity Objects Page

    Step 2 of the Create View Object wizard
  4. On the Attributes page, select the attributes you want to include from each entity usage in the Available list and shuttle them to the Selected list. Click Next.

    For example, Figure 5-5 shows the attributes have been selected from the ProductEO.

    Figure 5-5 Create View Object Wizard, Attributes Page

    Step 3 of the Create View Object wizard
  5. On the Attribute Settings page, optionally, use the Select Attribute dropdown list to switch between the view object attributes in order to change their names or any of their initial settings.

    For more information about any of the attribute settings, press F1 or click Help.

  6. On the Query page, optionally, add a WHERE and ORDER BY clause to the query to filter and order the data as required. JDeveloper automatically generates the SELECT statement based on the entity attributes you've selected.

    Do not include the WHERE or ORDER BY keywords in the Where and Order By field values. The view object adds those keywords at runtime when it executes the query.

    For example, Figure 5-6 shows the ORDER BY clause is specified to order the data by name and suggested price.

    Figure 5-6 Create View Object Wizard, Query Page

    Step 5 of the Create View Object wizard
  7. Click Finish.

5.2.2 What Happens When You Create an Entity-Based View Object

When you create a view object, JDeveloper creates the XML document file that represents the view object's declarative settings and saves it in the directory that corresponds to the name of its package. For example, the view object ProductVO, added to the views package, will have the XML file ./views/ProductVO.xml created in the project's source path.

To view the view object settings, select the desired view object in the Applications window and open the Structure window. The Structure window displays the list of XML definitions, including the SQL query, the name of the entity usage, and the properties of each attribute. To open the XML definition in the editor, right-click the corresponding node and choose Go to Source.


Note:

If you configure JDeveloper preferences to generate default Java classes for ADF Business Components, the wizard will also create an optional custom view object class (for example, ProductVOImpl.java) and/or a custom view row class (for example, ProductVORowImpl.java). For details about setting preferences, see Section 3.2.8, "How to Customize Model Project Properties for ADF Business Components."


Figure 5-7 depicts the entity-based view object ProductVO and the singe entity usage referenced in its query statement. The dotted lines represent the metadata captured in the entity-based view object's XML document that map SELECT list columns in the query to attributes of the entity objects used in the view object.

Figure 5-7 View Object Encapsulates a SQL Query and Entity Attribute Mapping Metadata

View objects encapsulate queries and metadata

5.2.3 What You May Need to Know About Non-Updatable View Objects

When you use the Create View Object wizard to create an entity-based view object, by default the attributes of the view object will be updatable. When you want to make all the attributes of the view object read-only, you can deselect Updatable when you add the entity object in the wizard. Later you may decide to convert the view object to one that permits updates to its SQL-mapped table columns. However, this cannot be accomplished by merely changing the attribute's Updatable property. You must delete the read-only view object and recreate the entity-based view object so that the intended attributes are updatable.

5.2.4 How to Edit a View Object

After you've created a view object, you can edit any of its settings in the overview editor for the view object.


Performance Tip:

How you configure the view object to fetch data plays a large role in the runtime performance of the view object. For information about the tuning parameters that you can edit to optimize performance, see Section 8.3.12, "What You May Need to Know About Optimizing View Object Runtime Performance."


Before you begin:

It may be helpful to have an understanding of view objects. For more information, see Section 5.2, "Populating View Object Rows from a Single Database Table."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To edit a view object definition:

  1. In the Applications window, double-click the view object that you want to edit.

  2. In the overview editor, click the desired navigation tab.

    The pages of the view object overview editor let you adjust the SQL query, change the attribute names, add named bind variables, add UI controls hints, control Java generation options, and edit other settings.

5.2.4.1 Overriding the Inherited Properties from Underlying Entity Object Attributes

One interesting aspect of entity-based view objects is that each attribute that relates to an underlying entity object attribute inherits that attribute's properties. Figure 5-8 shows the Details section of the view object editor's Attributes page with an inherited attribute selected. You can see that fields like the Java attribute type and the query column type are disabled and their values are inherited from the related attribute of the underlying entity object to which this view object is related. Some properties like the attribute's data type are inherited and cannot be changed at the view object level.

Other properties like Queryable and Updatable are inherited but can be overridden as long as their overridden settings are more restrictive than the inherited settings. For example, the attribute from underlying entity object might have an Updatable setting of Always. As shown Figure 5-8, the Details section of the Attributes page of the view object overview editor allows you to set the corresponding view object attribute to a more restrictive setting like While New or Never. However, if the attribute in the underlying entity object had instead an Updatable setting of Never, then the editor would not allow the view object's related attribute to have a less restrictive setting like Always.

Figure 5-8 View Object Attribute Properties Inherited from Underlying Entity Object

Attribute details section displays inherited properties

5.2.4.2 Customizing View Object Attribute Display in the Overview Editor

When you edit view objects in the overview editor, you can customize the Attributes page of the overview editor to make better use of the attributes table displayed for the view object.

Customization choices that you make for the attributes table include the list of attribute properties to display as columns in the attributes table, the order that the columns appear (from left to right) in the attributes table, the sorting order of the columns, and the width of the columns. The full list of columns that you can choose to display correspond to the properties that you can edit for the attribute.

For example, you can add the Updatable property as a column to display in the attributes table when you want to quickly determine which attributes of your view object are updatable. Or, you can add the attributes' Label property as a column and see the same description as the end user. Or, you might want to view the list of attributes based on their entity usages. In this case, you can display the Entity Usage column and sort the entire attributes table on this column.

When you have set up the attributes table with the list of columns that you find most useful, you can apply the same set of columns to the attributes table displayed for other view objects by right-clicking the attributes table and choose Apply to All View Objects.

Before you begin: 

It may be helpful to have an understanding of view objects. For more information, see Section 5.2, "Populating View Object Rows from a Single Database Table."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To customize the attributes table display:

  1. In the Applications window, double-click the view object for which you want to customize the attributes table display.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, click the dropdown menu icon to the right of the attribute column headers (just below the attributes table's button bar) and choose Select Columns.

    Figure 5-9 Changing the Attribute Columns to DIsplay in the Overview Editor

    Overview editor displays attribute mapping
  4. In the Select Columns dialog, perform any of the following actions:

    1. Click the left/right shuttle buttons to change the list of visible columns in the attributes table of the overview editor. The overview editor displays only those columns corresponding to the attribute properties that appear the Selected list.

    2. Click one of the Move Selection buttons to change the position of the columns in the attributes table of the overview editor. The overview editor displays the attribute properties arranged from left to right starting with the property at the top of the Selected list.

  5. Click OK.

  6. On the Attributes page of the overview editor, perform any of the following actions:

    1. Select any column header and drag to change the position of the column in the attributes table of the overview editor.

    2. Click any column header to sort all columns in the attributes table by the selected column.

      This feature is particularly useful when you want to focus on a particular column. For example, in the case of an entity-based view object, you can click the Entity Usage column header to group attributes in the attributes table by their underlying entity objects.

    3. Click any column header border and drag to adjust the width of the attributes table's column.

    4. Click the dropdown list to the right of the column headers and select among the list of displayed columns to change the visibility of a column in the current attributes table display.

      This feature lets you easily hide columns when you want to simplify the attributes table display in the current view object overview editor.

  7. To extend the changes in the columns (including column list, column order, column sorting, and column width) to all other view object overview editors, click the dropdown menu to the right of the column headers and choose Apply to All View Objects.

    This feature allows you to easily compare the same attributes across view objects. The overview editor will apply the column selections (and order) that you make in the Select Columns dialog and the current attributes table's column sorting and column widths to all view objects that you edit. View objects that are currently displayed in an open overview editor are not updated with these settings; you must close the open view object overview editor and then reopen the view object to see these settings applied.

5.2.4.3 Modifying the Order of Attributes in the View Object Source File

After you create a view object definition, you may decide to change the order of the attributes queried by the view object. This view object editing feature allows you to easily change the order that the attributes will appear in the attributes table displayed on the Attributes page of the view object overview editor. Because this feature acts on specific attributes and alters the XML definition of the current view object, it does not apply to other view objects that you may edit. Alternatively, you can sort the display of attributes on the Attribute page of the view object overview editor without affecting the source file by clicking any column header in the overview editor's attributes table.

Before you begin:

It may be helpful to have an understanding of view objects. For more information, see Section 5.2, "Populating View Object Rows from a Single Database Table."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To modify the order of attributes in the view object source file: 

  1. In the Applications window, double-click the view object that you want to modify.

  2. In the overview editor, click the Attributes navigation tab and then click Set Source Order.

  3. In the Set Source Order dialog, select the attribute you want to reposition and click one of the Move Selection buttons.

  4. Click OK.

    This feature has no affect on other view objects that you may edit; it only affects the current view object.

5.2.5 How to Show View Objects in a Business Components Diagram

JDeveloper's UML diagramming lets you create a Business Components diagram to visualize your business services layer. In addition to supporting entity objects, JDeveloper's UML diagramming allows you to drop view objects onto diagrams as well to visualize their structure and entity usages. For example, if you create a new Business Components Diagram in the oracle.summit.model package, and drag the CustomerAddressVO view object from the Applications window onto the diagram, its entity usages would display, as shown in Figure 5-10. When viewed as an expanded node, the diagram shows a compartment containing the view objects entity usages.

Figure 5-10 View Object and Its Entity Usages in a Business Components Diagram

Business components diagram for object usages

Before you begin:

It may be helpful to have an understanding of view objects. For more information, see Section 5.2, "Populating View Object Rows from a Single Database Table."

You may also find it helpful to understand how to create an entity diagram, see Section 4.4, "Creating a Diagram of Entity Objects for Your Business Layer."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To create a business components diagram that models existing view objects: 

  1. In the Applications window, right-click the package in the data model project in which you want to create the business component diagram and choose New and then Business Components Diagram.

  2. In the Create Business Components Diagram dialog, enter the name of the diagram and enter the package name in which the diagram will be created. Select any additional diagram features.

  3. Click OK.

  4. To add existing view objects to the diagram, select them in the Applications window and drop them onto the diagram surface.

5.3 Creating View Objects Populated With Static Data

ADF Business Components lets you create view objects in your data model project with rows that you populate at design time. Typically, you create static data view objects when you have a small amount of data to maintain and you do not expect that data to change frequently. The decision whether to use a lookup table from the database or whether to use a static data view object based on a list of hardcoded values depends on the size and nature of the data. The static data view object is useful when you have no more than 100 entries to list. Any larger number of rows should be read from the database with a conventional table-based view object. The static data view object has the advantage of being easily translatable since attribute values are stored in a resource bundle. However, all of the rows of a static data view object will be retrieved at once and therefore, using no more than 100 entries yields the best performance.


Best Practice:

When you need to create a view object to access a small list of static data, you should use the static data view object rather than query the database. The static data view object is ideal for lists not exceeding 100 rows of data. Because the Create View Object wizard saves the data in a resource message file, these data are easily translatable.


Static data view objects are useful as an LOV data source when it is not desirable to query the database to supply the list of values. Suppose your order has the following statuses: open, closed, pending. You can create a static data view object with these values and define an LOV on the static data view object's status attribute. Because the wizard stores the values of the status view object in a translatable resource file, the UI will display the status values using the resource file corresponding to the application's current locale.

5.3.1 How to Create Static Data View Objects with Data You Enter

You use the Create View Object wizard to create static data view objects. The wizard lets you define the desired attributes (columns) and enter as many rows of data as necessary. The wizard displays the static data table as you create it.


Note:

Because the data in a static data view object does not originate in database tables, the view object will be read-only.


You can also use the Create View Object wizard to create the attributes based on data from a comma-separated value (CSV) file format like a spreadsheet file.

Before you begin:

It may be helpful to have an understanding of static data view objects. For more information, see Section 5.3, "Creating View Objects Populated With Static Data."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To manually create attributes for a static data view object:

  1. In the Applications window, right-click the package in the data model project in which you want to create the static data view object and choose New and then View Object.

  2. In the Create View Object wizard, on the Name page, enter a package name and a view object name. Select Static list to indicate that you want to supply static data for this view object. Click Next.

  3. On the Attributes page, click New to add an attribute that corresponds to the columns in the static list table. In the New View Object Attribute dialog, enter a name and select the attribute type. Click OK to return to the wizard, and click Next.

  4. On the Attribute Settings page, do nothing and click Next.

  5. On the Static List page, click the Add button to enter the data directly into the wizard page. The attributes you defined will appear as the columns for the static data table.

  6. On the Application Module pages, do nothing and click Next.

  7. On the Summary page, click Finish.

5.3.2 How to Create Static Data View Objects with Data You Import

Using the Import feature of the Create View Object wizard, you can create a static data view object with attributes based on data from a comma-separated value (CSV) file format like a spreadsheet file. The wizard will use the first row of a CSV flat file to identify the attributes and will use the subsequent rows of the CSV file for the data for each attribute. For example, if your application needs to display choices for international currency, you might define the columns Symbol, Country, and Description in the first row and then add rows to define the data for each currency type, as shown in Figure 5-11.

Figure 5-11 Sample Data Ready to Import from CSV Flat File

Sample flat file data

Before you begin:

It may be helpful to have an understanding of static data view objects. For more information, see Section 5.3, "Creating View Objects Populated With Static Data."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To create attributes of a static data view object based on a flat file:

  1. In the Applications window, right-click the project in which you want to create the static data view object and choose New and then View Object.

  2. In the Create View Object wizard, on the Name page, enter a package name and a view object name. Select Static list to indicate that you want to supply static data for this view object. Click Next.

  3. On the Attributes page, if the CSV flat file does not define column names in the first row of the file, click New to add an attribute that corresponds to the column names in the static data table. In the New View Object Attribute dialog, enter a name and select the attribute type. Click OK to return to the wizard, and click Next.

    The attributes you add must match the order of the data columns defined by the flat file. If you create fewer attributes than columns, the wizard will ignore extra columns during import. Conversely, if you create more attributes than columns, the wizard will define extra attributes with value null.

  4. On the Attribute Settings page, do nothing and click Next.

  5. On the Static List page, click Import to locate the CSV file and display the data in the wizard. Verify the data and edit the values as needed.

    If you created the attribute names yourself and the first row of the CSV file displays the column names in the first row, the column names will be displayed in the wizard as data and should be deleted. To edit an attribute value, double-click in the value field.

  6. Optionally, click the Add button or Remove button to change the number of rows of data. Click Next.

    To enter values for the attributes of a new row, double-click in the value field.

  7. On the Application Module page, do nothing and click Next.

  8. On the Summary page, click Finish.

5.3.3 What Happens When You Create a Static Data View Object

When you create a static data view object, the overview editor for the view object displays the rows of data that you defined in the wizard. You can use the editor to define additional data, as shown in Figure 5-12.

Figure 5-12 Static Values Page Displays Data

Static values page of overview editor for view object.

The generated XML definition for the static data view object contains one transient attribute for each column of data. For example, if you import a CSV file with data that describes international currency, your static data view object might contain a transient attribute for Symbol, Country, and Description, as shown in Example 5-1.

Example 5-1 XML Definition for Static Data View Object

<ViewObject
...
<!-- Transient attribute for first column -->
  <ViewAttribute
    Name="Symbol"
    IsUpdateable="false"
    IsSelected="false"
    IsPersistent="false"
    PrecisionRule="true"
    Precision="255"
    Type="java.lang.String"
    ColumnType="VARCHAR2"
    AliasName="Symbol"
    SQLType="VARCHAR"/>
<!-- Transient attribute for second column -->
  <ViewAttribute
    Name="Country"
    IsUpdateable="false"
    IsPersistent="false"
    PrecisionRule="true"
    Precision="255"
    Type="java.lang.String"
    ColumnType="VARCHAR"
    AliasName="Country"
    SQLType="VARCHAR"/>
<!-- Transient attribute for third column -->
  <ViewAttribute
    Name="Description"
    IsUpdateable="false"
    IsPersistent="false"
    PrecisionRule="true"
    Precision="255"
    Type="java.lang.String"
    ColumnType="VARCHAR"
    AliasName="Description"
    SQLType="VARCHAR"/>
  <StaticList
    Rows="4"
    Columns="3"/>
<!-- Reference to file that contains static data -->
  <ResourceBundle>
    <PropertiesBundle
      PropertiesFile="model.ModelBundle"/>
  </ResourceBundle>
</ViewObject>

Because the data is static, the overview editor displays no Query page and the generated XML definition for the static data view object contains no query statement. Instead, the <ResourceBundle> element in the XML definition references a resource bundle file. Example 5-1 shows the reference to the file as PropertiesFile="model.ModelBundle". The resource bundle file describes the rows of data and also lets you localize the data. When the default resource bundle type is used, the file ModelBundle.properties appears in the data model project, as shown in Example 5-2.

Example 5-2 Default Resource Bundle File for Static Data View Object

model.ViewObj.SL_0_0=USD
model.ViewObj.SL_0_1=United States of America
model.ViewObj.SL_0_2=Dollars
model.ViewObj.SL_1_0=CNY
model.ViewObj.SL_1_1=P.R. China
model.ViewObj.SL_1_2=Yuan Renminbi
model.ViewObj.SL_2_0=EUR
model.ViewObj.SL_2_1=Europe
model.ViewObj.SL_2_2=Euro
model.ViewObj.SL_3_0=JPY
model.ViewObj.SL_3_1=Japan
model.ViewObj.SL_3_2=Yen

5.3.4 How to Edit Static Data View Objects

When you need to make changes to the static list table, double-click the view object in the Applications window to open the overview editor for the view object. You can add and delete attributes (columns in the static list table), add or delete rows (data in the static list table), sort individual rows, and modify individual attribute values. The editor will update the view object definition file and save the modified attribute values in the message bundle file. For information about localizing message bundles, see Section 4.7, "Working with Resource Bundles."

5.3.5 What You May Need to Know About Static Data View Objects

The static data view object has a limited purpose in the application module's data model. Unlike entity-based view objects, static data view objects will not be updatable. You use the static data view object when you want to display read-only data to the end user and you do not want to create a database table for the small amount of data the static list table contains.

5.4 Adding Calculated and Transient Attributes to a View Object

In addition to having attributes that map to underlying entity objects, your view objects can include calculated attributes that don't map to any entity object attribute value. The two kinds of calculated attributes are known as:

A view object can include an entity-mapped attribute which itself is a transient attribute at the entity object level.

5.4.1 How to Add a SQL-Calculated Attribute

You use the overview editor for the view object to add a SQL-calculated attribute.

Before you begin:

It may be helpful to have an understanding of calculated attributes. For more information, see Section 5.4, "Adding Calculated and Transient Attributes to a View Object."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.8.1, "How to Create an Expert Mode View Object."

To add a SQL-calculated attribute to a view object:

  1. In the Applications window, double-click the view object for which you want to define a SQL-calculated attribute.

  2. In the overview editor, click the Attributes navigation tab and then click the Create new attribute button.

  3. In the New View Object Attribute dialog, enter a name for the attribute.

  4. In the overview editor, in the Attributes page, select the new attribute.

  5. Click the Details tab, set the Java type to an appropriate value.

    For example, a calculated attribute that concatenates a first name and a last name would have the type String, as shown in Figure 5-13.

  6. In the Default Value section, select SQL and provide a SQL expression in the expression field.

    For example, to change the order of first name and last name, you could write the expression LAST_NAME||', '||FIRST_NAME, as shown in Figure 5-13.

    Figure 5-13 New SQL-Calculated Attribute

    New View Object Attribute dialog
  7. Consider changing the SQL column alias to match the name of the attribute.

  8. Verify the database query column type and adjust the length (or precision/scale) as appropriate.

5.4.2 What Happens When You Add a SQL-Calculated Attribute

When you add a SQL-calculated attribute in the overview editor for the view object, JDeveloper updates the XML document for the view object to reflect the new attribute. The entity-mapped attribute's <ViewAttribute> tag looks like the sample shown in Example 5-3. The entity-mapped attribute inherits most of it properties from the underlying entity attribute to which it is mapped.

Example 5-3 Metadata For Entity-Mapped Attribute

<ViewAttribute
   Name="LastName"
   IsNotNull="true"
   EntityAttrName="LastName"
   EntityUsage="EmpEO"
   AliasName="LAST_NAME" >
</ViewAttribute>

Whereas, in contrast, a SQL-calculated attribute's <ViewAttribute> tag looks like sample shown in Example 5-4. As expected, the tag has no EntityUsage or EntityAttrName property, and includes datatype information along with the SQL expression.

Example 5-4 Metadata For SQL-Calculated Attribute

<ViewAttribute
   Name="LastCommaFirst"
   IsUpdatable="false"
   IsPersistent="false"
   PrecisionRule="true"
   Type="java.lang.String"
   ColumnType="VARCHAR2"
   AliasName="FULL_NAME"
   SQLType="VARCHAR" >
   Precision="62"
   Expression="LAST_NAME||', '||FIRST_NAME">
</ViewAttribute>

5.4.3 What You May Need to Know About SQL-Calculated Attributes

The view object includes the SQL expression for your SQL-calculated attribute in the SELECT list of its query at runtime. The database is the one that evaluates the expression, and it returns the result as the value of that column in the query. The value is reevaluated each time you execute the query.

5.4.4 How to Add a Transient Attribute

Transient attributes are often used to provide subtotals or other calculated expressions that are not stored in the database.

Before you begin:

It may be helpful to have an understanding of transient attributes. For more information, see Section 5.4, "Adding Calculated and Transient Attributes to a View Object."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

Transient attributes that you define may be evaluated using the Groovy Expression Language. Groovy lets you insert expressions and variables into strings. The expression will be saved as part of the view object definition. For more information, see Section 3.5.6, "How to Use Groovy Scripting Language With Business Components."

You should be familiar with the limitations of using transient attributes. For more information, see Section 9.1.8, "Handling View Object Queries with Primary Keys Defined by Transient Attributes."

You will need to complete this task:

Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.8.1, "How to Create an Expert Mode View Object."

To add a transient attribute to a view object:

  1. In the Applications window, double-click the view object for which you want to define a transient attribute.

  2. In the overview editor, click the Attributes navigation tab and then click the Create new attribute button.

  3. In the New View Object Attribute dialog, enter a name for the attribute and select the Java type, then click OK.

  4. In the Attributes page of the overview editor, select the new attribute, and then click the Details tab.

  5. If the transient attribute's value is to be calculated by an expression, for the Default Value, select Expression and click Edit value.

    1. In the Edit Expression dialog, enter an expression that calculates the value of the attribute.

      Transient attribute expressions may derive the value from persistent attributes that are defined by the view object. If you need to refer to an entity attribute, that attribute must be added to the view object definition.

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

    3. 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"));
      
    4. When 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 in the Edit Expression dialog. Locate each attribute in the Available list and shuttle it to the Selected list.

    5. Click OK.

      For example, a transient attribute that uses an expression to calculate an order average is shown in Figure 5-14.

      Figure 5-14 New Transient Attribute

      Image of New View Object Attribute dialog

5.4.5 How to Add a Transient Attribute Defined by an Entity Object

A view object can include an entity-mapped attribute which itself is a transient attribute at the entity object level.

Before you begin:

It may be helpful to have an understanding of transient attributes. For more information, see Section 5.4, "Adding Calculated and Transient Attributes to a View Object."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.8.1, "How to Create an Expert Mode View Object."

To add a transient attribute from an entity object to an entity-based view object:

  1. In the Applications window, double-click the view object for which you want to add a transient attribute based on an entity usage.

  2. In the overview editor, click the Attributes navigation tab and then click the Create new attribute button and choose Add Attribute from Entity to view the list of available entity-derived attributes.

  3. In the Attributes dialog, move the desired transient attribute from the Available list into the Selected list.

  4. Click OK.

5.4.6 How to Add a Validation Rule to a Transient Attribute

Attribute-level validation rules are triggered for a particular view object transient attribute when either the end user or the program code attempts to modify the attribute's value. Since you cannot determine the order in which attributes will be set, attribute-level validation rules should be used only when the success or failure of the rule depends exclusively on the candidate value of that single attribute.

The process for adding a validation rule to a view object transient attribute is similar to the way you create any declarative validation rule, and is done using the Add Validation Rule dialog. You can open this dialog from the overview editor for the view object by clicking the Add Validation Rule button in the Validation Rules section of the Attributes page. You must first select the transient attribute from the attributes list and the transient attribute must be defined as updatable. Validation rules cannot be defined for read-only transient attributes.

Before you begin:

It may be helpful to have an understanding of attribute UI hints. For more information, see Section 5.13, "Defining UI Hints for View Objects."

You may also find it helpful to understand the different types of validation rules you can define. For more information, see Section 11.4, "Using the Built-in Declarative Validation Rules."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.8.1, "How to Create an Expert Mode View Object."

To add a validation rule for a transient attribute:

  1. In the Applications window, double-click the desired view object.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the transient attribute, and then click the Details tab and verify that Updatable displays Always.

    Validation rules for transient attributes must be updatable. The value Never specifies a read-only attribute.

  4. In the Attributes page, click the Validation Rules tab and then click the Add Validation Rule icon.

  5. In the Add Validation Rule dialog, select the type of validation rule desired from the Type dropdown list.

  6. In the Rule Definition tab, use the dialog settings to configure the new rule.

    The controls will change depending on the kind of validation rule you select. For more information about the different validation rules, see Section 11.4, "Using the Built-in Declarative Validation Rules."

  7. 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 11.7, "Creating Validation Error Messages."

  8. Click OK.

5.4.7 What Happens When You Add a Transient Attribute

When you add a transient attribute in the overview editor for a view object, JDeveloper updates the XML document for the view object to reflect the new attribute. A transient attribute's <ViewAttribute> tag in the XML is similar to the SQL-calculated one, but it lacks an Expression property.

When you base a transient attribute on a Groovy expression, a <TransientExpression> tag is created within the appropriate attribute, as shown in Example 5-5.

Example 5-5 Calculating a Transient Attribute Using a Groovy Expression

<TransientExpression>
   <![CDATA[
      (Quantity !== null) ? Quantity : 0) * (Price !== null ? Price : 0)
   ]]>
</TransientExpression>

5.4.8 What You May Need to Know About Transient Attributes and Calculated Values

A transient attribute is a placeholder for a data value. If you change the Updatable property of the transient attribute to Always, the end user can enter a value for the attribute. If you want the transient attribute to display a calculated value, then you'll typically leave the Updatable property set to Never and write a Groovy Language expression on the Attribute page of the overview editor for the view object.

Alternatively, if you want to write Java code to calculate the transient attribute, you need to enable a custom view row class and choose to generate accessor methods, in the Java dialog that you open by clicking the Edit button on the Java page of the overview editor for the view object. Then you would write Java code inside the accessor method for the transient attribute to return the calculated value. Example 5-5 shows the CustomerVORowImpl.java view row class contains the Java code to return a calculated value in the getFirstDotLast() method.

// In CustomerVORowImpl.java
public String getFirstDotLast() {
  // Commented out this original line since we're not storing the value
  // return (String) getAttributeInternal(FIRSTDOTLAST);
  return getFirstName().substring(0,1)+". "+getLastName();
}

5.5 Limiting View Object Rows Using Effective Date Ranges

Applications that need to query data over a specific date range can generate date-effective row sets. To define a date-effective view object you must create an entity-based view object that is based on an date-effective entity object. User control over the view object's effective date usage is supported by metadata on the view object at design time. At runtime, ADF Business Components generates the query filter that will limit the view rows to an effective date.

5.5.1 How to Create a Date-Effective View Object

Whether or not the query filter for an effective date will be generated depends on the value of the Effective Dated property displayed in the Properties window for the view object (to view the property, click the General tab in the overview editor for the view object and expand the Name section in the Properties window).

The overview editor for the view object does not display the date-effective query clause in the WHERE clause. You can use the Test Query dialog to view the clause. A typical query filter for effective dates looks like this:

(:Bind_SysEffectiveDate BETWEEN CustomerVO.EFFECTIVE_START_DATE AND CustomerVO.EFFECTIVE_END_DATE)

At runtime, the bind value for the query can be obtained from a property of the root application module or can be assigned directly to the view object. In order to set the effective date for a transaction, use code similar to the following snippet:

am.setProperty(ApplicationModule.EFF_DT_PROPERTY_STR, new Date("2008-10-01));

If you do not set EFF_DT_PROPERTY_STR on the application module, the current date is used in the query filter, and the view object returns the effective rows filtered by the current date.

The view object has its own transient attribute, SysEffectiveDate, that you can use to set the effective date for view rows. This transient attribute is generated in the view object by JDeveloper when you set the view object to be date-effective. Otherwise, the SysEffectiveDate attribute value for new rows and defaulted rows is derived from the application module. ADF Business Components propagates the effective date from the view row to the entity object during DML operations only.

Before you begin:

It may be helpful to have an understanding of data-effective row sets. For more information, see Section 5.5, "Limiting View Object Rows Using Effective Date Ranges."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete these tasks:

  1. Create an effective dated entity object, as described in Section 4.2.8, "How to Store Data Pertaining to a Specific Point in Time."

  2. Use the Create View Object wizard to create the entity-based view object, as described in Section 5.2.1, "How to Create an Entity-Based View Object."

    The view object you create should be based on the effective dated entity object you created. In the Attributes page of the wizard, be sure to add the date-effective attributes that specify the start date and end date on the entity object to the Selected list for the view object.

To enable effective dates for a view object using the SysEffectiveDate attribute:

  1. In the Applications window, double-click the view object you created based on the effective dated entity object.

  2. In the overview editor, click the General navigation tab.

  3. In the Properties window, expand the Name section, and verify that the Effective Dated dropdown menu displays True.

    If the Name section is not displayed in the Properties window, click the General navigation tab in the overview editor to set the proper focus.

  4. In the overview editor, click the Attributes navigation tab and select the attribute for the start date, and then click the Details tab and verify that Effective Date is enabled and that Start is selected, as shown in Figure 5-15.

    Verify that the attribute for the end date is also enabled correctly, as shown in the figure. Note that these fields appear grayed out to indicate that they cannot be edited for the view object.

    Figure 5-15 View Object Overview Editor Displays Effective Date Setting

    Effective dated view object attribute enabled

    No additional steps are required once you have confirmed that the view object has inherited the desired attributes from the date-effective entity object.

5.5.2 How to Create New View Rows Using Date-Effective View Objects

Creating (inserting) date-effective rows is similar to creating or inserting ordinary view rows. The start date and end date can be specified as follows:

  • The user specifies the effective date on the application module. The start date is set to the effective date, and the end date is set to end of time.

    End of time is defined for ADF Business Components as December 31st, 4712.

  • The user specifies values for the start date and the end date (advanced).

In either case, during entity validation, the new row is checked to ensure that it does not introduce any gaps or overlaps. During post time, ADF Business Components will acquire a lock on the previous row to ensure that the gap or overlaps are not created upon the row insert.

5.5.3 How to Update Date-Effective View Rows

Date-effective rows are updated just as non date-effective rows are updated, using a Row.setAttribute() call. However, for the desired operation to take effect, an effective date mode must be set on the row before the update. ADF Business Components supports various modes to initiate the row update.

To set the update mode, invoke the Row.setEffectiveDateMode(int mode) method with one of the following mode constants defined by the oracle.jbo.Row class.

  • CORRECTION (Correction Mode)

    The effective start date and effective end dates remain unchanged. The values of the other attributes may change. This is the standard row update behavior.

  • UPDATE (Update Mode)

    The effective end date of the latest row will be set to the effective date. All user modifications to the row values are reverted on this row. A new row with the modified values is created. The effective start date of the new row is set to the effective date plus one day, and the effective end date is set to end of time. The new row will appear after the transaction is posted to the database.

  • OVERRIDE (Update Override Mode)

    The effective end date of the modified row will be set to the effective date. The effective start date of the next row is set to effective date plus one day and the effective end date of the next row is set to end of time.

  • CHANGE_INSERT (Change Insert Mode)

    Similar to update mode, but change insert mode operates on a past row not the latest row. The effective end date of the modified row should be set to the effective date. All user modifications to the row values are reverted on this row. A new row with the modified values will be created. The effective start date of the new row is set to effective date plus one day, and the effective end date is set to effective start date of the next row minus one day. The new row will appear after the transaction is posted to the database.

5.5.4 How to Delete Date-Effective View Rows

ADF Business Components supports various modes to initiate the row deletion. You can mark view rows for deletion by using API calls like RowSet.removeCurrentRow() or Row.remove().

To set the deletion mode, invoke the Row.setEffectiveDateMode(int mode) method with one of the following mode constants defined by the oracle.jbo.Row class.

  • DELETE (Delete Mode)

    The effective end date of the row is set to the effective date. The operation for this row is changed from delete to update. All rows with the same noneffective date key values and with an effective start date greater than the effective date are deleted.

  • NEXT_CHANGE (Delete Next Change Mode)

    The effective end date of the row is set to the effective end date of the next row with the same noneffective date key values. The operation for this row is changed from delete to update. The next row is deleted.

  • FUTURE_CHANGE (Delete Future Change Mode)

    The effective end date of the row is set to the end of time. The operation for this row is changed from delete to update. All future rows with the same noneffective date key values are deleted.

  • ZAP (Zap Mode)

    All rows with the same non-effective date key values are deleted.

The effective date mode constants are defined on the row interface as well.

5.5.5 What Happens When You Create a Date-Effective View Object

When you create a date-effective view object, the view object inherits the transient attribute SysEffectiveDate from the entity object to store the effective date for the row. Typically, the insert/update/delete operations modify the transient attribute while Oracle ADF decides the appropriate values for effective start date and effective end date.

The query displayed in the overview editor for the date-effective view object does not display the WHERE clause needed to filter the effective date range. To view the full query for the date-effective view object, including the WHERE clause, edit the query and click Test and Explain in the Query page of the overview editor. The following sample shows a typical query and query filter for effective dates:

SELECT OrdersVO.ORDER_ID,        OrdersVO.CREATION_DATE, 
       OrdersVO.LAST_UPDATE_DATE
FROM ORDERS OrdersVO
WHERE (:Bind_SysEffectiveDate BETWEEN OrdersVO.CREATION_DATE AND
                                      OrdersVO.LAST_UPDATE_DATE)

Example 5-6 shows sample XML entries that are generated when you create an date-effective view object.

Example 5-6 XML Definition for Date-Effective View Object

<ViewObject
...
<!-- Property that enables date-effective view object. -->
  IsEffectiveDated="true">
  <EntityUsage
    Name="Orders1"
    Entity="model.OrdersDatedEO"
    JoinType="INNER JOIN"/>
<!-- Attribute identified as the start date -->
  <ViewAttribute
    Name="CreationDate"
    IsNotNull="true"
    PrecisionRule="true"
    IsEffectiveStartDate="true"
    EntityAttrName="CreationDate"
    EntityUsage="Orders1"
    AliasName="CREATION_DATE"/>
<!-- Attribute identified as the end date -->
  <ViewAttribute
    Name="LastUpdateDate"
    IsNotNull="true"
    PrecisionRule="true"
    IsEffectiveEndDate="true"
    EntityAttrName="LastUpdateDate"
    EntityUsage="Orders1"
    AliasName="LAST_UPDATE_DATE"/>
<!-- The SysEffectiveDate transient attribute -->
  <ViewAttribute
    Name="SysEffectiveDate"
    IsPersistent="false"
    PrecisionRule="true"    Type="oracle.jbo.domain.Date"
    ColumnType="VARCHAR2"
    AliasName="SysEffectiveDate"
    Passivate="true"
    SQLType="DATE"/>
</ViewObject>

5.5.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.6 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:

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

Figure 5-16 Join Query Result

Join query result

5.6.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 ItemEO entity object. It contains foreign key attribute of type Number like:

  • ItemId, representing the product to which the order item pertains

Showing an end user exclusively these "raw" numerical values is not 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 data, this presents an additional challenge. Luckily, entity-based view objects support easily including reference information that's always up to date. The key requirement to leverage this feature is the presence of associations between the entity object that act as the view object's primary entity usage and the entity objects that contribute reference information.

To include reference entities in a join view object, use the Create View Object wizard. The Create View Object wizard lets you specify the type of join:

  • Inner Join

    Select when you want the view object to return all rows between two or more entity objects, where each entity defines the same primary key column. The inner join view object will not return rows when a primary key value is missing from the joined entities.

  • Outer Join

    Select when you want the view object to return all rows that exist in one entity object, even though corresponding rows do not exist in the joined entity object. Both left and right outer join types are supported. The left and right designation refers to the source (left) and destination (right) entity object named in an association. For details about changing the default inner join to an outer join, see Section 5.6.2, "How to Modify a Default Join Clause to Be an Outer Join When Appropriate." For details about cases where a matching outer entity row is not found (none exists), see Section 5.6.7, "What You May Need to Know About Outer Joins."

Both inner joins and outer joins are supported with the following options:

Before you begin:

It may be helpful to have an understanding of how the type of view object effects joins. For more information, see Section 5.6, "Working with Multiple Tables in Join Query Results."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You may also find it helpful to understand Oracle Database features related to join queries. For more information, see the "SQL Queries and Subqueries" chapter in the Oracle Database SQL Language Reference.

You will need to complete this task:

Create the desired entity objects, as described in Section 4.2.1, "How to Create Multiple Entity Objects and Associations from Existing Tables."

To create a view object that joins entity objects:

  1. In the Applications window, right-click the package in the data model project in which you want to create the view object and choose New and then View Object.

  2. In the Create View Object wizard, on the Name page, enter a package name and a view object name. Keep the default setting Entity object enabled to indicate that you want this view object to manage data with its base entity object. Click Next.

  3. In the Entity Objects page, the first entity usage in the Selected list is known as the primary entity usage for the view object. Select the primary entity object from the Available list and shuttle it to the Selected list.

    The list is not limited to a single, primary entity usage.

  4. To add additional, secondary entity objects to the view object, select them in the Available list and shuttle them to the Selected list.

    The Association dropdown list shows you the name of the association that relates the selected secondary entity usage to the primary one. For example, Figure 5-17 shows the result of adding one secondary reference entity usage, ProductEO, in addition to the primary ItemEO entity usage. The association that relates to this secondary entity usage is SItemProductIdFkAssoc.ProductEO.

    Figure 5-17 Create View Object Wizard, Entity Objects Page

    Entity Object page in View Object wizard
  5. Optionally, use the Entity Usage field to give a more meaningful name to the entity usage when the default name is not clear.

  6. If you add multiple entity usages for the same entity, use the Association dropdown list to select which association represents that usage's relationship to the primary entity usage. Click Next.

    For each secondary entity usage, the Reference option is enabled to indicate that the entity provides reference information and that it is not the primary entity. The Updatable option is disabled. This combination represents the typical usage. However, when you want to create a join view object with multiple, updatable entity usages, see Section 7.2.1, "How to Create a View Object with a Polymorphic Entity Usage."

    Secondary entity usages that are updatable can also have the Participate in row delete option enabled. This will allow secondary entity attributes to appear NULL when the primary entity is displayed.

  7. On the Attributes page, select the attributes you want each entity object usage to contribute to the view object. Click Next.

  8. On the Attribute Settings page, you can rename an attribute when the names are not as clear as they ought to be.

    The same attribute name often results when the reference and secondary entity objects derive from the same table. Figure 5-18 shows the attribute Id in the Select Attribute dropdown list, which has been renamed to ProductId in the Name field.

    Figure 5-18 Create View Object Wizard, Attribute Settings Page

    Attribute Setting page in View Object wizard
  9. Click Finish.

5.6.2 How to Modify a Default Join Clause to Be an Outer Join When Appropriate

When you add a secondary entity usage to a view object, the entity usage is related to an entity usage that precedes it in the list of selected entities. This relationship is established by an entity association displayed in the Association dropdown list in the Entity Objects page of the overview editor for the view object. You use the Association dropdown list in the editor to select the entity association that relates the secondary entity usage to the desired preceding entity usage in the Selected list. The name of the preceding entity usage is identified in the Source Usage dropdown list.

When JDeveloper creates the WHERE clause for the join between the table for the primary entity usage and the tables for related secondary entity usages, by default it always creates inner joins. You can modify the default inner join clause to be a left or right outer join when appropriate. The left designation refers to the source entity object named in the selected association. This is the entity identified in the Source Usage dropdown list. The right designation refers to the current secondary entity usage that you have selected in the Selected list.

In the left outer join, you will include all rows from the left table (related to the entity object named in the Source Usage list) in the join, even if there is no matching row from the right table (related to the current secondary entity object selection). The right outer join specifies the reverse scenario: you will include all rows from the right table (related to the entity object named in the Selected list) in the join, even if there is no matching row from the left table (related to the current secondary entity object selection).

For example, assume that a person is not yet assigned a membership status. In this case, the MembershipId attribute will be NULL. The default inner join condition will not retrieve these persons from the MEMBERSHIPS_BASE table. Assuming that you want persons without membership status to be viewable and updatable through the MembershipDiscountsVO view object, you can use the Entity Objects page in the overview editor for the view object to change the query into an left outer join to the MEMBERSHIPS_BASE table for the possibly null MEMBERSHIP_ID column value. When you add the person entity to the view object, you would select the left outer join as the join type. As shown in Figure 5-19, the association PersonsMembershipsBaseFkAssoc identifies a source usage MembershipBaseEO on the left side of the join and the selected PersonEO entity usage on the right side. The view object MembershipDiscountsVO joins the rows related to both of these entity objects and defines a left outer join for PersonEO to allow the view object to return rows from the table related to MembershipBaseEO even if they do not have a match in the table related to PersonEO.

Figure 5-19 Setting an Outer Join to Return NULL Rows from Joined Entities

Outer join set on entity-based view object

The view object's updated WHERE clause includes the addition (+) operator on the right side of the equals sign for the related table whose data is allowed to be missing in the left outer join:

PersonEO.MEMBERSHIP_ID = MembershipBaseEO.MEMBERSHIP_ID(+)

Before you begin:

It may be helpful to have an understanding of how the type of view object effects joins. For more information, see Section 5.6, "Working with Multiple Tables in Join Query Results."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired entity objects, as described in Section 4.2.1, "How to Create Multiple Entity Objects and Associations from Existing Tables."

To change an inner join type to an outer join:

  1. In the Applications window, double-click the view object that you want to modify.

  2. In the overview editor, click the Entity Objects navigation tab.

    The entity object you select represents the table on the right side of the join.

  3. In the Entity Objects page, in the Selected list, select the entity object that you want to change the join type for.

    The entity object you select represents the table on the right side of the join.

  4. In the Association dropdown list, if only one association is defined, leave it selected; otherwise, select among the list of entity object associations that relate the secondary entity object to the desired entity object.

    The entity usage that represents the joined table will be displayed in the Source Usage dropdown list. The entity object in the Source Usage dropdown list that you choose through the association selection represents the table on the left side of the join.

  5. In the Join Type dropdown list, decide how you want the view object to return rows from the joined entity objects:

    • left outer join will include rows from the left table in the join, even if there is no matching row from the right table.

    • right outer join will include rows from the right table in the join, even if there is no matching row from the left table.

    The Source Usage dropdown list is the left side of the join and the current entity usage in the Selected list is the right side.

5.6.3 How to Select Additional Attributes from Reference Entity Usages

After adding secondary entity usages, you can use the overview editor for the view object to select the specific, additional attributes from these new usages that you want to include in the view object.


Tip:

The overview editor lets you sort attributes displayed in the Attributes page by their entity usages. By default, the attributes table displays attributes in the order they appear in the underlying entity object. To sort the attributes by entity usage, click the header for the Entity Usage column of the attributes table. If the Entity Usage column does not appear in the attributes table, click the dropdown menu on the top-right corner of the table (below the button bar) and choose Select Columns to add the column to the Selected list.


Before you begin:

It may be helpful to have an understanding of how the type of view object effects joins. For more information, see Section 5.6, "Working with Multiple Tables in Join Query Results."

You may also find it helpful to understand Oracle Database features related to join queries. For more information, see the "SQL Queries and Subqueries" chapter in the Oracle Database SQL Language Reference.

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired entity objects, as described in Section 4.2.1, "How to Create Multiple Entity Objects and Associations from Existing Tables."

To select attributes from a secondary entity usage:

  1. In the Applications window, double-click the entity-based view object that you want to modify.

  2. In the overview editor, click the Attributes navigation tab and then click the Create new attribute button and choose Add Attribute from Entity to view the list of available entity-derived attributes.

  3. In the Attributes dialog, select the desired attribute and add it to the Selected list.

    Note that even if you didn't intend to include them, JDeveloper automatically verifies that the primary key attribute from each entity usage is part of the Selected list. If it's not already present in the list, JDeveloper adds it for you. When you are finished, the overview editor Query page shows that JDeveloper has included the new columns in the SELECT statement.

  4. Click OK.

5.6.4 How to Remove Unnecessary Key Attributes from Reference Entity Usages

The view object attribute corresponding to the primary key attribute of the primary entity usage acts as the primary key for identifying the view row. When you add secondary entity usages, JDeveloper marks the view object attributes corresponding to their primary key attributes as part of the view row key as well. When your view object consists of a single updatable primary entity usage and a number of reference entity usages, the primary key attribute from the primary entity usage is enough to uniquely identify the view row. Further key attributes contributed by secondary entity usages are not necessary and you should disable their Key Attribute settings.

For example, based on the view object with primary entity usage ShippingOptionEO, you could disable the Key Attribute property for the ShippingOptionTranslationEO entity usage so that this property is no longer selected for this additional key attribute: ShippingTranslationsId.

However, when your view object consists of multiple updatable primary entity usages, then the primary key to identify the view row must consist at the minimum of all the key attributes of all updatable entity usages included in the view object.

Before you begin:

It may be helpful to have an understanding of how the type of view object effects joins. For more information, see Section 5.6, "Working with Multiple Tables in Join Query Results."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired entity objects, as described in Section 4.2.1, "How to Create Multiple Entity Objects and Associations from Existing Tables."

To remove unnecessary key attributes:

  1. In the Applications window, double-click the entity-based view object that you want to modify.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, in the attributes table, select the key attribute (identified by the key icon in the Name column), and then click the Details tab and deselect the Key Attribute property.

5.6.5 How to Hide the Primary Key Attributes from Reference Entity Usages

Since you generally won't want to display the primary key attributes that were automatically added to the view object, you can set the attribute's Display Hint property to Hide.

Before you begin:

It may be helpful to have an understanding of how the type of view object effects joins. For more information, see Section 5.6, "Working with Multiple Tables in Join Query Results."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired entity objects, as described in Section 4.2.1, "How to Create Multiple Entity Objects and Associations from Existing Tables."

To hide the primary key attribute:

  1. In the Applications window, double-click the entity-based view object that you want to modify.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the primary key attribute (identified by the key icon in the Name column), and then click the UI Hints tab and select Hide for the Display type.

5.6.6 What Happens When You Reference Multiple Entities in a View Object

Figure 5-7 depicts the entity-based view object ItemVO and the two entity usages referenced in its query statement. The dotted lines represent the metadata captured in the entity-based view object's XML document that map SELECT list columns in the query to attributes of the entity objects used in the view object. The query of the entity-based view object joins data from a primary entity usage (ItemEO) with that from the secondary reference entity usage (ProductEO).

Figure 5-20 View Object Maps Attributes of Multiple Entity Objects

View objects encapsulate queries and metadata

When you create a join view object to include one or more secondary entity usages by reference, JDeveloper updates the view object's XML document to include information about the additional entity usages. For example, the ItemVO.xml file for the view object includes an additional reference entity usage. You will see this information recorded in the multiple <EntityUsage> elements. For example, Example 5-0 shows an entity usage entry that defines the primary entity usage.

Example 5-7 Primary Entity Usage

<EntityUsage
   Name="ItemEO"
   Entity="oracle.summit.model.entities.ItemEO"/>

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

Example 5-8 Secondary Reference Entity Usage

<EntityUsage
   Name="ProductEO"
   Entity="oracle.summit.model.entities.ProductEO"
   Association="oracle.summit.model.entities.assoc.SItemProductIdFkAssoc"
   AssociationEnd="oracle.summit.model.entities.assoc.
                    SItemProductIdFkAssoc.ProductEO"
   SourceUsage="oracle.summit.model.views.ItemVO.ItemEO"
   ReadOnly="true"
   Reference="true"
   Participant="false"
   JoinType="INNER JOIN/>

Each attribute entry in the XML file indicates which entity usage it references. For example, the entry for the OrdId attribute in Example 5-9 shows that it's related to the ItemEO entity usage, while the Name attribute is related to the ProductEO entity usage.

Example 5-9 Entity Usage Reference of View Object Attribute

   <ViewAttribute
      Name="OrdId"
      IsNotNull="true"
      EntityAttrName="OrdId"
      EntityUsage="ItemEO"
      AliasName="ORD_ID" >
   </ViewAttribute>
...
   <ViewAttribute
      Name="Name"
      IsUpdatable="true"
      IsNotNull="true"
      EntityAttrName="Name"
      EntityUsage="ProductEO"
      AliasName="NAME" >
   </ViewAttribute>

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.6.7 What You May Need to Know About Outer Joins

If you specify an outer join and no matching outer entity row is found, the database return null for that portion of the query. For example, if you join Dept entity and Emp entity through DeptEmpView with an outer join and Dept 40 has no employees. Then, when the row for Dept 40 is reached, database returns [40, null] and ADF Business Components will create an entity row for Dept 40 and an blank Emp entity row. If the Emp entity in the view object is set as Updatable, you can set attribute values into this blank entity row. Later if you commit the transaction, a new entity row will be inserted.

5.6.8 What You May Need to Know About Entity Based Joins and Entity Cardinality

Suppose you have Customer and Order entity objects and you create view object joins based on the entity association CustOrderIdFKAssoc, where Customer has cardinality many and Order has cardinality 1.

If you were to create a 1-many join OrderCustVO view object that joins Order entity (the primary entity with cardinality of 1) to Customer entity (secondary entity with cardinality of many), the application may return the same Customer entity row for many Order rows.

If you were to create a many-1 join CustOrderVO view object that joins Customer (primary, many) to Order (secondary, one), the application may return the same Customer entity row with many Order entity rows.

In the OrderCustVO (1-many) case, where Customer is a reference entity, when the end user deletes a row, the application only deletes the Order entity row and Customer is unaffected. Similarly, in the CustOrderView (m-1 case), where Order is a reference entity, when the end user deletes a row, the application only deletes the Customer entity row and Order is unaffected.

But, in the CustOrderVO (many-1) case, when the end user deletes one row, the application may remove multiple rows from the join view instance. For example, suppose you have three orders (A, B, C) for customer 10. If the end user deletes the first of these joined view rows [10, A], the application will actually remove three view rows: [10, A], [10, B], and [10, C]. At the entity level, only Customer 10 entity row is removed because Order is a reference entity.

5.6.9 What You May Need to Know About Entity Based Joins and Participates in Row Delete

Suppose you create a 1-many join (like OrderCustVO view object) and a many-1 join (like CustOrderVO view object) where the secondary entity object has Participate in Row Delete enabled (and Customer 10 has Orders A, B, C).

If you were to create a 1-many join OrderCustVO and the Customer entity object has Participate in Row Delete enabled, when the end user deletes [A, 10], the application will delete Order A entity row first, followed by the Customer 10 entity row. When this Customer 10 is deleted, the application actually remove all view rows that refer to that entity row. This mean [A, 20] and [A, 30] will also be removed (3 view rows in total).

If you were to create a many-1 join CustOrderVO and the Order entity object has Participate in Row Delete enabled, when the end user deletes [10, A], the application will delete Customer 10 entity row first. The application will then remove all view rows that refer to that entity row. This means [20, A] and [30, A] will be removed from the view. Then, the application will delete the Order A entity row.

5.6.10 What You May Need to Know About Composition Associations and Joins

Suppose the association between entity objects Order and OrderItem is a composition association and you create a view object joins based on these entities, where Order A contains Items 1, 2, 3.

In the ItemOrdVO view object case, where Order (secondary) is a reference entity, when the end user deletes [1, A], the application will only delete the 1 OrderItem entity row and there will be no issue. However, when the Order entity object has Participate in Row Delete enabled, when the end user deletes [1, A], the application will also attempt to delete the Item 1 entity row, followed by deleting Order A. However, due to the composition relationship, this will fail and the application will throw RemoveWithDetailsException because Order A still has OrderItem 2 and OrderItem 3 that belong to Order A.

In the OrdItemVO view object case, where Item (secondary) entity is a reference entity, when the end user deletes [A, 1], the application will also attempt to delete the Order A entity row. However, due to the composition relationship, this will fail and the application will throw RemoveWithDetailsException because Order A still has Item 1, Item 2, and <code>Item 3 that belong to Order A.

If the Item (secondary) entity object has Participate in Row Delete enabled, removing [A, 1] will produce the same exception since Order A has child rows.

The situation is different if the entity association has Implement Cascade Delete under Composition Association enabled.

In the ItemOrderVO view object case, where Order is a reference entity, when the end user deletes [1, A], the application only deletes the Item A entity row (with no exception thrown). If the Order entity object has Participate in Row Delete enabled, when the end user deletes [1, A], the application will delete Item A first, followed by deletion of Order A. Because cascade delete is enabled, deletion of Order A will delete all the remaining children of Order A, including Item 2 and Item 3. This will result in removal of view rows [2, A] and [3, A] from the view instance.

Similarly, in the OrderItemVO view object case, where Item is a reference entity, when the end user deletes [A, 1], the application deletes Order A. Because Implement Cascade Delete is enabled, the application will also delete all the children of Order A, including Item 1, 2, and 3. This will result in the removal of view rows [A, 2], [A, 2], and [A, 3] from the view instance.

If the Item entity object has Participate in Row Delete enabled, the same behavior is produced: all three view rows are removed.

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

Before you begin:

It may be helpful to have an understanding of how the type of view object effects joins. For more information, see Section 5.6, "Working with Multiple Tables in Join Query Results."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To create a read-only view object joining two tables:

  1. In the Applications window, right-click the project in which you want to create the view object and choose New and then View Object.

  2. If you have not yet created a database connection for the data model project, in the Initialize Business Components Project dialog, select the database connection or choose New to create a connection. Click OK.

    If this is the first component you're creating in the project, the Initialize Business Components Project dialog appears to allow you to select a database connection.

  3. In the Create View Object wizard, on the Name page, enter a package name and a view object name. Select SQL query to indicate that you want this view object to manage data with read-only access. Click Next.

  4. On the Query page, use one of the following techniques to create the SQL query statement that joins the desired tables:

  5. After entering or building the query statement, click Next.

  6. On the Bind Variables page, do one of the following:

  7. On the Attribute Mappings page, click Finish.

5.6.12 How to Test the Join View

To test the new view object, edit the application module and on the Data Model page add an instance of the new view object to the data model. Then, use the Oracle ADF Model Tester to verify that the join query is working as expected. For details about editing the data model and running the Oracle ADF Model Tester, see Section 8.3, "Testing View Object Instances Using the Oracle ADF Model Tester."

5.6.13 How to Use the SQL Statement Dialog with Read-Only View Objects

The Quick-pick objects page of the SQL Statement dialog lets you view the tables in your schema, including the foreign keys that relate them to other tables. To include columns in the select list of the query, shuttle the desired columns from the Available list to the Selected list. For example, Figure 5-21 shows the result of selecting the ID, NAME, and SUGGESTED_WHLSL_PRICE columns from the S_PRODUCT table, along with the CATEGORY column from the S_PRODUCT_CATEGORIES table. The column from the second table appears, beneath the S_PRODUCT_CATEGORY_ID_FK foreign key in the Available list. When you select columns from tables joined by a foreign key, the SQL Statement dialog automatically determines the required join clause for you.

Figure 5-21 View Object SQL Statement Dialog to Define a Join

SQL Statement dialog

Optionally, use the WHERE clause page of the SQL Statement dialog to define the expression. To finish creating the query, click OK in the SQL Statement dialog. The Query page of the overview editor will show a query like the one shown in Example 5-10.

Example 5-10 Creating a Query Using SQL Builder

SELECT
    S_PRODUCT.ID ID,
    S_PRODUCT.NAME NAME,
    S_PRODUCT.SUGGESTED_WHLSL_PRICE SUGGESTED_WHLSL_PRICE,
    S_PRODUCT_CATEGORIES.CATEGORY CATEGORY
FROM
    S_PRODUCT JOIN S_PRODUCT_CATEGORIES ON S_PRODUCT.CATEGORY_ID = 
                                         S_PRODUCT_CATEGORIES.ID

You can use the Attributes page of the Create View Object wizard to rename the view object attribute directly as part of the creation process. Renaming the view object here saves you from having to edit the view object again, when you already know the attribute names that you'd like to use. As an alternative, you can also alter the default Java-friendly name of the view object attributes by assigning a column alias, as described in Section 5.8.5.1, "Attribute Names for Calculated Expressions in Expert Mode."

5.7 Working with View Objects in Declarative SQL Mode

At runtime, when ADF Business Components works with JDBC to pass a query to the database and retrieve the result, the mechanism to retrieve the data is the SQL query. As an alternative to creating view objects that specify a SQL statement at design time, you can create entity-based view objects that contain no SQL statements. This capability of the ADF Business Components design time and runtime is known as declarative SQL mode. When the data model developer works with the wizard or editor for a view object in declarative SQL mode, they require no knowledge of SQL. In declarative SQL mode, the ADF Business Components runtime generates the SQL query statements based on metadata that you must define for the view object, as follows:

Additionally, the SQL statement that a declarative SQL mode view object generates at runtime will be determined by the SQL platform specified in the Business Components page of the Project Properties dialog.


Note:

Currently, the supported platforms for runtime SQL generation are SQL92 (ANSI) style and Oracle style. For information about setting the SQL platform for your project, see Section 3.2.3, "How to Initialize the Data Model Project With a Database Connection."


Declarative SQL mode selection is supported in JDeveloper as a setting that you can apply either to the entire data model project or to individual view objects that you create. The ADF Business Components design time also allows you to override the declarative SQL mode project-level setting for any view object you create.

The alternatives to declarative SQL mode are normal mode and expert mode. When you work in either of those modes, the view object definitions you create at design time always contain the entire SQL statement based on the SQL platform required by your application module's defined database connection. Thus the capability of SQL independence does not apply to view objects that you create in normal or expert mode. For information about using the wizard and editor to customize view objects when SQL is desired at design time, see Section 5.2, "Populating View Object Rows from a Single Database Table."

5.7.1 How to Create Declarative SQL View Objects

All view objects that you create in JDeveloper rely on the same design time wizard and editor. However, when you enable declarative SQL mode, the wizard and editor change to support customizing the view object definition without requiring you to display or enter any SQL. For example, the Query page of the Create View Object wizard with declarative SQL mode enabled lacks the Generated SQL field present in normal mode.

Additionally, in declarative SQL mode, since the wizard and editor do not allow you to enter WHERE and ORDERBY clauses, you provide equivalent functionality by defining a view criteria and sort criteria respectively. In declarative SQL mode, these criteria appear in the view object metadata definition and will be converted at runtime to their corresponding SQL clause. When the databound UI component has no need to display filtered or sorted data, you may omit the view criteria or sort criteria from the view object definition.

Otherwise, after you enable declarative SQL mode, the basic procedure to create a view object with ensured SQL independence is the same as you would follow to create any entity-based view object. For example, you must still ensure that your view object encapsulates the desired entity object metadata to support the intended runtime query. As with any entity-based view object, the columns of the runtime-generated FROM list must relate to the attributes of one or more of the view object's underlying entity objects. In declarative SQL mode, you automatically fulfill this requirement when working with the wizard or editor when you add or remove the attributes of the entity objects on the view object definition.

If you prefer to optimize the declarative SQL query so that the SELECT and FROM clauses of the SQL query statement are based solely on whether or not the attributes you add to the view object are rendered at runtime by a databound UI component, then you must disable the Selected in Query checkbox (sets IsSelected=false for the view object definition) for all added attributes. By default, the IsSelected property is true for any attribute that you add to the view object in declarative SQL mode. The default setting means the added attribute will be selected in the SQL statement regardless of whether or not the attribute is exposed by a databound UI component. When you create a new view object in declarative SQL mode, you can use the Attribute Settings page of the Create View Object wizard to change the setting for each attribute. If you need to alter this setting after you generate the view object, you can use the Properties window to change the Selected in Query setting for one or more attributes that you select in the Attributes page of the view object editor.


Performance Tip:

A view object instance configured to generate SQL statements dynamically will requery the database during page navigation if a subset of all attributes with the same list of key entity objects is used in the subsequent page navigation. Thus performance can be improved by activating a superset of all the required attributes to eliminate a subsequent query execution.


5.7.1.1 Enabling Declarative SQL Mode for All New View Objects

You can enable declarative SQL mode as a global preference so that it is the Create View Object wizard's default mode, or you can leave the setting disabled and select the desired mode directly in the wizard. The editor for a view object also lets you select and change the mode for an existing view object definition.

Before you begin:

It may be helpful to have an understanding of declarative SQL mode. For more information, see Section 5.7.1, "How to Create Declarative SQL View Objects."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To enable declarative SQL mode for all new view objects: 

  1. In the main menu, choose Tools and then Preferences.

  2. In the Preferences dialog, expand ADF Business Component and choose View Objects.

  3. On the ADF Business Components: View Object page, select Enable Declarative SQL mode for new objects and click OK.

    To predetermine how the FROM list will be generated at runtime you can select Include all attributes in runtime-generated query, as described in Section 5.7.4, "How to Support Programmatic Execution of Declarative SQL Mode View Objects."

5.7.1.2 Enabling Declarative SQL Mode for Specific View Objects

There are no unique requirements for creating entity-based view objects in declarative SQL mode. The basic procedure to create a view object with ensured SQL independence is the same as you would follow to create any entity-based view object. To create an entity-based view object in declarative SQL mode, use the Create View Object wizard, which is available from the New Gallery. The editor for a view object lets you select and change the mode for an existing view object definition.

Before you begin: 

It may be helpful to have an understanding of declarative SQL mode. For more information, see Section 5.7.1, "How to Create Declarative SQL View Objects."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To create declarative SQL-based view objects: 

  1. In the Applications window, right-click the package in the data model project in which you want to create the view objects and choose New and then View Object.

  2. In the Create View Object wizard, on the Name page, enter a package name and a view object name. Keep the default setting Entity object selected to indicate that you want this view object to manage data with its base entity object. Click Next.

    Any other choice for the data selection will disable declarative SQL mode in the Create View Object wizard.

  3. On the Entity Objects page, select the entity object whose data you want to use in the view object. Click Next.

    When you want to create a view object that joins entity objects, you can add secondary entity objects to the list. To create more complex entity-based view objects, see Section 5.6.1, "How to Create Joins for Entity-Based View Objects."

  4. On the Attributes page, select at least one attribute from the entity usage in the Available list and shuttle it to the Selected list. Attributes you do not select will not be eligible for use in view criteria and sort criteria. Click Next.

    You should select any attribute that you intend to customize (in the Attribute Settings page) or any attribute that you intend to use in a view criteria or sort criteria (in the Query page). Additionally, the tables that appear in the FROM list of the runtime-generated query will be limited to the tables corresponding to the attributes of the entity objects you select.

  5. On the Attribute Settings page, use the Select Attribute dropdown list to switch between the view object attributes and deselect Selected in Query for each attribute that you want to defer adding to the SQL statement until runtime.

    By default, the Selected in Query checkbox is enabled for all view object attributes that you add in declarative SQL mode. This default setting will generate a SQL statement with all added attributes selected. When you deselect the checkbox for an attribute, the IsSelected property is set to false and whether or not the attribute is selected will be determined at runtime by the databound UI component's usage of the attribute.

  6. Optionally, change the attribute names or any of their initial settings. Click Next.

  7. On the Query page, select Declarative in the Query Mode dropdown list if it is not already displayed. The wizard changes to declarative SQL mode.

    Changing the mode to Declarative in the wizard allows you to override the default mode for this single view object. If you did not select Enable declarative SQL mode for new objects, in the Preferences dialog, the wizard displays the default query mode, Normal.

  8. Optionally, define Where and Order By criteria to filter and order the data as required. At runtime, ADF Business Components automatically generates the corresponding SQL statements based on the criteria you create.

    Click Edit next to the Where field to define the view criteria you will use to filter the data. The view criteria you enter will be converted at runtime to a WHERE clause that will be enforced on the query statement. For information about specifying view criteria, see Section 5.9, "Working with Named View Criteria."

    In the Order By field select the desired attribute in the Available list and shuttle it to the Selected list. Attributes you do not select will not appear in the SQL ORDERBY clause generated at runtime. Add additional attributes to the Selected list when you want the results to be sorted by more than one column. Arrange the selected attributes in the list according to their sort precedence. Then for each sort attribute, assign whether the sort should be performed in ascending or descending order. Assigning the sort order to each attribute ensures that attributes ignored by the UI component still follow the intended sort order.

    For example, as shown in Figure 5-22, to limit the CustomerCardStatus view object to display only the rows in the CUSTOMERS table for customers with a specific credit card code, the view criteria in the Where field limits the CardTypeCode attribute to a runtime-determined value. To order the data by customer ID and the customer's card expiration date, the Order By field identifies those attributes in the Selected list.

    Figure 5-22 Creating View Object Wizard, Query Page with Declarative Mode Selected

    Step 5 of Create View Object wizard in SI mode
  9. Click Finish.

5.7.2 How to Filter Declarative SQL-Based View Objects When Table Joins Apply

When you create an entity-based view object you can reference more than one entity object in the view object definition. In the case of view objects you create in declarative SQL mode, whether the base entity objects are activated from the view object definition will depend on the requirements of the databound UI component at runtime. If the UI component displays attribute values from multiple entity objects, then the SQL generated at runtime will contain a JOIN operation to query the appropriate tables.

Just as with any view object that you create, it is possible to filter the results from table joins by applying named view criteria. In the case of normal mode view objects, all entity objects and their attributes will be referenced by the view object definition and therefore will be automatically included in the view object's SQL statement. However, by delaying the SQL generation until runtime with declarative SQL mode, there is no way to know whether the view criteria should be applied.


Note:

In declarative SQL mode, you can define a view criteria to specify the WHERE clause (optional) when you create the view object definition. This type of view criteria when it exists by default will be applied at runtime. For a description of this usage of the view criteria, see Section 5.7.1, "How to Create Declarative SQL View Objects."


Because the UI component may not display sufficient attributes to cause a SQL JOIN for a view object with multiple entity objects defined in declarative SQL mode, named view criteria that you define to filter query results should be applied conditionally at runtime. In other words, named view criteria that you create for declarative SQL-based view objects need not be applied as required, automatic filters. To support declarative SQL mode, named view criteria that you apply to a view object created in declarative SQL mode can be set to apply only on the condition that the UI component is bound to the attributes referenced by the view criteria. The named view criteria once applied will, however, support the UI component's need to display a filtered result set.

Before you begin:

It may be helpful to have an understanding of SQL independence at runtime. For more information, see Section 5.7, "Working with View Objects in Declarative SQL Mode."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete these tasks:

To define a view criteria to filter only when the join is satisfied:

  1. In the Applications window, double-click the declarative SQL view object that supports table joins.

  2. In the overview editor, click the View Criteria navigation tab.

  3. In View Criteria page, select the view criteria you created to filter the declarative SQL view object.

    The join view criteria must refer only to attributes from the joined entity objects.

  4. In the Properties window, when you have selected one or more attributes from the joined entity objects, select true from the AppliedIfJoinSatisfied dropdown list.

    The property value true means you want the view criteria to be applied only on the condition that the UI component requires the attributes referenced by the view criteria. The default value false means that the view criteria will automatically be applied at runtime. In the case of declarative SQL mode-based view objects, the value true ensures that the query filter will be appropriate to needs of the view object's databound UI component.

5.7.3 How to Filter Master-Detail Related View Objects with Declarative SQL Mode

Just as with normal mode view objects, you can link view objects that you create in declarative SQL mode to other view objects to form master-detail hierarchies of any complexity. The steps to create the view links are the same as with any other entity-based view object, as described in Section 6.2.1, "How to Create a Master-Detail Hierarchy Based on Entity Associations." However, in the case of view objects that you create in declarative SQL mode, you can further refine the view object results in the Source SQL or Destination SQL dialog for the view link by selecting a previously defined view criteria in the Create View Link wizard or the overview editor for the view link.

Before you begin:

It may be helpful to have an understanding of SQL independence at runtime. For more information, see Section 5.7, "Working with View Objects in Declarative SQL Mode."

You may also find it helpful to understand functionality that can be added using other view object features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete these tasks:

  1. Create the master and detail view objects with declarative SQL mode enabled, as described in Section 5.7.1, "How to Create Declarative SQL View Objects."

  2. Define the desired view criteria for either the source (master) view object or the destination (detail) view object, as described in Section 5.7.2, "How to Filter Declarative SQL-Based View Objects When Table Joins Apply."

  3. Create the view link, as described in Section 6.2.1, "How to Create a Master-Detail Hierarchy Based on Entity Associations."

To filter a view link source or view link destination:

  1. In the Applications window, double-click the view link you created to form the master-detail hierarchy.

  2. In the overview editor, click the Query navigation tab.

  3. In the Query page, expand the Source or Destination section and from the View Criteria dropdown list, select the desired view criteria.

    The dropdown list will be empty if no view criteria exist for the view object.


    Tip:

    If the overview editor does not display a dropdown list for view criteria selection, then the view objects you selected for the view link were not created in declarative SQL mode. For view objects created in normal or expert mode, you must edit the WHERE clause to filter the data as required.


5.7.4 How to Support Programmatic Execution of Declarative SQL Mode View Objects

Typically, when you define a declarative SQL mode view object, the attributes that get queried at runtime will be determined by the requirements of the databound UI component as it is rendered in the web page. This is the runtime-generation capability that makes view objects independent of the design time database's SQL platform. However, you may also need to execute the view object programmatically without exposing it to an ADF data binding in the UI. In this case, you can enable the Include all attributes in runtime-generated query option to ensure that a programmatically executed view object has access to all of the entity attributes.


Note:

Be careful to limit the use of the Include all attributes in runtime-generated query option to programmatically executed view objects. If you expose the view object with this setting enabled to a databound UI component, the runtime query will include all attributes.


The Include all attributes in runtime-generated query option can be specified as a global preference setting or as a setting on individual view objects. Both settings may be used in these combinations:

  • Enable the global preference so that every view object you create includes all attributes in the runtime query statement.

  • Enable the global preference, but disable the setting on view objects that will not be executed programmatically and therefore should not include all attributes in the runtime query statement.

  • Disable the global preference (default), but enable the setting on view objects that will be executed programmatically and therefore should include all attributes in the runtime query statement.

5.7.4.1 Forcing Attribute Queries for All Declarative SQL Mode View Objects

You can enable the global preference to force attribute queries for all declarative SQL mode view objects as the default mode, or you can leave the option disabled and enable the option directly in the overview editor for a specific view object.

Before you begin:

It may be helpful to have an understanding of how the Include all attributes in runtime-generated query option supports programmatic execution of declarative SQL mode view objects. For more information, see Section 5.7.4, "How to Support Programmatic Execution of Declarative SQL Mode View Objects."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To set the global preference to include all attributes in the query: 

  1. In the main menu, choose Tools and then Preferences.

  2. In the Preferences dialog, expand ADF Business Components and select View Objects.

  3. In the ADF Business Components: View Object page, select Enable Declarative SQL mode for new objects.

  4. Select Include all attributes in runtime-generated query to force all attributes of the view object's underlying entity objects to participate in the query and click OK.

    Enabling this option sets a flag in the view object definition but you will still need to add entity object selections and entity object attribute selections to the view object definition.

5.7.4.2 Forcing Attribute Queries for Specific Declarative SQL Mode View Objects

When you want to force all attributes for a specific view object to participate in the view object query, you can specify this in the Tuning section of the General page of the overview editor. The overview editor only displays the Include all attributes in runtime-generated query option if you have created the view object in declarative SQL mode.

Before you begin: 

It may be helpful to have an understanding of how the Include all attributes in runtime-generated query option supports programmatic execution of declarative SQL mode view objects. For more information, see Section 5.7.4, "How to Support Programmatic Execution of Declarative SQL Mode View Objects."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:


Create the view object in the Create View Object wizard and be sure that you have enabled declarative SQL mode, as described in Section 5.7.1, "How to Create Declarative SQL View Objects."

To set the view object-specific preference to include all attributes in the query: 

  1. In the Applications window, double-click the declarative SQL view object.

  2. In the overview editor, click the General navigation tab.

    You can verify that the view object was created in declarative SQL mode in the overview editor. In the overview editor, click the Query navigation tab and then in the Query page, verify that the Mode dropdown list shows the selection Declarative.

  3. In the General page, expand the Tuning section and select Include all attributes in runtime-generated query.

    Enabling this option forces all attributes of the view object's underlying entity objects to participate in the query. When enabled, it sets a flag in the view object definition but you will still need to add entity object selections and entity object attribute selections to the view object definition.

5.7.5 What Happens When You Create a View Object in Declarative SQL Mode

When you create the view object in declarative SQL mode, three properties get added to the view object's metadata: SelectListFlags, FromListFlags, and WhereFlags. Properties that are absent in declarative SQL mode are the normal mode view object's SelectList, FromList, and Where properties, which contain the actual SQL statement (or, for expert mode, the SQLQuery element). Example 5-11 shows the three view object metadata flags that get enabled in declarative SQL mode to ensure that SQL will be generated at runtime instead of specified as metadata in the view object's definition.

Example 5-11 View Object Metadata with Declarative SQL Mode Enabled

<ViewObject
  xmlns="http://xmlns.oracle.com/bc4j"
  Name="CustomerCardStatus"
  SelectListFlags="1"
  FromListFlags="1"
  WhereFlags="1"
   ...

Similar to view objects that you create in either normal or expert mode, the view object metadata also includes a ViewAttribute element for each attribute that you select in the Attribute page of the Create View Object wizard. However, in declarative SQL mode, when you "select" attributes in the wizard (or add an attribute in the overview editor), you are not creating a FROM or SELECT list in the design time. The attribute definitions that appear in the view object metadata only determine the list of potential entities and attributes that will appear in the runtime-generated statements. For information about how ADF Business Components generates these SQL lists, see Section 5.7.6, "What Happens at Runtime: Declarative SQL Mode Queries."

Example 5-12 shows the additional features of declarative SQL mode view objects, including the optional declarative WHERE clause (DeclarativeWhereClause element) and the optional declarative ORDERBY clause (SortCriteria element).

Example 5-12 View Object Metadata: Declarative View Criteria and Sort Criteria

<DeclarativeWhereClause>
    <ViewCriteria
        Name="CustomerStatusWhereCriteria"
        ViewObjectName="oracle.summit.model.views.CustomerCardStatus"
        Conjunction="AND"
        Mode="3"
        AppliedIfJoinSatisfied="false">
        <ViewCriteriaRow
            Name="vcrow60">
            <ViewCriteriaItem
                Name="CardTypeCode"
                ViewAttribute="CardTypeCode"
                Operator="STARTSWITH"
                Conjunction="AND"
                Required="Optional">
            <ViewCriteriaItemValue
                Value=":cardtype"
                IsBindVarValue="true"/>
            </ViewCriteriaItem>
        </ViewCriteriaRow>
    </ViewCriteria>
    </DeclarativeWhereClause>
    <SortCriteria>
       <Sort
        Attribute="CustomerId"/>
       <Sort
        Attribute="CardTypeCode"/>
    </SortCriteria>

5.7.6 What Happens at Runtime: Declarative SQL Mode Queries

At runtime, when a declarative SQL mode query is generated, ADF Business Components determines which attributes were defined from the metadata ViewCriteria element and SortCriteria element. It then uses these attributes to generate the WHERE and ORDERBY clauses. Next, the runtime generates the FROM list based on the tables corresponding to the entity usages defined by the metadata ViewAttribute elements. Finally, the runtime builds the SELECT statement based on the attribute selection choices the end user makes in the UI. As a result, the view object in declarative SQL mode generates all SQL clauses entirely at runtime. The runtime-generated SQL statements will be based on the platform that appears in the project properties setting. Currently, the runtime supports SQL92 (ANSI) style and Oracle style platforms.

5.7.7 What You May Need to Know About Overriding Declarative SQL Mode Defaults

JDeveloper lets you control declarative SQL mode for all new view objects you add to your data model project or for individual view objects you create or edit. These settings may be used in these combinations:

  • Enable the global preference in the Preferences dialog (select Tools > Preferences). Every view object you create will delay SQL generation until runtime. Figure 5-23 shows the global preference Enable Declarative SQL for new objects set to enabled.

  • Enable the global preference in the Preferences dialog, but change the SQL mode for individual view objects. In this case, unless you change the SQL mode, the view objects you create will delay SQL generation until runtime.

  • Disable the global preference (default) in the Preferences dialog, but select declarative SQL mode for individual view objects. In this case, unless you change the SQL mode, view objects you create will contain SQL statements.

Figure 5-23 Preferences Dialog with Declarative SQL Mode Enabled

View object preferences dialog

To edit the SQL mode for a view object you have already created, open the Query page in the overview editor for the view object and select Declarative from the Mode dropdown list. The same option appears in the Query page of the Create View Object wizard.

5.7.8 What You May Need to Know About Working Programmatically with Declarative SQL Mode View Objects

As a convenience to developers, the view object implementation API allows individual attributes to be selected and deselected programmatically. This API may be useful in combination with the view objects you create in declarative SQL mode and intend to execute programmatically. Example 5-13 shows how to call selectAttributeDefs() on the view object when you want to add a subset of attributes to those already configured with SQL mode enabled.

Example 5-13 ViewObjectImpl API with SQL Mode View Objects

ApplicationModule am = Configuration.createRootApplicationModule(amDef, config);
ViewObjectImpl vo = (ViewObjectImpl) am.findViewObject("CustomerVO");
vo.resetSelectedAttributeDefs(false);
vo.selectAttributeDefs(new String[] {"FirstName, "LastName"});
vo.executeQuery();

The call to selectAttributeDefs() adds the attributes in the array to a private member variable of ViewObjectImpl. A call to executeQuery() transfers the attributes in the private member variable to the actual select list. It is important to understand that these ViewObjectImpl attribute calls are not applicable to the client layer and are only accessible inside the Impl class of the view object on the middle tier.

Additionally, you might call unselectAttributeDefs() on the view object when you want to deselect a small subset of attributes after enabling the Include all attributes in runtime-generated query option. Alternatively, you can call selectAttributeDefs() on the view object to select a small subset of attributes after disabling the Include all attributes in runtime-generated query option.


Caution:

Be careful not to expose a declarative SQL mode view object executed with this API to the UI since only the value of the Include all attributes in runtime-generated query option will be honored.


5.8 Working with View Objects in Expert Mode

When defining entity-based view objects in Normal mode, you can fully specify the WHERE and ORDER BY clauses, whereas, by default, the FROM clause and SELECT list are automatically derived. The names of the tables related to the participating entity usages determine the FROM clause, while the SELECT list is based on the:

When you require full control over the SELECT or FROM clause in a query, you can enable expert mode.


Tip:

The view object editors and wizard in the JDeveloper provide full support for generating SQL from choices that you make. For example, two such options allow you to declaratively define outer joins and work in declarative SQL mode (where no SQL is generated until runtime).


5.8.1 How to Create an Expert Mode View Object

When you need full control over the SQL statement, the Create View Object wizard lets you specify this using expert mode. Primarily, the expert-mode view object that you create will be useful when you need to write Unions or Group By queries. Additionally, you can create an expert-mode view object if you need to create SQL-based validation queries used by the view object-based Key Exists validator, provided that you have marked a key attribute.

For more information about the tradeoffs between working with entity-based view objects and expert-mode view objects that are not based on entity objects, see Section 9.2.2, "Consider Using Entity-Based View Objects for Read-Only Data."

To create a expert-mode view object, use the Create View Object wizard, which is available from the New Gallery.

Before you begin:

It may be helpful to have an understanding of view objects. For more information, see Section 5.2, "Populating View Object Rows from a Single Database Table."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To create an expert-mode view object:

  1. In the Applications window, right-click the package in which you want to create the view object and choose New and then View Object.

  2. If you have not yet created a database connection for the data model project, in the Initialize Business Components Project dialog, select the database connection or choose New to create a connection. Click OK.

    If this is the first component you're creating in the project, the Initialize Business Components Project dialog appears to allow you to select a database connection.

  3. In the Create View Object wizard, on the Name page, enter a package name and a view object name. Select SQL query to indicate that you want this view object to manage data without the benefit of entity objects. Click Next.

  4. On the Query page, use one of the following techniques:

    • Type or paste any valid SQL statement into the Select text box. The query statement can use a WHERE clause and an Order By clause. For example, Figure 5-24 shows a query statement that uses a WHERE clause and an Order By clause to query a list of country codes in the language used by the application.

    • Click Query Builder to open the SQL Statement dialog and build the query statement.

      Figure 5-24 Create View Object Wizard, Query Page

      Step 2 of the Create View Object wizard

      Note:

      If the Entity Objects page displays instead of the Query page, go back to Step 1 of the wizard and ensure that you've selected SQL query.


  5. After entering or building the query statement, click Next.

  6. On the Bind Variables page, do one of the following:

  7. On the Attribute Settings page, from the Select Attribute dropdown, select the attribute that corresponds to the primary key of the queried table and confirm that the Key Attribute checkbox is selected.

    The Create View Object wizard auto-detects key attributes from the database and enables the Key Attribute checkbox, as shown in Figure 5-25. Failure to define the key attribute can result in unexpected runtime behavior for ADF Faces components with a data control based on the view object collection.

    Figure 5-25 Create View Object Wizard, Attribute Settings Page

    Step 6 of the Create View Object wizard
  8. Click Finish.


Note:

In the ADF Business Components wizards and editors, the default convention is to use camel-capped attribute names, beginning with a capital letter and using uppercase letters in the middle of the name to improve readability when the name comprises multiple words.


5.8.2 What Happens When You Create an Expert-Mode View Object

When you create a view object using expert mode, JDeveloper first parses the query to infer the following from the columns in the SELECT list:

  • The Java-friendly view attribute names (for example, CountryName instead of COUNTRY_NAME)

    By default, the wizard creates Java-friendly view object attribute names that correspond to the SELECT list column names, as shown in Figure 5-26.

    For information about using view object attribute names to access the data from any row in the view object's result set by name, see Section 8.4, "Testing View Object Instances Programmatically."

  • The SQL and Java data types of each attribute

Figure 5-26 Create View Object Wizard, Attribute Mappings Page

Step 4 of the Create View Object wizard

Each part of an underscore-separated column name like SOME_COLUMN_NAME is turned into a camel-capped word (like SomeColumnName) in the attribute name. While the view object attribute names correspond to the underlying query columns in the SELECT list, the attribute names at the view object level need not match necessarily.


Tip:

You can rename the view object attributes to any names that might be more appropriate without changing the underlying query.


JDeveloper then creates the XML document file that represents the view object's declarative settings and saves it in the directory that corresponds to the name of its package. For example, the XML file created for a view object named CountriesVO in the lookups package is ./lookups/CountriesVO.xml under the project's source path.

To view the view object settings, select the desired view object in the Applications window and open the Structure window. The Structure window displays the list of XML definitions, including the SQL query and the list of attributes. To open the XML definition in the editor, right-click the corresponding node and choose Go to Source.

5.8.3 How to Customize SQL Statements in Expert Mode

To enable expert mode, select Expert from the Mode dropdown list on the Query page of the Create View Object wizard. You can also modify the SQL statement of an existing entity-based view object in the view object overview editor. In the overview editor, navigate to the Query page and select Expert from the Mode dropdown list.

5.8.4 What Happens When You Enable Expert Mode

When you enable expert mode, the Select text box in the Query page of the overview editor or wizard becomes fully editable, displaying the full SQL statement. Using this text box, you can change every aspect of the SQL query.

While you can add the ORDER BY clause directly to the Select text box when you are in expert mode, it is still useful to keep the ORDER BY portion of the clause separate, since the runtime engine might need to append additional WHERE clauses to the query. Keeping the ORDER BY clauses separated will ensure they are applied correctly.

5.8.5 What You May Need to Know About Expert Mode

When you define a SQL query using expert mode, you type a SQL language statement directly into the editor. Using this mode places some responsibility on the Business Components developer to understand how the view object handles the metadata resulting from the query definition. Review the following information to familiarize yourself with the behavior of editing queries that you create in expert mode.

5.8.5.1 Attribute Names for Calculated Expressions in Expert Mode

If your SQL query includes a calculated expression, use a SQL alias to assist the Create View Object wizard in naming the column with a Java-friendly name. Example 5-14 shows a SQL query that includes a calculated expression.

Example 5-14 SQL Query with Calculated Expression

select CUSTOMER_ID, EMAIL, 
       SUBSTR(FIRST_NAME,1,1)||'. '||LAST_NAME
from CUSTOMERS
order by EMAIL

Example 5-15 uses a SQL alias USER_SHORT_NAME to assist the Create View Object wizard in naming the column with a Java-friendly name. The wizard will display UserShortName as the name of the attribute derived from this calculated expression.

Example 5-15 SQL Query with SQL Alias

select CUSTOMER_ID, EMAIL, 
       SUBSTR(FIRST_NAME,1,1)||'. '||LAST_NAME AS USER_SHORT_NAME
from CUSTOMERS
order by EMAIL

5.8.5.2 Attribute Mapping Assistance in Expert Mode

The automatic cooperation of a view object with its underlying entity objects depends on correct attribute-mapping metadata saved in the XML document. This information relates the view object attributes to corresponding attributes from participating entity usages. JDeveloper maintains this attribute mapping information in a fully automatic way for normal entity-based view objects. However, when you decide to use expert mode with a view object, you need to pay attention to the changes you make to the SELECT list. That is the part of the SQL query that directly relates to the attribute mapping. Even in expert mode, JDeveloper continues to offer some assistance in maintaining the attribute mapping metadata when you do the following to the SELECT list:

  • Reorder an expression without changing its column alias

    JDeveloper reorders the corresponding view object attribute and maintains the attribute mapping.

  • Add a new expression

    JDeveloper adds a new SQL-calculated view object attribute with a corresponding camel-capped name based on the column alias of the new expression.

  • Remove an expression

    JDeveloper converts the corresponding SQL-calculated or entity-mapped attribute related to that expression to a transient attribute.

However, if you rename a column alias in the SELECT list, JDeveloper has no way to detect this, so it is treated as if you removed the old column expression and added a new one of a different name.

After making any changes to the SELECT list of the query, visit the Attribute Mappings page of the overview editor to ensure that the attribute-mapping metadata is correct. The table on this page, which is disabled for view objects in normal mode, becomes enabled for expert mode view objects. For each view object attribute, you will see its corresponding SQL column alias in the table. By clicking into a cell in the View Attributes column, you can use the dropdown list that appears to select the appropriate entity object attribute to which any entity-mapped view attributes should correspond.


Note:

If the view attribute is SQL-calculated or transient, a corresponding attribute with a "SQL" icon appears in the View Attributes column to represent it. Since neither of these type of attributes are related to underlying entity objects, no entity attribute related information is required for them.


5.8.5.3 Custom Edits in Expert Mode

When you disable expert mode for a view object, it will return to having its SELECT and FROM clause be derived again. JDeveloper warns you that doing this might cause your custom edits to the SQL statement to be lost. If this is what you want, after acknowledging the alert, your view object's SQL query reverts back to the default.

5.8.5.4 Changes to SQL Expressions in Expert Mode

Consider a Products view object with a SQL-calculated attribute named Shortens whose SQL expression you defined as SUBSTR(NAME,1,10). If you switch this view object to expert mode, the Select text box will show a SQL query similar to the one shown in Example 5-16.

Example 5-16 SQL-Calculated Attribute Expression in Expert Mode

SELECT Products.PROD_ID, 
       Products.NAME, 
       Products.IMAGE, 
       Products.DESCRIPTION, 
       SUBSTR(NAME,1,10) AS SHORT_NAME
FROM PRODUCTS Products

If you go back to the attribute definition for the Shortens attribute and change the SQL Expression field from SUBSTR(NAME,1,10) to SUBSTR(NAME,1,15), then the change will be saved in the view object's XML document. Note, however, that the SQL query in the Select text box will remain as the original expression. This occurs because JDeveloper never tries to modify the text of an expert mode query. In expert mode, the developer is in full control. JDeveloper attempts to adjust metadata as a result of some kinds of changes you make yourself to the expert mode SQL statement, but it does not perform the reverse. Therefore, if you change view object metadata, the expert mode SQL statement is not updated to reflect it.

Therefore, you need to update the expression in the expert mode SQL statement itself. To be completely thorough, you should make the change both in the attribute metadata and in the expert mode SQL statement. This would ensure — if you (or another developer on your team) ever decides to toggle expert mode off at a later point in time — that the automatically derived SELECT list would contain the correct SQL-derived expression.


Note:

If you find you had to make numerous changes to the view object metadata of an expert mode view object, you can avoid having to manually translate any effects to the SQL statement by copying the text of your customized query to a temporary backup file. Then, you can disable expert mode for the view object and acknowledge the warning that you will lose your changes. At this point JDeveloper will rederive the correct generated SQL statement based on all the new metadata changes you've made. Finally, you can enable expert mode once again and reapply your SQL customizations.


5.8.5.5 SQL Calculations that Change Entity Attributes in Expert Mode

If you need to present altered versions of entity-mapped attribute data, you must introduce a new SQL-calculated attribute with the appropriate expression to handle the task. In expert mode, when editing the SELECT list expression that corresponds to entity-mapped attributes, you must not introduce SQL calculations into SQL statements that change the value of the attribute when retrieving the data.

To illustrate the problem that will occur if you introduce SQL calculations into SQL statements, consider the query for a simple entity-based view object named Products shown in Example 5-17.

Example 5-17 Query Statement Without SQL-Calculated Expression

SELECT Products.PROD_ID, 
       Products.NAME, 
       Products.IMAGE, 
       Products.DESCRIPTION
FROM PRODUCTS Products

Imagine that you wanted to limit the name column to display only the first ten characters of the name of a product query. The correct way to do that would be to introduce a new SQL-calculated field, such as ShortName with an expression like SUBSTR(Products.NAME,1,10). One way you should avoid doing this is to switch the view object to expert mode and change the SELECT list expression for the entity-mapped NAME column to the include the SQL-calculate expression, as shown in Example 5-18.

Example 5-18 Query Statement with SQL-Calculated Expression

SELECT Products.PROD_ID, 
       SUBSTR(Products.NAME,1,10) AS NAME, 
       Products.IMAGE, 
       Products.DESCRIPTION
FROM PRODUCTS Products

This alternative strategy would initially appear to work. At runtime, you see the truncated value of the name as you are expecting. However, if you modify the row, when the underlying entity object attempts to lock the row it does the following:

  • Issues a SELECT FOR UPDATE statement, retrieving all columns as it tries to lock the row.

  • If the entity object successfully locks the row, it compares the original values of all the persistent attributes in the entity cache as they were last retrieved from the database with the values of those attributes just retrieved from the database during the lock operation.

  • If any of the values differs, then the following error is thrown:

    (oracle.jbo.RowInconsistentException) 
    JBO-25014: Another user has changed the row with primary key [...]
    

If you see an error like this at runtime even though you are the only user testing the system, it is most likely due to your inadvertently introducing a SQL function in your expert mode view object that changed the selected value of an entity-mapped attribute. In Example 5-18, the SUBSTR(Products.NAME,1,10) function introduced causes the original selected value of the Name attribute to be truncated. When the row-lock SQL statement selects the value of the NAME column, it will select the entire value. This will cause the comparison shown in Example 5-18 to fail, producing the "phantom" error that another user has changed the row.

The same thing would happen with NUMBER-valued or DATE-valued attributes if you inadvertently apply SQL functions in expert mode to truncate or alter their retrieved values for entity-mapped attributes.

5.8.5.6 Formatting of the SQL Statement in Expert Mode

When you change a view object to expert mode, its XML document changes from storing parts of the query in separate XML attributes, to saving the entire query in a single <SQLQuery> element. The query is wrapped in an XML CDATA section to preserve the line formatting you may have done to make a complex query be easier to understand.

5.8.5.7 Query Clauses in Expert Mode

If your expert-mode view object:

  • Contains a ORDERBY clause specified in the Order By field of the Query page of the overview editor at design time, or

  • Has a dynamic WHERE clause or ORDERBY clause applied at runtime using setWhereClause() or setOrderByClause()

Then its query gets nested into an inline view before applying these clauses. For example, suppose your expert mode query was defined like the one shown in Example 5-19.

Example 5-19 Expert Mode Query Specified At Design Time

select CUSTOMER_ID, EMAIL, FIRST_NAME, LAST_NAME
from CUSTOMERS 
union all
select CUSTOMER_ID, EMAIL, FIRST_NAME, LAST_NAME
from INACTIVE_CUSTOMERS

Then, at runtime, when you set an additional WHERE clause like email = :TheUserEmail, the view object nests its original query into an inline view like the one shown in Example 5-20.

Example 5-20 Runtime-Generated Query with Inline Nested Query

SELECT * FROM(
select CUSTOMER_ID, EMAIL, FIRST_NAME, LAST_NAME
from CUSTOMERS 
union all
select CUSTOMER_ID, EMAIL, FIRST_NAME, LAST_NAME
from INACTIVE_CUSTOMERS) QRSLT

And, the view object adds the dynamic WHERE clause predicate at the end, so that the final query the database sees looks like the one shown in Example 5-21.

Example 5-21 Runtime-Generated Query with Dynamic WHERE Clause

SELECT * FROM(
select CUSTOMER_ID, EMAIL, FIRST_NAME, LAST_NAME
from CUSTOMERS 
union all
select CUSTOMER_ID, EMAIL, FIRST_NAME, LAST_NAME
from INACTIVE_CUSTOMERS) QRSLT
WHERE email = :TheUserEmail

This query "wrapping" is necessary in general for expert mode queries, because the original query could be arbitrarily complex, including SQL UNION, INTERSECT, MINUS, or other operators that combine multiple queries into a single result. In those cases, simply "gluing" the additional runtime WHERE clause onto the end of the query text could produce unexpected results. For example, the clause might apply only to the last of several UNION'ed statements. By nesting the original query verbatim into an inline view, the view object guarantees that your additional WHERE clause is correctly used to filter the results of the original query, regardless of how complex it is.

5.8.5.8 Inline View Wrapping at Runtime

Inline view wrapping of expert mode view objects, limits a dynamically added WHERE clause to refer only to columns in the SELECT list of the original query. To avoid this limitation, when necessary you can disable the use of the inline view wrapping by calling setNestedSelectForFullSql(false).

5.8.5.9 Expert Mode Affect on Dependent Objects

When you modify a view object query to be in expert mode after you have already created the view links that involve that view object or after you created other view objects that extend the view object, JDeveloper will warn you with the alert shown in Figure 5-27. The alert reminds you that you should revisit these dependent components to ensure their SQL statements still reflect the correct query.

Figure 5-27 Proactive Reminder to Revisit Dependent Components

Dependent components dialog reminder

For example, if you were to modify the OrdersVO view object to use expert mode, because the OrdersByStatusVO view object extends it, you need to revisit the extended component to ensure that its query still logically reflects an extension of the modified parent component.

5.8.5.10 SQL Types of Attributes in Expert Mode

JDeveloper tries to infer the SQL type of the mapped column for view object attributes that you create in expert mode automatically. The Type property of the attribute records the SQL type of the column, including the length information for VARCHAR2 columns and the precision and scale information for NUMBER columns. However, for some SQL expressions the inferred value might default to VARCHAR2(255).

You can update the Type value for this type of attribute to reflect the correct length if you know it. For example, VARCHAR2(20) which shows as the Type for the State attribute in Figure 5-28 means that it has a maximum length of 20 characters. For a NUMBER column, you would indicate a Type of NUMBER(7,2) for an attribute that you want to have a precision of 7 digits and a scale of 2 digits after the decimal.


Performance Tip:

Your SQL expression can control how long the describe from the database says the column is. Use the SUBSTR() function around the existing expression. For example, if you specify SUBSTR(yourexpression, 1, 15), then the describe from the database will inform JDeveloper that the column has a maximum length of 15 characters.


Figure 5-28 Custom Attribute Settings in the Details Section of SQL-Derived Attributes

Attribute details section displays custom attribute

In the case of entity-based view objects, you must edit the Type property in the Details section of the Attributes page of the overview editor that you display for the entity object, as described in Section 4.10.2, "How to Indicate Data Type Length, Precision, and Scale."

5.9 Working with Named View Criteria

A view criteria you define lets you specify filter information for the rows of a view object collection. The view criteria object is a row set of one or more view criteria groups, whose attributes mirror those in the view object. The view criteria definition comprises query conditions that augment the WHERE clause of the target view object. However, unlike the WHERE clause defined by the view object query statement, which applies to all instances of the view object, the view criteria query condition is added to specific view object instances. This allows you to create specific usages of the target view object definition using query conditions that apply to the individual attributes of the target view object.

View criteria definitions support Query-by-Example operators and therefore allows the user to enter conditions such as "OrderId > 304", for example.

The Edit View Criteria dialog lets you create view criteria and save them as part of the view object's definition, where they appear as named view criteria. You use the View Criteria page of the overview editor to define view criteria for specific view objects. View criteria that you define at design time can participate in these scenarios where filtering results is desired at runtime:

Additionally, view criteria have full API support, and it is therefore possible to create and apply view criteria to view objects programmatically.

5.9.1 How to Create Named View Criteria Declaratively

View criteria have a number of uses in addition to applying them to declarative queries at runtime. In all usages, the named view criteria definition consists of a set of attribute requirements that you specify to filter individual view object results. The features of the view criteria definition that you can use will depend on its intended usage.

To define view criteria for the view object you wish to filter, you open the view object in the overview editor and click the Create button in the View Criteria page. A dedicated editor (the Create View Criteria dialog) helps you to build a WHERE clause using attribute names instead of the target view object's corresponding SQL column names. You may define multiple named view criteria for each view object.

Before you work with the Create View Criteria dialog to create named view criteria, familiarize yourself with the usages described in Section 5.9, "Working with Named View Criteria." The chapter references provide additional details that will help you to anticipate using the appropriate features of the Create View Criteria dialog. For example, when you create a view criteria to specify the searchable attributes of a search form, the view criteria condition defines a simple list of attributes (a subset of the view object's attributes) to be presented to the user, but then the view criteria definition requires that you specify UI hints (model-level properties) to control the behavior of those attributes in the search form. The Create View Criteria dialog displays all the UI hints in a separate tabbed page that you select for the view criteria you are defining. Whereas, when your view criteria is intended to specify view instances in the data model, you can define arbitrarily complex query filter conditions, but you can ignore the UI hints features displayed by the Create View Criteria dialog.

Each view criteria definition consists of the following elements:

  • An arbitrary number of view criteria groups or an arbitrary number of references to another named view criteria already defined for the current view object.

  • An arbitrary number of view criteria items (grouped by view criteria groups) consisting of an attribute name, an attribute-appropriate operator, and an operand. Operands can be a literal value when the filter value is defined or a bind variable that can optionally utilize a scripting expression that includes dot notation access to attribute property values.

    Expressions are based on the Groovy scripting language, as described in Section 3.5.6, "How to Use Groovy Scripting Language With Business Components."

When you define a view criteria, you control the source of the filtered results. You can limit the results of the filtered view object to:

  • Just the database query results.

  • Just the in-memory results of the view object query. For example, new rows added by the user.

  • Both the database and the in-memory results of the view object query.

Filtering on both database tables and the view object's in-memory results allows you to filter rows that were created in the transaction but not yet committed to the database.

View criteria expressions you construct in the Edit View Criteria dialog use logical conjunctions to specify how to join the selected criteria item or criteria group with the previous item or group in the expression:

  • AND conjunctions specify that the query results meet both joined conditions. This is the default for each view criteria item you add.

  • OR conjunctions specify that the query results meet either or both joined conditions. This is the default for view criteria groups.

Additionally, you may create nested view criteria when you want to filter rows in the current view object based on criteria applied to view-linked detail views. A nested view criteria group consists of an arbitrary number of nested view criteria items. You can use nested view criteria when you want to have more controls over the logical conjunctions among the various view criteria items. The nested criteria place restrictions on the rows that satisfy the criteria under the nested criteria's parent view criteria group. For example, you might want to query both a list of employees with (Salary > 3000) and belonging to (DeptNo = 10 or DeptNo = 20). You can define a view criteria with the first group with one item for (Salary > 3000) and a nested view criteria with the second group with two items DeptNo = 10 and DeptNo =20.

Before you begin:

It may be helpful to have an understanding of the ways you can use view criteria. The usage you intend will affect the best practices for creating named view criteria. For more information about the supported usages, see Section 5.9, "Working with Named View Criteria."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete these tasks:

To define a named view criteria:

  1. In the Applications window, double-click the view object for which you want to create the named view criteria.

  2. In the overview editor, click the View Criteria navigation tab and then click the Create New View Criteria button.

  3. In the Create View Criteria dialog, enter the name of the view criteria to identify its usage in your application.

  4. In the Query Execution Mode dropdown list, decide how you want the view criteria to filter the view object query results.

    You can limit the view criteria to filter the database table specified by the view object query, the in memory row set produced by the query, or both the database table and the in-memory results.

    Choosing Both may be appropriate for situations where you want to include rows created as a result of enforced view link consistency. In this case, in-memory filtering is performed after the initial fetch. For details about view link consistency, see Section 9.1.2, "Maintaining New Row Consistency in View Objects Based on the Same Entity."

  5. In the Criteria Definition tab, click one of these Add buttons to define the view criteria.

    • Add Item to add a single criteria item. The editor will add the item to the hierarchy beneath the current group or view criteria selection. By default each time you add an item, the editor will choose the next attribute to define the criteria item. You can change the attribute to any attribute that the view object query defines.

    • Add Group to add a new group that will compose criteria items that you intend to add to it. When you add a new group, the editor inserts the OR conjunction into the hierarchy. You can change the conjunction as desired.

    • Add Criteria to add a view criteria that you intend to define. This selection is an alternative to adding a named criteria that already exists in the view object definition. When you add a new view criteria, the editor inserts the AND conjunction into the hierarchy. You can change the conjunction as desired. Each time you add another view criteria, the editor nests the new view criteria beneath the current view criteria selection in the hierarchy. The root node of the hierarchy defines the named view criteria that you are currently editing.

      Search forms that the UI designer will create from view criteria are not able to use directly nested view criteria. For more information about defining nested expressions for use with search forms, see Section 5.9.4, "What You May Need to Know About Nested View Criteria Expressions."

    • Add Named Criteria to add a view criteria that the view object defines. The named criteria must appear in the overview editor for the view object you are defining the view criteria.

  6. Select a view criteria item node in the view criteria hierarchy and define the added node in the Criteria Item section.

    • Choose the desired Attribute for the criteria item. By default the editor adds the first one in the list.

      Optionally, you can add a nested view criteria inline when a view link exists for the current view object you are editing. The destination view object name will appear in the Attribute dropdown list. Selecting a view object lets you filter the view criteria based on view criteria items for the nested view criteria based on a view link relationship. For example, EmpVO is linked to the PaymentOptionsVO and a view criteria definition for PaymentOptionsVO will display the destination view object AddressVO. You could define the nested view criteria to filter payment options based on the CountryId attribute of the current customer, as specified by the CustomerId criteria item, as shown in Figure 5-29.

      Figure 5-29 Edit View Criteria Dialog with Nested View Criteria Specified

      Edit View Criteria dialog displays view criteria definition
    • Choose the desired Operator.

      The list displays only the operators that are appropriate for the selected attribute or view object. In the case of a view object selection, the exists operator applies to a view criteria that you will define (or reference) as an operand. In the case of String and Date type attributes, the Between and Not between operators require you to supply two operand values to define the range. In the case of Date type attributes, you can select operators that test for a date or date range (with date values entered in the format YYYY-MM-DD). For example, for December 16th, 2010, enter 2010-12-16.

      JDeveloper does not support the IN operator. However, you can create a view criteria with the IN operator using the API, as described in Section 5.9.8, "How to Create View Criteria Programmatically."

  7. Choose the desired Operand for the view criteria item selection.

    • Select Literal when you want to supply a value for the attribute or when you want to define a default value for a user-specified search field for a Query-by-Example search form. When the view criteria defines a query search form for the user interface, you may leave the Value field empty. In this case, the user will supply the value. You may also provide a value that will act as a search field default value that the user will be able to override. The value you supply in the Value field can include wildcard characters * or %.

    • Select Bind Variable when you want the value to be determined at runtime using a bind variable. If the variable was already defined for the view criteria, select it from the Parameter dropdown list. Otherwise, click New to display the New Variable dialog that lets you name a new bind variable on the view criteria.

      When you select an existing bind variable from the dropdown list for use by the view criteria, you will be able to select bind variables that have been defined for the view object query or for the view criteria. The difference between these two sets of bind variables is that query bind variables (ones that you define in the Query page of the overview editor) are typically used within the view object query statement and therefore support different validation use cases than view criteria-defined bind variables. For view criteria, typically you always select a bind variable that is defined in the View Criteria page of the overview editor.

      For further discussion about view criteria use cases for bind variables and literals, see Section 5.9.3, "What You May Need to Know About Bind Variables in View Criteria."

  8. For each item, group, or nested view criteria that you define, optionally change the default conjunction to specify how the selection should be joined.

    • AND conjunction specifies that the query results meet both joined conditions. This is the default for each view criteria item or view nested view criteria that you add.

    • OR conjunction specifies that the query results meet either or both joined conditions. This is the default for view criteria groups.

  9. Verify that the view criteria definition is valid by doing one of the following:

    • Click Explain Plan to visually inspect the view criteria's generated WHERE clause.

    • Click Test to allow JDeveloper to verify that the WHERE clause is valid.

  10. To disable case-sensitive filtering of the attribute based on the case of the runtime-supplied value, leave Ignore Case selected.

    The criteria item can be a literal value that you define or a runtime parameter that the end user supplies. This option is supported for attributes of type String only. The default disables case sensitive searches.

  11. In the Validation dropdown list, decide whether the view criteria item is a required or an optional part of the attribute value comparison in the generated WHERE clause.

    • Selectively Required means that the WHERE clause will ignore the view criteria item at runtime if no value is supplied and there exists at least one criteria item in the same view criteria group that has a criteria value. Otherwise, an exception is thrown.

    • Optional means the view criteria (or search field) is added to the WHERE clause only if the value is non-NULL. The default Optional for each new view criteria item means no exception will be generated for null values.

    • Required means that the WHERE clause will fail to execute and an exception will be thrown when no value is supplied for the criteria item.

  12. If the view criteria uses a bind variable as the operand, decide whether the IS NULL condition is the generated in the WHERE clause. This field is enabled only if you have selected Optional for the validation of the bind variable.

    • Leave Ignore Null Values selected (default) when you want to permit the view criteria to return a result even when the bind variable value is not supplied at runtime. For example, suppose you define a view criteria to allow users to display a cascading list of countries and states (or provinces) through a bind variable that takes the countryID as the child list's controlling attribute. In this case, the default behavior for the view criteria execution returns the list of all states if the user makes no selection in the parent LOV (an empty countryId field). The generated WHERE clause would look similar to (((CountryEO.COUNTRY_ID =:bvCountryId) OR (:bvCountryId IS NULL))), where the test for a null value guarantees that the child list displays a result even when the bind variable is not set. When validation is set to Required or Selectively Required, the view criteria expects to receive a value and thus this option to ignore null values is disabled.

    • Deselect Ignore Null Values when you expect the view criteria to return a null result when the bind variable value is not supplied at runtime. In the example of the cascading lists, the view criteria execution returns no states if the user makes no selection with an empty countryID field. In this case, the generated WHERE clause would look similar to ((CountryEO.COUNTRY_ID=:bvCountryId)), where the test for null is not performed, which means the query is expected to function correctly with a null value bind variable. Note that the combination of optional validation with null values is only possible for bind variables that are required. Required bind variables are those defined in the Query page of the overview editor and used in the query WHERE clause.

      Note that the validation settings Required or Selectively Required also remove the null value condition but can be used in combination with a deselected Ignore Null Values setting to support a different use case. For more details about the interaction of these settings, see Section 5.9.3, "What You May Need to Know About Bind Variables in View Criteria."

  13. Click OK.

  14. If any of the view criteria conditions you defined reference a bind variable, then in the View Criteria page, select the bind variable and then in the Details section, click the Value tab and optionally specify a default value for the bind variable:

    • When you want the value to be determined at runtime using an expression, enter a Groovy scripting language expression, select the Expression value type and enter the expression in the Value field.

    • When you want to define a default value, select the Literal value type and enter the literal value in the Value field.

  15. Leave Updatable selected when you want the bind variable value to be defined through the user interface.

    The Updatable checkbox controls whether the end user will be allowed to change the bind variable value through the user interface. If a bind variable is not updatable (it may not be changed either programmatically or by the end user), deselect Updatable.

  16. In the View Criteria page, click the UI Hints tab and specify hints like Label, Format Type, Format mask, and others.

    The view layer will use bind variable UI hints when you build user interfaces like search pages that allow the user to enter values for the named bind variables. Note that formats are only supported for bind variables defined by the Date type or any numeric data type.

  17. If you created bind variables that you do not intend to reference in the view criteria definition, select the bind variable and click the Delete button.

    Confirm that your bind variable has been named in the view criteria by moving your cursor over the bind variable name field, as shown in Figure 5-30. JDeveloper identifies unreferenced bind variables by displaying the name field with an orange border.

    Figure 5-30 Orange Border Reminds to Reference the Bind Variable

    Unreference bind variable displays orange border

5.9.2 What Happens When You Create a Named View Criteria

The Create View Criteria dialog in JDeveloper lets you easily create view criteria and save them as named definitions. These named view criteria definitions add metadata to the XML document file that represents the target view object's declarative settings. Once defined, named view criteria appear by name in the View Criteria page of the overview editor for the view object.

To view the view criteria, expand the desired view object in the Applications window, select the XML file under the expanded view object, open the Structure window, and expand the View Criteria node. Each view criteria definition for a view object contains one or more <ViewCriteriaRow> elements corresponding to the number of groups that you define in the Create View Criteria dialog. Example 5-22 shows the ProductsVO.xml file with the <ViewCriteria> definition FindByProductNameCriteria and a single <ViewCriteriaRow> that defines a developer-defined search form for products using the bind variable :bvProductName. Any UI hints that you selected to customize the behavior of a developer-defined search from will appear in the <ViewCriteria> definition as attributes of the <CustomProperties> element. For details about specific UI hints for view criteria, see Section 5.9.5, "How to Set User Interface Hints on View Criteria to Support Search Forms."

Example 5-22 FindByProductNameCriteria View Criteria in the ProductsVO View Object Definition

<ViewObject
    xmlns="http://xmlns.oracle.com/bc4j"
    Name="ProductsVO"
    ... >
  <SQLQuery>
    ...
  </SQLQuery>
  ...
  <ViewCriteria
    Name="FindByProductNameCriteria"
    ViewObjectName="oracle.summit.model.views.ProductsVO"
    Conjunction="AND">
    <Properties>
      <CustomProperties>
        <Property
          Name="mode"
          Value="Basic"/>
        <Property
          Name="autoExecute"
          Value="false"/>
        <Property
          Name="showInList"
          Value="true"/>
        <Property
          Name="displayName"
          Value="Find Products By Name"/>
        <Property
          Name="displayOperators"
          Value="InAdvancedMode"/>
        <Property
          Name="allowConjunctionOverride"
          Value="true"/>
      </CustomProperties>
    </Properties>
    <ViewCriteriaRow
      Name="vcrow87">
      <ViewCriteriaItem
        Name="ProductName"
        ViewAttribute="ProductName"
        Operator="CONTAINS"
        Conjunction="AND"
        Value=":bvProductName"
        UpperColumns="1"
        IsBindVarValue="true"
        Required="Optional"/>
    </ViewCriteriaRow>
  </ViewCriteria>
  ...
</ViewObject>

Additionally, when you create view objects and specify them as instances in an application module, JDeveloper automatically creates a data control to encapsulate the collections (view instances) that the application module contains. JDeveloper then populates the Data Controls panel with these collections and any view criteria that you have defined, as shown in Section 17.3.1.3, "How View Objects Appear in the Data Controls Panel."

5.9.3 What You May Need to Know About Bind Variables in View Criteria

The view criteria filter that you define using a bind variable expects to obtain its value at runtime. This can be helpful in a variety of user interface scenarios. To support a particular use case, familiarize yourself with the combination of the Validation and Ignore Null Values settings shown in Table 5-1.

Table 5-1 Use Cases for Bind Variable Options in View Criteria

ValidationIgnore Null ValuesUse CasesNotes

Optional

True (Default)

Configure cascading List of Values (LOV) where the parent LOV value is optional.

Generate an optional search field in a search form.

This combination generates the SQL query (ProductName = :bind) OR (:bind IS NULL).

When used for cascading LOVs, no selection in the parent LOV returns all rows in the child LOV.

To ensure that all rows are not returned prior to executing a search, a view criteria item with a literal operand (not a bind variable) type is preferred. When a bind variable on a view criteria with optional validation usage is not resolved, the result will be all rows returned.

Optional

False (must select a required bind variable that has been defined in a query WHERE clause to achieve this combination)

Configure cascading LOVs where the parent LOV value is required.

This combination generates the SQL query (ProductName = :bind).

When used for cascading LOVs, no selection in the parent LOV returns no rows in the child LOV.

Avoid this combination for search forms, because when the user leaves the search field blank the search will attempt to find rows where this field is explicitly NULL. A better way to achieve this is for the user to explicitly select the "IS NULL" operator in advanced search mode.

Required

False (default and cannot be modified for this combination)

Generate a required search field in a search form.

This combination generates the SQL query ProductName = :bind.

Avoid this setting for cascading LOVs, because no selection in the parent LOV will cause a validation error.

To ensure that a non-NULL search result exists prior to executing a search, a view criteria item with a literal operand (not a bind variable) type is preferred. When a bind variable on a view criteria with required validation usage is not resolved, the result will be no rows returned.


5.9.4 What You May Need to Know About Nested View Criteria Expressions

Search forms that the UI designer will create from view criteria are not able to work with all types of nested expressions. Specifically, search forms do not support expressions with directly nested view criteria. This type of nested expression defines one view criteria as a direct child of another view criteria. Query search forms do support nested expressions where you nest the view criteria as a child of a criteria item which is itself a child of a view criteria. For more information about using view criteria to create search forms, see Section 33.1.1, "Implicit and Named View Criteria."

5.9.5 How to Set User Interface Hints on View Criteria to Support Search Forms

Named view criteria that you create for view object collections can be used by the web page designer to create Query-by-Example search forms. Web page designers select your named view criteria from the JDeveloper Data Controls panel to create search forms for the Fusion web application. In the web page, the search form utilizes an ADF Faces query search component that will be bound initially to the named view criteria selected in the Data Controls panel. At runtime, the end user may select among all other named view criteria that appear in the Data Controls panel. Named view criteria that the end user can select in a search form are known as developer-defined system searches. The query component automatically displays these system searches in its Saved Search dropdown list. For more information about creating search forms and using the ADF query search component, see Section 33.2, "Creating Query Search Forms."


Note:

By default, any named view criteria you create in the Edit View Criteria dialog will appear in the Data Controls panel. As long as the Show In List option appears selected in the UI Hints page of the Edit View Criteria dialog, JDeveloper assumes that the named view criteria should be available as a developer-defined system search. When you want to create a named view criteria that you do not want the end user to see in search forms, deselect the Show In List option in the dialog. For example, you might create a named view criteria only for an LOV-enabled attribute and so you would need to deselect Show In List.


Because developer-defined system searches are created in the data model project, the UI Hints page of the Edit View Criteria dialog lets you specify the default properties for the query component's runtime usage of individual named view criteria. At runtime, the query component's behavior will conform to the selections you make for the following system search properties:

Search Region Mode: Select the mode that you want the query component to display the system search as. The Basic mode has all features of Advanced mode, except that it does not allow the end user to dynamically modify the displayed search criteria fields. The default is Basic mode for a view criteria you define in the Edit View Criteria dialog.

Query Automatically: Select when you want the query associated with the named view criteria to be executed and the results displayed in the web page. Any developer-defined system search with this option enabled will automatically be executed when the end user selects it from the query component's Saved Search list. Deselect when the web page designer prefers not to update the previously displayed results until the end user submits the search criteria values on the form. Additionally, when a search form is invoked from a task flow, the search form will appear empty when this option is deselected and populated when enabled. By default, this option is disabled for a view criteria you define in the Edit View Criteria dialog.

Show Operators: Determine how you want the query component to display the operator selection field for the view criteria items to the end user. For example, select Always when you want to allow the end user to customize the operators for criteria items (in either basic or advanced modes) or select Never when you want the view criteria to be executed using the operators it defines. Note that although search forms display any bind variables used in the query WHERE clause as search criteria, this setting does not support displaying the operators associated with these bind variable expressions.

Show Match All and Match Any: Select to allow the query component to display the Match All and Match Any radio selection buttons to the end user. When these buttons are present, the end user can use them to modify the search to return matches for all view criteria items or any one view criteria item. This is equivalent to enforcing AND (match all) or OR (match any) conjunctions between view criteria items. Deselect when you want the view criteria to be executed using the view criteria item conjunctions it defines. In this case, the query component will not display the radio selection buttons.

Rendered Mode: Select individual view criteria items from the view criteria tree component and choose whether you want the selected item to appear in the search form when the end user toggles the query component between basic mode and advanced mode. The default for every view criteria item is All. The default mode permits the query component to render an item in either basic or advanced mode. By changing the Rendered Mode setting for individual view criteria items, you can customize the search form's appearance at runtime. For example, you may want basic mode to display a simplified search form to the end user, reserving advanced mode for displaying a search form with the full set of view criteria items. In this case, you would select Advanced for the view criteria item that you do not want displayed in the query component's basic mode. In contrast, when you want the selected view criteria item to be rendered only in basic mode, select Basic. Set any item that you do not want the search form to render in either basic or advanced mode to Never.


Note:

When your view criteria includes an item that should not be exposed to the user, use the Rendered Mode setting Never to prevent it from appearing in the search form. For example, a view criteria may be created to search for products in the logged-in customer's cart; however, you may want to prevent the user from changing the customer ID to display another customer's cart contents. In this scenario, the view criteria item corresponding to the customer ID would be set to the current customer ID using a named bind variable. Although the bind variable definition might specify the variable as not required and not updatable, with the UI hint property Display set to Hide, only the Rendered Mode setting determines whether or not the search form displays the value.


Support Multiple Value Selection: Select when you want to allow the end user to make multiple selections for an individual criteria item that the query component displays. This option is only enabled when the view object attribute specified by the view criteria item has a List of Values (LOV) defined. Additionally, multiple selections will only be supported by the query component when the end user selects the operator equal to or not equal to. For example, if the criteria item names an attribute CountryId and this attribute derives its values from a list of country IDs accessed by the attribute's associated LOV, then selecting this option would allow the end user to submit the query with multiple country selections. At runtime, the query component will generate the appropriate query clause based on the end user's operator selection.

Display Width: Enter the character width to be used by the control that displays this criteria item in the query component. The value you enter will override the display width control hint defined for the criteria item's corresponding view object attribute. For example, in an edit form the attribute control hint may allow text of 1024 length, but in the search form you might want to limit the field for the criteria item to 20 character length.

Show In List: Select to ensure that the view criteria is defined as a developer-seeded query. Deselect when the named view criteria you are defining is not to be used by the query search component to display a search form. Your selection determines whether the named view criteria will appear in the query search component's Saved Search dropdown list of available system searches. By default, this option is enabled for a view criteria you define in the Edit View Criteria dialog.

Display Name: Enter the name of the system search that you want to appear in the query component's Saved Search dropdown list or click the ... button (to the right of the edit field) to select a message string from the resource bundle associated with the view object. The display name will be the name by which the end user identifies the system search. When you select a message string from the resource bundle, JDeveloper saves the string's corresponding message key in the view object definition file. At runtime, the UI locates the string to display based on the end user's locale setting and the message key in the localized resource bundle. When you do not specify a display name, the view criteria name displayed in the Edit View Criteria dialog will be used by default.

To create a system search for use by the ADF query search component, you select Show In List in the UI Hints page of the Edit View Criteria dialog. You deselect Show In List when you do not want the end user to see the view criteria in their search form.

Before you begin:

It may be helpful to have an understanding of view criteria. For more information, see Section 5.9, "Working with Named View Criteria."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete these tasks:

To customize a named view criteria for the user interface:

  1. In the Applications window, double-click the view object that defines the named view criteria you want to use as a system search.

  2. In the overview editor, click the View Criteria navigation tab and select the named view criteria that you want to allow in system searches and then click the Edit Selected View Criteria button.

  3. In Edit View Criteria dialog, click the UI Hints tab and ensure that Show In List is selected.

    This selection determines whether or not the query component will display the system search in its Saved Search dropdown list.

  4. Enter a user-friendly display name for the system search to be added to the query component's Saved Search dropdown list.

    When left empty, the view criteria name displayed in the Edit View Criteria dialog will be used by the query component.

  5. Optionally, enable Query Automatically when you want the query component to automatically display the search results whenever the end user selects the system search from the Saved Search dropdown list.

    By default, no search results will be displayed.

  6. Optionally, apply Criteria Item UI Hints to customize whether the query component renders individual criteria items when the end user toggles the search from between basic and advanced mode.

    By default, all view criteria items defined by the system search will be displayed in either mode.

    If a rendered criteria item is of type Date, you must also define UI hints for the corresponding view object attribute. Set the view object attribute's Format Type hint to Simple Date and set the Format Mask to an appropriate value, as described in Section 5.13.1, "How to Add Attribute-Specific UI Hints." This will allow the search form to accept date values.

  7. Click OK.

5.9.6 How to Test View Criteria Using the Oracle ADF Model Tester

To test the view criteria you added to a view object, use the Oracle ADF Model Tester, which is accessible from the Applications window.

The Oracle ADF Model Tester, for any view object instance that you browse, lets you bring up the View Criteria dialog, as shown in Figure 5-31. The dialog allows you to create a view criteria comprising one or more view criteria groups.

To apply criteria attributes from a single view criteria group, click the Specify View Criteria toolbar button in the browser and enter Query-by-Example criteria in the desired fields, then click Find.

To test view criteria using the Oracle ADF Model Tester:

  1. In the Applications window, expand the project containing the desired application module and view objects.

  2. Right-click the application module and choose Run.

  3. In the Oracle ADF Model Tester, double-click the view instance you want to filter, and then right-click the view instance and choose Find.

    Alternatively, after you double-click a view instance, you can click the Specify View Criteria toolbar button to test the view criteria.

  4. In the View Criteria dialog, perform one of the following tasks:

    • To test a view criteria that you added to the view object in your project, select from the list and click Find. Any additional criteria that you enter in the ad hoc Criteria panel will be added to the filter.

    • To test ad hoc criteria attributes from a single view criteria group, enter the desired values for the view criteria and click Find. For example, Figure 5-31 shows the filter to return all customers whose names begins with "S" and who live in CA.

    • To test additional ad hoc view criteria groups, click the OR tab and use the additional tabs that appear to switch between pages, each representing a distinct view criteria group. When you click Find, the Oracle ADF Model Tester will create and apply the view criteria to filter the result.

    Figure 5-31 View Criteria Dialog in Oracle ADF Model Tester

    View Criteria dialog in ADF Model Tester

5.9.7 How to Use View Criteria to Filter a View Object for the Current User

You can use the Groovy expression adf.context.securityContext.userName to set the default value for the named bind variable that you use to provide the current user in a view instance filter. Specifically, you can use the bind variable in a named view criteria that you define to filter a view object instance in the data model for the project. For example, the named bind variable UserPrincipal is defined in the View Criteria page of the overview editor, as shown in Figure 5-32.

Figure 5-32 Groovy Expression Used to Set userPrincipal Bind Variable

Bind Variable dialog with user name expression

The CustomerVO view object also defines the AuthenticatedUserByPrincipalCriteria view criteria. This view criteria defines a filter for the PrincipalName attribute of the PersonsVO with the bind variable userPrincipal providing the value. In this example, the bind variable userPrincipal is defined with Updatable enabled. This ensures that the view criteria is able to set the value obtained at runtime from the ADF security context. Since the bind variable is not used in the SQL WHERE clause for the PersonsVO view object, the Required field is unselected. This ensures that the value is optional and that no runtime exception will be thrown if the bind variable is not resolved.

Then in the data model, where the CustomerVO specifies the view definition for the usage AuthenticatedUser, the view criteria AuthenticatedUserByPrincipalCriteria with the named bind variable is defined as the view usage's runtime filter. For details about creating view instances for your project's data model, see Section 13.2.3.3, "Customizing a View Object Instance that You Add to an Application Module."

5.9.8 How to Create View Criteria Programmatically

Example 5-23 shows the main() method finds the CustomerList view object instance to be filtered, creates a view criteria for the attributes of this view object, and applies the view criteria to the view object.

To create a view criteria programmatically, follow these basic steps (as illustrated in Example 5-23 from the oracle.summit.model.viewobjects.ProgrammaticVOCriteria.java example in the SummitADF_Examples workspace):

  1. Find the view object instance to be filtered.

  2. Create a view criteria row set for the view object.

  3. Use the view criteria to create one or more empty view criteria groups

  4. Set attribute values to filter on the appropriate view criteria groups.

    You use the ensureCriteriaItem(), setOperator(), and setValue() methods on the view criteria groups to set attribute name, comparison operator, and value to filter on individually.

  5. Add the view criteria groups to the view criteria row set.Apply the view criteria to the view object.

  6. Execute the query.

The last step to execute the query is important, since a newly applied view criteria is applied to the view object's SQL query only at its next execution.

Example 5-23 Creating and Applying a View Criteria

public class ProgrammaticVOCriteria {
    public static void main(String[] args) {

      // get the application module
      String amDef = "oracle.summit.model.viewobjects.AppModule";
      String config = "AppModuleLocal";
      ApplicationModule am = 
            Configuration.createRootApplicationModule(amDef, config);

      // 1. Find the View Object you want to filter
      ViewObject customerList = am.findViewObject("SCustomerView1");

      // Work with your appmodule and view object here

      // iterate through all the rows first, just to see to full VO results
      customerList.executeQuery();
      while (customerList.hasNext()) {
          Row customer = customerList.next();
          System.out.println("Customer: " + customer.getAttribute("Name") + "   
                State: " + customer.getAttribute("State"));

      System.out.println("********* Set View Criteria and requery *********");

      // 2. Create a view criteria row set for this view object
      ViewCriteria vc = customerList.createViewCriteria();

      // 3. Use view criteria row set to create at least one view criteria group
      ViewCriteriaRow vcr1 = vc.createViewCriteriaRow();

      // 4. Set attribute values to filter on
      ViewCriteriaItem vci = vcr1.ensureCriteriaItem("State");
      vci.setOperator("=");
      vci.setValue("TX");

      // 5. Add the view criteria group to the view criteria row set
      vc.add(vcr1);

      // 6. Apply the view criteria to the view object
      customerList.applyViewCriteria(vc, true);

      // 7. Execute the query
      customerList.executeQuery();

      // Iterate throught the rows to see the new results
      while (customerList.hasNext()) {
          Row customer = customerList.next();
          System.out.println("Customer: " + customer.getAttribute("Name") + "   
                  State: " + customer.getAttribute("State"));
      }

      System.out.println("********* Set View Criteria and requery *********");

      // set the attribute to a different value
      vcr1.setAttribute("State", "CA");

      // Add the view criteria group to the view criteria row set
      vc.add(vcr1);

      // Apply the view criteria to the view object
      customerList.applyViewCriteria(vc);

      // Execute the query
        customerList.executeQuery();

      // iterate throught the rows to see the new results
      while (customerList.hasNext()) {
          Row customer = customerList.next();
          System.out.println("Customer: " + customer.getAttribute("Name") + "   
                      State: " + customer.getAttribute("State"));
      }


      Configuration.releaseRootApplicationModule(am, true);
    }
}

Running the ProgrammaticVOCriteria.java test client produces one set of records each time the query is executed. The first query is with no criteria applied (shows all records), the second query is with one criteria set (shows records for TX only), and the third query is with the criteria changed (shows records for CA only).

Customer: Great Gear   State: TX
Customer: Acme Outfitters   State: TX
Customer: Athena's Closet   State: TX
Customer: Big John's Sports Emporium   State: CA
Customer: Perfect Purchase   State: CA
Customer: Father Gym's   State: CA
...
********* Set View Criteria and requery *********
Customer: Great Gear   State: TX
Customer: Acme Outfitters   State: TX
Customer: Athena's Closet   State: TX
...
********* Set View Criteria and requery *********
Customer: Big John's Sports Emporium   State: CA
Customer: Perfect Purchase   State: CA
Customer: Father Gym's   State: CA
...

5.9.9 What Happens at Runtime: How the View Criteria Is Applied to a View Object

When you apply a view criteria containing one or more view criteria groups to a view object, the next time it is executed it augments its SQL query with an additional WHERE clause predicate corresponding to the Query-by-Example criteria that you've populated in the view criteria groups. As shown in Figure 5-33, when you apply a view criteria containing multiple view criteria groups, the view object augments its design time WHERE clause by adding an additional runtime WHERE clause based on the non-null example criteria attributes in each view criteria group.

A corollary of the view criteria feature is that each time you apply a new view criteria (or remove an existing one), the text of the view object's SQL query is effectively changed. Changing the SQL query causes the database to reparse the statement the next time it is executed. You can eliminate the reparsing and improve the performance of a view criteria, as described in Section 5.9.11, "What You May Need to Know About Query-by-Example Criteria."

Figure 5-33 View Object Automatically Translates View Criteria Groups into Additional Runtime WHERE Filter

View object creating more runtime WHERE filters

5.9.10 What You May Need to Know About the View Criteria API

When you need to perform tasks that the Edit View Criteria dialog does not support, review the View Criteria API. For example, programmatically, you can alter compound search conditions using multiple view criteria groups, search for a row whose attribute value is NULL, search case insensitively, and clear view criteria in effect.

5.9.10.1 Referencing Attribute Names in View Criteria

The setWhereClause() method allows you to add a dynamic WHERE clause to a view object, as described in Section 8.4.1, "ViewObject Interface Methods for Working with the View Object's Default RowSet." You can also use setWhereClause() to pass a string that contains literal database column names like this:

vo.setWhereClause("LAST_NAME LIKE UPPER(:NameToFind)");

In contrast, when you use the view criteria mechanism, shown in Example 5-23, you must reference the view object attribute name instead, like this:

    ViewCriteriaItem vc_item1 = vc_row1.ensureCriteriaItem("UserId");
    vc_item1.setOperator(">");
    vc_item1.setValue("304");

Note that method calls like vcr.setAttribute("UserId", "> 304") as documented in a past release must not be used to set the attribute values for the view criteria.

The view criteria groups are then translated by the view object into corresponding WHERE clause predicates that reference the corresponding column names. The programmatically set WHERE clause is AND-ed with the WHERE clauses of any view criteria that have been defined for the view object at design time.

5.9.10.2 Referencing Bind Variables in View Criteria

When you want to set the value of a view criteria item to a bind variable, use setIsBindVarValue(true), like this:

    ViewCriteriaItem vc_item1 = vc_row1.ensureCriteriaItem("UserId");
    vc_item1.setIsBindVarValue(true);
    vc_item1.setValue(":VariableName");

5.9.10.3 Altering Compound Search Conditions Using Multiple View Criteria

When you add multiple view criteria, you can call the setConjunction() method on a view criteria to alter the conjunction used between the predicate corresponding to that view criteria and the one for the previous view criteria. The legal constants to pass as an argument are:

  • ViewCriteriaComponent.VC_CONJ_AND

  • ViewCriteriaComponent.VC_CONJ_NOT

  • ViewCriteriaComponent.VC_CONJ_UNION

  • ViewCriteriaComponent.VC_CONJ_OR (default)

The NOT value can be combined with AND or OR to create filter criteria like:

( PredicateForViewCriteria1 ) AND (NOT ( PredicateForViewCriteria2 ) )

or

( PredicateForViewCriteria1 ) OR (NOT ( PredicateForViewCriteria2 ) )

The syntax to achieve compound search conditions requires using Java's bitwise OR operator like this:

vc2.setConjunction(ViewCriteriaComponent.VC_CONJ_AND | ViewCriteriaComponent.VC_CONJ_NOT);

Performance Tip:

Use the UNION value instead of an OR clause when the UNION query can make use of indices. For example, if the view criteria searches for sal > 2000 or job = 'CLERK' this query may turn into a full table scan. Whereas if you specify the query as the union of two inner view criteria, and the database table has an index on sal and an index on job, then the query can take advantage of these indices and the query performance will be significantly better for a large data set.


The limitation for the UNION clause is that it must be defined over one view object. This means that the SELECT and the FROM list will be the same for inner queries of the UNION clause. To specify a UNION query, call setConjunction() on the outer view criteria like this:

vc.setConjunction(ViewCriteriaComponent.VC_CONJ_UNION);

The outer view criteria should contain inner queries whose results will be the union. For example, suppose you want to specify the union of these two view criteria:

  • A view criteria named MyEmpJob, which searches for Job = 'SALESMAN'.

  • A view criteria named MyEmpSalary, which searches for Sal = 1500.

To create the UNION query for these two view criteria, you would make the calls shown in Example 5-24.

Example 5-24 Applying the Union of Two View Criteria

vcu = voEmp.createViewCriteria();
vcm = voEmp.getViewCriteriaManager();

vcu.setConjunction(ViewCriteria.VC_CONJ_UNION);
vcu.add(vcm.getViewCriteria("MyEmpJob"));
vcu.add(vcm.getViewCriteria("MyEmpSal"));

voEmp.applyViewCriteria(vcu);

When this view criteria is applied, it will return rows where Job is SALESMAN or Sal is greater than 1500.

When you use a UNION view criteria, be sure that only one of the applied view criteria has the UNION conjunction. Other view criteria that you apply will be applied to each inner query of the UNION query.

5.9.10.4 Searching for a Row Whose Attribute Is NULL

To search for a row containing NULL in a column, populate a corresponding view criteria group attribute with the value "IS NULL" or use ViewCriteriaItem.setOperator("ISBLANK").

5.9.10.5 Searching for Rows Whose Attribute Value Matches a Value in a List

To search for all rows with a value in a column that matches any value in a list of values that you specify, populate a corresponding view criteria group attribute with the comma-separated list of values and use the IN operator. For example, to filter the list of persons by IDs that match 204 and 206, set:

ViewCriteriaItem vci = vcr.ensureCriteriaItem("CustomerId");
vci.setOperator("IN");
vci.setValue(0, 204);
vci.setValue(1, 206);

5.9.10.6 Searching Case-Insensitively

To search case-insensitively, call setUpperColumns(true) on the view criteria group to which you want the case-insensitivity to apply. This affects the WHERE clause predicate generated for String-valued attributes in the view object to use UPPER(COLUMN_NAME) instead of COLUMN_NAME in the predicate. Note that the value of the supplied view criteria group attributes for these String-valued attributes must be uppercase or the predicate won't match. In addition to the predicate, it also possible to use UPPER() on the value. For example, you can set UPPER(ename) = UPPER("scott").

5.9.10.7 Clearing View Criteria in Effect

To clear any view criteria in effect, you can call getViewCriteria() on a view object and then delete all the view criteria groups from it using the remove() method, passing the zero-based index of the criteria row you want to remove. If you don't plan to add back other view criteria groups, you can also clear the entire view criteria in effect by simply calling removeApplyViewCriteriaName("namedViewCriteria") on the view object with the name of the view criteria passed in.

5.9.11 What You May Need to Know About Query-by-Example Criteria

For performance reasons, you want to avoid setting a bind variable as the value of a view criteria item in these two cases:

  • In the specialized case where the value of a view criteria item is defined as selectively required and the value changes from non-NULL to NULL.

    In this case, the SQL statement for the view criteria will be regenerated each time the value changes from non-NULL to NULL.

  • In the case where the value of the view criteria item is optional and that item references an attribute for an indexed column.

    In the case of optional view criteria items, an additional SQL clause OR (:Variable IS NULL) is generated, and the clause does not support using column indices.

In either of these cases, you will get better performance by using a view object whose WHERE clause contains the named bind variables, as described in Section 5.10.2, "How to Add WHERE Clause Bind Variables to a View Object Definition."

5.10 Working with Bind Variables

Bind variables provide you with the means to supply attribute values at runtime to the view object or view criteria. All bind variables are defined at the level of the view object and used in one of the following ways:

In contrast, to query WHERE clause bind variables that are needed anytime the view object is executed, bind variables that you define for view criteria are needed only when the view criteria is applied.


Best Practice:

Oracle recommends that your application use view criteria to filter view objects rather than hardcoding the filter in the query WHERE clause. When you use view criteria you can change the values of the search criteria without changing the text of the view object's SQL statement each time those values change.


You can define a default value for the bind variable or write scripting expressions for the bind variable that includes dot notation access to attribute property values. Expressions are based on the Groovy scripting language, as described in Section 3.5.6, "How to Use Groovy Scripting Language With Business Components."

5.10.1 How to Add View Criteria Bind Variables to a View Object Definition

Bind variable usages that you specify in a view criteria also require that you add the bind variable to the view object definition. If you add a bind variable usage to the view criteria definition and the view object does not have a bind variable definition, a runtime exception will result when the view criteria is applied. To create the bind variable definition, you use the View Criteria page in the overview editor for the view object. When you define the variable in the editor, the bind variable will receive a value at runtime, which when left undefined will be null. The default value of null may be suitable in some scenarios but not in others. When a non-null value is required, you can specify a default value for the bind variable definition, or you may let the end user supply the value at runtime (for example, through search criteria in the case of query search forms).

To add a view criteria bind variable to a view object, use the View Criteria page of the overview editor for the view object.

Before you begin:

It may be helpful to have an understanding of the support for bind variables at the level of view objects. For more information, see Section 5.10, "Working with Bind Variables."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.8.1, "How to Create an Expert Mode View Object."

To define a named bind variable for the view criteria:

  1. In the Applications window, double-click the view object.

  2. In the overview editor, click the View Criteria navigation tab.

  3. In the Query page, in the Bind Variables section, click the Create New Bind Variable button.

  4. In the New Variable dialog, enter the name of bind variable and select the data type. Click OK.

    Because the bind variables share the same namespace as view object attributes, specify names that don't conflict with existing view object attribute names. As with view objects attributes, by convention bind variable names are created with an initial capital letter, but you can rename it as desired.

  5. Optionally, in the View Criteria page, in the Details section, click the Value tab and specify a default value for the bind variable:

    • When you want the value to be determined at runtime using an expression, enter a Groovy scripting language expression, select the Expression value type and enter the expression in the Value field. For example, you might want to define a bind variable to filter view instances based on the current user, as described in Section 5.9.7, "How to Use View Criteria to Filter a View Object for the Current User."

    • When you want to define a default value, select the Literal value type and enter the literal value in the Value field.

    • If you do not supply a default value for your named bind variable, it defaults to NULL at runtime and the view criteria will return no rows.

  6. Leave Updatable selected when you want the bind variable value to be defined through the user interface.

    The Updatable checkbox controls whether the end user will be allowed to change the bind variable value through the user interface. If a bind variable is not updatable (it may not be changed either programmatically or by the end user), deselect Updatable.

  7. In the View Criteria page, click the UI Hints tab and specify hints like Label, Format Type, Format mask, and others.

    The view layer will use bind variable UI hints when you build user interfaces like search forms that allow the user to enter values for the named bind variables. Note that formats are only supported for bind variables defined by the Date type or any numeric data type.

  8. Reference the bind variables you defined in the view criteria of the view object.

    You must either reference the bind variable at runtime or use it in the view object query definition. Unreferenced bind variables that you configure in the overview editor will result in a runtime error, as described in Section 5.10.8.1, "Errors Related to the Names of Bind Variables."

  9. If you created bind variables that you do not intend to name in your view criteria or reference programmatically, select the bind variable and click the Delete button.

    Confirm that your bind variable has been named in the view criteria by moving your cursor over the bind variable name field, as shown in Figure 5-35. JDeveloper identifies unreferenced bind variables by displaying the name field with an orange border.

    Figure 5-34 Orange Border Reminds to Reference the Bind Variable

    Unreference bind variable displays orange border

5.10.2 How to Add WHERE Clause Bind Variables to a View Object Definition

Bind variable usages that you specify in a query WHERE clause also require that you add the bind variable to the view object definition. If you add a bind variable usage to the query statement and the view object does not have a bind variable definition, a runtime exception will result. To create the bind variable definition, you use the Query page in the overview editor for the view object. When you define the variable in the editor, the bind variable will receive a value at runtime, which when left undefined will be null. The default value of null may be suitable in some scenarios but not in others. When a non-null value is required, you can specify a default value for the bind variable definition, or you set the value at runtime, as described in Section 5.10.6, "How to Set Existing WHERE Clause Bind Variable Values at Runtime.".

To add a WHERE clause bind variable to a view object, use the Query page of the overview editor for the view object. You can define as many bind variables as you need.


Caution:

Unreferenced bind variables that you configure in the overview editor will result in a runtime error, as described in Section 5.10.8.1, "Errors Related to the Names of Bind Variables." Delete all bind variables definitions from the overview editor unless you name it in the view object definition or reference it programmatically.


Before you begin:

It may be helpful to have an understanding of the support for bind variables at the level of view objects. For more information, see Section 5.10, "Working with Bind Variables."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.8.1, "How to Create an Expert Mode View Object."

To define a named bind variable for the WHERE clause:

  1. In the Applications window, double-click the view object.

  2. In the overview editor, click the Query navigation tab.

  3. In the Query page, in the Bind Variables section, click the Create New Bind Variable button.

  4. In the New Variable dialog, enter the name of bind variable and select the data type. Click OK.

    Because the bind variables share the same namespace as view object attributes, specify names that don't conflict with existing view object attribute names. As with view objects attributes, by convention bind variable names are created with an initial capital letter, but you can rename it as desired.

  5. Optionally, in the Query page, in the Details section, click the Value tab and specify a default value for the bind variable:

    • When you want the value to be determined at runtime using an expression, enter a Groovy scripting language expression, select the Expression value type and enter the expression in the Value field.

    • When you want to define a default value, select the Literal value type and enter the literal value in the Value field.

    • If you do not supply a default value for your named bind variable, it defaults to NULL at runtime and the query will return no rows. If this makes sense for your application, you might want to leverage SQL functions to handle this situation, as described in Section 5.10.8.2, "Default Value of NULL for Bind Variables."

  6. Leave Updatable selected when you want the bind variable value to be defined through the user interface.

    The Updatable checkbox controls whether the end user will be allowed to change the bind variable value through the user interface. If a bind variable is not updatable (it may not be changed programmatically or by the end user), deselect Updatable.

  7. In the Query page, click the UI Hints tab and specify hints like Label, Format Type, Format mask, and others.

    The view layer will use bind variable UI hints when you build user interfaces like search pages that allow the user to enter values for the named bind variables. Note that formats are only supported for bind variables defined by the Date type or any numeric data type.

  8. Reference the bind variables you defined in the SQL statement of the view object.

    You must either reference the bind variable at runtime or use it in the view object query definition. Unreferenced bind variables that you configure in the overview editor will result in a runtime error, as described in Section 5.10.8.1, "Errors Related to the Names of Bind Variables."

    While SQL syntax allows bind variables to appear both in the SELECT list and in the WHERE clause, you'll typically use them in the latter context, as part of your WHERE clause. For example, Example 5-25 shows the bind variables LowUserId and HighUserId introduced into a SQL statement created using the Query page in the overview editor for the view object.

    Example 5-25 Bind Variables in the WHERE Clause of View Object SQL Statement

    select CUSTOMER_ID, EMAIL, FIRST_NAME, LAST_NAME
    from CUSTOMERS
    where (upper(FIRST_NAME) like upper(:TheName)||'%'
       or  upper(LAST_NAME)  like upper(:TheName)||'%')
      and CUSTOMER_ID between :LowUserId and :HighUserId
    order by EMAIL
    

    Notice that you reference the bind variables in the SQL statement by prefixing their name with a colon like :TheName or :LowUserId. You can reference the bind variables in any order and repeat them as many times as needed within the SQL statement.

  9. If you created bind variables that you do not intend to name in your view object SQL query or reference programmatically, select the bind variable and click the Delete button.

    Confirm that your bind variable has been named in the view object query by moving your cursor over the bind variable name field, as shown in Figure 5-35. JDeveloper identifies unreferenced bind variables by displaying the name field with an orange border.

    Figure 5-35 Orange Border Reminds to Reference the Bind Variable

    Unreference bind variable displays orange border

5.10.3 What Happens When You Add Named Bind Variables

Once you've added one or more named bind variables to a view object, you gain the ability to easily see and set the values of these variables at runtime. Information about the name, type, and default value of each bind variable is saved in the view object's XML document file. If you have defined UI hints for the bind variables, this information is saved in the view object's component message bundle file along with other UI hints for the view object.

Note that the overview editor displays an orange warning box around the bind variable name for any bind variable that you define but do not use in the view object query. Be sure to delete bind variables that the query statement or view criteria definition does not reference. A runtime error will result when the view object query is executed and one or more bind variable definitions remain unreferenced, as described in Section 5.10.8.1, "Errors Related to the Names of Bind Variables."

5.10.4 How to Test Named Bind Variables

The Oracle ADF Model Tester allows you to interactively inspect and change the values of the named bind variables for any view object, which can really simplify experimenting with your application module's data model when named bind parameters are involved. For more information about editing the data model and running the Oracle ADF Model Tester, see Section 8.3, "Testing View Object Instances Using the Oracle ADF Model Tester."

The first time you execute a view object in the Oracle ADF Model Tester to display the results in the data view page, a Bind Variables dialog will appear, as shown in Figure 5-36.

The Bind Variables dialog lets you:

  • View the name, as well as the default and current values, of the particular bind variable you select from the list

  • Change the value of any bind variable by updating its corresponding Value field before clicking OK to set the bind variable values and execute the query

  • Inspect and set the bind variables for the view object in the current data view page, using the Edit Bind Parameters button in the toolbar — whose icon looks like ":id"

  • Verify UI hints are correctly set up by showing the label text hint in the Bind Variables list and by formatting the Value attribute using the respective format mask

Figure 5-36 Setting Bind Variables in the Oracle ADF Model Tester

Bind Variables tester

If you defined the bind variable in the Bind Variables dialog with the Required checkbox deselected, you will be able to test view criteria and supply the bind variable with values as needed. Otherwise, if you left the Required checkbox selected (the default), then you must supply a value for the bind variable in the Oracle ADF Model Tester. The Oracle ADF Model Tester will throw the same exception seen at runtime for any view object whose SQL statement use bind variables that do not resolve with a supplied value.

5.10.5 How to Add a WHERE Clause with Named Bind Variables at Runtime

Using the view object's setWhereClause() method, you can add an additional filtering clause at runtime. This runtime-added WHERE clause predicate does not replace the design-time generated predicate, but rather further narrows the query result by adding to the existing design time WHERE clause. Whenever the dynamically added clause refers to a value that might change during the life of the application, you should use a named bind variable instead of concatenating the literal value into the WHERE clause predicate.

For example, assume you want to further filter the CustomerList view object at runtime based on the value of the CUSTOMER_TYPE_CODE column in the table. Also assume that you plan to search sometimes for rows where CUSTOMER_TYPE_CODE = 'CUST' and other times for rows where CUSTOMER_TYPE_CODE = 'SUPP'. While it contains slightly fewer lines of code, Example 5-26 is not desirable because it changes the WHERE clause twice just to query two different values of the same CUSTOMER_TYPE_CODE column.

Example 5-26 Incorrect Use of setWhereClause() Method

// Don't use literal strings if you plan to change the value!
vo.setWhereClause("customer_type_code = 'CUST'");
// execute the query and process the results, and then later...
vo.setWhereClause("customer_type_code = 'SUPP'");

Instead, you should add a WHERE clause predicate that references named bind variables that you define at runtime as shown in Example 5-27.

Example 5-27 Correct Use of setWhereClause() Method and Bind Variable

vo.setWhereClause("customer_type_code = :TheCustomerType");
vo.defineNamedWhereClauseParam("TheCustomerType", null, null);
vo.setNamedWhereClauseParam("TheCustomerType","CUST");
// execute the query and process the results, and then later...
vo.setNamedWhereClauseParam("TheCustomerType","SUPP");

This allows the text of the SQL statement to stay the same, regardless of the value of CUSTOMER_TYPE_CODE you need to query on. When the query text stays the same across multiple executions, the database will return the results without having to reparse the query.

An updated test client class illustrating these techniques would look like what you see in Example 5-28. In this case, the functionality that loops over the results several times has been refactored into a separate executeAndShowResults() method. The program first adds an additional WHERE clause of customer_id = :TheCustomerId and then later replaces it with a second clause of customer_type_code = :TheCustomerType.

Example 5-28 TestClient Program Exercising Named Bind Variable Techniques

package devguide.examples.readonlyvo.client;

import oracle.jbo.ApplicationModule;
import oracle.jbo.Row;
import oracle.jbo.ViewObject;
import oracle.jbo.client.Configuration;

public class TestClientBindVars {
  public static void main(String[] args) {
    String        amDef = "devguide.examples.readonlyvo.CustomerService";
    String        config = "CustomerServiceLocal";
    ApplicationModule am =
     Configuration.createRootApplicationModule(amDef,config);
    ViewObject vo = am.findViewObject("CustomerList");
    // Set the two design time named bind variables
    vo.setNamedWhereClauseParam("TheName","shelli%");
    vo.setNamedWhereClauseParam("HighUserId", 215);
    executeAndShowResults(vo);
    // Add an extra where clause with a new named bind variable
    vo.setWhereClause("customer_type_code = :TheCustomerId");
    vo.defineNamedWhereClauseParam("TheCustomerId", null, null);
    vo.setNamedWhereClauseParam("TheCustomerId",116);
    executeAndShowResults(vo);
    vo.removeNamedWhereClauseParam("TheCustomerId");
    // Add an extra where clause with a new named bind variable
    vo.setWhereClause("customer_type_code = :TheCustomerType");
    vo.defineNamedWhereClauseParam("TheCustomerType", null, null);
    vo.setNamedWhereClauseParam("TheCustomerType","SUPP");
    // Show results when :TheCustomerType = 'SUPP'
    executeAndShowResults(vo);
    vo.setNamedWhereClauseParam("TheCustomerType","CUST");
    // Show results when :TheCustomerType = 'CUST'
    executeAndShowResults(vo);
    Configuration.releaseRootApplicationModule(am,true);
  }  
  private static void executeAndShowResults(ViewObject vo) {
    System.out.println("---");
    vo.executeQuery();
    while (vo.hasNext()) {
      Row curUser = vo.next();
      System.out.println(curUser.getAttribute("CustomerId")+" "+
                         curUser.getAttribute("ShortName"));
    }    
  }
}

However, if you run this test program, you may actually get a runtime error like the one shown in Example 5-29.

Example 5-29 Runtime Error Resulting From a SQL Parsing Error

oracle.jbo.SQLStmtException: JBO-27122: SQL error during statement preparation.
Statement: 
SELECT * FROM (select PERSON_ID, EMAIL, FIRST_NAME, LAST_NAME
from PERSONS 
where (upper(FIRST_NAME) like upper(:TheName)||'%'
   or  upper(LAST_NAME)  like upper(:TheName)||'%')
  and PERSON_ID between :LowUserId and :HighUserId
order by EMAIL) QRSLT  WHERE (person_type_code = :TheCustomerType)
## Detail 0 ##
java.sql.SQLException: ORA-00904: "PERSON_TYPE": invalid identifier

The root cause, which appears after the ## Detail 0 ## in the stack trace, is a SQL parsing error from the database reporting that PERSON_TYPE_CODE column does not exist even though the PERSONS table definitely has a PERSON_TYPE_CODE column. The problem occurs due to the mechanism that view objects use by default to apply additional runtime WHERE clauses on top of read-only queries. Section 5.10.7, "What Happens at Runtime: Dynamic Read-Only View Object WHERE Clause," explains a resolution for this issue.

5.10.6 How to Set Existing WHERE Clause Bind Variable Values at Runtime

To set named bind variables at runtime, use the setNamedWhereClauseParam() method on the ViewObject interface. In JDeveloper, you can choose Refactor > Duplicate in the main menu to create a new TestClientBindVars class based on the existing TestClient.java class as shown in Section 8.4.2, "How to Create a Command-Line Java Test Client." In the test client class, you can set the values of the bind variables using a few additional lines of code. For example, the setNamedWhereClauseParam() might take as arguments the bind variables HighUserId and TheName as shown in Example 5-30.

Example 5-30 Setting the Value of Named Bind Variables Programmatically

// changed lines in TestClient class 
ViewObject vo = am.findViewObject("CustomerList");
vo.setNamedWhereClauseParam("TheName","alex%");
vo.setNamedWhereClauseParam("HighUserId", 315);
vo.executeQuery();
// etc.

Running the test client class shows that your bind variables are filtering the data. For example, the resulting rows for the setNamedWhereClauseParam() method shown in Example 5-30 may show only two matches based on the name alex as shown in Example 5-31.

Example 5-31 Result of Bind Variables Filtering the Data in TestClient Class

303 ahunold
315 akhoo

Whenever a view object's query is executed, you can view the actual bind variable values in the runtime debug diagnostics like the sample shown in Example 5-32.

Example 5-32 Debug Diagnostic Sample with Bind Variable Values

[256] Bind params for ViewObject: CustomerList
[257] Binding param "LowUserId": 0
[258] Binding param "HighUserId": 315
[259] Binding param "TheName": alex%

This information that can be invaluable when debugging your applications. Notice that since the code did not set the value of the LowUserId bind variable, it took on the default value of 0 (zero) specified at design time. Also notice that the use of the UPPER() function in the WHERE clause and around the bind variable ensured that the match using the bind variable value for TheName was performed case-insensitively. The sample code set the bind variable value to "alex%" with a lowercase "a", and the results show that it matched Alexander.

5.10.7 What Happens at Runtime: Dynamic Read-Only View Object WHERE Clause

If you dynamically add an additional WHERE clause at runtime to a read-only view object, its query gets nested into an inline view before applying the additional WHERE clause.

For example, suppose your query was defined as shown in Example 5-33.

Example 5-33 Query Specified At Design Time

select PERSON_ID, EMAIL, FIRST_NAME, LAST_NAME
from PERSONS 
where (upper(FIRST_NAME) like upper(:TheName)||'%'
   or  upper(LAST_NAME)  like upper(:TheName)||'%')
  and PERSON_ID between :LowUserId and :HighUserId
order by EMAIL

At runtime, when you set an additional WHERE clause like person_type_code = :TheCustomerType as the test program did in Example 5-28, the framework nests the original query into an inline view like the sample shown in Example 5-34.

Example 5-34 Runtime-Generated Query with Inline Nested Query

SELECT * FROM(
select PERSON_ID, EMAIL, FIRST_NAME, LAST_NAME
from PERSONS 
where (upper(FIRST_NAME) like upper(:TheName)||'%'
   or  upper(LAST_NAME)  like upper(:TheName)||'%')
  and PERSON_ID between :LowUserId and :HighUserId
order by EMAIL) QRSLT

Then the framework adds the dynamic WHERE clause predicate at the end, so that the final query the database sees is like the sample shown in Example 5-35.

Example 5-35 Runtime-Generated Query with Dynamic WHERE Clause

SELECT * FROM(
select PERSON_ID, EMAIL, FIRST_NAME, LAST_NAME
from PERSONS 
where (upper(FIRST_NAME) like upper(:TheName)||'%'
   or  upper(LAST_NAME)  like upper(:TheName)||'%')
  and PERSON_ID between :LowUserId and :HighUserId
order by EMAIL) QRSLT
WHERE person_type_code = :TheCustomerType

This query "wrapping" is necessary in the general case since the original query could be arbitrarily complex, including SQL UNION, INTERSECT, MINUS, or other operators that combine multiple queries into a single result. In those cases, simply "gluing" the additional runtime WHERE clause onto the end of the query text could produce unexpected results because, for example, it might apply only to the last of several UNION'ed statements. By nesting the original query verbatim into an inline view, the view object guarantees that your additional WHERE clause is correctly used to filter the results of the original query, regardless of how complex it is. The consequence (that results in an ORA-00904 error) is that the dynamically added WHERE clause can refer only to columns that have been selected in the original query.

The simplest solution is to add the dynamic query column names to the end of the query's SELECT list in the Query page of the overview editor for the view object. Just adding the new column name at the end of the existing SELECT list — of course, preceded by a comma — is enough to prevent the ORA-00904 error: JDeveloper will automatically keep your view object's attribute list synchronized with the query statement. Alternatively, Section 5.8.5.8, "Inline View Wrapping at Runtime" explains how to disable this query nesting when you don't require it.

The test client program in Example 5-28 now produces the results shown in Example 5-36.

Example 5-36 Named Bind Variables Resulting From Corrected TestClient

---
116 S. Baida
---
116 S. Baida
---
---
116 S. Baida

5.10.8 What You May Need to Know About Named Bind Variables

There are several things you may need to know about named bind variables, including the runtime errors that are displayed when bind variables have mismatched names and the default value for bind variables.

5.10.8.1 Errors Related to the Names of Bind Variables

You need to ensure that the list of named bind variables that you reference in your SQL statement matches the list of named bind variables that you've defined in the Bind Variables section of the Query page for the view object overview editor. Failure to have these two agree correctly can result in one of the following two errors at runtime.

If you use a named bind variable in your SQL statement but have not defined it, you'll receive an error like this:

(oracle.jbo.SQLStmtException) JBO-27122: SQL error during statement preparation.
## Detail 0 ##
(java.sql.SQLException) Missing IN or OUT parameter at index:: 1

On the other hand, if you have defined a named bind variable, but then forgotten to reference it or mistyped its name in the SQL, then you will see an error like this:

oracle.jbo.SQLStmtException: JBO-27122: SQL error during statement preparation.
## Detail 0 ##
java.sql.SQLException: Attempt to set a parameter name that does not occur in the SQL: LowUserId

To resolve either of these errors, double-check that the list of named bind variables in the SQL matches the list of named bind variables in the Bind Variables section of the Query page for the overview editor.

5.10.8.2 Default Value of NULL for Bind Variables

If you do not supply a default value for your named bind variable, it defaults to NULL at runtime. This means that if you have a WHERE clause like:

PERSON_ID = :TheCustomerId

and you do not provide a default value for the TheCustomerId bind variable, it will default to NULL and cause the query to return no rows. Where it makes sense for your application, you can leverage SQL functions like NVL(), CASE, DECODE(), or others to handle the situation as you require. For example, the following WHERE clause fragment allows the view object query to match any name if the value of :TheName is null.

upper(FIRST_NAME) like upper(:TheName)||'%'

5.11 Working with Row Finders

Row finders are objects that the application may use to locate specific rows within a row set using a view criteria. You can define a row finder when you need to perform row lookup operations on the row set and you do not want the application to use row key attributes to specify the row lookup.

Currently, row finders that you define at design time can participate in these scenarios where non-row key attribute lookup is desired at runtime:


Note:

Row finders that you define on a view object are not currently supported by the ADF Business Components data control for use in a view project. Therefore the row-finder mapped attributes of a view object that the application exposes as a collection in the Data Controls panel will not participate in row finder lookup operations.


When the application programmatically invokes the row finder on the view object instance, or when the end user supplies a value for a row-finder mapped attribute in the web service payload, the row finder locates the rows that match the values supplied to bind variables of the view criteria. The row finder does not alter the row set when locating matching rows.

You can specify the row finder to locate all row matches or a specified number of row matches. If the row finder locates more rows than the fetch limit you specify, you can enable the row finder to throw an exception.

The view object definition with row finder includes the following elements.

  1. A specified view criteria that applies one or more view criteria items to filter the view object. View criteria items are defined on the view object attributes that determine the row match and must be defined by bind variables to allow the row finder to supply the values at runtime.

  2. A mapping between view criteria bind variables and the source of the value: either a transient attribute of the view object or an attribute-value expression.

For example, where EmpVO has an attribute email, an EmpVO row finder may locate a specific employee row using a view criteria defined on the EmpVO and the email address of the employee. The view criteria for the EmpVO might look similar to the one shown in Example 5-37. In this example, the view criteria statement uses a bind variable EmailBindVar to set the value of the email attribute on the view object EmpVO.

Example 5-37 View Criteria Statement Uses Bind Variables

 ( (UPPER(EmpEO.EMAIL) = UPPER(:EmailBindVar) ) ) 

The application may invoke the row finder by applying values to the mapped view criteria bind variables in a variety of ways:

5.11.1 How to Add Row Finders to a View Object Definition

You use the Row Finders page of the view object's overview editor to define the row finder. In the editor, you define a value source for each bind variable of the view criteria that you select. Attributes of the view object or attribute-value expressions are both valid sources for bind variables defined by the row finder.

The row finder that you define can map any number of view criteria bind variables to a valid value source. Mapping additional variables in the row finder definition will result in more restrictive row matches. In this regard, row finders are similar to query search operations that do not alter the row set. Using an appropriately defined row finder, the application can locate a single, specific row and the allow the end user to perform row updates on the row.

Figure 5-37 shows the overview editor with a row finder that maps the view criteria bind variable EmailBindVar specified in the findEmpByEmpEmail view criteria to the transient attribute TrEmpEmail defined by the view object EmpVO as its value source.

Figure 5-37 View Object Overview Editor with Row Finder

View object editor displays a row finder

Note:

You can define row finders on master view objects in a master-detail hierarchy when you want to filter the master by attributes of the detail view object. In this scenario, the view criteria uses an inline view criteria, as described in Section 6.2.8, "How to Find Rows of a Master View Object Using Row Finders."


Before you begin:

It may be helpful to have an understanding of the row finder. For more information, see Section 5.11, "Working with Row Finders."

It may be helpful to have an understanding of view criteria. For more information, see Section 5.9, "Working with Named View Criteria."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete these tasks:

To create a row finder for a view object:

  1. In the Applications window, double-click the view object for which you want to create the row finder.

  2. In the overview editor, click the Row Finders navigation tab and then click the Add Row Finder button.

  3. In the Name field, rename the row finder.

    For example, a row finder that you define to locate an employee by their email address, might be named EmailAddressFinder.

  4. Select the new row finder in the Row Finders list and then, in the View Criteria dropdown, select the view criteria that filters the view object row set.

    The desired row finder should appear highlighted, as shown in Figure 5-37. The view criteria list will be empty unless you have created a view criteria for the row finder to use.

  5. When you want the end user of an ADF Business Components web service to supply a value, leave Attribute selected, select the bind variable from the list, and then, in the Attribute dropdown, select the transient attribute from the view object that supplies the bind variable value at runtime.

    The transient attribute that you select will be the one that the end user updates to supply the criteria attribute value. For example, a row finder that matches the employee record by their email address, might include a transient attribute named TrEmpEmail that you define on the EmpVO view object.

    Note: When you create the transient attribute in the overview editor for the view object, be sure to define the transient attribute as Updatable so it can receive the criteria lookup value.

  6. Deselect FetchAll when you want to specify the number of rows that the row finder is allowed to match.

    When you enter a number of rows for Fetch Limit, you can also select Error Exceeding Limit to enable Oracle ADF to throw an exception when more matching rows exist in the database than the number you specify for Fetch Limit.

5.11.2 What Happens When You Define a Row Finder

When you create a view object row finder, the view object definition contains all the metadata required by the row finder, including the row finder definition itself. As Example 5-38 shows, the metadata for a row finder RowFinder includes a bind variable EmailBindVar in the <Variable> element, a transient attribute TrEmpEmail in the <ViewAttribute> element, a view criteria findEmpByEmpEmail and a view criteria row EmpVOCriteria_Row0 in the <ViewCriteria> element, and finally the row finder EmailAddressFinder in the <RowFinders> element of the view object definition.

The row finder <VarAttributeMapping> subelement maps the view criteria bind variable EmailBindVar to the transient attribute TrEmpEmail of the view object, which allows the end user to supply a value at runtime and allows the application to invoke the row finder with the required criteria attribute. The <ViewCriteriaItem> subelement sets the criteria attribute Email to the value of the bind variable EmailBindVar.

At runtime, when the row finder is invoked on the view object, the transient attribute values passed to one or more criteria attributes identify the matching rows in the row set. In this example, the email of the employee is used to match the employee record from the S_EMP table. The row finder locates the record for the employee without the need to pass a row key value.

Example 5-38 Row Finder Defined on a View Object

<ViewObject
  xmlns="http://xmlns.oracle.com/bc4j"
  Name="EmpVO"
  SelectList="EmpEO.ID, 
       EmpEO.LAST_NAME, 
       EmpEO.FIRST_NAME"
       EmpEO.USERID"
       EmpEO.DEPT_ID"
       EmpEO.EMAIL"
  FromList="S_EMP EmpEO"
  ... 
  <Variable
    Name="EmailBindVar"
    Kind="viewcriteria"
    Type="java.lang.String"/>
  <EntityUsage
    Name="EmpEO"
    Entity="model.entities.EmpEO"/>
  ...
  <ViewAttribute
    Name="TrEmpEmail"
    IsUpdateable="false"
    IsSelected="false"
    IsPersistent="false"
    PrecisionRule="true"
    Type="java.lang.String"
    ColumnType="CHAR"
    AliasName="VIEW_ATTR"
    SQLType="VARCHAR"/>
  ...
  <ViewCriteria
    Name="findEmpByEmpEmail"
    ViewObjectName="model.views.EmpVO"
    Conjunction="AND">
    ...
    <ViewCriteriaRow
      Name="EmpVOCriteria_row_0"
      UpperColumns="1">
      <ViewCriteriaItem
        Name="Email"
        ViewAttribute="Email"
        Operator="="
        Conjunction="AND"
        Value=":EmailBindVar"
        IsBindVarValue="true"
        Required="Optional"/>
    </ViewCriteriaRow>
  </ViewCriteria>
  ...
  <RowFinders>
    <AttrValueRowFinder
      Name="EmailAddressFinder"
      FetchLimit="1"
      ErrorOnExceedingLimit="true">
      <ViewCriteriaUsage
        Name="findEmpByEmpEmail"
        FullName="model.views.EmpVO.findEmpByEmpEmail"/>
      <VarAttributeMap>
        <VariableAttributeMapping
          Variable="EmailBindVar"
          Attribute="TrEmpEmail"/>
      </VarAttributeMap>
    </AttrValueRowFinder>
  </RowFinders>
</ViewObject>

5.11.3 What You May Need to Know About View Criteria and Row Finder Usage

Row finders and view criteria can both be used either programmatically or declaratively to filter a view object row set. The row finder differs from the view criteria because it defines a map between transient attributes that you define on the view object and view criteria attribute bind variables. Ultimately, the row finder matches one or more rows on the view object by applying the view criteria to the view object with the bind variable defined by a transient attribute value that is resolved at runtime.

The transient attribute mapped by the row finder allows the row finder to be used in application use cases that would not be suitable for view criteria alone. In particular, row finders are most useful when ADF Business Components web services enable CRUD operations. In this case, the row finder gives the ADF Business Components web services developer the ability to expose CRUD operations without needing obscure row key values.

Fusion web application developers can create a web service data control to expose the view objects of an ADF Business Components web service in the JDeveloper Data Controls panel. The exposed row-finder mapped transient attributes of the view object can then be used to design an input form that allows the end user to make the desired updates. For example, an end user may supply the value of a familiar attribute, such as a person's email address, to match a particular person row and then initiate an update operation on any attribute of that row, such as the one that would allow a name change.

For details about support for row finder in ADF web services, see Section 15.2.4, "What You May Need to Know About Row Finders and the ADF Web Service Operations." For details about creating data controls based on ADF web services, see Developing Applications with Oracle ADF Data Controls.

Note that the capability of row finders to match rows using non-key attributes extends to master-detail related view objects, as described Section 6.2.8, "How to Find Rows of a Master View Object Using Row Finders."

5.11.4 Programmatically Invoking the Row Finder

When you define a row finder you invoke the row finder on the view object. If the row finder definition specifies a row limit, the executed row finder will throw a RowFinderFetchLimitExceededException exception.

To invoke a row finder that you define on a view object, follow these basic steps (as illustrated in Example 5-39):

  1. Find the view object that defines the row finder.

  2. Find the row finder from the view object.

  3. Create a name value pair for each row finder bind variable mapping.

  4. Set each bind variable using a row-finder mapped transient attribute.

  5. Invoke the row finder on the desired view object.

  6. Throw an exception when the number of matching rows exceeds the row finder fetch limit.

At runtime, when the row finder is invoked on the view object, row-finder mapped transient attribute values populated by setAttribute() are set on criteria attributes to identify the matching rows in the row set. In the following example, the email address of the employee is used to match the employee record on the EmpView view object. The row finder EmpByEmailRowFinder locates the record for the employee using the transient attribute TrEmpEmail to specify the criteria attribute without the need to pass a row key value.

Example 5-39 Invoking a Row Finder on a View Object

package model;

import oracle.jbo.*;
import oracle.jbo.client.Configuration;
import oracle.jbo.server.RowFinder;
import oracle.jbo.server.ViewObjectImpl;

public class TestClient
{
   public TestClient()
   {
      super();
   }

   public static void main(String[] args)
   {
      TestClient testClient = new TestClient();
      String amDef = "model.AppModule";
      String config = "AppModuleLocal";
      ApplicationModule am = 
                 Configuration.createRootApplicationModule(amDef, config);

      // 1. Find the view object with the row finder
      ViewObjectImpl vo = (ViewObjectImpl)am.findViewObject("EmpView1");
      Row r;
      RowIterator ri;

      // 2. Find the row finder
      RowFinder finder = vo.lookupRowFinder("EmailAddressFinder");
      // 3. Create name value pair for the row finder
      NameValuePairs nvp = new NameValuePairs();
      // 4. Set the row-finder mapped attribute
      nvp.setAttribute("Email", "cee.mague@company.com");
      // 5. Invoke the row finder
      try
      {
         ri = finder.execute(nvp, vo);
      }
      // 6. Throw an exception when row match exceeds specified limit
      catch(RowFinderFetchLimitExceededException e)
      {
         System.out.println("Warning: more than one row match exists.");
      }

      while (ri.hasNext())
      {
        r = ri.next();
        System.out.println("Find row by email finder: " +
           r.getAttribute("FirstName") + "/" + r.getAttribute("LastName"));
      }

      Configuration.releaseRootApplicationModule(am, true);
   }
}

5.12 Working with List of Values (LOV) in View Object Attributes

Edit forms displayed in the user interface portion of your application can utilize LOV-enabled attributes that you define in the data model project to predetermine a list of values for individual input fields. For example, the edit form may display a list of countries to populate the corresponding address field in the edit form. To facilitate this common design task, ADF Business Components provides declarative support to specify the LOV usage in the user interface.

Defining an LOV for attributes of a view object in the data model project greatly simplifies the task of working with list controls in the user interface. Because you define the LOV on the individual attributes of the view object, you can customize the LOV usage for an attribute once and expect to see the list component in the form wherever the attribute appears.


Note:

In order for the LOV to appear in the UI, the LOV usage must exist before the user interface designer creates the databound form. Defining an LOV usage for an attribute referenced by an existing form will not change the component that the form displays to an LOV.


You can define an LOV for any view object attribute that you anticipate the user interface will display as a selection list. The characteristics of the attribute's LOV definition depend on the requirements of the user interface. The information you gather from the user interface designer will determine the best solution. For example, you might define LOV attributes in the following cases:

Before you can define the LOV attribute, you must create a data source view object in your data model project that queries the eligible rows for the attribute value you want the LOV to display. After this, you work entirely on the base view object to define the LOV. The base view object is the one that contains the primary data for display in the user interface. The LOV usage will define the following additional view object metadata:


Note:

The LOV feature does not support the use of attribute validation to validate the display list. Any validation rules that may have been defined on data source attributes (including supplemental ones) will be suppressed when the list is displayed and will therefore not limit the LOV list. Developers must ensure that the list of values returned from the data source view object contains only desired, valid values.


The general process for defining the LOV-enabled attribute relies on the Create List of Values dialog that you display for the base view object attribute.

To define the LOV-enabled attribute, follow this general process:

  1. Open the Create List of Values dialog for the base attribute.

  2. Create a new view accessor definition to point to the data source view object or select an existing view accessor that the base view object already defines.

    Always create a new view accessor for each use case that your wish to support. Oracle recommends that you do not reuse a view accessor to define multiple LOV lists that happen to rely on the same data source. Reusing a view accessor can produce unintended results at runtime.

  3. Optionally, you can filter the view accessor by creating a view criteria using a bind variable that obtains its value from any attribute of the base view object's current row.

    If you create a view criteria to filter the data source view object, you may also set a prerequisite LOV on the attribute of the base view object that you use to supply the value for the view criteria bind variable. LOV lists that cooperate in this manner, are known as cascading LOV lists. You set cascading LOV lists when you want the user's selection of one attribute to drive the options displayed in a second attribute's list.

  4. Select the list attribute from the view accessor's data source view object.

    This maps the attribute you select to the current attribute of the base view object.

  5. Optionally, select list return values to map any supplemental values that your list returns to the base view object.

  6. Select user interface hints to specify the list's display features.

  7. Save the attribute changes.

Once you create the LOV-enabled attribute, the user interface designer can create the list component in the web page by dragging the LOV-enabled attribute's collection from the Data Controls panel. For further information about creating a web page that display the list, see Chapter 32, "Creating Databound Selection Lists and Shuttles." Specifically, for more information about working with LOV-enabled attributes in the web page, see Section 32.3.1, "How to Create a Model-Driven List."

5.12.1 How to Define a Single LOV-Enabled View Object Attribute

When an edit form needs to display a list values that is not dependent on another selection in the edit form, you can define a view accessor to point to the list data source. For example, assume that a purchase order form contains a field that requires the user to select the order item's supplier. In this example, you would first create a view accessor that points to the data source view object (SuppliersView). You would then set the LOV on the SupplierDesc attribute of the base view object (PurchaseOrdersView). Finally, you would reference that view accessor from the LOV-enabled attribute (SupplierDesc) of the base view object and select the data source attribute (SupplierDesc).

You will use the Create List of Values dialog to define an LOV-enabled attribute for the base view object. The dialog lets you select an existing view accessor or create a new one to save with the LOV-attribute definition.

Before you begin:

It may be helpful to have an understanding of LOV-enabled attributes. For more information, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.8.1, "How to Create an Expert Mode View Object."

To define an LOV that displays values from a view object attribute:

  1. In the Applications window, double-click the view object that contains the attribute you wish to enable as an LOV.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the attribute that is to display the LOV, and then click the List of Values tab and click the Add list of values button.

    Use the Create List of Values dialog to create the LOV on the attribute you have currently selected in the attribute list of the overview editor. JDeveloper assigns a unique name to identify the LOV usage. For example, the metadata for the attribute SupplierDesc will specify the name SupplierDescLOV to indicate that the attribute is LOV enabled.

  4. In the Create List of Values dialog, on the Configuration tab, click the Create new view accessor button to add a view accessor to the view object you are currently editing.

    Alternatively, you can expand List Data Source and select among the existing view accessors. The dropdown list displays all view accessors that you have added to the view object you are editing.

  5. In the View Accessors dialog, select the view object definition or shared view instance that defines the data source for the attribute and shuttle it to the view accessors list.

    By default, the view accessor you create will display the same name as the view object. You can edit the accessor name to supply a unique name. For example, assign the name SuppliersViewAccessor for the SuppliersView view object.

    The view instance is a view object usage that you have defined in the data model of a shared application module. For more information about using shared view instances in an LOV, see Section 14.4.5, "How to Create an LOV Based on a Lookup Table."

  6. Click OK to save the view accessor definition for the view object.

  7. In the Create List of Values dialog, expand List Data Source and select the view accessor you created for the base view object to use as the data source. Then select the same attribute from this view accessor that will provide the list data for the LOV-enabled attribute.

    The editor creates a default mapping between the list data source attribute and the LOV-enabled attribute. For example, the attribute SuppliersDesc from the PurchaseOrdersView view object would map to the attribute SuppliersDesc from the SuppliersViewAccessor view accessor.

    The editor does not allow you to remove the default attribute mapping for the attribute for which the list is defined.

  8. If you want to specify supplemental values that your list returns to the base view object, click the Create return attribute map button in the List Return Values section and map the desired base view object attributes with attributes accessed by the view accessor.

    Supplemental attribute return values are useful when you do not require the user to make a list selection for the attributes, yet you want those values, as determined by the current row, to participate in the update. For example, to map the attribute SupplierAddress from the PurchaseOrdersView view object, you would choose the attribute SupplierAddress from the SuppliersViewAccessor view accessor.

  9. Click OK.

5.12.2 How to Define Cascading Lists for LOV-Enabled View Object Attributes

When the application user interface requires a list of values in one input field to be dependent on the user's entry in another field, you can create attributes that will display as cascading lists in the user interface. In this case, the list of possible values for the LOV-enabled attributes might be different for each row. As the user changes the current row, the LOV values vary based on the value of one or more controlling attribute values in the LOV-enabled attribute's view row. To apply the controlling attribute to the LOV-enabled attribute, you will create a view accessor to access the data source view object with the additional requirement that the accessor filters the list of possible values based on the current value of the controlling attribute. To filter the LOV-enabled attribute, you can edit the view accessor to add a named view criteria with a bind variable to obtain the user's selection.

For example, assume that a purchase order form contains a field that requires the user to select the supplier's specific site and that the available sites will depend on the order's already specified supplier. To implement this requirement, you would first create a view accessor that points to the data source view object. The data source view object will be specific to the LOV usage, because it must perform a query that filters the available supplier sites based on the user's supplier selection. You might name this data source view object definition SupplierIdsForCurrentSupplierSite to help distinguish it from the SupplierSitesView view object that the data model already contains. The data source view object will use a named view criteria (SupplierCriteria) with a single view criteria item set by a bind variable (TheSupplierId) to obtain the user's selection for the controlling attribute (SupplierId).

You would then set the LOV on the SupplierSiteId attribute of the base view object (PurchaseOrdersView). You can then reference the view accessor that points to the data source view object from the LOV-enabled attribute (PurchaseOrdersView.SupplierSiteId) of the base view object. Finally, you must edit the LOV-enabled attribute's view accessor definition to specify the corresponding attribute (SupplierIdsForCurrentSupplierSite.SupplierSiteId) from the view object as the data source and, importantly, source the value of the bind variable from the view row's result using the attribute SupplierId.

To define cascading lists for LOV-enabled view object attributes:

  1. Create a data source view object to control the cascading list.

  2. Create a view accessor to filter the cascading list.

5.12.2.1 Creating a Data Source View Object to Control the Cascading List

The data source view object defines the controlling attribute for the LOV-enabled attribute. To make the controlling attribute accessible to the LOV-enabled attribute of the base view object, you must define a named view criteria to filter the data source attribute based on the value of another attribute. Because the value of the controlling attribute is expected to change at runtime, the view criteria uses a bind variable to set the controlling attribute.

Before you begin: 

It may be helpful to have an understanding of cascading LOV-enabled attributes. For more information, see Section 5.12.2, "How to Define Cascading Lists for LOV-Enabled View Object Attributes."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To define the view criteria for the data source to be referenced by the LOV-enabled attribute: 

  1. In the Applications window, double-click the view object that you created to query the list of all possible values for the controlling attribute.

    For example, if the LOV-enabled attribute SupplierSiteId depends on the controlling attribute SupplierId value, you might have created the data source view object SupplierIdsForCurrentSupplierSite to query the list of all supplier sites.

  2. In the overview editor, click the Query navigation tab.

  3. In the Query page, in the Bind Variables section, click the Create New Bind Variable button to add a bind variable to the data source view object.

    For example, for a data source view object SupplierIdsForCurrentSupplierSite used to query the list of all supplier sites, you would create the bind variable TheSupplierId, since it will be the controlling attribute for the LOV-enabled attribute.

  4. In the New Variable dialog, enter the name and select the type of the bind variable and click OK.

    By default, the view accessor you create will display the same name as the view object instance. You can edit the accessor name to supply a unique name. For example, assign the name CurrencyLookupViewAccessor for the CurrencyLookupView view object instance.

  5. In the overview editor, click the View Criteria navigation tab and click the Create New View Criteria button to add the view criteria to the data source view object you are currently editing.

  6. In the Create View Criteria dialog, click Add Group and define a single Criteria Item for the group as follows:

    • Enter a Criteria Name to identify the view criteria. For example, you might enter the name SupplierCriteria for the SupplierIdsForCurrentSupplierSite.

    • Select the controlling attribute from the Attributes list. For example, you would select the SupplierSiteId attribute from the SupplierIdsForCurrentSupplierSite.

    • Select equal to from the view criteria Operator list.

    • Select Bind Variable from the view criteria Operand list.

    • Select the name of the previously defined bind variable from the Parameter list.

    • Select among the following bind variable configuration options to determine whether or not the value is required by the parent LOV:

      Optional from the Validation menu and deselect Ignore Null Values when you want to configure cascading LOVs where the parent LOV value is required. This combination supports the cascading LOV use case where no selection in the parent LOV returns no rows in the child LOV. The WHERE clause shown in the Edit View Criteria dialog should look similar to ((SupplierIdsForCurrentSupplierSite.SUPPLIER_ID = :TheSupplierId)).

      Optional from the Validation menu and leave Ignore Null Values selected (default) when you want to configure cascading LOVs where the parent LOV value is optional. This combination supports the cascading LOV use case where no selection in the parent LOV returns all rows in the child LOV. The WHERE clause shown in the Edit View Criteria dialog should look similar to (((SupplierIdsForCurrentSupplierSite.SUPPLIER_ID = :TheSupplierId) OR ( :TheSupplierId IS NULL ))).

      For more details about these settings, see Section 5.9.3, "What You May Need to Know About Bind Variables in View Criteria." Do not select Required for the Validation option for cascading LOVs, because no selection in the parent LOV will cause a validation error.

  7. Click OK.

5.12.2.2 Creating a View Accessor to Filter the Cascading List

To populate the cascading LOV-enabled attribute, you must first set up a named view criteria on a data source view object. To make the LOV-enabled attribute of the base view object dependent on the controlling attribute of the data source view object, you then add a view accessor to the LOV-enabled attribute of the base view object and reference the previously defined data source view object's named view criteria.

Before you begin: 

It may be helpful to have an understanding of cascading LOV-enabled attributes. For more information, see Section 5.12.2, "How to Define Cascading Lists for LOV-Enabled View Object Attributes."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the data source view object and named view criteria, as described in Section 5.12.2.1, "Creating a Data Source View Object to Control the Cascading List."

To create a view accessor that filters display values for an LOV-enabled attribute based on the value of another attribute in the same view row: 

  1. In the Applications window, double-click the base view object that contains the attribute you want to use the filtered view accessor as the list data source.

    For example, the base view object PurchaseOrdersView might contain the attribute SupplierSiteId that will depend on the value of the controlling attribute SupplierId.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the attribute that is to filter the cascading LOV, and then click the List of Values tab and click the Add List of Values button.

  4. In the Create List of Values dialog, click the Create New View Accessor button to add a view accessor to the view object you are currently editing.

    Alternatively, you can expand List Data Source and select among the existing view accessors. The dropdown list displays all view accessors that you have added to the view object you are editing.

  5. In the View Accessors dialog, select the view object instance name that you created for the data source view object and shuttle it to the view accessors list.

  6. With the new view accessor selected in the dialog, click Edit.

  7. In the Edit View Accessor dialog, apply the previously defined view criteria to the view accessor and provide a value for the bind variable as follows:

    • Click the data source view object's view criteria in the Available list and add it to the Selected list. For example, you would select SupplierCriteria from the SupplierIdsForCurrentSupplierSite view object definition.

    • Set the value for the bind variable to the name of the controlling attribute. The attribute name must be identical to the base view object's controlling attribute. For example, if the base view object PurchaseOrdersView contains the LOV-enabled attribute SupplierSiteId that depends on the value of the controlling attribute SupplierId, you would enter SupplierId for the bind variable value.

    • Select the name of the previously defined bind variable from the Parameter list.

    • Select Required from the Usage dropdown list.

  8. Click OK to save the view accessor definition for the base view object.

  9. In the Attributes page of the overview editor, select the attribute that is to display the LOV, and then click the List of Values tab and click the Add list of values button.

  10. In the Create List of Values dialog, expand List Data Source and select the view accessor you created for the data source view object instance to use as the data source. Then select the controlling attribute from this view accessor that will serve to filter the attribute you are currently editing.

    The editor creates a default mapping between the view object attribute and the LOV-enabled attribute. You use separate attributes in order to allow the bind variable (set by the user's controlling attribute selection) to filter the LOV-enabled attribute. For example, the LOV-enabled attribute SupplierId from the PurchaseOrdersView view object would map to the controlling attribute SupplierSiteId for the SupplierIdsForCurrentSupplierSiteViewAccessor. The runtime automatically supports these two cascading LOVs where the row set and the base row attribute differ.

  11. Click OK.

5.12.3 How to Specify Multiple LOVs for a Single LOV-Enabled View Object Attribute

Another way to vary the list of values that your application user interface can display is to define multiple list of values for a single LOV-enabled view object attribute. In contrast to a cascading list, which varies the list contents based on a dependent LOV list selection, an LOV-enabled switcher attribute with multiple LOVs lets you vary the entire LOV itself. The LOV choice to display is controlled at runtime by the value of an attribute that you have defined specifically to resolve to the name of the LOV to apply.

For example, you might want to define one LOV to apply in a create or edit form and another LOV to apply for a search component. In the first case, the LOV-enabled attribute that the form can use is likely to be an entity-based view accessor that is shared across all the view objects that reference the entity. The entity-based view accessor is useful for user interface forms because a single accessor definition can apply to each instance of the same LOV in the forms. However, in the case of the search component, LOV definitions based on view accessors derived from an underlying entity will not work. The LOV definitions for search components must be based on view accessors defined in the view object. Note that when the user initiates a search, the values in the criteria row will be converted into WHERE clause parameters. Unlike a regular view row displayed in create or edit type forms, the criteria row is not backed by an entity. In this scenario, one LOV uses the entity-based accessor as a data source and a second LOV uses the view object-based accessor as a data source.

To address this requirement to define multiple LOV lists that access the same attribute, you add a switcher attribute to the base view object. For example, you might add a ShipperLOVSwitcher attribute for the Orders view object that resolves through an expression to the name of the LOV to display. Such an expression can specify two LOVs that may apply to the ShipperID attribute:

(adf.isCriteriaRow) ? "LOV_ShipperID_ForSearch" : "LOV_ShipperID"

This expression would appear in the Value field of the switcher attribute. At runtime, in the case of the search component, the expression resolves to the value that identifies the view object-based accessor LOV. In the case of the create or edit form, the expression resolves to the value that identifies the entity-based accessor LOV.

You will use the Create List of Values dialog to add multiple LOV lists to an attribute of the base view object. You will also use the List of Values section in the Attributes page of the overview editor for the base view object to define the default LOV to display and the switcher attribute to apply.

Before you begin:

It may be helpful to have an understanding of LOV-enabled attributes. For more information, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

  • Create the first LOV list for the attribute, as described in Section 5.12.1, "How to Define a Single LOV-Enabled View Object Attribute."

    Note that the switcher attribute scenario requires that you create unique view accessors. You must not reuse a view accessor to define multiple LOV lists. Reusing a view accessor across various use cases can produce unintended results at runtime.

To specify additional LOV lists for a view object attribute with an existing LOV:

  1. In the Applications window, double-click the view object that contains the attribute for which you want to specify multiple LOV lists.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the desired attribute, and then click the List of Values tab and click the Add list of values button.

  4. In the Create List of Values dialog, define the first LOV, as described in Section 5.12.1, "How to Define a Single LOV-Enabled View Object Attribute."

    When you define the LOV, change the name of the LOV to match the value returned by the attribute that you will use to determine which LOV your application applies to the LOV-enabled attribute.

  5. After you define the first LOV, return to the List of Values tab of the Attributes page of the overview editor and, with the original attribute selected, click the Add List of Values button.

    If you have selected the correct attribute from the Attributes page of the overview editor, the List of Values section should display your previously defined LOV.

  6. In the Create List of Values dialog, repeat the procedure described in Section 5.12.1, "How to Define a Single LOV-Enabled View Object Attribute" to define each subsequent LOV.

    The name of each LOV must correspond to a unique value returned by the attribute that determines which LOV to apply to the LOV-enabled attribute.

    You must define the second LOV using a unique view accessor, but you may use any attribute. There are no restrictions on the type of LOV lists that you can add to an attribute with multiple LOV lists specified.

    After you finish defining the second LOV, the List of Values section in the view object overview editor changes to display additional features that you will use to control the selection of the LOV.

  7. In the Attributes page of the overview editor, click the List of Values tab and use the List of Values Switcher dropdown list to select the attribute that will return the name of the List of Value to use.

    The dropdown list displays the attributes of the base view object. If you want your application to dynamically apply the LOV from the LOVs you have defined, your view object must define an attribute whose values resolve to the names of the LOVs you defined. If you have not added this attribute to the view object, be sure that the dropdown list displays <None Specified>. In this case, at runtime your application will display the LOV-enabled attribute with the default LOV and it will not be possible to apply a different LOV.

  8. To change the default LOV to apply at runtime, choose the Default radio button corresponding to the desired LOV definition.

    The default LOV selection determines which list of values your application will display when the List of Values Switcher dropdown list displays <None Specified>. Initially, the first LOV in the overview editor List of Values section is the default.

  9. To change the component that your application will use to display the various LOV lists, select from desired component from the List Type UI Hint dropdown list.

    The component you select will apply to all LOV lists. For a description of the available components, see Table 5-2.

5.12.4 How to Define an LOV to Display a Reference Attribute

Reference attributes that your view objects define are often desirable attributes to use as the source for LOV lists. Reference attributes belong to secondary entity usages that you have added to the view object to provide meaningful information beyond the entity usage's primary key attribute. For example, when you create an OrderInfo view object, the view object may define a secondary entity usage for PaymentOptionsEO to include billing information for the order, including the list of credit cards the end user has added to their account.

An LOV that you define for the secondary entity object needs to be able to update the primary attribute value, but to be meaningful to the end user, you typically hide the primary attribute in the list and display one or more reference attributes instead. In this case, your LOV might display the list of credit cards by institution name, but hide the payment option ID value that gets updated by the end user's selection. Figure 5-38 shows the LOV defined on the reference attribute InstitutionName. The List Return Values section of the Create List of Values dialog lists the reference attribute and then lists the primary key attribute PaymentOptionId to provide supplemental values.

Figure 5-38 Create View Criteria Dialog with Reference Attribute Specified

Create List of Values dialog displays reference attribute

Before you begin:

It may be helpful to have an understanding of reference attributes in secondary entity usages. For more information, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the entity-based view object and add a secondary entity usage that defines the desired LOV attributes, as described in Section 5.12.1, "How to Define a Single LOV-Enabled View Object Attribute." By default, the secondary entity usage will include the primary key attribute that you want the LOV to update.

To define reference attributes for an LOV:

  1. In the Applications window, double-click the view object that contains the secondary entity usage attribute you wish to enable as an LOV.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the desired reference attribute that is to display the LOV, click the List of Values tab, and then click the Add List of Values button.

    Use the Create List of Values dialog to create the LOV on the attribute you have currently selected in the attribute list of the overview editor. JDeveloper assigns a unique name to identify the LOV usage. For example, the metadata for the attribute SupplierDesc will specify the name SupplierDescLOV to indicate that the attribute is LOV-enabled.

  4. In the Create List of Values dialog, click the Create new view accessor button to add a view accessor to the view object you are currently editing.

    Alternatively, you can expand List Data Source and select among the existing view accessors. The dropdown list displays all the view accessors that you have added to the view object you are editing.

  5. In the View Accessors dialog, select the view object definition or shared view instance that defines the data source for the attribute and shuttle it to the view accessors list.

    By default, the view accessor you create will display the same name as the view object. You can edit the accessor name to supply a unique name. For example, assign the name SuppliersViewAccessor for the SuppliersView view object.

  6. Click OK to save the view accessor definition for the view object.

  7. In the Create List of Values dialog, expand List Data Source and select the view accessor you created for the base view object to use as the data source. Then select the same attribute from this view accessor that will provide the list data for the LOV-enabled attribute.

    The editor creates a default mapping between the list data source attribute and the LOV-enabled attribute. For example, the attribute SuppliersDesc from the PurchaseOrdersView view object would map to the attribute SuppliersDesc from the SuppliersViewAccessor view accessor.

    The editor does not allow you to remove the default attribute mapping for the attribute for which the list is defined.

  8. If you want to specify supplemental values that your list returns to the base view object, click the Create return attribute map button in the List Return Values section and map the desired base view object attributes with attributes accessed by the view accessor.

    Supplemental attribute return values are useful when you do not require the user to make a list selection for the attributes, yet you want those values, as determined by the current row, to participate in the update. For example, to map the attribute SupplierAddress from the PurchaseOrdersView view object, you would choose the attribute SupplierAddress from the SuppliersViewAccessor view accessor.

  9. Click OK.

5.12.5 How to Set User Interface Hints on a View Object LOV-Enabled Attribute

When you know how the view object attribute that you define as an LOV should appear in the user interface, you can specify additional properties of the LOV to determine its display characteristics. These properties, or UI hints, augment the attribute hint properties that ADF Business Components lets you set on any view object attribute. Among the LOV UI hints for the LOV-enabled attribute is the type of component the user interface will use to display the list. For a description of the available components, see Table 5-2. (Not all ADF Faces components support the default list types, as noted in the Table 5-2.)

Table 5-2 List Component Types for List Type UI Hint

LOV List Component TypeUsage

Choice List

Choice list type

This component does not allow the user to type in text, only select from the dropdown list.

Combo Box

Combo box type

This component allows the user to type text or select from the dropdown list. This component sometimes supports auto-complete as the user types.

This component is not supported for ADF Faces.

Combo Box with List of Values

Combo Box with List of Values LOV type.

This component is the same the as the combo box, except that the last entry (More...) opens a List of Values lookup dialog that supports query with filtering when enabled for the LOV attribute in its UI hints. The default UI hint enables queries on all attributes.

Note that when the LOV attribute appears in a table component, the list type changes to an Input Text with List of Values component.

Input Text with List of Values

Input Text with LOV type

This component displays an input text field with an LOV button next to it. The List of Values lookup dialog opens when the user clicks the button or enters an invalid value into the text field. The List of Values lookup dialog for this component supports query with filtering when enabled in the UI hints for the LOV attribute. The default UI hint enables queries on all attributes.

This component may also support auto-complete when a unique match exists.

List Box

List box type

This component takes up a fixed amount of real estate on the screen and is scrollable (as opposed to the choice list, which takes up a single line until the user clicks on it).

Radio Group

Radio group type

This component displays a radio button group with the selection choices determined by the LOV attribute values. This component is most useful for very short, fixed lists.


Before you begin:

It may be helpful to have an understanding of LOV-enabled attributes. For more information, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the LOV list for the attribute, as described in Section 5.12.1, "How to Define a Single LOV-Enabled View Object Attribute."

To set view object attribute UI hints for an LOV-enabled attribute:

  1. In the Applications window, double-click the view object that contains the attribute that you want to customize.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the desired attribute and then click the List of Values tab.

  4. In the List of Values page, select the LOV list that you want to customize and click the Edit list of values button.

  5. In the Edit List of Values dialog, click the UI Hints tab.

  6. In the UI Hints page, select a default list type as the type of component to display the list.

    For a description of the available components, see Table 5-2.

    The list component displayed by the web page and the view object's default list type must match at runtime or a method-not-found runtime exception results. To avoid this error, confirm the desired list component with the user interface designer. You can also edit the default list type to match, so that, should the user interface designer subsequently change the component used in the web page, the two stay in sync.

  7. Optionally, select additional display attributes to add values to the display.

    The list of additional attributes is derived from the LOV-enabled attribute's view row. The additional attribute values can help the end user select an item from the list.

  8. If you selected the Combo Box with List of Values type component, by default, the dropdown list for the component will display the first 10 records from the data source. This limit also serves to keep the view object fetch size small. To change the number of records the dropdown list of a Combo Box with List of Values component can display, enter the number of records for Query Limit.

    When you want the user to be able to view the full set of records, do not use Query Limit for this purpose. Because Query Limit also controls the number of rows the view object will fetch (it sets the view object definition ListRangeSize property), the value should be keep small for optimal performance. The end user who needs access to the full set of records should click on the component's lookup icon to open an LOV lookup dialog and view the records there.

    Query Limit is disabled for all other component types and those components place no restriction on the number of rows that the LOV will access.

    For details about the ListRangeSize property, see Section 5.12.10, "What Happens at Runtime: How an LOV Queries the List Data Source."

  9. If you selected a component type that allows the user to open a List of Values lookup dialog to select a list value (this includes either the Combo Box with List of Values type component or Input Text with List of Values type component), by default, the lookup dialog will display a search form that will allow the user to search on all queryable attributes of the data source view object (the one defined by the LOV-enabled attribute's view accessor). Decide how you want to customize these components.

    1. When you select the Combo Box with List of Values type component and you have added a large number of attributes to the Selected list, use Show in Combo Box to improve the readability of the dropdown list portion of the component. To limit the attribute columns to display in the dropdown list that the Combo Box with List of Values component displays, choose First from Show in Combo Box and enter a number corresponding to the number of attributes from the top of the Selected list that you want the dropdown list to display (this combination means you are specifying the "first" x number of attributes to display from the Create List of Values dialog's Selected list). Limiting the number of attribute columns to display in the dropdown list ensures that the user does not have to horizontally scroll to view the full list, but it does not limit the number of attribute columns to display in the List of Values lookup dialog. This option is disabled for all list component types except Combo Box with List of Values.

    2. You can limit the attributes to display in the List of Values lookup dialog by selecting a view criteria from the Include Search Region dropdown list. To appear in the dropdown list, the view criteria must already have been defined on the data source view object (the one that the LOV-enabled attribute's view accessor defines). Click the Edit View Criteria button to set search form properties for the selected view criteria. For more information about customizing view criteria for search forms, see Section 5.9.5, "How to Set User Interface Hints on View Criteria to Support Search Forms."

    3. You can prepopulate the results table of the List of Values lookup dialog by selecting Query List Automatically. The List of Values lookup dialog will display the results of the query when the user opens the dialog. If you leave this option deselected, no results will be displayed until the user submits the search form.

  10. Alternatively, if you prefer not to display a search region in the List of Values lookup dialog, select <No Search> from the Include Search Region dropdown list. In this case, the List of Values lookup dialog will display only attributes you add to the Display Attributes list.

  11. If you selected a choice type component to display the list, you can specify a Most Recently Used Count as an alternative to displaying all possible values.

    For example, your form might display a choice list of SupplierId values to drive a purchase order form. In this case, you can allow the user to select from a list of their most recently viewed suppliers, where the number of supplier choices is determined by the count you enter. The default count 0 (zero) for the choice list displays all values for the attribute.

  12. If you selected a Combo Box with List of Values type component to display the list, you can select a view criteria from the Filter Combo Box Using dropdown list to limit the list of valid values the LOV will display.

    When you enable Filter Combo Box Using, the dropdown list displays the existing view criteria from the view object definition related to the LOV's view accessor. If the dropdown list displays no view criteria, then the data source view object defines no view criteria. When you do not enable this feature, the Combo Box with List of Values component derives its values from the full row set returned by the view accessor. The filtered Combo Box with List of Values is a useful feature when you want to support the use of an LOV with popup search dialog or LOV with a dropdown list that has a limited set of valid choices. For details about using the Combo Box with List of Values component in user interfaces, see Section 33.1.2, "List of Values (LOV) Input Fields."

  13. Decide how you want the list component to handle a null value choice to display in the list component. This option is not enabled for every list component type that you can select.

    If you enable Include "No Selection" Item, you can also determine how the null value selection should appear in the list by making a selection from the dropdown list. For example, when you select Labeled Item, you can enter the desired label in the edit field to the right of the dropdown list or you can click the ... button (to the right of the edit field) to select a message string from the resource bundle associated with the view object. When you select a message string from the resource bundle, JDeveloper saves the string's corresponding message key in the view object definition file. At runtime, the UI locates the string to display based on the current user's locale setting and the message key in the localized resource bundle.

  14. Click OK.

5.12.6 How to Handle Date Conversion for List Type UI Components

When the LOV-enabled attribute of the view object is bound to date information (such as the attribute OrderShippedDate), by default Oracle ADF assumes a format for the field like yyyy-MM-dd hh:mm:ss, which combines date and time. This combined date-time format is specified by the ADF Business Components Date domain class (jbo.domain.Date) and creates a conversion issue for the ADF Faces component when the user selects a date supplied by the LOV-enable attribute. When the ADF Faces component is unable to convert the domain type to the Date type, the user interface invalidates the input field and displays the message Error: The date is not in the correct format.

To avoid this potential conversion error, configure a UI hint setting for the date value attribute of the view object that you want to enable for an LOV. The UI hint you specify will define a date-only mask, such as yyyy-MM-dd. Subsequently, any ADF Faces component that references the attribute will perform the conversion based on a pattern specified by its EL value-binding expression (such as #{bindings.Hiredate.format) and will reference the UI hint format instead of the ADF Business Components domain date-time. The conversion error happens when the EL expression evaluates to null because no format mask has been specified.

Before you begin:

It may be helpful to have an understanding of LOV-enabled attributes. For more information, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes."

You may also find it helpful to understand support for UI hints at the level of view objects. For more information about UI hints, see Section 5.13, "Defining UI Hints for View Objects."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the LOV list for the attribute, as described in Section 5.12.1, "How to Define a Single LOV-Enabled View Object Attribute."

To set a UI hint to match the date format for the LOV-enable attribute:

  1. In the Applications window, double-click the view object that contains the LOV-enabled attribute.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the date-value attribute that you want to customize with UI hints, and then click the UI Hints tab.

  4. In the UI Hints page, select Simple Date for the Format Type and choose the format with the date-only mask.

    Mapping of the ADF Business Components domain type to its available formatters is provided in the formatinfo.xml file in the BC4J subdirectory of the JDeveloper system directory (for example, C:\Documents and Settings\<username>\Application Data\JDeveloper\system<version#>\o.BC4J.\formatinfo.xml).

5.12.7 How to Automatically Refresh the View Object of the View Accessor

If you need to ensure that your view accessor always queries the latest data from the database table, you may set the Auto Refresh property on the data source view object. This property allows the view object instance to refresh itself after a change in the database. You can enable this feature for any view instance that your application modules define. Once you enable this property on a view object, it ensures that the changes a user commits to a database table will become available to any other user working with the same database table. A typical use case is to enable auto refresh for the data source view object when you define a view accessor for an LOV-enabled view object attribute.

Because the auto-refresh feature relies on the database change notification feature, observe these restrictions when enabling auto-refresh for your view object:

  • The view objects should query as few read-only tables as possible. This will ensure the best performance and prevent the database invalidation queue from becoming too large.

  • The application module that contains Updatable, auto-refresh view instances must be configured to lock rows during updates.

  • The database user must have database notification privileges. For example, to accomplish this with a SQL*Plus command use grant change notification to <user name>.

When you enable auto refresh for the view object, at runtime, prior to executing the view object query, the framework will use the JDBC API to register the view object query to receive Oracle database change notifications for underlying data changes. When the view object receives a notification (because its underlying data has changed), the row sets of the view object are marked as dirty and the framework will refresh the row set on the next server trip from the client to the middle tier. At that point, the dirty collections will be discarded and the request for the updated data will trigger a new query execution by the view object. For example, assume that a user can create or edit a calendar entry but cannot edit calendar entries added by other users. When the user creates a new entry, then in the same server trip the calendar entries that other users modified or entered will be updated. But when another user creates a calendar entry, the view object receives a notification and waits for the next server trip before it refreshes itself; the delay to perform the update prevents contention among various users to read the same data.


Best Practice:

Use optimistic row locking for web applications. Optimistic locking, the default configuration setting, assumes that multiple transactions can complete without affecting each other. Optimistic locking therefore allows auto-refresh to proceed without locking the rows being refreshed. Pessimistic row locking prevents the row set refresh and causes the framework to throw an exception anytime the row set has a transaction pending (for example, a user may be in the process of adding a new row). To ensure that the application module configuration uses optimistic row locking, open the Properties tab of the Edit Configuration dialog and confirm the property jbo.locking.mode is set to optimistic, as described in Section 49.11.1, "How to Confirm That Applications Use Optimistic Locking."


Before you begin:

It may be helpful to have an understanding of LOV-enabled attributes. For more information, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To register a view object to receive data change notifications:

  1. In the Applications window, double-click the view object that you want to receive database change notifications.

  2. In the overview editor, click the General navigation tab.

  3. In the Properties window, expand the Tuning section, and select True from the Auto Refresh dropdown list.

    If the Tuning section is not displayed in the Properties window, click the General navigation tab in the overview editor to set the proper focus.

5.12.8 How to Test LOV-Enabled Attributes Using the Oracle ADF Model Tester

To test the LOV you created for a view object attribute, use the Oracle ADF Model Tester, which is accessible from the Applications window.

The Oracle ADF Model Tester, for any view object instance that you browse, will display any LOV-enabled attributes using one of two component types you can select in the UI Hints page of the List of Values dialog. Currently, only a Choice List component type and Input Text with List of Values component type are supported. Otherwise, the Oracle ADF Model Tester uses the default choice list type to display the LOV-enabled attribute.

Before you begin:

It may be helpful to have an understanding of LOV-enabled attributes. For more information, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

To test an LOV using the Oracle ADF Model Tester:

  1. In the Applications window, expand the project containing the desired application module and view objects.

  2. Right-click the application module and choose Run.

  3. In the Oracle ADF Model Tester, select the desired view object from the section on the left. The Oracle ADF Model Tester displays the LOV-enabled attribute values in a dropdown list unless you specified the component type as an Input Text with List of Value, UI hint.

    Figure 5-39 shows an LOV-enabled attribute, SalesRepId for the CustomerVO, that specifies an input text field and List of Values dialog as the UI hint list type. The Input Text with List of Values component is useful when you want to display the choices in a separate LOV dialog. Other list types are not supported by the Oracle ADF Model Tester.

Figure 5-39 Displaying LOV-Enabled Attributes in the Oracle ADF Model Tester

LOV attribute values in tester

5.12.9 What Happens When You Define an LOV for a View Object Attribute

When you define an LOV for a view object attribute, the view object metadata defines the following additional information, as shown in Example 5-40 for the CustomerVO.SalesRepId attribute .

  • The <ViewAttribute> element names the attribute, points to the list binding element that defines the LOV behavior, and specifies the component type to display in the web page. For example, the LOV-enabled attribute SalesRepId points to the list binding named LOV_SalesRepId and defines the CONTROLTYPE input text field with list (input_text_lov) to display the LOV data.

    When the user interface designer creates the web page using the Data Controls panel, the <CONTROLTYPE Value="namedType"/> definition determines the component that JDeveloper will add to the web page. When the component type definition in the data model project does not match the component type displayed in the web page, a runtime exception will result. For more information, see Section 5.12.10, "What Happens at Runtime: How an LOV Queries the List Data Source."

  • The <ListBinding> element defines the behavior of the LOV. It also identifies a view accessor to access the data source for the LOV-enabled attribute. The view accessor is the ADF Business Components mechanism that lets you obtain the full list of possible values from the row set of the data source view object. For example, ListVOName="EmpVO1" points to the EmpVO1 view accessor, which accesses the view object EmpVO.

  • The <ListBinding> element maps the list data source attribute to the LOV-enabled attribute. For example, the ListAttrNames item Id is mapped to the LOV-enabled attribute SalesRepId.

  • The <ListBinding> element also identifies one or more attributes to display from the current row and provides a few options that are specific to the choice list type component. For example, the ListDisplayAttrNames item FirstName and LastName are extra attributes displayed by the LOV-enabled attribute SalesRepId. In this example, the value none for NullValueFlag means the user cannot select a blank item from the list.

Example 5-40 View Object MetaData For LOV-Attribute Usage

<ViewAttribute
    Name="SalesRepId"
    LOVName="LOV_SalesRepId"
    PrecisionRule="true"
    EntityAttrName="SalesRepId"
    EntityUsage="CustomerEO"
    AliasName="SALES_REP_ID">
    <Properties>
      <SchemaBasedProperties>
        <LABEL
          ResId="oracle.summit.model.views.CustomerVO.SalesRepId_LABEL"/>
        <CONTROLTYPE
          Value="input_text_lov"/>
      </SchemaBasedProperties>
    </Properties>
</ViewAttribute>
. . .
<ListBinding
    Name="LOV_SalesRepId"
    ListVOName="EmpVO1"
    ListRangeSize="10"
    NullValueFlag="none"
    MRUCount="0">
    <AttrArray Name="AttrNames">
      <Item Value="SalesRepId"/>
    </AttrArray>
    <AttrArray Name="ListAttrNames">
      <Item Value="Id"/>
    </AttrArray>
    <AttrArray Name="ListDisplayAttrNames">
      <Item Value="Id"/>
      <Item Value="FirstName"/>
      <Item Value="LastName"/>
    </AttrArray>
    <DisplayCriteria
      Hint="hide"/>
</ListBinding>
. . .
<ViewAccessor
    Name="EmpVO1"
    ViewObjectName="oracle.summit.model.views.EmpVO"
    OrderBy="EmpEO.LAST_NAME">
    <ViewCriteriaUsage
      Name="FilterByTitleIdVC"
      FullName="oracle.summit.model.views.EmpVO.FilterByTitleIdVC"/>
    <ParameterMap>
      <PIMap Variable="TitleIdBind">
        <TransientExpression><![CDATA[2]]></TransientExpression>
      </PIMap>
    </ParameterMap>
  </ViewAccessor>

5.12.10 What Happens at Runtime: How an LOV Queries the List Data Source

The ADF Business Components runtime adds view accessors in the attribute setters of the view row and entity object to facilitate the LOV-enabled attribute behavior. In order to display the LOV-enabled attribute values in the user interface, the LOV facility fetches the data source, and finds the relevant row attributes and mapped target attributes. The databound list component's default AutoSubmit property setting of false ensures the browser makes a server roundtrip only when the end user selects a value. As a result of the roundtrip, all list bindings in the ADF Model layer that are derived from the same LOV-enabled attribute get updated and the end-user selection is reflected in the corresponding list components of the user interface.

The number of data objects that the LOV facility fetches is determined in part by the ListRangeSize setting in the LOV-enabled attribute's list binding definition, which is specified in the Edit List of Values dialog that you display on the attribute from the view object overview editor. If the number of records fetched is very large, the default value for ListRangeSize may truncate the values available to the dropdown list component used to display the records. The default number of fetched records for LOV queries depends on the type of list component used to display the records. In the case of the Combo Box with List of Values component and the Input Text with List of Values component, the default value for ListRangeSize is 10. In the case of all other types of list components that you can select (including choice list, combo box, list box, and radio button group), the default value for ListRangeSize is set to -1. The value -1 means that the user will be able to view all the data objects from the data source. The ListRangeSize value has no effect on the records that the end user can search on in the lookup dialog displayed for the two List of Values type components. For more information about how each list component displays values, see Section 5.12.5, "How to Set User Interface Hints on a View Object LOV-Enabled Attribute."

Note that although you can alter the ListRangeSize value in the metadata definition for the <ListBinding> element, setting the value to a discrete number of records (for example, ListRangeSize="5") most likely will not provide the user with the desired selection choices. Instead, if the value is -1 (default for simple list components without an LOV dialog), then no restrictions are made to the number of records the list component will display, and the user will have access to the full set of values.


Performance Tip:

To limit the set of values an LOV displays, use a view accessor to filter the LOV binding, as described in Section 5.12.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.12.5, "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 Data Controls panel, JDeveloper automatically inserts the list component identified by the Default List Type selection you made for the view object's LOV-enabled attribute in the List UI Hint dialog. However, if the user interface designer changes the list type subsequent to creating the web page, ruyou will need to edit the selection in the List UI Hint dialog to match.

5.12.11 What You May Need to Know About Lists

There are several things you may need to know about LOVs that you define for attributes of view objects, including how to propagate LOV-enabled attributes from parent view objects to child view objects (by extending an existing view object) and when to use validators instead of an LOV to manage a list of values.

5.12.11.1 Inheritance of AttributeDef Properties from Parent View Object Attributes

When a view object extends another view object, you can create the LOV-enabled attribute on the base object. Then when you define the child view object in the overview editor, the LOV definition will be visible on the corresponding view object attribute. This inheritance mechanism allows you to define an LOV-enabled attribute once and later apply it across multiple view objects instances for the same attribute.

You can also use the overview editor to extend the inherited LOV definition. For example, you may add extra attributes already defined by the base view object's query to display in selection list. Alternatively, you can define a view object that uses a custom WHERE clause to query the supplemental attributes not already queried by the based view object. For information about customizing entity-based view objects, see Section 5.10, "Working with Bind Variables."

5.12.11.2 Using Validators to Validate Attribute Values

If you have created an LOV-enabled attribute for a view object, there is no need to validate the attribute using a List Validator. You only use an attribute validator when you do not want the list to display in the user interface, but still need to restrict the list of valid values. List validation may be a simple static data or it may be a list of possible values obtained through a view accessor you define. Alternatively, you might prefer to use Key Exists validation when the attribute displayed in the UI is one that references a key value (such as a primary, foreign, or alternate key). For information about declarative validation in ADF Business Components, see Chapter 11, "Defining Validation and Business Rules Declaratively."

5.13 Defining UI Hints for View Objects

One of the built-in features of ADF Business Components is the ability to define UI hints on view objects and attributes of view objects. UI hints are settings that the view layer can use to automatically display the queried information to the user in a consistent, locale-sensitive way. For example, in web pages, a UI developer may access UI hint values by entering EL expressions utility methods defined on the bindings name space and specified for ADF binding instance names.

JDeveloper stores the hints in resource bundle files that you can easily localize for multilingual applications.

5.13.1 How to Add Attribute-Specific UI Hints

To create UI hints for attributes of a view object, use the overview editor for the view object, which is accessible from the Applications window. You can also display and edit UI hints using the Properties window that you display for an attribute.

Before you begin:

It may be helpful to have an understanding of attribute UI hints. For more information, see Section 5.13, "Defining UI Hints for View Objects."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.8.1, "How to Create an Expert Mode View Object."

To customize view object attribute with UI hints:

  1. In the Applications window, double-click the view object that you want to customize with UI hints.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the attribute that you want to customize with UI hints, and then click the UI Hints tab and define the desired hints.

    For example, for an attribute UserId, you might enter a value for its Label Text hint like "Id" or set the Format Type to Number, and enter a Format mask of 00000.


Note:

Java defines a standard set of format masks for numbers and dates that are different from those used by the Oracle database's SQL and PL/SQL languages. For reference, see the Javadoc for the java.text.DecimalFormat and java.text.SimpleDateFormat classes.


5.13.2 How to Add View Object UI Hints

To create UI hints for attributes of a view object, use the overview editor for the view object, which is accessible from the Applications window. You can also display and edit several additional UI hints using the Properties window that you display for the view object.

Before you begin:

It may be helpful to have an understanding of UI hints. For more information, see Section 5.13, "Defining UI Hints for View Objects."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.8.1, "How to Create an Expert Mode View Object."

To customize view objects with UI hints:

  1. In the Applications window, double-click the view object that you want to customize with UI hints.

  2. In the overview editor, click the General navigation tab.

  3. In the General page, enter a Display Name to define an EL accessible hint for the view object name.

    For example, for a view object OrdersVO, you might enter a value for its Display Name hint like "Order".

  4. With the General page displayed in the overview editor, open the Properties window for the view object and expand the UI Hints section, and then enter additional hints as needed.

    For example, for a view object OrdersVO, you might enter a value for the Display Name (Plural) hint like "Orders" and, for the Description hint, you might enter a value like "customer orders".

5.13.3 How to Access UI Hints Using EL Expressions

A UI developer can access UI hints using EL expressions and display the hint values as data in a web page. The UI developer may access UI hints through the ADF binding instances that they create after dropping databound components into their web pages.

In the case of the view object hints, the UI developer accesses the view object hints through the collection binding defined for the view object. For example, assume that you have configured the view object UI hints as follows.

  • OrdersVO view object Display Name hint = Order

  • OrdersVO view object Display Name (Plural) hint = Orders

  • OrdersVO view object Description hint = customer orders

The UI developer might display a header that makes use of these hints like this:

Showing customer orders number 10 of 51 Orders.

Example 5-41 shows that the EL expression that produces the above text. In this EL expression the collection binding OrdersVO1 provides access to the view object hints. The names of the EL expression utility methods match the property names defined in the view object XML definition file for the UI hints. For example, the view object property name labelPlural, which defines the Display Name (Plural) hint, corresponds to the utility method name used in the expression bindings.OrdersVO1.hints.labelPlural.

Example 5-41 EL to Access View Object UI HInts

<af:panelHeader id="ph1"
           text="Showing #{bindings.OrdersVO1.hints.description} number
                          #{bindings.OrdersVO1.Orderno.inputValue} of
                          #{bindings.OrdersVO1.estimatedRowCount} 
                          #{bindings.OrdersVO1.hints.labelPlural}.">

5.13.4 What Happens When You Add UI Hints

When you define attribute UI hints for a view object or view object attributes, by default JDeveloper stores them in a resource bundle file. This allows the hints that you define to be localized for the generated forms and tables of the user interface.

The type of resource bundle file that JDeveloper uses and the granularity of the file are determined by settings on the Resource Bundle page of the Project Properties dialog. By default, JDeveloper sets the option to Properties Bundle and generates one .properties file for the entire data model project. For example, when you define UI hints for a view object in the Model project, JDeveloper creates the bundle file named ModelBundle.properties for the package.

Alternatively, if you select the option in the Project Properties dialog to generate one resource bundle per file, you can inspect the message bundle file for any view object by selecting the object in the Applications window and looking under the corresponding Sources node in the Structure window. The Structure window shows the implementation files for the component you select in the Applications window. You can inspect the resource bundle file for the view object by expanding the parent package of the view object in the Applications window, as shown in Figure 5-40.

Figure 5-40 Resource Bundle File in Applications Window

Image of Application Navigator with property file

For more information on the resource bundle options you can select, see Section 4.7.1, "How to Set Message Bundle Options."

Example 5-42 shows a sample message bundle file where the UI hint information appears. The first entry in each String array is a message key; the second entry is the locale-specific String value corresponding to that key.

Example 5-42 Resource File with Locale-Sensitive UI Hints

oracle.summit.model.views.CustomerVO.Id_FMT_FORMATTER=
                                       oracle.jbo.format.DefaultNumberFormatter
oracle.summit.model.views.CustomerVO.Id_FMT_FORMAT=00000
oracle.summit.model.views.CustomerVO.Id_LABEL=Id
oracle.summit.model.views.CustomerVO.Email_LABEL=Email Address
oracle.summit.model.views.CustomerVO.LastName_LABEL=Surname
oracle.summit.model.views.CustomerVO.FirstName_LABEL=Given Name

5.13.5 How to Define UI Category Hints

UI categories provide the means to group attributes that a view object defines. The category names that you create are identifiers to be used by the dynamic rendering user interface to group attributes for display. The user interface will render the attribute with other attributes of the same category. You can use the category hint to aid the user interface to separate a large list of view object attributes into smaller groups related by categories.

Additionally, you can specify the field order hint to reorder how the user interface will render the attribute values within its category. For example, if a view object defines four attributes attributeA, attributeB, attributeC, and attributeD and you specify the field order 4, 3, 2, and 1 respectively for each attribute, then wherever the user interface renders the category, the attributes of that category will appear in the order attributeD, attributeC, attributeB, and attributeA.


Note:

Use the UI Categories page in the overview editor for the view object to change the order of the attributes listed within a category you've created. JDeveloper automatically assigns and maintains the field order values of the attributes based on their order in the list, and you do not need to edit numeric values to define the field order hint.


The category and field order hints will be utilized by any dynamic rendering user interface that displays the attribute, including dynamic forms and search forms:

  • In the case of dynamic forms, the attributes from each category will appear in a separate tab.

  • In the case of search forms, the order of the form's individual view criteria is determined by the field order and category assigned to the attribute upon which the view criteria items are based.

To create UI categories for attributes of a view object, use the overview editor for the view object, which is accessible from the Applications window. You can create and edit categories for the entire view object using the UI Categories page, as shown in Figure 5-41.

Figure 5-41 Attribute UI Categories in View Object Overview Editor

Image of UI Categories overview editor page

When you assign a view object attribute to a category that you create in the UI Categories page, the order of the attributes displayed in the category list determines its numeric field order. The UI Categories page lets you change the field order of the attributes you've assigned to a category by dragging and dropping attributes within the list. When you drag and drop the attributes into the list, JDeveloper automatically maintains the correct sequence of the field order hints within the category. In the editor for the view object, you can view the assigned category name and field order value of individual attributes in the UI Hints tab of the Attributes page. JDeveloper synchronizes the UI Hints tab definitions with the changes you make in the UI Categories page.

Each category can have a label and tooltip text string resource to be utilized by the user interface when the category is rendered. You can localize these resource strings in the resource bundle file that you select to store the entries. For example, Figure 5-42 shows the attributes LastName and CreditRatingId with labels Sales Rep Name and Credit Rating in a category with the label Personal Information.

Figure 5-42 UI Categories Displayed in Oracle ADF Model Tester

UI categories displayed in tester

Before you begin:

It may be helpful to have an understanding of attribute UI hints. For more information, see Section 5.13, "Defining UI Hints for View Objects."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 5.1.2, "Additional Functionality for View Objects."

You will need to complete this task:

Create the desired view objects, as described in Section 5.2.1, "How to Create an Entity-Based View Object," and Section 5.8.1, "How to Create an Expert Mode View Object."

To create user interface categories and reorder the attributes for display:

  1. In the Applications window, double-click the view object that you want to customize with user interface categories.

  2. In the overview editor, click the UI Categories navigation tab.

  3. In the UI Categories page, click the Create New Category button to create the category and then right-click the new category and choose Rename.

  4. In the Rename dialog, enter the name of the category.

  5. In the overview editor, in the UI Hints section, enter the user interface Label Text and Tooltip Text for the category.

    The text that you enter will be added to the default resource bundle file for the project, as described in Section 5.13.4, "What Happens When You Add UI Hints." To select a different resource bundle file to store the label and tooltip strings, click the browse (. . .) button beside the text field.

  6. In the Categories list, expand the Default category and scroll the list of attributes to locate the attribute you want to add to a category.

    The Default category displays all the attributes that the view object you are editing defines. This category is displayed only by the overview editor as a selection list for the creation of UI Category hints and is not used as a category to render attributes in the user interface.

  7. Select the desired attribute and drag it into the new category you created. If the category contains more than one attribute, the position of the attribute that you drop into the list will determine its field order value.

    JDeveloper automatically assigns a numeric value to the field order hint based on the sequence of the attributes that appear within a UI Category list. The attribute you place at the top of a category list will be rendered by the user interface first, the attribute second in the list will be rendered second, and so on.

  8. To view the field order hint for the attribute, in the overview editor, click the Attributes navigation tab, select the attribute in the page, and then click the UI Hints tab.


    Tip:

    Do not edit the field order hint in the UI Hints tab; instead, use the UI Categories page of the view object editor to reorder the attributes in the list by dragging and dropping them. You can also right-click an attribute within a category list and choose Move Up, Move Down, or Move to Category to change the field order within the categories.


    The field order hint does not appear in the overview editor UI Categories page. The hint value is visible in the source for the view object definition or in the UI Hints tab that you display in the view object editor for a specific attribute.

5.13.6 What Happens When You Assign Attributes to UI Categories

When you define attribute UI categories for a view object, JDeveloper updates the view object's XML document file. JDeveloper adds the CATEGORY and the FIELDORDER UI hints in the <SchemaBasedProperties> element of the <ViewAttribute> element. The definition of the categories appears in a new <Category> element.

The metadata in Example 5-43 shows that the CustomerId attribute's CATEGORY hint refers to the AccountInformation category and the FirstName attribute's CATEGORY hint refers to the UserInformation category. The definition for both categories appears in <Category> elements. The FIELDORDER hint for each attribute specifies a numeric value, which JDeveloper assigns and maintains based on the order of the attributes in the UI categories lists you create in the overview editor. As shown in Example 5-43, the FIELDORDER hint is a decimal value. A decimal value is used by JDeveloper to allow you to insert new attributes into a category without requiring JDeveloper to change all the existing attribute values and still be able to maintain the correct order.

Note that the default field order value for the first attribute in a category is assigned by JDeveloper as 0.0. The field order value can be changed to any number to sort the category list, and it is not an index. The field order numeric values do not need to be contiguous.

Example 5-43 View Object MetaData for Attribute UI Category Hints

<Category
    Name="AccountInformation">
    <Properties>
      <SchemaBasedProperties>
        <LABEL
          ResId="CUSTOMER_DETAILS"/>
        <TOOLTIP
          ResId="AccountInformation_TOOLTIP"/>
      </SchemaBasedProperties>
    </Properties>
</Category>
<Category
    Name="UserInformation">
    <Properties>
      <SchemaBasedProperties>
        <TOOLTIP
          ResId="UserInformation_TOOLTIP"/>
        <LABEL
          ResId="CUSTOMER_DETAILS"/>
      </SchemaBasedProperties>
    </Properties>
</Category>
...
<ViewAttribute
    Name="CustomerId"
    IsNotNull="true"
    PrecisionRule="true"
    EntityAttrName="CustomerId"
    EntityUsage="CustomerEO"
    AliasName="CUSTOMER_ID">
    <Data>
      <Property
        Name="OWNER_SCOPE"
        Value="INSTANCE"/>
      ...
    </Data>
    <Properties>
      <SchemaBasedProperties>
        <CATEGORY
          Value="AccountInformation"/>
        <FIELDORDER
          Value="0.0"/>
      </SchemaBasedProperties>
    </Properties>
  </ViewAttribute>
...
<ViewAttribute
    Name="FirstName"
    PrecisionRule="true"
    EntityAttrName="FirstName"
    EntityUsage="CustomerEO"
    AliasName="FIRST_NAME">
    <Data>
      <Property
        Name="OWNER_SCOPE"
        Value="INSTANCE"/>
      ...
    </Data>
    <Properties>
      <SchemaBasedProperties>
        <CATEGORY
          Value="UserInformation"/>
        <FIELDORDER
          Value="0.0"/>
      </SchemaBasedProperties>
    </Properties>
</ViewAttribute>

5.13.7 What You May Need to Know About Resource Bundles

Internationalizing the model layer of an application built using ADF Business Components entails producing translated versions of each component's resource bundle file. For example, the Italian version of the QueryDataWithViewObjectsBundle.properties file would be a file named QueryDataWithViewObjectsBundle_it.properties, and a more specific Swiss Italian version would have the name QueryDataWithViewObjectsBundle_it_ch.properties.

Resource bundle files contain entries for the message keys that need to be localized, together with their localized translation. For example, assuming you didn't want to translate the number format mask for the Italian locale, the Italian version of the QueryDataWithViewoObjects view object message keys would look like what you see in Example 5-44. At runtime, the resource bundles are used automatically, based on the current user's locale settings.

Example 5-44 Localized View Object Component Resource Bundle for Italian

oracle.summit.model.views.CustomerVO.Id_FMT_FORMATTER=
                                          oracle.jbo.format.DefaultNumberFormatter
oracle.summit.model.views.CustomerVO.Id_FMT_FORMAT=00000
oracle.summit.model.views.CustomerVO.Id_LABEL=Codice Utente
oracle.summit.model.views.CustomerVO.Email_LABEL=Indirizzo Email
oracle.summit.model.views.CustomerVO.LastName_LABEL=Cognome
oracle.summit.model.views.CustomerVO.FirstName_LABEL=Nome

The resource bundles of the model project contribute one aspect of internationalizing the Fusion web application. Internationalization for specific locales also requires localizing the ADF Faces pages of the user interface. For more information about how to localize ADF Faces pages, see the "Internationalizing and Localizing Pages" chapter in Developing Web User Interfaces with Oracle ADF Faces.

PKkïPKz$DOEBPS/placeholder_controls.htm Designing a Page Using Placeholder Data Controls

19 Designing a Page Using Placeholder Data Controls

This chapter describes how to create and use placeholder data controls in an Oracle ADF application. It shows you how to create placeholder data types, including master-detail relationships. It also describes how to create and import sample data.

This chapter includes the following sections:

19.1 About Placeholder Data Controls

Application development is typically divided into two separate processes: technical implementation and user interface design. More often than not, they are undertaken by separate teams with very different skill sets. The two teams can work together either in a data-first approach or a UI-first approach, or with some overlap between the two. With either approach, the teams usually work together iteratively, refining the application with each cycle.

In a data-first approach, the model, or data control is built first. Then the designer creates the layout and page flow by dragging and dropping the data controls onto pages as UI components. The model data is automatically bound to the components. This approach requires the data model to be available before the designer can proceed.

In a UI-first approach, the designer creates the layout using components from the Components window. When the data controls do become available, UI components are then bound to them. With this approach, you should be able to see most of the layout and page flows to make a development evaluation. However, until the data controls are available and bound to components, the application may not fully convey the intent of its design. For instance, an application that has a master-detail relationship is best reviewed when there is actual data that dynamically drives that relationship.

Placeholder data controls are easy-to-create, yet fully functional, stand-in data controls that can efficiently speed up the design-development process. UI designers can use placeholder data controls to create page layouts and page flows without the need to have real data controls available. These placeholder controls can be loaded with sample data to realistically simulate application execution for design evaluations. When the real data controls are ready, the UI components can be easily rebound to complete the application.

Creating placeholder data controls is a purely declarative process and does not require coding. It does not require in-depth knowledge of the underlying model, data source technology, actual database schema, or any of the complex relationships in an actual production data control. Placeholder data controls do not require an existing data source or a database connection. You can define multiple data types with multiple attributes. You can also define nested master-detail hierarchies between data types. Placeholder data controls have the same built-in operations such as Execute, Next, and Create. An implicitly created named criteria item allows the user to create search forms as if view objects and view criteria were available.

19.1.1 Placeholder Data Controls Use Cases and Examples

For many complex applications, the UI design may actually drive the development of the model, or data source. In this UI-first scenario, having placeholder data controls with sample data is essential to properly model the behavior of the application. In some cases, even if production data controls are available, UI designers may opt to use placeholder data controls because of their flexibility and ease of use.

Placeholder data controls can be used in many situations. In addition to being used for design review and development, they can be used to develop realistic runtime mock-ups for usability studies, or for proof-of-concept requirements. They can be used to create demos when the data model is not yet ready.

19.1.2 Additional Functionality for Placeholder Data Controls

You may find it helpful to understand some data access features before you start working with placeholder data controls. Following are links to other functionality that may be of interest.

19.2 Creating Placeholder Data Controls

You add placeholder data controls to a project using the New Gallery. After the placeholder data control has been created, it appears as a node in the Data Controls panel. It has a different icon than do standard data controls. Instead of an Operations node, the placeholder data control has a Built-in Operations node. Although the Built-in Operations node contains Commit and Rollback operations, these operations do not perform commits or rollbacks because there is not an actual data source for the data.

When a data control is initially created, it does not have any data types associated with it. You will need to manually create the data types as described in section Section 19.3, "Creating Placeholder Data Types."

19.2.1 How to Create a Placeholder Data Control

Placeholder data controls are defined at the project level in JDeveloper. You must already have created a project before you can create placeholder data controls.

Before you begin:

It may be helpful to have an understanding of the options you have for creating placeholder data controls. For more information, see Section 19.2, "Creating Placeholder Data Controls."

You may also find it helpful to understand additional functionality that can be added after using placeholder data controls. For more information, see Section 19.1.2, "Additional Functionality for Placeholder Data Controls."

To create a placeholder data control:

  1. In the Applications window, right-click the project to which you want to add a placeholder data control and choose New > From Gallery.

  2. In the New Gallery, expand Business Tier, select Data Controls and then Placeholder Data Control, and click OK.

  3. In the Placeholder Data Control dialog, as shown in Figure 19-1, enter:

    • Name: The name of the placeholder data control.

    • Package: The package name that will be used to reference the placeholder data control.

    • Description: Optional description of the placeholder data control.

    Figure 19-1 New Placeholder Data Control

    New Placeholder Data Control dialog
  4. Click OK.

19.2.2 What Happens When You Create a Placeholder Data Control

When you create a placeholder data control, the package you selected to contain the data control appears under the project node in the Applications window. A data control XML file PlaceholderDataControl.xml appears under the package, where PlaceholderDataControl is the name of the placeholder data control. Example 19-1 shows a sample file called Placeholder01.xml, which was created when the Placeholder01 data control was created.

Example 19-1 Sample placeholder01.xml file

<?xml version='1.0' encoding='windows-1252' ?>
<AppModule
   xmlns="http://xmlns.oracle.com/placeholder"
   Name="Placeholder01" >
</AppModule>

JDeveloper also creates a DataControls.dcx file if it has not yet been defined, and adds entries for the placeholder data control, as shown in Example 19-2.

Example 19-2 Placeholder Data Control entry in DataControls.dcx

<?xml version="1.0" encoding="UTF-8" ?>
<DataControlConfigs xmlns="http://xmlns.oracle.com/adfm/configuration"
                    version="12.1.2" id="DataControls"
                    Package="model">
  <PlaceholderDataControl SupportsTransactions="true" SupportsFindMode="true"
                          SupportsResetState="true" SupportsRangesize="true"
                          SupportsSortCollection="true"
                          FactoryClass=
                            "oracle.adf.model.placeholder.DataControlFactoryImpl"
                          id="Placeholder01"
                          xmlns="http://xmlns.oracle.com/adfm/datacontrol"
                          Definition="model.prototype.Placeholder01"
                          Package="model.prototype"/>
</DataControlConfigs>

In the Data Controls panel, the placeholder data control appears alongside other data controls in the root tree. A placeholder data control that does not yet have data types defined will have only the Commit and Rollback built-in operations available, as shown in Figure 19-2.

Figure 19-2 Applications Window and Data Controls Panel

Application Navigator wit placeholder data control artifacts

19.3 Creating Placeholder Data Types

A standard data control obtains its data collections and attributes from its underlying data source in the model or business service layer. For example, an application module data control obtains its data collections from the view objects and associated database tables.

For a placeholder data control, instead of data collections, it has placeholder data types. A placeholder data type is analogous to a data collection. It can be dropped onto a page to create complex components such as forms, tables, and trees. It also has a set of attributes that can be dropped onto pages as individual components such as input text, output text, and select choice. Some attributes may be defined as LOVs.

When you first create a placeholder data control, it is devoid of any data types because there are no underlying database tables for the placeholder data control to reference. You must declaratively create one or more placeholder data types. For each data type, you specify attribute names, types, default UI components, and other options. You can create multiple data types for a data control, similar to the multiple data collections in an application module.

After you have created a placeholder data type, it appears as a child node of the placeholder data control. It also has a Built-in operations node with the standard set of operations. It has a Named Criteria node that contains an All Queriable Attributes item that is analogous to the named view criteria of a view object in a standard data control. You can drag and drop the All Queriable Attributes item onto a page to create a query or quick query search form. In a standard data control, you can create multiple view criteria on a view object. Because there is no real view object in a placeholder data type, only one All Queriable Attributes item is available. For more information about query search forms, see Chapter 33, "Creating ADF Databound Search Forms."

You can create master-detail relationships between placeholder data types, similar to the master-detail data collections in a standard data control. You can drop master-detail data types onto pages to create master-detail forms and tables. For more information on master-detail forms and tables, see Chapter 31, "Displaying Master-Detail Data."

JDeveloper allows you to reuse placeholder data types created for other placeholder data controls in the same project. When you are creating a data type, you can select an option to load existing data types from another placeholder data control. If you select the Import From: Existing Data Type option, the attributes from the imported data type will be added to the list of attributes.

You can also select an option to import the sample data associated with the imported data type when the attributes are added.


Note:

Although you do not need sample data until you run the application, you should add sample data to provide a consistent design time rendering of the components.


19.3.1 How to Create a Placeholder Data Type

After you have created a placeholder data control, you can proceed to create data types. You define a name for the data type, and define each of its individual attributes. For each attribute, you then define its type, format, default UI component, and whether or not it should be an LOV.

In order to simplify the process of creating placeholder data types, you can select from a list of four of the most common types: String, Boolean, Date, and Number. Because placeholder attributes are typed, you can create column labels and include UI control hints in the design.

If you have a sample data file in comma-separated value (CSV) format, you can create all the attributes and load sample data using the sample data file import function. You do not need to create the attributes. JDeveloper will create them for you from the format of the CSV file, which can optionally contain a list of column headings as the first row. The attributes default to type String. You can manually reset each attribute to another type as required. For instructions to import sample data, see Section 19.3.2.3, "How to Import Attributes and Sample Data to a Placeholder Data Type."

Before you begin:

It may be helpful to have an understanding of the options you have for creating placeholder data types. For more information, see Section 19.3, "Creating Placeholder Data Types."

You may also find it helpful to understand additional functionality that can be added after using placeholder data controls. For more information, see Section 19.1.2, "Additional Functionality for Placeholder Data Controls."

Additionally, you must first create the placeholder data control, as described in Section 19.2.1, "How to Create a Placeholder Data Control."

To create a placeholder data type:

  1. In the Applications window, double-click the placeholder data control to which you want to add a placeholder data type.

  2. In the overview editor, in the Data Types section, select the placeholder data control and click the New Placeholder Data Type icon.


    Note:

    You can alternatively open the Create Placeholder Data Type dialog by right-clicking the placeholder data control in the Data Controls panel, and choosing New Placeholder Data Type.


    Figure 19-3 shows the Create Placeholder Data Type dialog.

    Figure 19-3 Create Placeholder Data Type Dialog

    Create Placeholder Data Type dialog
  3. In the Create Placeholder Data Type dialog, enter a file name and package for the placeholder data type.

  4. If you have an existing placeholder data type or a .csv file, from which you want to import attributes and data, select Import From and select either .CSV File or Existing Data Type, and then specify the options for the import.

    To import from a .csv file:

    1. In the File Name field, specify the file from which you want to import, or click the Browse icon to navigate to and select the file.

    2. From the Character Set dropdown list, select the character set that the file uses.

    3. If your file has a header row with the names of the columns, select First row of the file contains Attribute names to import.

    To import from an existing placeholder data type:

    1. Expand the tree to locate and select an existing placeholder data type.

    2. If the existing data type contains data that you want to import, select Also Import Sample Data.

  5. Click OK.

    The placeholder data type is created and opened in the overview editor.

  6. In the overview editor, click the Attributes navigation tab to view, add, and edit attributes for the placeholder data type.

  7. Click the Data navigation tab to view, add, and edit sample data for the placeholder data type.

    You need sample data for runtime and for a consistent design time.

19.3.2 How to Add Attributes and Sample Data to a Placeholder Data Type

If you intend to run an application using the placeholder data control, you will need to add sample data to be displayed during execution. You can add sample data to the placeholder data type attributes manually or by importing the data from another placeholder data type or CSV file. Although having sample data is necessary only at runtime, you should add sample data for a consistent design time rendering of the components.

If you did not import attributes when you created your placeholder data type, you can add them using the Attributes page of the overview editor. Also, you can use the Data page of the overview editor to add sample data to be displayed during execution. Both the Attributes page and the Data page have an Import button that opens the Import Placeholder Data Type dialog, which allows you to import attributes and sample data.

Before you begin to add sample data to a placeholder data type, you should have already created a placeholder data control and a placeholder data type. If you are entering the data manually, you should have the data ready. If you are loading the data from a CSV file, you need to have the location of the file. If you are importing from another placeholder data type, you must have already created the other data type.

19.3.2.1 Manually Adding Attributes to a Placeholder Data Type

Using the Attributes page of the overview editor, you can add and configure attributes to a placeholder data type.

Before you begin:

It may be helpful to have an understanding of the options you have for creating placeholder data types. For more information, see Section 19.3, "Creating Placeholder Data Types."

You may also find it helpful to understand additional functionality that can be added after using placeholder data controls. For more information, see Section 19.1.2, "Additional Functionality for Placeholder Data Controls."

Additionally, you must first create the placeholder data control, as described in Section 19.2.1, "How to Create a Placeholder Data Control," and create the placeholder data type, as described in Section 19.3.1, "How to Create a Placeholder Data Type."

To manually add a placeholder data type attribute:

  1. In the Applications window, double-click the placeholder data type to which you want to add attributes.

  2. In the overview editor, click the Attributes navigation tab.

  3. On the Attributes page, click the Add icon.

  4. In the Insert View Attributes dialog, enter a name for the attribute, and click OK.

  5. After adding attributes, select an attribute and use the fields beside the attributes list to configure the selected attribute.

    • Name: Enter a name for the attribute.

    • Data Type: Select a type for the attribute from the dropdown list. The supported types are String, Boolean, Date, and Number.

    • Default Component: Select a default component for the attribute from the dropdown list. For an LOV, select Combo Box List of Values. Then click the Edit icon to configure the LOV. For more information, see Section 19.3.4, "How to Configure a Placeholder Data Type Attribute to Be a List of Values."

    • Default Value: Enter the initial value for the attribute.

    • Label: Enter a label for the attribute. The label will be used when the component is displayed.

    • Tooltip: Enter text to be displayed as a tooltip for the attribute.

    • Format Type: This field is enabled only when the type is Date or Number. Select a format type from the dropdown list.

    • Format: This field is enabled only when a format mask has been defined for that format type.

    • Display Width: Enter the character width to be used by the control that displays this attribute.

    • Searchable: Select this checkbox to make the attribute searchable.

    Click the Add icon to add more attributes.

19.3.2.2 Adding Sample Data Manually

You can use the Sample Data page of the Edit Placeholder Data Type dialog to manually enter sample data for your placeholder data control.

Before you begin:

It may be helpful to have an understanding of the options you have for creating placeholder data types. For more information, see Section 19.3, "Creating Placeholder Data Types."

You may also find it helpful to understand additional functionality that can be added after using placeholder data controls. For more information, see Section 19.1.2, "Additional Functionality for Placeholder Data Controls."

Before you add sample data to a placeholder data type, you need to perform the following tasks:

To add sample data to a placeholder data type manually:

  1. In the Data Controls panel, right-click the placeholder data type to which you want to add sample data, and choose Open.

  2. In the overview editor, click the Data navigation tab.

  3. In the Data page, click the Add icon to add a row to the data table, and enter a value for each attribute. Repeat as necessary until you have entered adequate sample data.

19.3.2.3 How to Import Attributes and Sample Data to a Placeholder Data Type

As an alternative to manually entering attributes and sample data for a placeholder data type, you can import them in a single operation. Using the Attributes page of the overview editor, you can import attributes from an existing placeholder data type or from a .csv file.

A .csv (comma-separated values) file is a plain text file containing rows of attribute values, delimited by commas. A .csv file can optionally have a header row that defines the names of each attribute.

In the overview editor for a placeholder data type, both the Attributes page and the Data page have an Import button that opens the Import Placeholder Data Type dialog, which allows you to import attributes and sample data.

Before you begin:

It may be helpful to have an understanding of the options you have for creating placeholder data types. For more information, see Section 19.3, "Creating Placeholder Data Types."

You may also find it helpful to understand additional functionality that can be added after using placeholder data controls. For more information, see Section 19.1.2, "Additional Functionality for Placeholder Data Controls."

Additionally, you must first create the placeholder data control, as described in Section 19.2.1, "How to Create a Placeholder Data Control," and create the placeholder data type, as described in Section 19.3.1, "How to Create a Placeholder Data Type."

To imcmport attributes into a placeholder data type:

  1. In the Applications window, double-click the placeholder data type to which you want to add attributes.

  2. In the overview editor, click the Attributes navigation tab.

  3. If you are importing attributes as well as sample data, you must delete any existing attributes in the placeholder data type.

    If you do not remove the existing attributes, JDeveloper imports only the first columns of data for the number of defined attributes. For example, if you have two attributes defined in your data type and four columns of sample data in your CSV file, JDeveloper will import only the first two columns of data.

  4. On the Attributes page, click Import.

  5. In the Import Placeholder Data Type dialog, specify where you want to import attributes from.

    To use a .csv file:

    1. Select Import from .CSV File.

    2. In the File Name field, enter the full path and name of the file, or click the Browse icon to navigate to and select it.

    3. From the Character Set dropdown list, select the character set represented in the specified .csv file.

    4. If the .csv file has a header row that contains the names of the attributes, select First row of the file contains Attribute names to import.

    To use an existing placeholder data type:

    1. Select Import from an Existing Placeholder Data Type.

    2. Expand the available placeholder data controls displayed to see the placeholder data types they contain, and select the one you want to copy.

    Figure 19-4 Import Placeholder Data Type Dialog

    Copy Placeholder Data Type dialog.
  6. Select the Also Import Sample Data checkbox to load sample data from the file or existing placeholder data type.

  7. Specify whether you would like to append or overwrite the attributes already defined for the placeholder data type.

    • Select Append to add the imported attributes to the current list of attributes in the placeholder data type

    • Select Overwrite to replace the current attributes with the imported attributes.

  8. Click OK.

  9. After importing attributes, you can optionally go to the Attributes page and reconfigure the attributes.

19.3.2.4 What Happens When You Add Sample Data

Placeholder sample data, whether added manually added or imported, are stored in message bundle files. Example 19-3 shows a sample message bundle with two rows of five attributes.

Example 19-3 Sample Data Properties File TelevisionMsgBundle.properties

model.prototype.SupplierLocationsDataType.SL_0_0=101
model.prototype.SupplierLocationsDataType.SL_0_1=so
model.prototype.SupplierLocationsDataType.SL_0_2=Houston
model.prototype.SupplierLocationsDataType.SL_0_3=TX
model.prototype.SupplierLocationsDataType.SL_0_4=USA
model.prototype.SupplierLocationsDataType.SL_1_0=101
model.prototype.SupplierLocationsDataType.SL_1_1=dw
model.prototype.SupplierLocationsDataType.SL_1_2=Atlanta
model.prototype.SupplierLocationsDataType.SL_1_3=GA
model.prototype.SupplierLocationsDataType.SL_1_4=USA

19.3.3 What Happens When You Create a Placeholder Data Type

When you create a placeholder data type, JDeveloper creates a PlaceholderDataType.xml file, where PlaceholderDataType is the name of the placeholder data type you had specified.

The PlaceholderDataType.xml file has the same format as a view object XML file. It includes the name of the view object and the name and values of each placeholder attribute that was defined.

Example 19-4 shows a PlaceholderDataType.xml for a Supplier data type. Two attributes are declaratively defined: Supplier_Id and Supplier_Name.

Example 19-4 Sample Placeholder Data Type XML File

<?xml version='1.0' encoding='windows-1252' ?>
<ViewObject
  xmlns="http://xmlns.oracle.com/placeholder"
  Name="SuppliersDataType"
  InheritPersonalization="merge"
  BindingStyle="OracleName"
  CustomQuery="true">
  <ViewAttribute
    Name="Supplier_Id"
    Type="oracle.jbo.domain.Number"/>
  <ViewAttribute
    Name="Supplier_Name"
    Type="java.lang.String"/>
</ViewObject>

Since a data type is similar to a data collection and is based on a view object, each data type will have a corresponding PlaceholderDataType.xml file.

JDeveloper also adds entries for each placeholder data type to the PlaceholderDataControl.xml file. For example, after the Suppliers data type is created, the data control XML file includes a new ViewUsage entry for the Suppliers data type, as shown in Example 19-5.

Example 19-5 Sample PlaceholderDataControl.xml File After Addition of Placeholder Data Type

<?xml version="1.0" encoding="windows-1252" ?>
<AppModule
  xmlns="http://xmlns.oracle.com/placeholder"
  Name="Placeholder01"
  InheritPersonalization="merge">
  <ViewUsage
    Name="SuppliersDataType"
    ViewObjectName="model.prototype.SuppliersDataType"/>
</AppModule>

In the Data Controls panel, a placeholder data type node appears under the placeholder data control. Expanding the node reveals the presence of each of the attributes, the Built-in Operations node, and the Named Criteria node.

Figure 19-5 shows a placeholder data control as it appears in the Data Controls panel.

Figure 19-5 Data Controls Panel Showing Placeholder Data Control

Placeholder data controls

19.3.4 How to Configure a Placeholder Data Type Attribute to Be a List of Values

A placeholder data type attribute can be configured to be a list of values (LOV). An LOV-formatted attribute binds to UI components that display dropdown lists or list picker dialogs. For more information about LOVs, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes."

When you are configuring a placeholder data type attribute, you can select an option to bring up a dialog to configure that attribute to be an LOV.

If you have only one data source, you can only create a fixed LOV. To create a dynamic LOV, there must be more than one placeholder data type available to be the source.

19.3.4.1 Configuring an Attribute to Be a Fixed LOV

Before you begin, you should determine which attribute you want to be a fixed LOV and which values should be in the fixed list.

Before you begin:

It may be helpful to have an understanding of the options you have for creating placeholder data types. For more information, see Section 19.3, "Creating Placeholder Data Types."

You may also find it helpful to understand additional functionality that can be added after using placeholder data controls. For more information, see Section 19.1.2, "Additional Functionality for Placeholder Data Controls."

Additionally, you must have already created the placeholder data type for your placeholder data control.

To configure an attribute to be a fixed LOV:

  1. In the Data Controls panel, right-click the placeholder data type and choose Open.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the attribute you want to configure as an LOV.

  4. Click the Edit LOV Binding icon next to the Default Component pulldown list.

    The Configure List of Values dialog appears, as shown in Figure 19-6.

    Figure 19-6 Configure List of Values Dialog for a Fixed LOV

    Configure LOV Fixed List dialog
  5. In the dialog, select Fixed List.

  6. Click the Add icon to add an entry to the list of values.

  7. For each entry, enter a label and a value.

    When the user selects an item from the list of values, the value entry will be entered into the input field.

  8. Specify the maximum number of the most recently used items that will be displayed in the dropdown list.

  9. From the No Selection Item dropdown list, select an option for how you want the "no selection" item to be displayed.

    For instance, selecting Blank Item (First of List) will display the "no selection" item as a blank at the beginning of the list.

  10. Click OK.

19.3.4.2 Configuring an Attribute to Be a Dynamic LOV

Using a placeholder data type to serve as the source, you can configure an attribute to be a dynamic LOV.

Before you begin:

It may be helpful to have an understanding of the options you have for creating placeholder data types. For more information, see Section 19.3, "Creating Placeholder Data Types."

You may also find it helpful to understand additional functionality that can be added after using placeholder data controls. For more information, see Section 19.1.2, "Additional Functionality for Placeholder Data Controls."

Also, you should have already created another placeholder data type to serve as the source of the dynamic LOV.

To configure an attribute to be a dynamic LOV:

  1. In the Data Controls panel, right-click the placeholder data type and choose Open.

  2. In the overview editor, click the Attributes navigation tab.

  3. In the Attributes page, select the attribute you want to configure as an LOV.

  4. Click the Edit LOV Binding icon next to the Default Component pulldown list.

    The Configure List of Values dialog appears, as shown in Figure 19-7.

    Figure 19-7 Configure List of Values Dialog for a Dynamic LOV

    Configure LOV dialog
  5. In the Configure List of Values dialog, select Dynamic List.

  6. Select the list data type with the source attribute. You must have a source placeholder data type for this selection to be available.

  7. Select the list attribute.

  8. Shuttle the desired display attributes from the Available list to the Selected list.

  9. Select the maximum number of the most recently used items that will be displayed in the dropdown list.

  10. From the No Selection Item dropdown list, select an option for how you want the "no selection" item to be displayed. For example, selecting Blank Item (First of List) will display the "no selection" item as a blank at the beginning of the list.

  11. Click OK.

19.3.5 How to Create Master-Detail Data Types

You create master-detail relationships between data types in the same way you create master-detail hierarchies between tables. In a standard data control, you can use view links to define source and target view objects that would become the master and the detail objects. For more information about master-detail relationships, see Chapter 31, "Displaying Master-Detail Data."

You first create a master data type and its attributes. Then you create a detail data type as a child of the master data type. You define the source attribute in the master data type that defines the relationship to the detail data type.

Before you begin:

It may be helpful to have an understanding of the options you have for creating placeholder data types. For more information, see Section 19.3, "Creating Placeholder Data Types."

You may also find it helpful to understand additional functionality that can be added after using placeholder data controls. For more information, see Section 19.1.2, "Additional Functionality for Placeholder Data Controls."

Before you create a placeholder master-detail hierarchy, you must perform the following tasks:

  • Determine the data structure of the master data type and the data structure of the detail data type.

  • Determine which attribute in the master will be the source for the detail data type.

  • Create a placeholder data type to be the master, as described in Section 19.3.1, "How to Create a Placeholder Data Type."

To create master-detail hierarchical data types:

  1. In the Data Controls panel, right-click the master placeholder data type and choose New Child Placeholder Data Type.

    Figure 19-8 shows the Create Placeholder Data Type dialog for entering detail data type attributes.

    Figure 19-8 Create Child Placeholder Data Type Dialog

    Create Placeholder Data Type dialog
  2. In the Create Placeholder Data Type dialog, enter a name and package for the detail data type.

  3. From the Join Attribute to Parent dropdown list, select the attribute from the master data type that will be used to join to the new detail data type.

  4. If you have an existing placeholder data type or a .csv file, from which you want to import attributes and data, select Import From and select either .CSV File or Existing Data Type, and then specify the options for the import.

    To import from a .csv file:

    1. In the File Name field, specify the file from which you want to import, or click the Browse icon to navigate to and select the file.

    2. From the Character Set dropdown list, select the character set that the file uses.

    3. If your file has a header row with the names of the columns, select First row of the file contains Attribute names to import.

    To import from an existing placeholder data type:

    1. Expand the tree to locate and select an existing placeholder data type.

    2. If the existing data type contains data that you want to import, select Also Import Sample Data.

  5. Click OK.

The Data Controls panel displays the detail data type as a child of the master data type, as shown in Figure 19-9. If you did not import attributes, you can add them now, as described in Section 19.3.2, "How to Add Attributes and Sample Data to a Placeholder Data Type."

Figure 19-9 Master Detail Hierarchy in Placeholder Data Control

Placeholder data control in Data Control pane

19.3.6 What Happens When You Create a Master-Detail Data Type

A master-detail relationship is implemented in the same way as is a standard master-detail relationship, using view object and view links. When you define placeholder data types in a master-detail hierarchy, JDeveloper creates a DTLink.xml file that contains metadata entries for view links that define that relationship. For more information about view links, see Section 6.2, "Working with Multiple Tables in a Master-Detail Hierarchy." For example, in the relationship between the master data type SuppliersDataType and the detail data type SupplierLocationsDataType associated with a key Supplier_Id, JDeveloper creates a DTLink.xml file in the form of a view link file to define that relationship, as shown in Example 19-6.

Example 19-6 DTLink.xml file for Master-Detail Data Type Relationships

<?xml version="1.0" encoding="windows-1252" ?>
<ViewLink
  xmlns="http://xmlns.oracle.com/placeholder"
  Name="DTLink"
  InheritPersonalization="merge">
  <ViewLinkDefEnd
    Name="SuppliersDataType"
    Cardinality="1"
    Source="true"
    Owner="model.prototype.SuppliersDataType">
    <AttrArray Name="Attributes">
      <Item Value="model.prototype.SuppliersDataType.Supplier_Id"/>
    </AttrArray>
  </ViewLinkDefEnd>
  <ViewLinkDefEnd
    Name="SupplierLocationsDataType"
    Cardinality="-1"
    Owner="model.prototype.SupplierLocationsDataType">
    <AttrArray Name="Attributes">
      <Item Value="model.prototype.SupplierLocationsDataType.Supplier_Id"/>
    </AttrArray>
  </ViewLinkDefEnd>
</ViewLink>

19.4 Using Placeholder Data Controls

You use placeholder data controls in the same way you would use standard data controls. You can drag data types onto pages and use the context menus to drop the data types as forms, tables, trees, graphs, and other components. You can drop individual attributes onto pages as text, lists of values, single selections, and other components. You can use any of the built-in operations such as Create, Execute, and Next by dropping them as buttons, command links, and menu items.

You can work in several ways to take advantage of placeholder data controls:

19.4.1 Limitations of Placeholder Data Controls

You can use placeholder data controls in your application development in many situations. For most UI design evaluations, placeholder data controls should be able to fully substitute for real data controls.

There are a few limitations:

  • Because data types are not tied to an underlying data source, the Commit and Rollback operations do not perform real transactions, nor do they update the cache.

  • Placeholder data controls can only be created declaratively. You cannot create custom methods like you can with a real application module or data control.

  • Placeholder data controls cannot be used when there is a need either for custom data or for filtering or custom code to fetch data. Placeholder data controls will disable those operations.

19.4.2 Creating Layout

Use the drag-and-drop feature to create the page using the placeholder data controls, any available real data controls, and components from the Components window. If you intend to run a page or application that requires real data, enter sample data for your placeholder data types. If you have a large amount of sample data, you may be able to create CSV files from the data source and load them into the data type. You may also use spreadsheets and other tools to create CSV sample data files.

19.4.3 Creating a Search Form

In a standard data control, you can create view criteria on view objects to modify the query. These view criteria are also used for drag-and-drop creation of query and quick query search forms. The named view criteria items appear under the Named Criteria node for a data collection. For more information about query and quick query search forms, see Chapter 33, "Creating ADF Databound Search Forms."

For placeholder data controls, there is also a Named Criteria node under each data type node. An automatically created All Queriable Attributes item appears under this node and can be used to drag and drop onto pages to create the query or quick query search forms.

19.4.4 Binding Components

Instead of building the page using the data controls, for instance, if you are unsure of the shape of your data, you can lay out the page first using the Components window and later bind it to the data types, attributes, or operations of the placeholder data controls.

19.4.5 Rebinding Components

After the final data controls are available, you can simply rebind the components. You can select the component in the Structure window and use the context menu to open the relevant rebind dialog. You can also drag and drop the data control item onto the UI component to initiate a rebinding editor. The rebinding procedures are the same whether the component was originally bound to a placeholder data control or a standard data control.

For more information about rebinding components, see Chapter 28, "Creating a Basic Databound Page" and Chapter 29, "Creating ADF Databound Tables."

19.4.6 Packaging Placeholder Data Controls to ADF Library JARs

A useful feature of placeholder data controls is that they allow parallel development and division of labor among developers and designers. You may be able to leverage that further by packaging placeholder data controls into reusable components as ADF Library JARs. ADF Libraries are JARs that have been packaged to contain all the necessary artifacts of an ADF component. For more information about reusable components and the ADF Library, see Chapter 44, "Reusing Application Components." You can create libraries of placeholder data controls and distribute them to multiple designers working on the same UI project. Because they are lightweight, you can even use them in place of available real data controls for the earlier phases of UI design.

PK4L1PKz$DOEBPS/lists.htm Creating Databound Selection Lists and Shuttles

32 Creating Databound Selection Lists and Shuttles

This chapter describes how to create lists and shuttle components from data modeled with ADF Business Components, using ADF data binding and ADF Faces components. It describes how to create the List of Value (LOV) components that utilize a query to populate the selection list. It includes instructions for creating standard selection components that use a model-driven, fixed-value, or dynamically generated list. It describes how to add navigation list bindings to let users navigate through a list of objects in a collection. It also describes how to use the shuttle component to allow the user to quickly move items between two lists.

This chapter includes the following sections:

32.1 About Selection Lists and Shuttles

Selection list components present the user with a list of choices as input values. The selection list may be model-driven, obtained from a fixed list, or dynamically created at runtime. Selection list components can be rendered as lists, radio buttons, checkboxes, and list boxes. Some selection types can also be singular (select one) or multiple (select many).

Selection lists and shuttles work the same way as do standard JSF list components. ADF Faces list components, however, provide extra functionality such as support for label and message display, automatic form submission, and partial page rendering. When you present users with a list, they can readily see the available choices and make a selection. Picking from a list also eliminates typing errors that may occur.

List of values (LOV) components are UI components that allow the user to enter values by picking from a list that is generated by a query. The LOV displays inside a modal popup dialog that typically includes search capabilities. The af:inputListOfValues and af:inputComboboxListOfValues components, for example, offer additional features that are not available in selection lists, such as search fields inside the LOV modal dialog and queries based on multiple table columns. For more information, see Section G.3.6, "How to Create a Popup List of Values" and Developing Web User Interfaces with Oracle ADF Faces.

List of values components offer more complex search and input capabilities by using the query component to create a popup search panel with a results table. The query component also has features such as auto-suggestion, smart list filtering, and custom facets for additional functionality.

When the user selects an item from a navigation list, a corresponding component bound to the list also changes its value in response to the selection. For example, when the user selects a product from a shopping list, the table that is bound to the products list updates to display the details of the selected product.

A shuttle allows the user to easily see the available items on an available list and the selected items in the selected list and to quickly move those items back and forth between the lists.

Shuttles provide a visual way to select items from an available list and at the same time see those selected items. ADF Faces provides the selectManyShuttle component and the selectOrderShuttle component, which allow reordering of the selected list. Both components can be implemented by adding code in a managed bean to populate the lists.

32.1.1 Selection Lists and Shuttles Use Cases and Examples

You can use a selection list component such as selectOneChoice for a single value input selection situation in which the list is relatively small. For example, you can use a selectOneChoice to select from a list of product colors or the type of credit card being used.

For larger lists and with more complex filtering, use an af:inputListOfValues or af:inputComboboxListOfValues component. These components use the query component to perform a transactional search to populate the list. For instance, you can use the af:inputComboboxListOfValues to select from a list of countries in an address input page.

Use the selectShuttle components when you want the user to be able to assemble a list of items and be able to select and unselect them. You should use the shuttle components when the number of items is large but not overwhelming to display. The user can review the selection and be able to iteratively select and unselect the items until the user is satisfied with the final selection. For instance, the available list could be the options available for a particular automobile and the user can shuttle the options the user likes to the selected list.

32.1.2 Additional Functionality for Selection Lists and Shuttles

You may find it helpful to understand other ADF features before you configure or use the ADF Model layer. Additionally, you may want to read about what you can do with your model layer configurations. Following are links to other functionality that may be of interest.

32.2 Creating List of Values (LOV) Components

List of values (LOV) components are input components that allow the user to enter values by picking from a list that is generated by a query. ADF Faces provides the af:inputListOfValues and af:inputComboboxListOfValues components. If you are creating a fully featured LOV component, you must define the LOV in the view object as described in Section 5.12, "Working with List of Values (LOV) in View Object Attributes."

If you are using dependent LOVs as part of your search form, you must use them with the af:query component. For more information about using LOV components with search forms, see Section 33.1.2, "List of Values (LOV) Input Fields."

The af:inputListOfValues component has a search icon next to the search criteria field, as shown in Figure 32-1.

Figure 32-1 Search Criteria Input Field Defined as an inputListOfValues

inputLOV component.

The af:inputComboboxListOfValues component has a dropdown icon next to the field, as shown in Figure 32-2 for the State attribute.

Figure 32-2 Search Criteria Input Field Defined as an inputComboboxListOfValues

inputComboboxListOfValues

For af:inputComboboxListOfValues, clicking the dropdown icon displays the LOV dropdown list and either a More or a Search link, as shown in Figure 32-3. A Search link appears when the LOV Search and Select popup dialog contains a search panel to refine the search. A More link appears when the popup dialog contains only the list-of-values table or when a smart list is used.

Figure 32-3 LOV Dropdown List with Search Link for inputComboboxListOfValues

inputComboboxListOfValues dropdown list.

The user can select any of the items in the dropdown list to populate the input field. The dropdown list includes a filtered list of values and an optional list of most recently used items. The width of each attribute in the dropdown list can be configured using the DisplayWidth UI hint for that attribute in the view object definition. The width of the dropdown list will be the sum of the widths of all the attributes in the dropdown list.

The user can also enter the value into the field. If the user enters data that is of a different data type than what is defined for the inputcomboboxListOfValues, a conversion error will be thrown. For example, if the inputcomboboxListOfValues is of NUMBER datatype and the user enters an alphanumeric string, a conversion error will result.

You can create custom content to be rendered in the Search and Select dialog using the searchContent facet. You can add components such as input text, tables, and trees to display the custom content. You will need to define the returnPopupDataValue attribute and implement a returnPopupListener. When you want to add the auto-complete feature with your custom popup, you can disable the popup by adding launchPopupEvent.setLaunchPopup(false) to your LaunchPopupListener() code. However, clicking on the Search link will still launch the Search and Select dialog. For more information about adding custom content, see the "Using List-of-Values Components" chapter of Developing Web User Interfaces with Oracle ADF Faces.

The resultsTable facet is used to display a custom message when the results table of the Search and Select dialog is empty.

If the component's readOnly attribute is set to true, then the input field will not be rendered and the value cannot be changed. By default, the readOnly attribute is set to false, which also enables the editMode attribute to determine whether the user is permitted only to select a value from the list (editMode set to select) or whether the user can also enter a value into the input field (editMode set to input).

You can also set up the LOV component to display a list of selectable suggested items when the user types in a partial value. For example, when the user types in CA, then a suggested list which partially matches CA is displayed as a suggested items list. The user can select an item from the list to be entered into the input field. If there are no matches, a "No results found" message will be displayed. You add the af:autoSuggestBehavior tag from the Components window into the LOV and set the selectedItem attribute to the suggestedItems method implemented in ADF Model.

Note that auto suggest behavior occurs in the Apply Request Values phase. If the immediate property is set to true, validation will be performed in the same phase. If there is a validation error, the suggestion list will not be displayed. If you want to add auto suggest behavior, do not set immediate to true.

When the user clicks the Search or More link (or for af:inputListOfValues, the search icon), the LOV Search and Select dialog appears with the full list of values in a table format. The LOV Search and Select dialog launched from a More link is shown in Figure 32-4.

Figure 32-4 LOV Search and Select Dialog

LOV search and select dialog

If a user enters a partial string in the LOV and click Search or tab out, a Search and Select dialog will appear with the partial string displayed in the search field and the resulting list of matching values in a table. The user can then select an entry from the list to be the LOV value.

The Search and Select popup dialog also presents a create function that allows the user to add a new row. Be aware that if you are creating a new record using the LOV Search and Select dialog, the new row will appear as an empty row in the table if the LOV has the Query Automatically control hint set to false. The content of the row will appear when you perform a query using the Search button. Example 32-1 shows a code sample that uses a link to invoke the create function.

Example 32-1 Create Function Sample Code

<f:facet name="customActions">
      <af:link id="createLink" text="Create..."
         partialSubmit="true">
                 <af:showPopupBehavior popupId="createSLPopup"
                 alignId="createLink"/>
      </af:link>
</f:facet>

If the LOV is part of a task flow that is using an isolated data control, and you use the create function to add a new record, the newly added record will not be displayed in the parent page. This is because the search region is also using an isolated data control scope, so the underlying view object updates are not displayed. For more information about shared and isolated data controls, see Section 24.2, "Sharing Data Controls Between Task Flows."

To programmatically refresh the LOV and display the view object updates, add a returnListener to the Create link with code similar to that shown in Example 32-2.

Example 32-2 Code to Refresh the LOV

public void refreshLOV() {
     BindingContainer bindings = this.getBindings(); 
     oracle.jbo.uicli.binding.JUCtrlListBinding lovBinding = 
         (oracle.jbo.uicli.binding.JUCtrlListBinding)
          bindings.get("Description1"); 
     JUIteratorBinding lovIter = lovBinding.getIteratorBinding(); 
     RowSet rs = lovIter.getRowSetIterator().getRowSet(); 
     rs.executeQuery(); 
       
    //Add LOV as the partialTrigger 
           
    AdfFacesContext.getCurrentInstance().addPartialTarget(this.getPlatformDesc()); 

An LOV is associated with a data source via the view accessor. You can apply one or more view criteria to the view accessor associated with the LOV. The view accessor provides permanent filtering to the LOV data source. In addition to this permanent filtering, you may be able to apply other filters.

The LOV dialog may include a query panel to allow the user to enter criteria to search for the list of values, or it may contain only a table of results. When you define the LOV in the view object, you can use the UI hints to specify whether a search region should be displayed, which view criteria should be used as the search to populate the list of values, and which LOV component to use. Figure 32-5 shows the Create List of Values dialog and some of its options. In this example, the search region will be made available with the All Queryable Attributes named view criteria used for the query, and af:inputComboboxListOfValues as the component. Another useful option for the af:inputComboboxListOfValues is the Show in Combo Box option, which allows you to select the number of attributes to display in the dropdown list and in the Search and Select dialog. For more information on LOV UI hints, see Section 5.12.5, "How to Set User Interface Hints on a View Object LOV-Enabled Attribute."

For both af:inputListOfValues and af:inputComboboxListOfValues, if the user enters a partial match in the input search field and presses the Tab or Enter key, the LOV automatically launches the LOV Search and Select dialog and executes the query after applying an auto-generated view criteria with a single item representing the partial match value entered by the user. If there are matches, the Search and Select dialog displays all the entries matching the partially entered criteria. If there are no entries that match the entered partial match, then the dialog displays all the entries.

By default, in the af:inputComboboxListOfValues component auto-complete feature, the search is case-sensitive. If you want the search to be case-insensitive, create a view criteria to be associated with that LOV attribute. In the Create View Criteria dialog, deselect the Ignore Case checkbox for that view criteria item before you apply that view criteria to the LOV definition. For more information about setting view criteria options, see Section 5.9.1, "How to Create Named View Criteria Declaratively."

Figure 32-5 List of Values Dialog UI Hints Tab

LOV UI hints.

You can also set up the LOV component to display a list of selectable suggested items when the user types in a partial value. For example, when the user types in Ca, then a suggested list which partially matches CA is displayed as a suggested items list. The user can select an item from the list to be entered into the input field. You add this auto-suggest behavior feature by including an af:autoSuggestBehavior tag from the Components window in the LOV and set the selectedItem attribute to the suggestedItems method implemented in ADF Model.

If the LOV is an af:inputComboboxListOfValues, you can apply an additional view criteria to further filter the values in the dropdown list to create a smart list. If the Filter Combo Box Using UI hint is not applied, the dropdown list is filtered by the view criteria applied to the view accessor. Note that this smart list filter applies only to the dropdown list. The full list is still used for validation and for searching from the LOV Search and Select popup dialog. When smart list is enabled, the LOV's Search and Select dialog will display a More link instead of the Search link.

If both the auto-suggest behavior and smart list filter are enabled for an LOV, auto-suggest will search from the smart list first. If the user waits for two seconds without clicking, then auto-suggest will also search from the full list and append the results. You can also specify the number of suggested items returned by setting the maxSuggestedItems attribute (-1 indicates a complete list). If maxSuggestedItems > 0, a More link is rendered for the user to click on to launch the LOV's Search and Select dialog. Example 32-3 shows the code from an LOV with both auto-suggest behavior and a smart list.

Example 32-3 Auto-Suggest Behavior and Smart List

af:autoSuggestBehavior 
    suggestItems="#{bindings.CountryName.suggestItems}" 
    smartList="#{bindings.CountryName.smartList}"/>
    maxSuggestedItems="5"

You can define an attribute in the view object to be one or more LOVs. If multiple LOVs are defined on an attribute, each LOV has its own name, view accessor, data mappings, validator, and UI hints (except for the Default List Type hint, which is defined once for the attribute). To switch between LOVs to be used at runtime, an LOV switcher is used. The LOV switcher can be based on an existing attribute of type String, or created as a new String attribute solely for switching between LOVs. The LOV switcher returns the name of the LOV to use at runtime. For instance, you can create three LOVs for the price attribute, and designate the CountryName attribute as the LOV switcher. At runtime, the value of CountryName will switch the price attribute to use the LOV that reflects the country's price and currency.

If an attribute is defined as an LOV, you can set the Support Multiple Value Selection control hint in its view criteria to enable users to make multiple selections in the search criteria field. If multiple selection is enabled on an LOV attribute, and the Equal to or Not equal to operator is chosen, a selectManyChoice component will render in the query panel. The user can select multiple items as the search criteria.

If the value of an LOV depends on the value of another LOV, then the two LOVs are called cascading LOVs. For instance, the list of values for the City LOV depends on the value of the CountryName LOV that was selected. If the LOV is defined as a named bind variable, or if validation is enabled, the LOV query may behave differently depending on such conditions as whether null values for the named bind variable are acceptable. If the bind variable is null, you may want the LOV query to return an empty list. The view criteria's Ignore Null Values and Validation options can be used to define LOV query behavior.

If the view object has an LOV with a bind variable, you should set that view object bind variable's control hint to Hide. Otherwise, the bind variable will be displayed in the LOV Search and Select popup dialog. In the view object overview editor's Query tab, double-click the bind variable, click the Control Hints tab and select Hide from the Display Hint dropdown list.


Note:

List of values are designed to return valid values only. As a result, validation rules defined on data source view object attributes will be suppressed. You should ensure that the list of values returned only contains valid values. For more information, see Section 11.3.5, "What You May Need to Know About List of Values and Attribute Validation Rules."



Best Practice:

An attribute that has been enabled as an LOV should not be used as search criteria in a manually created search form using the "Find Mode" iterator. Creating a search form in this way could result in SQL exception: java.sql.SQLException: Attempt to set a parameter name that does not occur in the SQL. It is best practice to use the query and quick query components for creating search forms. For more information, see Chapter 33, "Creating ADF Databound Search Forms."


Displaying an LOV list for a name attribute when the view object's key attribute is a numerical value requires mapping supplemental attributes on the LOV-enabled attribute. For example, to display a list of credit cards by name instead of by their payment option ID value, you can create an LOV on the name reference attribute and define the primary key attribute as a supplemental attribute to the LOV. For details about creating an LOV-enabled reference attribute, see Section 5.12.4, "How to Define an LOV to Display a Reference Attribute."


Note:

af:inputListOfValues and af:inputComboboxListOfValues assume the list of values returned from the Search and Select dialog to be valid. Any ADF Business Components validation errors will not be displayed.


For more information about different usage scenarios and other view criteria options, see Section 5.9.1, "How to Create Named View Criteria Declaratively," and Section 5.9.3, "What You May Need to Know About Bind Variables in View Criteria."

32.2.1 How to Create an LOV

You can create the LOV using either the af:inputListOfValues or the af:inputComboboxListOfValues component. You can add auto-suggest behavior to the component to display a list of possible matches from user input.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create an LOV. For more information, see Section 32.2, "Creating List of Values (LOV) Components."

You may also find it helpful to understand functionality that can be used with LOVs. For more information, see Section 32.1.2, "Additional Functionality for Selection Lists and Shuttles."

You will need to complete this task:

Define the attribute to be an LOV in the view object by following the procedure described in Section 5.12, "Working with List of Values (LOV) in View Object Attributes."

To create an LOV:

  1. In the Application window, double-click the web page that will display the component.

  2. From the Data Controls panel, drag and drop the attribute onto the JSF page and choose Create > List of Values > ADF LOV Input or Create > List of Values > ADF LOV Choice List.

  3. In the ADF Faces page of the Components window, from the Operations panel drag and drop Auto Suggest Behavior as a child to the LOV component.

  4. In the Property Inspector, enter values for Auto Suggest Behavior:

    • SuggestItems: EL expression that resolves to the suggestItems method.

    • SmartList: EL expression that resolves to the smartList method.

    • MaxSuggestedItems: Number of items to be displayed in the auto-suggest list. Enter -1 to display the complete list.

    Example 32-4 shows an inputListOfValues component with the auto-suggest behavior and smart list features.

    Example 32-4 LOV Component with Auto-Suggest Behavior

    <af:inputListOfValues id="salesRepIdId"      popupTitle="Search and Select: #{bindings.SalesRepId.hints.label}"      value="#{bindings.SalesRepId.inputValue}"      label="#{bindings.SalesRepId.hints.label}"      model="#{bindings.SalesRepId.listOfValuesModel}"      required="#{bindings.SalesRepId.hints.mandatory}"      columns="#{bindings.SalesRepId.hints.displayWidth}"      shortDesc="#{bindings.SalesRepId.hints.tooltip}">      <f:validator binding="#{bindings.SalesRepId.validator}"/>
          <af:autoSuggestBehavior suggestItems="#{bindings.SalesRepId.suggestedItems}"
                smartList="#{bindings.SalesRepId.smartList}"
                maxSuggestedItems="5"/>
    </af:inputListOfValues>
    
    
  5. If you added the auto-suggest behavior, you must not set the component's immediate property to true.

32.2.2 What Happens When You Create an LOV

When you drag and drop an attribute from the Data Controls panel, JDeveloper does many things for you. For a full description of what happens and what is created when you use the Data Controls panel, see Section 28.2.2, "What Happens When You Create a Text Field."

When you drag and drop an attribute defined as an LOV from the Data Controls panel onto a JSF page as an inputListOfValues or inputComboboxListOfValues component, JDeveloper adds code to the page similar to that shown in Example 32-5. The State attribute in the CustomerVO view object has been defined as an LOV and its default component is set to be an inputComboboxListOfValues. The component gets its properties from the control hints defined declaratively in the view object. If you want to include the auto-suggest behavior, you must manually add that tag from the Components window.

Example 32-5 inputComboboxListOfValues Component Code in a JSF Page

<af:inputComboboxListOfValues id="stateId"
        popupTitle="Search and Select: #{bindings.State.hints.label}"
        value="#{bindings.State.inputValue}" 
        label="#{bindings.State.hints.label}"
        model="#{bindings.State.listOfValuesModel}"
        required="#{bindings.State.hints.mandatory}"
        columns="#{bindings.State.hints.displayWidth}"
        shortDesc="#{bindings.State.hints.tooltip}">
        <f:validator binding="#{bindings.State.validator}"/>
</af:inputComboboxListOfValues>

In the page definition file, JDeveloper adds code as shown in Example 32-6. The bindings section of the page definition specifies that the LOV is for the State attribute and the name of the LOV is LOV_State. JDeveloper adds the definitions for the iterator binding objects into the executables element, and the list of values binding object into the bindings element.

Example 32-6 inputComboboxListOfValues Component Code in Page Definition

<executables>
    <variableIterator id="variables"/>
    <iterator Binds="Customers" RangeSize="25"
              DataControl="BackOfficeAppModuleDataControl"
              id="CustomersIterator"/>
</executables>
<bindings>
    <listOfValues StaticList="false" IterBinding="CustomersIterator"
                  Uses="LOV_State" id="State"/>
</bindings>

For more information about the page definition file and ADF data binding expressions, see Section 17.7, "Working with Page Definition Files,"and Section 17.8, "Creating ADF Data Binding EL Expressions."

32.2.3 What You May Need to Know About List Validators and LOV

If you are defining an attribute in the view object to be a list of values attribute, you can define an equivalent list validation rule in the underlying entity object as long as the list validation rule is based on the same list. You should not define other types of validation rules in the entity object for an attribute already defined as a list of values in the view object. Doing so may result in unexpected behavior and validation errors. For more information about defining validation rules, see Section 11.4.5, "List Validator Using a View Object Attribute," and Section 11.4, "Using the Built-in Declarative Validation Rules."

32.3 Creating a Selection List

ADF Faces Core includes components for selecting a single value and multiple values from a list. For example, selectOneChoice allows the user to select an item from a dropdown list, and selectManyChoice allow the user to select several items from a list of checkboxes. Selection lists are described in Table 32-1.

Table 32-1 ADF Faces Single and Multiple List Components

ADF Faces componentDescriptionExample

SelectOneChoice

Select a single value from a list of items.

selectOneChoice

SelectOneRadio

Select a single value from a set of radio buttons.

SelectOneRadio

SelectOneListbox

Select a single value from a scrollable list of items.

SelectOneListbox


SelectManyChoice

Select multiple values from a scrollable list of checkboxes. Each selection displays at the top of the list.

SelectManyChoice

SelectManyCheckbox

Select multiple values from a group of checkboxes.

SelectManyCheckbox


SelectManyListbox

Select multiple values from a scrollable list of checkboxes,

SelectManyListbox



You can create selection lists using the SelectOneChoice ADF Faces component. The steps are similar for creating other single-value selection lists, such as SelectOneRadio and SelectOneListbox.

A databound selection list displays values from a data control collection or a static list and updates an attribute in another collection or a method parameter based on the user's selection. When adding a binding to a list, you use an attribute from the data control that will be populated by the selected value in the list.


Note:

By default, ADF Model list binding passes the index to the component. If you set valuePassThru=true, then you should set the list binding entry in the corresponding page definition file Mode attribute to Object. When Mode=Object, the list binding will pass an object instead of an index to the component. For more information, see Section 32.3.4, "What Happens When You Create a Fixed Selection List."


To create a selection list, you choose a base data source and a list data source in the Edit List Binding dialog:

The data collection is based on the view object. For more information about creating a view object, see Section 5.2.1, "How to Create an Entity-Based View Object."

You can create three types of selection lists in the Edit List Binding dialog:

32.3.1 How to Create a Model-Driven List

A model-driven list is based on a list of values that is bound to a view data object. Lists of Values are typically used in forms to enable an end user to select an attribute value from a dropdown list instead of having to enter it manually. When the user submits the form with the selected values, ADF data bindings in the ADF Model layer update the value on the view object attributes corresponding to the databound fields.


Note:

One way to create a model-driven list is to drag a collection from the Data Controls panel onto a JSF page, choose one of the ADF Forms in the context menu, and accept the defaults. The advantage is that if there are LOVs defined on the underlying view object attributes, all the LOVs on the entire form will be configured automatically. For more information, see Section 5.12.1, "How to Define a Single LOV-Enabled View Object Attribute."


You can also use the list of values as the basis for creating a selection list. The advantages of creating a model-driven list based on a list of values are:

  • Reuse: The list of values is bound to a view data collection. Any selection list that you create based on the data collection can use the same list of values. Because you define the LOV on the individual attributes of view objects in a data model project with ADF Business Components, you can customize the LOV usage for an attribute once and expect to see the changes anywhere that the business component is used in the user interface.

  • Translation: Values in the list of values can be included in resource bundles used for translation.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create an selection list component. For more information, see Section 32.3, "Creating a Selection List."

You may also find it helpful to understand functionality that can be used with selection lists. For more information, see Section 32.1.2, "Additional Functionality for Selection Lists and Shuttles."

You will need to complete these tasks:

  1. Create a view object.

  2. Create a view accessor on the object.

  3. Create a list of values that is bound to an attribute on the base data source for the selection list. For example, you can create a list of values bound to the CountryId attribute of the Addresses view data object.

    For more information, see Section 5.12.1, "How to Define a Single LOV-Enabled View Object Attribute."

To create a model-driven selection list:

  1. From the Data Controls panel, drag and drop the attribute onto the JSF page and, from the context menu, choose Create > Single Selections > ADF Select One Choice.

  2. In the Edit List Binding dialog, click the Model Driven List radio button.

  3. In the Base Data Source Attribute dropdown list, select an attribute on which you want to display a list of values.

    The Base Data Source should be the collection you dragged from the Data Controls panel. If the collection does not appear in the dropdown list, click the Add button to select the collection you want.

  4. In the Server List Binding Name dropdown list, select the name of the list-of-values definition that was created for the base attribute.

    If a list-of-values definition was created for the attribute you have selected, the definition will appear in the dropdown list. For example, if you have defined LOV_State as the list-of-value definition for the State attribute, then LOV_State should appear in the Server List Binding Name dropdown list.

  5. Click OK.

32.3.2 What Happens When You Create a Model-Driven Selection List

When you drag and drop an attribute from the Data Controls panel, JDeveloper does many things for you. For a full description of what happens and what is created when you use the Data Controls panel, see Section 28.2.2, "What Happens When You Create a Text Field."

Example 32-7 shows the page source code after you add a model-driven SelectOneChoice component to it.

Example 32-7 Model-Driven SelectOneChoice List in JSF Page Source Code

<af:selectOneChoice value="#{bindings.State.inputValue}"
                    label="#{bindings.State.label}"
                    required="#{bindings.State.hints.mandatory}"
                    shortDesc="#{bindings.State.hints.tooltip}"
                    id="soc1">
          <f:selectItems value="#{bindings.State.items}" id="si1"/>
</af:selectOneChoice>

The f:selectItems tag, which provides the list of items for selection, is bound to the items property on the State list binding object in the binding container. For more information about ADF data binding expressions, see Section 17.6, "Configuring the ADF Binding Filter."

In the page definition file, JDeveloper adds the list binding object definitions in the bindings element, as shown in Example 32-8.

Example 32-8 List Binding Object for the Model-Driven List in the Page Definition File

<executables>
    <variableIterator id="variables"/>
    <iterator Binds="Customers" RangeSize="25"
              DataControl="BackOfficeAppModuleDataControl"
              id="CustomersIterator"/>
</executables>
<bindings>
    <list IterBinding="CustomersIterator"
          StaticList="false" Uses="LOV_State"
          id="State" DTSupportsMRU="true"
          SelectItemValueMode="ListObject"/>
</bindings>

In the list element, the id attribute specifies the name of the list binding object. The IterBinding attribute references the variable iterator, whose current row is a row of attributes representing each variable in the binding container. The variable iterator exposes the variable values to the bindings in the same way as do other collections of data.

For more information about the page definition file and ADF data binding expressions, see Section 17.7, "Working with Page Definition Files,"and Section 17.8, "Creating ADF Data Binding EL Expressions."

32.3.3 How to Create a Selection List Containing Fixed Values

You can create a selection list containing selections that you code yourself, rather than retrieving the values from another data source. See Section 32.3.5, "How to Create a Selection List Containing Dynamically Generated Values," for information about populating selection lists with values that are dynamically generated from another data source.

Figure 32-6 Selection List Bound to a Fixed List of Values

select list with static list

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create a selection list component. For more information, see Section 32.3, "Creating a Selection List."

You may also find it helpful to understand functionality that can be used with selection lists. For more information, see Section 32.1.2, "Additional Functionality for Selection Lists and Shuttles."

You will need to complete this task:

Prepare a list of values that you will enter into the component as a fixed list.

To create a list bound to a fixed list of values:

  1. From the Data Controls panel, drag and drop the attribute onto the JSF page and, from the context menu, choose Create > Single Selections > ADF Select One Choice.

  2. In the Edit List Binding dialog, click the Fixed List radio button.

  3. In the Base Data Source Attribute dropdown list, select an attribute on which you want to display a list of values.

    The Base Data Source should be the collection you dragged from the Data Controls panel. If the collection does not appear in the dropdown list, click the Add button to select the collection you want.

  4. In the Set of Values box, enter each value you want to appear in the list. Press the Enter key to set a value before typing the next value. For example, if your attribute is Country, you could add the country codes India, Japan, and Russia.

    The order in which you enter the values is the order in which the list items are displayed in the SelectOneRadio control at runtime.

    The SelectOneRadio component supports a null value. If the user has not selected an item, the label of the item is shown as blank, and the value of the component defaults to an empty string. Instead of using blank or an empty string, you can specify a string to represent the null value. By default, the new string appears at the top of the list.

  5. Click OK.

32.3.4 What Happens When You Create a Fixed Selection List

When you add a fixed selection list, JDeveloper adds source code to the JSF page and list and iterator binding objects to the page definition file.

Example 32-9 shows the page source code after you add a fixed SelectOneChoice component to it.

Example 32-9 Fixed SelectOneChoice List in JSF Page Source Code

<af:selectOneChoice value="#{bindings.CountryIdStatic.inputValue}"
                            label="#{bindings.CountryIdStatic.label}">
          <f:selectItems value="#{bindings.CountryIdStatic.items}"/>
</af:selectOneChoice>

The f:selectItems tag, which provides the list of items for selection, is bound to the items property on the CountryId list binding object in the binding container. For more information about ADF data binding expressions, see Section 17.8, "Creating ADF Data Binding EL Expressions."

In the page definition file, JDeveloper adds the definitions for the iterator binding objects into the executables element, and the list binding object into the bindings element, as shown in Example 32-10.

Example 32-10 List Binding Object for the Fixed Selection List in the Page Definition File

<executables>
    <iterator Binds="Addresses1" RangeSize="10"
              DataControl="BackOfficeAppModuleDataControl"
              id="Addresses1Iterator"/>
</executables>
<bindings>
    <list IterBinding="Addresses1Iterator" id="CountryIdStatic" ListOperMode="0"
          StaticList="true">
      <AttrNames>
        <Item Value="CountryIdStatic"/>
      </AttrNames>
      <ValueList>
        <Item Value="India"/>
        <Item Value="Japan"/>
        <Item Value="Russia"/>
      </ValueList>
    </list>
</bindings>

For complete information about page definition files, see Section 17.7, "Working with Page Definition Files."

32.3.5 How to Create a Selection List Containing Dynamically Generated Values

You can populate a selection list component with values dynamically at runtime.


Tip:

Another option is to create a static view object or a database view object within a shared application module. Then use a model- driven LOV to create the list. This provides caching and translatability.


Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create a selection list component. For more information, see Section 32.3, "Creating a Selection List."

You may also find it helpful to understand functionality that can be used with selection lists. For more information, see Section 32.1.2, "Additional Functionality for Selection Lists and Shuttles."

You will need to complete these tasks:

  1. Define a data source for the list data source that provides the dynamic list of values.

  2. Define a data source for the base data source that is to be updated based on the user's selection.

To create a selection list bound containing dynamically generated values:

  1. From the Data Controls panel, drag and drop the attribute onto the JSF page and, from the context menu, choose Create > Single Selections > ADF Select One Choice.

  2. In the Edit List Binding dialog, click the Dynamic List radio button.

  3. Select the Base Data Source from the dropdown list or click Add.

  4. In the Add Data Source dialog, select the data collection that contains the attribute to be updated and click OK.

  5. Select the List Data Source from the dropdown list or click Add.

  6. In the Add Data Source dialog, select the data collection that contains the attribute that will be displayed and click OK.


    Note:

    The list and base collections do not have to form a master-detail relationship, but the attribute in the list collection must have the same type as the base collection attributes.


  7. In the Data Mapping section, you can accept the default mapping or select different attributes items from the Data Value and List Attribute lists to update the mapping.

    The Data Value control contains the attribute on the data collection that is updated when the user selects an item in the selection list. The List Attribute control contains the attribute that populates the values in the selection list.

    To add a second mapping, click Add.

  8. In the List Items section, select values for:

    • Display Attribute: Select the attribute you want to be displayed.

    • "No Selection" Item: Specify whether or not the list displays a NULL value selection and how it is displayed.

    • MRU: Select to show a list of most recently used items. Specify the number of items to display in the MRU list and the separator to be used.

  9. Click OK.

32.3.6 What Happens When You Create a Dynamic Selection List

When you add a dynamic selection list to a page, JDeveloper adds source code to the JSF page and list and iterator binding objects to the page definition file.

Example 32-11 shows the page source code after you add a dynamic SelectOneChoice component to it.

Example 32-11 Dynamic SelectOneChoice List in JSF Page Source Code

<af:selectOneChoice value="#{bindings.SalesRepId.inputValue}"
                    label="#{bindings.SalesRepId.label}"
                    required="#{bindings.SalesRepId.hints.mandatory}"
                    shortDesc="#{bindings.SalesRepId.hints.tooltip}" id="soc2">
        <f:selectItems value="#{bindings.SalesRepId.items}" id="si4"/>
        <f:validator binding="#{bindings.SalesRepId.validator}"/>
</af:selectOneChoice>

The f:selectItems tag, which provides the list of items for selection, is bound to the items property on the SalesRepId list binding object in the binding container. For more information about ADF data binding expressions, see Section 17.8, "Creating ADF Data Binding EL Expressions."

In the page definition file, JDeveloper adds the definitions for the iterator binding objects into the executables element, and the list binding object into the bindings element, as shown in Figure 32-6.

Example 32-12 List Binding Object for the Dynamic Selection List in the Page Definition File

<executables>
    <variableIterator id="variables"/>
    <iterator Binds="SummitAppModuleDataControl.dataProvider.
              BackOfficeAM.Customers"
              DataControl="SummitAppModuleDataControl" RangeSize="25"
              id="CustomersIterator"/>
    <iterator Binds="Countries" RangeSize="10"
              DataControl="BackOfficeAppModuleDataControl"
              id="CountriesIterator"/>
    <iterator Binds="Customers" RangeSize="-1"
              DataControl="BackOfficeAppModuleDataControlQ^"
              id="CustomersIterator1"/>
</executables>
<bindings>
    <list IterBinding="CountriesIterator" StaticList="false" id="SalesRepId"
          DTSupportsMRU="true" SelectItemValueMode="ListObject"
          ListIter="CustomersIterator1">
      <AttrNames>
        <Item Value="Id"/>
      </AttrNames>
      <ListAttrNames>
        <Item Value="Id"/>
      </ListAttrNames>
      <ListDisplayAttrNames>
        <Item Value="Id"/>
      </ListDisplayAttrNames>
    </list>
</bindings>

By default, JDeveloper sets the RangeSize attribute on the iterator element for the Customers iterator binding to a value of -1 thus allowing the iterator to furnish the full list of valid products for selection. In the list element, the id attribute specifies the name of the list binding object. The IterBinding attribute references the iterator that iterates over the Countries collection. The ListIter attribute references the iterator that iterates over the Customers collection. The AttrNames element specifies the base data source attributes returned by the base iterator. The ListAttrNames element defines the list data source attributes that are mapped to the base data source attributes. The ListDisplayAttrNames element specifies the list data source attribute that populates the values users see in the list at runtime.

For complete information about page definition files, see Section 17.7, "Working with Page Definition Files."

32.3.7 What You May Need to Know About Values in a Selection List

Once you have created a list binding, you may want to access a value in the list. You can set the component's valuePassThru attribute to true either in the visual editor or in the Property Inspector. Example 32-13 shows the code for a selectOneChoice component.

Example 32-13 valuePassThru Attribute Set to true in selectOneChoice

 <af:selectOneChoice value="#{bindings.Language.inputValue}"
                     label="#{bindings.Language.label}"
                     required="#{bindings.Language.hints.mandatory}"
                     shortDesc="#{bindings.Language.hints.tooltip}"
                     valueChangeListener="#{myBean.valueChanged}" 
                     id="soc1" valuePassThru="true">
      <f:selectItems value="#{bindings.Language.items}" id="si1"/>
</af:selectOneChoice>

Only when the valuePassThru attribute is set to true and the Mode attribute in the corresponding page definition file is set to Object can the value passed to the valueChangeListener be of type Object (which is the actual value). By default, Mode is set to Index. Example 32-14 shows the Mode attribute in the page definition file.

Example 32-14 Mode Attribute Set to Object in the Page Definition File

 <list IterBinding="AvailableLanguagesView1Iterator" id="Language"
          DTSupportsMRU="true" StaticList="false"
          ListIter="CountryCodesView1Iterator"
          Mode="Object"/>

32.4 Creating a List with Navigation List Binding

Navigation list binding lets users navigate through the objects in a collection. As the user changes the current object selection using the navigation list component, any other component that is also bound to the same collection through its attributes will display from the newly selected object. In addition, if the collection whose current row you change is the master view object instance in a data model master-detail relationship, the row set in the detail view object instance is automatically updated to show the appropriate data for the new current master row.

32.4.1 How to Create a List with Navigation List Binding

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create a navigation list. For more information, see Section 32.4, "Creating a List with Navigation List Binding."

You may also find it helpful to understand functionality that can be used with navigation lists. For more information, see Section 32.1.2, "Additional Functionality for Selection Lists and Shuttles."

To create a list that uses navigation list binding:

  1. From the Data Controls panel, drag and drop the master collection to the page and choose Create > Navigation > ADF Navigation List.

    The master collection is where the user selects from.

  2. In the Edit List Binding dialog, from the Base Data Source dropdown list, select the collection whose members will be used to create the list.

    This should be the collection you dragged from the Data Controls panel. If the collection does not appear in the dropdown list, click the Add button to select the collection you want.

  3. From the Display Attribute dropdown list, select the attribute that will display in the list. You can choose the selection that includes all the attributes, and you can choose Select Multiple to launch a selection dialog.

  4. In the Select Multiple Display Attributes dialog, shuttle the attributes you want to display from the Available Attributes list to the Attributes to Display list. Click OK to close the dialog.

  5. Click OK.

  6. From the Data Controls panel, drag and drop the detail collection inside the Details section of the page as an output component.

    The output component can be any component that is used to display the data. If you decide to use a table, you can choose Create> Table > ADF Table.

    The Detail section is an af:panelHeader component that was added by JDeveloper when you created the navigation list in Step 1.

32.4.2 What Happens When You Create a Navigational List Binding

When you add a navigation list to a page, JDeveloper adds source code to the JSF page and list and iterator binding objects to the page definition file.

On the page, JDeveloper adds a selectOneChoice component with a f:selectItems tag. The selectOneChoice component allows the user to select from a list of values based on the selected attribute in the source data collection. JDeveloper also adds an af:panelHeader component that will contain the component you chose to display the data based on the selection. In this example, a table component is added to display the data. Note that the af:panelHeader component has partialtriggers set to the selectOneChoice component id so that when the selection changes, new data will be displayed. Example 32-15 shows the page source code after you add a navigation list.

Example 32-15 Navigation List in JSF Page Source Code

<af:selectOneChoice id="nl1" autoSubmit="true"
    value="#{bindings.Customers.inputValue}"
    label="#{bindings.Customers.label}">
    <f:selectItems value="#{bindings.Customers.items}" id="si1"/>
</af:selectOneChoice>
<af:panelHeader text="Details" partialTriggers="nl1" id="ph1">
    <af:table value="#{bindings.OrdersForCustomer.collectionModel}" var="row"
        rows="#{bindings.OrdersForCustomer.rangeSize}"
        emptyText="#{bindings.OrdersForCustomer.viewable ? 
                   'No data to display.' : 'Access Denied.'}"
        fetchSize="#{bindings.OrdersForCustomer.rangeSize}" rowBandingInterval="0"
        id="t1">
     <af:column headerText="#{bindings.OrdersForCustomer.hints.Id.label}" id="c1">
        <af:inputText value="#{row.bindings.Id.inputValue}"
...

In the page definition file, JDeveloper adds the definitions for the iterator binding objects into the executables element. Example 32-16 shows the iterator bindings and navigation list bindings in the page definition file.

Example 32-16 List Binding for Navigation List in the Page Definition File

<executables>
    <variableIterator id="variables"/>
    <iterator Binds="Customers" RangeSize="25"
         DataControl="BackOfficeAppModuleDataControl" id="CustomersIterator"/>
    <iterator Binds="OrdersForCustomer" RangeSize="25"
         DataControl="BackOfficeAppModuleDataControl"
              id="OrdersForCustomerIterator"/>
</executables>
<bindings>
    <navigationlist IterBinding="CustomersIterator" ListOperMode="navigation"
              ListIter="CustomersIterator"
              id="Customers" DTSupportsMRU="false">
      <AttrNames>
        <Item Value="Name"/>
      </AttrNames>
    </navigationlist>
    <tree IterBinding="OrdersForCustomerIterator" id="OrdersForCustomer">
      <nodeDefinition DefName="oracle.summit.model.views.OrdVO"
             Name="OrdersForCustomer0">
        <AttrNames>
          <Item Value="Id"/>
          <Item Value="CustomerId"/>
          <Item Value="DateOrdered"/>
          <Item Value="LastName"/>
          <Item Value="Name"/>
        </AttrNames>
      </nodeDefinition>
    </tree>
</bindings>

32.5 Creating a Databound Shuttle

The selectManyShuttle and selectOrderShuttle components render two list boxes and buttons that allow the user to select multiple items from the leading (or available) list box and to move or shuttle those items over to the trailing (or selected) list box, and vice versa. You can also double-click an item to move it to the other list box. Figure 32-7 shows an example of a rendered selectManyShuttle component that is implemented in the Summit ADF sample application. You can specify any text you want for the headers that display above the list boxes.

Figure 32-7 SelectManyShuttle Component

This shows a SelectManyShuttle Component.

The only difference between selectManyShuttle and selectOrderShuttle is that in the selectOrderShuttle component, the user can reorder the items in the trailing list box by using the up and down arrow buttons on the side.

The Summit ADF sample application uses a selectManyShuttle component to allow the user to select the products to order from a All available products list box to an Selected Products list box. The leading list box on the left displays all the available products. The trailing list box on the right displays the products the customer has selected.

Like other ADF Faces selection list components, the selectManyShuttle and selectOrderShuttle components can use the f:selectItems tag to provide the list of items available for display and selection in the leading list.

Before you can bind the f:selectItems tag, create a generic class that can be used by any page that requires a shuttle. In the class, declare and include getter and setter methods for the properties that describe the view object instance names that should be used for the list of all available choices (leading list or available product categories) and the list of selected choices (trailing list or assigned product categories). In the Summit ADF sample application, f:selectItems uses the binding container to retrieve the list of available products. Example 32-17 shows the ShuttleBean class that is created to manage the population and selection state of the shuttle component on the showshuttle.jsf page.

Example 32-17 ShuttleBean Class

public class ShuttleBean {
    
    private List<oracle.jbo.domain.Number> _selectedProducts = 
         new ArrayList<oracle.jbo.domain.Number>();
    
    public ShuttleBean()
    {
    }
 
    public void setSelectedProducts(List<oracle.jbo.domain.Number> 
         _allocatedRoles) {
        this._selectedProducts = _allocatedRoles;
    }
 
    public List<oracle.jbo.domain.Number> getSelectedProducts() {
        return _selectedProducts;
    }
 
    public void onAddMultipleProducts(ActionEvent actionEvent) {        
      DCBindingContainer dcBindings =
        (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
      OperationBinding createMethod =
         dcBindings.getOperationBinding("CreateInsert");
      if ( createMethod != null && _selectedProducts.size() > 0 ) {
            DCIteratorBinding iterator =
                 dcBindings.findIteratorBinding("ItemsForOrderIterator");
            for ( oracle.jbo.domain.Number productId : _selectedProducts )
            {
                createMethod.execute();
                iterator.getCurrentRow().setAttribute("ProductId", productId );
            }
        }
    }
}

The getSelectedProducts() method returns a List that defines the items in the shuttle's trailing list. The values returned by getSelectedProducts() are a subset of the values in the leading list. Values that are in the leading list but not in getSelectedProducts() will be ignored (and will generate an error in the server log). Note that the ShuttleBean class can call utility methods in the ADFUtils class if required. Also note that this class uses values for several properties of the base bean.

Example 32-18 shows the managed bean and managed properties configured in order-select-many-item.xml task flow for working with the shuttle component.

Example 32-18 Managed Bean for the Shuttle Component in the order-select-many-items Task Flow

<managed-bean id="__3">
      <managed-bean-name>ShuttleBean</managed-bean-name>
      <managed-bean-class>oracle.summit.backing.ShuttleBean</managed-bean-class>
      <managed-bean-scope>backingBean</managed-bean-scope>
</managed-bean>
<view id="showshuttle">
      <page>/orders/showshuttle.jsf</page>

32.5.1 How to Create a Databound Shuttle

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create a shuttle. For more information, see Section 32.5, "Creating a Databound Shuttle."

You may also find it helpful to understand functionality that can be used with selection lists. For more information, see Section 32.1.2, "Additional Functionality for Selection Lists and Shuttles."

You will need to complete these tasks:

  1. Create the relevant iterator bindings in the page definition file. Use Example 32-19 as a guide.

    In the Summit ADF sample application, a list binding for ProductId with ItemsForOrderIterator is added to the showshuttlePageDef.xml file to provide the list of products for populating the leading list.

  2. Create a class similar to the ShuttleBean class and provide methods to process the values as required. Use Example 32-17 as a guide.

  3. Configure the required managed bean and managed properties in the task flow definition or, in the case of an unbounded task flow, the adfc-config.xml file. Use Example 32-18 as a guide.

To create a shuttle component:

  1. In the Applications window, double-click the web page that will display the component.

  2. In the ADF Faces page of the Components window, from the Text and Selection panel, drag and drop SelectManyShuttle or SelectOrderShuttle onto the page.

    JDeveloper displays the Insert Shuttle wizard, as illustrated in Figure 32-8.

    Figure 32-8 Insert SelectManyShuttle Wizard

    Insert SelectManyShuttle dialog for binding select items.
  3. Select Bind to list (select items) and click Bind.

  4. In the Expression Builder, expand tree structure to create an expression that will populate the values for the leading list and click OK.

    In the Summit ADF sample application, select ADF Bindings > bindings > ProductId > items to build the expression #{bindings.ProductId.items} and click Finish. This binds the f:selectedItem tag of the selectManyShuttle component to the data collection that populates the shuttle's leading list with a list of products.

    If you decide to retrieve the values for the leading list using a method, for example, getAllProducts(), you should create this method in the managed bean. You would then bind to this method in the expression builder.

  5. Click Next.

  6. In the Common Properties page, click Bind next to the Value field.

  7. In the Expression Builder, expand the tree to create an expression that will populate the values for the trailing list and click OK.

    In the Summit ADF sample application, select ADF Managed Beans > BackingBeanScope > ShuttleBean > selectedProducts to build the expression #{backingBeanScope.ShuttleBean.selectedProducts} and click Finish. This binds the value attribute to the selectedProducts() method that populates the shuttle's trailing list.

  8. You may want to add additional controls to process the selected values.

    In the Summit ADF sample application, an af:button component labeled Done is added to the page to process the selected products by calling the onAddMultipleProducts method defined in the ShuttleBean.

32.5.2 What Happens When You Create a Databound Shuttle

All the bindings of the showshuttle.jsf page are defined in the file showshuttlePageDef.xml. Example 32-19 shows part of the page definition file for the showshuttle.jsf page.

Example 32-19 Page Definition File for the showshuttle Page

<?xml version="1.0" encoding="UTF-8" ?>
<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel"
 version="12.1.2.61.86" id="showshuttlePageDef" Package="orders">
  <parameters/>
  <executables>
    <variableIterator id="variables"/>
    <iterator Binds="ItemsForOrder" RangeSize="25"
              DataControl="BackOfficeAppModuleDataControl"
              id="ItemsForOrderIterator"/>
  </executables>
  <bindings>
    <list IterBinding="ItemsForOrderIterator" StaticList="false" 
          Uses="LOV_ProductId" id="ProductId"
          DTSupportsMRU="true" SelectItemValueMode="ListObject"/>
    <action IterBinding="ItemsForOrderIterator" id="CreateInsert"
            RequiresUpdateModel="true" Action="createInsertRow">
    </action>
  </bindings>
</pageDefinition>

Example 32-20 shows the code for the selectManyShuttle component after you complete the Insert SelectManyShuttle dialog.

Example 32-20 SelectManyShuttle Component in showshuttle.jsff File

<af:selectManyShuttle id="sms1"
       value="#{backingBeanScope.ShuttleBean.selectedProducts}"
       leadingHeader="All available products" trailingHeader="Selected products">
    <f:selectItems value="#{bindings.ProductId.items}" id="si1"/>
</af:selectManyShuttle>

PKh;T_`^Q^PKz$DOEBPS/cover.htm  Cover

Oracle Corporation

PK@t` PKz$DOEBPS/partpage4.htm Creating ADF Task Flows

Part IV

Creating ADF Task Flows

Part IV contains the following chapters:

PK֠PKz$DOEBPS/taskflows_regions.htm Using Task Flows as Regions

23 Using Task Flows as Regions

This chapter describes how to render ADF task flows in pages or page fragments using ADF regions in your Fusion web application. Key features such as the ability to specify parameters, how to refresh or activate an ADF region, navigate to a parent page, and create dynamic ADF regions are also described.

This chapter includes the following sections:

23.1 About Using Task Flows in ADF Regions

You can execute a bounded task flow in a JSF page or page fragment (.jsff) by using an ADF region. A primary reason for executing a bounded task flow as an ADF region is reuse. You can isolate specific pieces of application functionality in a bounded task flow and an ADF region in order to reuse it throughout the application. You can extract, configure, and package application functionality within a bounded task flow so that it can be added to other pages using an ADF region. ADF regions can be reused wherever needed, which means they are not dependent on a parent page. This also means that you can isolate the presentation of the parent pages from the ADF region; menus, buttons, and navigation areas are not affected by what is displayed in the ADF region. If you modify a bounded task flow, the changes apply to any ADF region that uses the task flow.

An ADF region comprises the following:

When first rendered, the ADF region's content is that of the first view activity in the bounded task flow. The view activities used in the bounded task flow must be associated with page fragments, not pages.

You can pass values to the ADF region using task flow binding input parameters or contextual events. In addition, you can configure the task flow binding's parametersMap property to determine what input parameters the task flow binding passes from the bounded task flow to the ADF region.

ADF regions can be configured so that you determine when the region activates or refreshes. You can also configure an ADF region and a bounded task flow so that navigation control stops in the bounded task flow and passes to the page that contains the ADF region. Finally, you can create dynamic regions (ADF dynamic regions) where the task flow binding determines at runtime what bounded task flow renders in the region and configure a dynamic region link so that end users can change the bounded task flow that renders in the ADF dynamic region at runtime.

Figure 23-1 shows how an ADF region references a bounded task flow using a task flow binding in the page definition file of the page that hosts the ADF region.

Figure 23-1 ADF Region Referencing a Bounded Task Flow

ADF Region Referencing a Bounded Task Flow

23.1.1 About Page Fragments and ADF Regions

A page fragment is a JSF document (file extension is .jsff) that renders as content in another JSF page. A page fragment should not have more than one root component. Wrapping multiple root components in a single root component helps you to optimize the display performance of the page fragment. In addition, if a page fragment has only one visual root component and a popup component (which is invisible to end users until invoked), consider wrapping these components in a single root component. For example, place the popup component in a panelStretchLayout component's bottom facet with the bottomHeight attribute set to 0 pixels.

If a page fragment has more than one root component, the Fusion web application logs a message at runtime, as shown in Example 23-1, where r1 identifies the ADF region that renders the page fragment.

Example 23-1 Log Message for a Page Fragment with Multiple Root Components

<RegionRenderer> <encodeAll> The region component with id: r1 has detected a page
 fragment with multiple root components. Fragments with more than one root
 component may not display correctly in a region and may have a negative impact
 on performance. It is recommended that you restructure the page fragment to have
 a single root component.

Apart from having only one root component element, a page fragment must not contain any of the following tags:

  • <af:document>

  • <f:view>

  • <f:form>

  • <html>

  • <head>

  • <body>

These tags can only appear once in a document and do not support nesting in a JSF page. For example, a page fragment embedded in a page cannot have an <html> tag because the JSF page already has one.

Example 23-2 contains an example of a simple page fragment. Unlike a JSF page, it contains no <f:view> or <f:form> tags.

Example 23-2 Page Fragment Source Code

<?xml version='1.0' encoding='UTF-8'?>
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                     xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <af:button text="button 1" id="b1"/>
</ui:composition>

You must nest a page fragment that you include in another JSF page within a region (af:region tag). A bounded task flow that you add to a JSF page as a region cannot call pages; it must call page fragments.

23.1.2 About View Ports and ADF Regions

A view port is a display area capable of navigating independently of other view ports. A browser window and an ADF region are both examples of view ports. The root view port displays the main page in a browser window. The root view port may have child view ports, for example, regions on the page, but does not have a parent view port.

Java classes that implement the ViewPortContext interface in the oracle.adf.controller package get you more information about view ports. For more information, see the Java API Reference for Oracle ADF Controller.

23.1.3 Task Flows and ADF Region Use Cases and Examples

Figure 23-2 shows the General Information page fragment (GeneralInfo.jsff) from the edit-customer-task-flow-definition.xml task flow in the Summit sample application for ADF task flows. This task flow renders in an ADF region and displays information about customers in a series of page fragments that authenticated users can navigate through and edit using the provided controls. For more information about creating this type of region, see Section 23.2, "Creating an ADF Region."

Figure 23-2 ADF Region in the Summit ADF Task Flow Sample Application

ADF Region in the Summit ADF Application for ADF Task Flows

Figure 23-2 also shows links (labeled Register as Employee and Register as Customer) that invoke different task flows in the ADF dynamic region that the showDetailItem component labeled Welcome renders. For more information about creating this type of region, see Section 23.9, "Creating ADF Dynamic Regions."

Figure 23-3 shows the edit-customer-task-flow-definition.xml task flow in JDeveloper. It contains three view activities to display information about customers to end users.

Figure 23-3 Edit Customer Task Flow in ADF Summit Application for ADF Task Flows

Edit Customer Task Flow

23.1.4 Additional Functionality for Task Flows that Render in ADF Regions

You may find it helpful to understand how a task flow that renders in an ADF region interacts with other task flow and ADF functionality. Following are links to other functionality that may be of interest.

23.2 Creating an ADF Region

You create an ADF region by dragging and dropping a bounded task flow that contains at least one view activity or one task flow call activity to the page where you want to render the ADF region. This makes sure that the ADF region you create has content to display at runtime.

The bounded task flow's view activities must be associated with page fragments (.jsff). If you attempt to drag and drop a bounded task flow that is associated with pages rather than page fragments, JDeveloper does not display the context menu that allows you to create an ADF region. You can convert a bound task flow that uses pages to use page fragments. For more information, see Section 20.6.4, "How to Convert Bounded Task Flows."

The context menu that appears to create an ADF region presents options to create a nondynamic and a dynamic region. A dynamic region (ADF dynamic region) determines the bounded task flow that it renders at runtime. For more information about creating an ADF dynamic region, see Section 23.9, "Creating ADF Dynamic Regions." You determine at design time the bounded task flow that a nondynamic region (ADF region) displays.

23.2.1 How to Create an ADF Region

Drag a bounded task flow from the Applications window to the page where you want to render an ADF region.

Before you begin:

It may be helpful to have an understanding of the requirements for a bounded task flow that you use in an ADF region. For more information, see Section 23.2, "Creating an ADF Region."

You may also find it helpful to understand functionality that can be added using other task flow features and ADF region features. For more information, see Section 23.1.4, "Additional Functionality for Task Flows that Render in ADF Regions."

You will need to complete these tasks:

  • Create a bounded task flow with one or more view activities associated with page fragments or one task flow call activity to a task flow with view activities.

    For more information, see Section 20.2, "Creating a Task Flow."

  • Create a JSF page to host the ADF region.

    For more information, see the "How to Create JSF Pages" section of Developing Web User Interfaces with Oracle ADF Faces.

To create an ADF region:

  1. In the Applications window, double-click the JSF page where you want to locate the ADF region.

  2. From the Applications window, drag and drop the bounded task flow onto the JSF page, and from the context menu, choose Create > Region.

  3. If the Edit Task Flow Binding dialog appears, click OK.

    The Edit Task Flow Binding dialog appears if the bounded task flow that you drop on the JSF page has an input parameter defined, as described in Section 22.3.1, "How to Pass an Input Parameter to a Bounded Task Flow."

    For more information about specifying parameters for an ADF region, see Section 23.3, "Specifying Parameters for an ADF Region."

    Figure 23-4 Edit Task Flow Binding Dialog for an ADF Region

    Edit Task Flow Binding Dialog for an ADF Region
  4. In the Structure window, right-click the node for the ADF region that you added (af:region) and choose Go to Properties.

  5. Review or modify (as appropriate) the following fields which JDeveloper automatically populates with default values in the Properties window for the ADF region:

    • Id: An ID that the JSF page uses to reference the ADF region, for example, r1.

    • Value: An EL reference to the ADF region model, for example, #{bindings.region1.regionModel}. This is the region model that describes the behavior of the region.

    • Rendered: If true (the default value), the ADF region renders when the JSF page renders.

  6. For information about how to map parameters between the view activity associated with the JSF page and the ADF region, see Section 23.3, "Specifying Parameters for an ADF Region."

23.2.2 What Happens When You Create an ADF Region

When you drop a bounded task flow onto a JSF page to create an ADF region, JDeveloper adds an af:region tag to the page. The af:region tag references an object that implements RegionModel. Example 23-3 shows the af:region tag that appears in the Customers.jsff page fragment of the Summit ADF task flow sample application.

Example 23-3 Metadata Added to a JSF Page to Create an ADF Region

<af:region value="#{bindings.editcustomertaskflowdefinition1.regionModel}"
                   id="r2"/>

JDeveloper also adds a task flow binding to the page definition file of the page that hosts the ADF region. Example 23-4 shows a sample of the metadata that JDeveloper adds. The task flow binding provides a bridge between the ADF region and the bounded task flow. It binds a specific instance of an ADF region to its associated bounded task flow and maintains all information specific to the bounded task flow. The taskFlowId attribute specifies the directory path and the name of the source file for the bounded task flow.

Example 23-4 Metadata Added to Page Definition to Create a Task Flow Binding

<taskFlow id="editcustomertaskflowdefinition1"
    taskFlowId="/WEB-INF/flows/edit-customer-task-flow-definition.xml#edit
    -customer-task-flow-definition"
    activation="deferred" 
    xmlns="http://xmlns.oracle.com/adf/controller/binding"/>

The bounded task flow preserves all of the data bindings when you drop it on the JSF page. At runtime, a request for a JSF page containing an ADF region initially handles like any other request for a JSF page. As the JSF page definition executes, data loads in to the JSF page. When the component tree for the parent JSF page encounters the <af:region> tag, it executes it in order to determine the first page fragment of content to display. Once it determine the first page fragment of content, it adds the appropriate UI components from the page fragment to the component tree for the parent JSF page.

The task flow binding creates an object for its task flow that implements the following interface in order to get the current view activity:

oracle.adf.controller.ViewPortContext

The task flow binding's taskFlowId attribute can also reference an EL expression that evaluates to one of the following:

  • java.lang.String

  • oracle.adf.controller.TaskFlowId

You use this capability if you create an ADF dynamic region. For more information, see Section 23.9, "Creating ADF Dynamic Regions."

23.3 Specifying Parameters for an ADF Region

You can make input parameters that you defined for a bounded task flow available to an ADF region by adding them to the task flow binding that the ADF region references. Use EL expressions to reference input parameters available in memory scopes, managed beans, or the ADF binding layer.

Specifying input parameters is one method of providing information to an ADF region. An alternative method is to use contextual events. The nature of the information that you want to provide to the ADF region determines the method you choose to provide the information. For example, choose:

For information about creating an ADF region and adding task flow bindings, see Section 23.2, "Creating an ADF Region." For information about how to define an input parameter for a bounded task flow, see Section 22.3, "Passing Parameters to a Bounded Task Flow."

23.3.1 How to Specify Parameters for an ADF Region

Use EL expressions to specify parameters available in memory scopes, managed beans, or the ADF binding layer as input for the ADF region.

Before you begin:

It may be helpful to have an understanding of the requirements for specifying parameters for an ADF region. For more information, see Section 23.3, "Specifying Parameters for an ADF Region."

You may also find it helpful to understand functionality that can be added using other task flow features and ADF region features. For more information, see Section 23.1.4, "Additional Functionality for Task Flows that Render in ADF Regions."

To specify input parameters for an ADF region:

  1. In the Applications window, right-click the JSF page that holds the ADF region and choose Go to Page Definition.

  2. In the overview editor, click the Bindings and Executables navigation tab, select the task flow binding for which you want to specify parameters and click the Edit icon.

  3. In the Edit Task Flow Binding dialog, write EL expressions that retrieve the values of each input parameter you want to specify for the ADF region. Note that you must write an EL expression for parameters that you defined as required. For example, write an EL expression similar to the following:

    #{pageFlowScope.inputParameter1}

    Figure 23-5 shows the Edit Task Flow Binding dialog where the Input Parameters section lists a number of input parameters that were defined for the bounded task, as described in Section 22.3, "Passing Parameters to a Bounded Task Flow."


    Note:

    You can write an EL expression that references a list of input parameters specified in a managed bean using the Input Parameters Map field of the Edit Task Flow Binding dialog. For more information about implementing this functionality, see Section 23.4, "Specifying Parameters for ADF Regions Using Parameter Maps."


    Figure 23-5 Edit Task Flow Binding Dialog

    Edit Task Flow Binding Dialog
  4. Click OK.

23.3.2 What Happens When You Specify Parameters for an ADF Region

JDeveloper writes entries that are child elements of the taskFlow element in the page definition of the JSF page, as illustrated in example Example 23-5.

Example 23-5 Metadata Entries to Specify Input Parameters for an ADF Region

<taskFlow id="tflow_tf11"
   taskFlowId="/WEB-INF/tflow_tf1.xml#tflow_tf1"
   activation="deferred" 
   xmlns="http://xmlns.oracle.com/adf/controller/binding">
  <parameters>
    <parameter id="inputParameter1"
      value="#{pageFlowScope.inputParameter1}"/>
    <parameter id="inputParameter2"
      value="#{pageFlowScope.inputParameter2}"/>
  </parameters>
</taskFlow>

At runtime, the values specified by the EL expression in the value attribute are passed to the ADF region.

23.4 Specifying Parameters for ADF Regions Using Parameter Maps

In addition (or as an alternative) to listing all the input parameters on the task flow binding, as described in Section 23.3, "Specifying Parameters for an ADF Region," you can use the parametersMap property of the task flow binding to specify a parameter map object on a managed bean. The parameter map object that you reference must be of a type that implements the following interface:

java.util.Map

The parameter map object that you reference specifies keys that map to the values you want to input to the ADF region. Using this approach reduces the number of parameter child elements that appear under the task flow binding (taskFlow) element or the multi task flow binding (multiTaskFlow) in the page definition for the page. This approach also allows you more flexibility in determining what input parameters pass to the ADF region. In particular, it provides a way to pass parameters to ADF dynamic regions as the number of input parameters can differ between the different task flow bindings in an ADF dynamic region. For more information, see Section 23.9, "Creating ADF Dynamic Regions."

You can configure an ADF region or an ADF dynamic region's task flow binding to reference a parameter map. You can also configure a multi task flow binding to reference a parameter map. Make sure that the name of an input parameter you define for a bounded task flow matches the name of a key that you define in the parameter map object.

If you specify a parameter with the same id attribute in a <parameter> element and in a <parametersMap> element, the <parametersMap> element always takes precedence. This is because the <parametersMap> element may need to override the static value of the parameter if you create an ADF dynamic region, as described in Section 23.9, "Creating ADF Dynamic Regions."

23.4.1 How to Create a Parameter Map to Specify Input Parameters for an ADF Region

You configure the task flow binding's parametersMap property to reference the parameter map object that defines the key-value pairs you want to pass to the ADF region.

Before you begin:

It may be helpful to have an understanding of the configuration options available to you when passing input parameters to an ADF region. For more information, see Section 23.4, "Specifying Parameters for ADF Regions Using Parameter Maps."

You may also find it helpful to understand functionality that can be added using other task flow and ADF region features. For more information, see Section 23.1.4, "Additional Functionality for Task Flows that Render in ADF Regions."

You will need to complete this task:

Create a managed bean or edit an existing managed bean so that it returns an object that implements the java.util.Map interface. Configure the managed bean so the object returns key-value pairs with the values that you want to pass to the ADF region. For more information about managed beans, see Section 26.4, "Using a Managed Bean in a Fusion Web Application."

To create a parameter map to specify input parameters for an ADF region:

  1. In the Applications window, right-click the JSF page that holds the ADF region and choose Go to Page Definition.

  2. In the overview editor, click the Bindings and Executables navigation tab, select the task flow binding or multi task flow binding for which you want to specify a parameter map, and then click the Edit icon.

    The type of task flow binding that you select determines the dialog that appears.

  3. In the Edit Task Flow Binding dialog or the Edit Multi Task Flow Binding dialog, select Expression Builder from the Input Parameters Map dropdown menu.

  4. Write or build an EL expression that references a parameter map. For example, write an EL expression similar to the following:

    #{pageFlowScope.userInfoBean.parameterMap}

  5. Click OK.

23.4.2 What Happens When You Create a Parameter Map to Specify Input Parameters

At runtime, the task flow binding or multi task flow binding evaluates the EL expression specified for its parametersMap property. It returns values to the ADF region from the managed bean for keys that match the name of the input parameters defined for the bounded task flow that render in the ADF region.

Example 23-6 shows code snippets from a managed bean that puts two values (isLoggedIn and principalName) into a parameter map named parameterMap.

Example 23-6 Managed Bean Defining a Parameter Map

import java.util.HashMap;
import java.util.Map;
 
public class UserInfoBean {
    private Map<String, Object> parameterMap = new HashMap<String, Object>();
 
    public Map getParameterMap() {
        
        parameterMap.put("isLoggedIn", getSecurity().isAuthenticated());
        parameterMap.put("principalName", getSecurity().getPrincipalName());
        return parameterMap;
    }
}

Figure 23-6 shows the Edit Task Flow Binding dialog after you close the Expression Builder dialog, having specified the parameter map object (parameterMap) shown in Example 23-6. The Input Parameters field in the Edit Task Flow Binding dialog lists the input parameters defined for the bounded task flow associated with this ADF region (checkout-flow). The task flow binding retrieves the values for these parameters from the managed bean shown in Example 23-6.

Figure 23-6 EL Expression Referencing Parameter Map on Task Flow Binding

Parameter Map Property for Task Flow Binding

Example 23-7 shows the metadata that appears for the task flow binding in the page definition file of the page that renders the ADF region. The metadata for the task flow binding references both the bounded task flow (taskFlowId attribute) and the managed bean (parametersMap).

Example 23-7 Task Flow Binding Specifying a Parameter Map

<taskFlow id="checkoutflow1"
              taskFlowId="/WEB-INF/checkout-flow.xml#checkout-flow"
              activation="deferred"
              xmlns="http://xmlns.oracle.com/adf/controller/binding"
              parametersMap="#{pageFlowScope.userInfoBean.parameterMap}"/>

You specify the <parameterMap> element in the page definition.


Note:

If you specify Refresh="ifNeeded", parameters are not supported in the <parameterMap> element. The only condition that determines whether the region need to be refreshed is the boolean value returned by the evaluation of RefreshCondition. For more information, see Section 23.5.2, "What You May Need to Know About Configuring an ADF Region to Refresh."


23.5 Configuring an ADF Region to Refresh

You can configure when an ADF region refreshes and whether it invokes a task flow. An ADF region can only invoke a task flow when the ADF region is in an active state. An ADF region in an inactive state cannot invoke a task flow and returns a null value for the ID of the referenced task flow to the parent page.

23.5.1 How to Configure the Refresh of an ADF Region

You set values for the task flow binding of the task flow associated with the ADF region to determine when an ADF region switches from an inactive to an active state and to determine when an ADF region refreshes.

Before you begin:

It may be helpful to have an understanding of the requirements for a bounded task flow that you use in an ADF region. For more information, see Section 23.5, "Configuring an ADF Region to Refresh."

You may also find it helpful to understand functionality that can be added using other task flow features and ADF region features. For more information, see Section 23.1.4, "Additional Functionality for Task Flows that Render in ADF Regions."

To configure the refreshing of an ADF Region:

  1. In the Applications window, select the page that contains the ADF region, right-click and choose Go to Page Definition.

  2. In the page definition file, select the task flow binding or multi task flowing binding in the Executables section, as illustrated in Figure 23-7.

    Figure 23-7 Task Flow Binding

    Task Flow Binding
  3. Choose the appropriate option to refresh the ADF region.

    • Refresh if the value of a task flow binding parameter changes.

      In the Properties window, select ifNeeded from the Refresh dropdown list.

      Do not select ifNeeded if you want to set a value for the RefreshCondition property. The RefreshCondition property will not be evaluated if you select ifNeeded for the Refresh property.

    • Refresh if a condition that you specify returns true.

      In the Properties window, write an EL expression in the RefreshCondition field that returns a boolean value. If the EL expression returns true, the ADF region refreshes.

  4. In the Properties window, select a value from the activation dropdown list, as described in the following list:

    • conditional: activates the ADF region if the EL expression set as a value for the task flow binding active property returns true.

    • deferred: select this option if your application uses Facelets XHTML pages in the view layer and you want to activate the ADF region when a Facelets XHTML page first requests a viewID. If your application uses JSP technology in the view layer, selecting this option has the same effect as selecting immediate (the ADF region activates immediately) provided that the parent component for the ADF region is not a popup or panelTabbed component that has its childCreation attribute set to deferred. If this latter scenario occurs, the parent component (popup or panelTabbed) determines behavior.

      Use this option if your application uses Facelets XHTML pages. For more information about Facelets with ADF Faces, see the "Getting Started with ADF Faces and JDeveloper" chapter in Developing Web User Interfaces with Oracle ADF Faces.

    • immediate: activates the ADF region immediately. This is the default value.

    The value that you select in the dropdown list determines when an ADF region switches from an inactive to an active state. An ADF region must have an active state before it can invoke a task flow.

  5. If you selected conditional as the value for the activation property, write an EL expression that returns a boolean value at runtime for the active property. If the EL expression returns true, the ADF region invokes the task flow.

23.5.2 What You May Need to Know About Configuring an ADF Region to Refresh

An ADF region initially refreshes when the parent JSF page on which the region is located first displays. During the initial refresh, any ADF region task flow binding parameter values are passed in from the parent page. The parameter values are used to display the initial page fragment within the ADF region. If the bounded task flow relies on input parameter values that are not available when the page is first created, make sure that your task flow behaves correctly if the input parameter values are null by, for example, using a NullPointerException object. Alternatively (or additionally), make sure that the task flow does not activate until the input parameters become available by configuring the task flow binding's active property.

An ADF region task flow binding can be refreshed again based on one of the following task flow binding attributes:

  • taskFlowId

    This attribute specifies the directory path and the name of the source file for the bounded task flow. The ADF region refreshes if this attribute value changes.

  • Neither Refresh or RefreshCondition attributes are specified (default)

    If neither the Refresh or RefreshCondition task flow binding attribute is specified, the ADF region is refreshed only once at the time the parent page is first displayed unless you configure a value for the task flow binding's active property.

  • RefreshCondition="#{EL.expression}"

    The ADF region is refreshed a single time when its RefreshCondition property 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 value causes the ADF region to refresh. If the ADF region task flow binding does not have parameters, Refresh="ifNeeded" is equivalent to not specifying the Refresh attribute.

    Refresh="ifNeeded" is not supported if you pass parameters to the task flow binding using a dynamic parameter map. You must instead use the RefreshCondition="#{EL.Expression}".

    For more information about specifying parameter values using a parameter map, see Section 23.4, "Specifying Parameters for ADF Regions Using Parameter Maps."

The Refresh="ifNeeded" property takes precedence over RefreshCondition and RefreshCondition will not be evaluated if you set Refresh="ifNeeded".

If the bindings variable 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 27, "Understanding the Fusion Page Lifecycle".

Example 23-8 contains a sample task flow binding located within the page definition of a page on which an ADF region has been added.

Example 23-8 Refresh Option Specified in ADF Region Binding

<taskFlow id="Department1" taskFlowId="/WEB-INF/Department#Department"
    xmlns="http://xmlns.oracle.com/adf/controller/binding">
  <parameters>
    <parameter id="DepartmentId" value="#{bindings.DepartmentId.inputValue}"
        xmlns="http://xmlns.oracle.com/adfm/uimodel"/>
  </parameters>
</taskFlow>

You do not need to refresh an ADF region to refresh the data controls inside the ADF region. During the ADF lifecycle, the refresh events telling the iterators to update will be propagated to the binding container of the current page of the ADF region.

23.6 Configuring Activation of an ADF Region

You can configure when an ADF region activates. This has the effect of determining when the task flows contained in ADF regions activate. Configuring the activation of ADF regions can optimize the performance of a Fusion web application's page. For example, a page that contains 5 ADF regions may reference 5 task flows. You may not want these 5 task flows to execute simultaneously when the Fusion web application page loads so you configure an activation property to determine when a task flow executes.

23.6.1 How to Configure Activation of an ADF Region

You configure the activation property for the task flow binding associated with the ADF region to determine when to activate the ADF region.

Before you begin:

It may be helpful to have an understanding of the configuration options for activating an ADF region. For more information, see Section 23.6, "Configuring Activation of an ADF Region."

You may also find it helpful to understand functionality that can be added using other task flow features and ADF region features. For more information, see Section 23.1.4, "Additional Functionality for Task Flows that Render in ADF Regions."

To configure the activation of an ADF region:

  1. In the Applications window, select the page that contains the ADF region(s), right-click and choose Go to Page Definition.

  2. In the page definition file, select the task flow binding or multi task flow binding in the Executables section, as illustrated in Figure 23-8.

    Figure 23-8 Task Flow Bindings for ADF Region Configured for Activation

    Task Flow Binding
  3. In the Properties window, select a value from the activation dropdown list, as described in the following list:

    • conditional: activates the ADF region if the EL expression set as a value for the task flow binding active property returns true.

    • deferred: select this option if your application uses Facelets XHTML pages in the view layer and you want to activate the ADF region when a Facelets XHTML page first requests a viewID. If your application uses JSP technology in the view layer, selecting this option has the same effect as selecting immediate (the ADF region activates immediately).

      Use this option if your application uses Facelets XHTML pages. For more information about Facelets with ADF Faces, see the "Getting Started with ADF Faces and JDeveloper" chapter in Developing Web User Interfaces with Oracle ADF Faces.

    • immediate: activates the ADF region immediately. This is the default value.

    The value that you select in the dropdown list determines when an ADF region switches from an inactive to an active state. An ADF region must have an active state before it can invoke a task flow.

  4. If you selected conditional as the value in the activation dropdown list, write an EL expression that returns a boolean value at runtime for the active property. If the EL expression returns true, the ADF region invokes the task flow. If the EL expression returns false, the ADF region deactivates a task flow that was active in the ADF region.

23.6.2 What Happens When You Configure Activation of an ADF Region

The behavior of the ADF region at runtime depends on the options that you set for the activation property.

Figure 23-9 shows the default behavior where all task flows in ADF regions execute when the page loads the ADF regions (Tab # 1, Tab # 2, Tab # 3).

Figure 23-9 Default Activation of ADF Regions

Default Activation of Task Flows

Figure 23-10 shows an example where the activation property was set to deferred and the application uses Facelets. The regions in Tab # 1 and Tab # 2 have an active state because the end user navigated to these regions. The region in Tab # 3 is inactive.

Figure 23-10 Deferred Activation of ADF Regions

Deferred Activation of ADF Regions

Figure 23-11 shows an example where the activation property was set to conditional and the active property to an EL expression that returns a boolean value at runtime. The region in Tab # 1 is in an active state because the EL expression specified for the active property returns true. The regions in Tab # 2 and Tab # 3 are inactive because the EL expression specified for the active property returns false.

Note that the following events occur if a region deactivates a task flow (the value returned by the active property changes from true to false):

Figure 23-11 Conditional Activation of ADF Regions

Conditional Activation of ADF Regions

23.7 Navigating Outside an ADF Region's Task Flow

A bounded task flow running in an ADF region may need to trigger navigation of its parent view activity or to navigate to the root page of its application. The parent action activity exposes properties (parent-outcome and root-outcome) that you configure if you want to implement either of these use cases.

For example, you might specify a value for parent-outcome if you have a page that displays employee information and an ADF region that contains an enroll button for an employee. After the enroll page completes and the ADF region returns, the employee information page refreshes with the next employee.


Note:

An ADF region does not maintain state when you navigate away from the region.


23.7.1 How to Trigger Navigation Outside of an ADF Region's Task Flow

You add a parent action activity to the bounded task that runs in the ADF region and configure it so that it navigates to the parent's view activity.

Before you begin:

It may be helpful to have an understanding of the configuration options for activating an ADF region. For more information, see Section 23.6, "Configuring Activation of an ADF Region."

You may also find it helpful to understand functionality that can be added using other task flow features and ADF region features. For more information, see Section 23.1.4, "Additional Functionality for Task Flows that Render in ADF Regions."

To trigger navigation outside of an ADF region's task flow:

  1. In the Applications window, double-click the bounded task flow that runs in the ADF region.

  2. In the ADF Task Flow page of the Components window, from the Component panel, in the Activities group, drag and drop a Parent Action onto the diagram for the bounded task flow.

  3. Select the parent action activity in the diagram for the bounded task flow.

  4. In the Properties window, choose the appropriate option:

    • Parent Outcome: enter a literal value or write an EL expression that returns an outcome so that the parent action activity navigates to the parent view activity. The outcome is then used to navigate the parent view activity's task flow rather than navigating the ADF region's bounded task flow.

      The parent view activity's task flow should contain a control flow case or wildcard control flow rule that accepts the value you specify for parent-outcome.

    • Root Outcome: enter a literal value or write an EL expression that returns an outcome so that the parent action activity navigates to the root page of the application.

      For example, to navigate from an ADF region to the home page in your application, you specify a value for Root Outcome, as illustrated in Figure 23-12.

      Figure 23-12 Navigating to Home Page

      Navigating to Home Page

    Note:

    Parent Outcome and Root Outcome are mutually exclusive.


  5. (Optional) In the Outcome field, enter a literal value that specifies an outcome for control flow within the ADF region after the parent action activity adds parent-outcome or root-outcome to the appropriate queue.

    Specifying an outcome element is useful in cases where the parent view activity or root page does not navigate as a result of the parent-outcome or root-outcome sent by the parent action activity. In addition, the ADF region should not continue to display the same view. If you do not specify a value for outcome, the ADF region's viewId remains unchanged.

23.7.2 What Happens When You Configure Navigation Outside a Task Flow

At design time, JDeveloper writes entries to the source file for the bounded task flow based on the property values you set for the parent action activity. Example 23-9 shows sample entries that JDeveloper generates when you write a literal value for the Parent Outcome and Outcome properties of the parent action activity.

Example 23-9 Metadata for a Parent Action Activity with a Parent Outcome

<parent-action id="parentAction1">
    <parent-outcome>parent_outcome</parent-outcome>
    <outcome id="__2">outcome</outcome>
</parent-action>

Example 23-10 shows sample entries that JDeveloper generates when you write a literal value for the Root Outcome and Outcome properties of the parent action activity.

Example 23-10 Metadata for a Parent Action Activity with a Root Outcome

<parent-action id="parentAction1">
      <root-outcome>root_outcome</root-outcome>
      <outcome id="__2">outcome</outcome>
</parent-action>

At runtime, the bounded task flow navigates to its parent view activity or the root page of the Fusion web application depending on the property that you configured for the parent action activity.

23.7.3 What You May Need to Know About How a Page Determines the Capabilities of an ADF Region

In some cases, a page may need to determine the capabilities currently available within one of the ADF regions that it contains. For example, the page may need to initiate control flow within the ADF region based on its current state using the queueActionEventInRegion() method. Region capabilities are used by a parent page to identify the current outcomes of one of its regions based on the region's current state. They identify to the parent page whether or not an outcome is possible within the region.

The following scenario describes how region capabilities might typically be used in an application:

  1. An ADF region within a page displays its associated page fragment.

  2. A user selects a button or performs some other action in the ADF region.

  3. The parent page identifies the outcomes (region capabilities) for the ADF region.

  4. 

    The parent page updates its buttons based on the ADF region capabilities.

The syntax of an EL expression to determine an ADF region's capabilities is as follows:

#{bindings.[regionId].regionModel.capabilities['outcome']}

where regionId is the ID of the ADF region component on the page and outcome is the possible outcome being verified within the ADF region.

Region capabilities require the availability of the specified ADF region's regionModel through an EL expression. The EL expression should never access bindings in any other binding container other than the current binding container. Region capabilities cannot be used in some cases. For example, a nested ADF region where a regionModel cannot be reached within the current binding container. This is because a nested region's nested binding container might not yet exist or might have already been released.

23.8 Configuring Transaction Management in an ADF Region

ADF task flows provide options to implement transactions, as described in Section 24.3, "Managing Transactions in Task Flows." You can choose whether a task flow shares or isolates its data controls with a calling task flow by setting a value for its data-control-scope property, as described in Section 24.2, "Sharing Data Controls Between Task Flows." Whether a task flow creates a new transaction depends on the values you choose for the transaction and data-control-scope properties, as described in Section 24.3.3, "What You May Need to Know About Sharing Data Controls and Managing Transactions."

If, for example, you share a task flow's data control with a calling task flow, a new transaction is created if you configure the task flow's transaction option to Always Begin New Transaction (new-transaction) or to Use Existing Transaction If Possible (requires-transaction). The requires-transaction option creates a new transaction only if a transaction does not already exist. The created transaction has the same lifespan as the ADF region that renders the task flow. This may cause behavior that you do not intend when the task flow renders in an ADF region. For example, if an ADF region refreshes, it restarts the task flow that it renders and causes the following events to occur:

There are a number of ways to prevent the inadvertent termination of a task flow's transaction by the refresh of an ADF region. All these options disassociate the lifespan of the transaction in the task flow that renders in an ADF region from the lifespan of the ADF region. These options make sure that the region's parent page owns the transaction and/or that the transaction starts before the region renders. Choose the most appropriate option for your application:

If you share the data controls of a task flow with a calling task flow, use the rollback or commit options exposed by the task flow's task flow return activity to commit or rollback changes rather than programmatically use the methods exposed by the ADF Model layer's DataControlFrame interface. Using the methods exposed by the DataControlFrame interface closes the transaction and may cause the task flow that renders in the ADF region to create a new transaction.

23.9 Creating ADF Dynamic Regions

An ADF dynamic region is an ADF region where the task flow binding dynamically determines the value of its taskFlowId attribute at runtime. This allows the Fusion web application to determine which bounded task flow to execute within the ADF dynamic region based on the result of evaluation of the task flow binding's taskFlowId attribute.

Figure 23-13 shows a runtime example from the Summit ADF task flow sample application where the index.jsf page renders a different registration task flow in the showDetailItem component labeled Welcome in response to the link component that the end user clicks. For example, if the end user clicks Register as Employee, the application renders the emp-reg-task-flow-definition.xml task flow in the ADF dynamic region. If the end user clicks Register as Customer, the application renders the edit-customer-task-flow-definition.xml task flow in the ADF dynamic region.

At runtime, the ADF dynamic region swaps the task flows that it renders during the Prepare Render lifecycle phase. To give components from a previous task flow the opportunity to participate smoothly in the lifecycle phases, do not navigate off the regionModel until the JSF Invoke Application lifecycle phase. It is good practice, therefore, not to navigate a task flow in a dynamic region in response to contextual events. For more information about lifecycle phases, see Chapter 27, "Understanding the Fusion Page Lifecycle," and for more information about contextual events, see Chapter 40, "Using Contextual Events."

Figure 23-13 ADF Dynamic Region in the Summit ADF Task Flow Sample Application

ADF Dynamic Region in Summit ADF Application

You create an ADF dynamic region by dragging and dropping a bounded task flow to the page where you want to render the ADF dynamic region. The view activities in the bounded task flow must be associated with page fragments (.jsff).

If you attempt to drag and drop a bounded task flow that is associated with pages rather than page fragments, JDeveloper does not display the context menu that allows you to create an ADF dynamic region. You can convert a bound task flow that uses pages to use page fragments. For more information, see Section 20.6.4, "How to Convert Bounded Task Flows."

After you create an ADF dynamic region, you can add additional bounded task flows to the dynamic region by creating ADF dynamic region links, as described in Section 23.10, "Adding Additional Task Flows to an ADF Dynamic Region."

23.9.1 How to Create an ADF Dynamic Region

Drag and drop bounded task flows to the page where you want to render the ADF dynamic region.

Before you begin:

It may be helpful to have an understanding of the configuration options available to you when creating an ADF dynamic region. For more information, see Section 23.9, "Creating ADF Dynamic Regions."

You may also find it helpful to understand other functionality that can be added using other task flow and ADF region features. For more information, see Section 23.1.4, "Additional Functionality for Task Flows that Render in ADF Regions."

To create an ADF dynamic region:

  1. In the Applications window, double-click the JSF page where you want to create the ADF dynamic region.

  2. From the Applications window, drag and drop the first bounded task flow onto the JSF page, and from the context menu, choose Create > Dynamic Region.

  3. Choose the appropriate option in the Choose Managed Bean for Dynamic Region dialog:

    • If you want an existing managed bean to store the bounded task flow's ID, select an existing managed bean from the Managed Bean dropdown list.

      The managed bean passes the value of the bounded task flow's ID into the task flow binding of the ADF dynamic region. Make sure that the managed bean you select is not used by another ADF dynamic region.

    • If no managed bean exists for the page, click the Add icon next to the Managed Bean dropdown list to create a new one. Enter values in the dialog that appears as follows:

      1. Bean Name: Enter a name for the new managed bean. For example, enter DynamicRegionBean.

      2. Class Name: Enter the name of the new managed bean class.

      3. Package: Enter the name of the package that is to contain the managed bean or browse to locate it.

      4. Extends: Enter the name of the Java class that the managed bean extends. The default value is java.lang.Object.

      5. Scope: This field is read-only and its value is set to backingBean. For more information about the memory scope for managed beans, see Section 20.2.4, "What You May Need to Know About Memory Scope for Task Flows."

      6. Click OK to close the dialogs where you configure the managed bean.

  4. Choose the appropriate option in the Edit Task Flow Binding dialog:

    Figure 23-14 shows the Edit Task Flow Binding dialog that appears after you configure a managed bean.


    Note:

    You can write an EL expression that references a list of input parameters specified in a managed bean using the Input Parameters Map field of the Edit Task Flow Binding dialog. For more information about implementing this functionality, see Section 23.4, "Specifying Parameters for ADF Regions Using Parameter Maps."


    Figure 23-14 Edit Task Flow Binding Dialog for an ADF Dynamic Region

    Edit Task Flow Binding Dialog for an ADF Dynamic Region
  5. Click OK.

23.9.2 What Happens When You Create an ADF Dynamic Region

When you drop a bounded task flow onto a JSF page to create an ADF dynamic region, JDeveloper adds an af:region tag to the page. The af:region tag contains a reference to a task flow binding. Example 23-11 shows the af:region tag that renders the ADF dynamic region in the index.jsf page of the Summit ADF task flow sample application.

Example 23-11 Metadata Added to a JSF Page to Create an ADF Dynamic Region

<af:region value="#{bindings.dynamicRegion1.regionModel}" id="r4"
                             rendered="#{WelcomePageBean.isRegistration}"/>

JDeveloper also adds a task flow binding to the page definition file of the page that hosts the ADF dynamic region. Example 23-12 shows a sample of the metadata that JDeveloper adds. The task flow binding provides a bridge between the ADF dynamic region and the bounded task flow. It binds the ADF dynamic region to the bounded task flow and maintains all information specific to the bounded task flow.

Example 23-12 Metadata Added to Page Definition to Create a Task Flow Binding

<taskFlow id="dynamicRegion1"
       taskFlowId="${WelcomePageBean.dynamicTaskFlowId}"
       activation="deferred"
       xmlns="http://xmlns.oracle.com/adf/controller/binding"/>

The taskFlowId attribute in the task flow binding metadata specifies the managed bean that determines at runtime what bounded task flow to associate with the ADF dynamic region. JDeveloper creates this managed bean or modifies an existing managed bean to store this data. Example 23-13 shows extracts of the code that JDeveloper writes to the managed bean.

Example 23-13 Managed Bean Entries to Retrieve Bounded Task Flow for an ADF Dynamic Region

import oracle.adf.controller.TaskFlowId;
 ...
    private String taskFlowId = "/directoryPath/toTaskFlow";
 ...
    public TaskFlowId getDynamicTaskFlowId() {
        return TaskFlowId.parse(taskFlowId);
    }
...

At runtime, the managed bean stores the value of the bounded task flow's ID (taskFlowId) that displays inside the ADF dynamic region. The managed bean swaps the different bounded task flows into the task flow binding of the ADF dynamic region.

When an ADF dynamic region reinitializes, the Fusion web application must reinitialize the task flow binding associated with the ADF dynamic region. This includes evaluating if there are new input parameters and input parameter values to pass to the ADF dynamic region.

23.10 Adding Additional Task Flows to an ADF Dynamic Region

An ADF dynamic region link swaps a bounded task flow for another bounded task flow within an ADF dynamic region. An end user clicks a command component (a button or a link) to update the ADF dynamic region with the new bounded task flow.

For example, a bounded task flow in the ADF dynamic region displays general information about an employee such as an ID and photo. When the end user clicks a link command component labeled Details, the ADF dynamic region updates with a table containing more information about the employee from another bounded task flow. The end user's action (clicking the link) invokes a method on the ADF dynamic region's managed bean. The value of the new bounded task flow is passed to the method, and the ADF dynamic region refreshes with the new bounded task flow. The new bounded task flow now displays within the ADF dynamic region.

By default, a ADF dynamic region link swaps another bounded task flow in for the original, but cannot swap back to the original. To toggle back to the original bounded task flow, you could add a second ADF dynamic region link on the page that, when clicked, swaps the current task flow back to the original one.

You can add an ADF dynamic region link if you already have at least one ADF dynamic region on a page and are adding a new bounded task flow as an ADF dynamic region to the same page. After you drop the bounded task flow on the page and choose to create an ADF dynamic region link, a menu displays all of the dynamic regions currently on the page, as shown in Figure 23-15.

A list of the current dynamic regions in a document appears when you choose Dynamic Region Link from the menu that appears after you drag and drop a bounded task that you want to add as an option to an existing dynamic region in the document, as shown in Figure 23-15.

Figure 23-15 ADF Dynamic Region Link Menu

Dynamic Region Link Menu

Use this menu to select the ADF dynamic region within which you want to display the contents of the bounded task flow.


Tip:

You can use the values in the dynamic region link in other UI components. For example, you could create a selection list in which each of the items in the list links to a different bounded task flow. All of the linked bounded task flows would display in the same dynamic region. The links perform a method in the class behind the managed bean created to swap the bounded task flow it displays.


23.10.1 How to Create an ADF Dynamic Region Link

You drag and drop a bounded task flow to a page that already contains an ADF dynamic region and you select Dynamic Region Link on the context menu that appears to view a list of ADF dynamic regions to which you can create a link.

Before you begin:

It may be helpful to have an understanding of the configuration required before you attempt to create an ADF dynamic region link. For more information, see Section 23.10, "Adding Additional Task Flows to an ADF Dynamic Region."

You may also find it helpful to understand functionality that can be added using other task flow and ADF region features. For more information, see Section 23.1.4, "Additional Functionality for Task Flows that Render in ADF Regions."

You will need to complete this task:

Add at least one ADF dynamic region to the JSF page where you are going to create an ADF dynamic region link. For information about adding an ADF dynamic region to a JSF page, see Section 23.9, "Creating ADF Dynamic Regions."

To create an ADF dynamic region link:

  1. In the Applications window, double-click the JSF page where you want to create the ADF dynamic region link.

  2. From the Applications window, drag and drop a bounded task flow onto the JSF page and, from the context menu, choose Dynamic Region Link.


    Note:

    The view activities of the bounded task flow must be associated with page fragments. You can convert a bounded task flow that uses pages to use page fragments. For more information, see Section 20.6.4, "How to Convert Bounded Task Flows."


  3. In the context menu that displays a list of the ADF dynamic regions that have already been added to the page, select the name of the ADF dynamic region in which you want to display the contents of the bounded task flow.

  4. Click OK.

23.10.2 What Happens When You Create an ADF Dynamic Region

JDeveloper adds a link to the page, as shown in Example 23-14. JDeveloper also updates the managed bean for the ADF dynamic region and updates the corresponding task flow binding with any new parameters.

Example 23-14 Dynamic Region Link

<af:link text="region2" action="#{RegionBean.region2}"
  id="dynamicRegionLink1"/>

23.11 Configuring a Page To Render an Unknown Number of Regions

You can configure a page at design time when you do not know the number of regions that render in the page at runtime. For example, you want to add or remove regions to tabs using the panelTabbed component. Each tab that you add or remove renders a region that references a bounded task flow.

To implement this functionality, you configure the JSF page definition file's multiTaskFlow element to reference a list of task flow bindings contained in a managed bean of the following type:

oracle.adf.controller.binding.TaskFlowBindingAttributes

Example 23-15 shows the code for the class of a managed bean named MultiBean that returns a list containing two task flows.

Example 23-15 Managed Bean Returning a List of Task Flow Bindings

package view;
 
import java.util.ArrayList;
import java.util.List;
 
import oracle.adf.controller.TaskFlowId;
import oracle.adf.controller.binding.TaskFlowBindingAttributes;
 
public class MultiBean {
    private List<TaskFlowBindingAttributes> mTaskFlowBindingAttrs = new 
                   ArrayList<TaskFlowBindingAttributes>(5);
 
    public MultiBean() {
        TaskFlowBindingAttributes tfAttr = new TaskFlowBindingAttributes();
        tfAttr.setId("region1");
        tfAttr.setTaskFlowId(new TaskFlowId("/WEB-INF/r1.xml", "r1"));
        mTaskFlowBindingAttrs.add(tfAttr);
 
        tfAttr = new TaskFlowBindingAttributes();
        tfAttr.setId("region2");
        tfAttr.setTaskFlowId(new TaskFlowId("/WEB-INF/r2.xml", "r2"));
        mTaskFlowBindingAttrs.add(tfAttr);
 
    }
 
    public List<TaskFlowBindingAttributes> getTaskFlowList() {
        return mTaskFlowBindingAttrs;
    }
}

For more information about the TaskFlowBindingAttributes class, see the Java API Reference for Oracle ADF Controller.

At runtime, the multiTaskFlow binding references a list of one or more task flows that an end user can add or remove to the page using command components that you also expose. Figure 23-16 shows the relationships between the different parts that make up this use case.


Note:

The page fragments that the bounded task flows render must use the Facelets document type.


Figure 23-16 ADF Regions Derived from a Multi Task Flow Binding

ADF Regions Derived from a Multi Task Flow Binding

23.11.1 How to Configure a Page to Render an Unknown Number of Regions

Configure the JSF page definition file's multiTaskFlow element to reference a list of bounded task flows. This list can be modified at runtime by adding or removing elements of type TaskFlowBindingAttributes.

Before you begin:

It may be helpful to have an understanding of the configuration options available to you when configuring a page to render an unknown number of ADF regions. For more information, see Section 23.11, "Configuring a Page To Render an Unknown Number of Regions."

You may also find it helpful to understand other functionality that can be added using other task flow and ADF region features. For more information, see Section 23.1.3, "Task Flows and ADF Region Use Cases and Examples."

You will need to complete this task:

Create a managed bean with a pageFlow scope that returns a list of type TaskFlowBindingAttributes. Example 23-15 shows the code for the class of a managed bean that returns such a list. For more information about how to create a managed bean, see Section 26.4.1, "How to Use a Managed Bean to Store Information."

To configure a page to render an unknown number of regions:

  1. In the Applications window, right-click the JSF page where you want to add or remove ADF regions at runtime and choose Go to Page Definition.

  2. If a confirmation dialog appears, click Yes.

  3. In the overview editor, click the Binding and Executables tab, and then click the Add icon in the Executables section.

  4. In the Insert Item dialog, select ADF Task Flow Bindings from the dropdown menu, then select multiTaskFlow as the item to create and click OK.

  5. In the Insert multiTaskFlow dialog, enter the following values:

    • id*: Enter a unique ID for the multi task flow binding.

    • taskFlowList *: Enter an EL expression that returns the list of TaskFlowBindingAttributes to return at runtime. For example, to return the list in Example 23-15, enter the following EL expression:

      #{pageFlowScope.multiBean.taskFlowList}

  6. In the Applications window, double-click the JSF page where you want end users to add or remove ADF regions at runtime.

  7. In the ADF Faces page of the Components window, from the Operations panel, drag and drop a For Each onto the component in the Structure window that you want to enclose the For Each component.

  8. In the Properties window for the For Each component, enter values in the following fields:

    • Items: Enter an EL expression that references the method that return the list of task flow bindings from the multi task flow binding runtime object.

      For example, enter an EL expression similar to the following:

      #{bindings.multiRegion1.taskFlowBindingList}

    • Var: Enter a value to identify the list of task flow bindings.

  9. In the JSF page that contains the For Each component, insert a Region component inside the For Each component that references the Region component's region model using an EL expression, as shown in Example 23-16.

    Example 23-16 ADF Region Referencing a Region Model

    <af:forEach var="tf" items="#{bindings.multiRegion1.taskFlowBindingList}">
      <af:panelBox text="#{tf.name}" id="pb1">
        <f:facet name="toolbar"/>
        <af:region value="#{tf.regionModel}" id="r1"/>
      </af:panelBox>
    </af:forEach>
    

23.11.2 What Happens When You Configure a Page to Render an Unknown Number of Regions

Metadata similar to that shown in Example 23-17 appears in the JSF page definition file for the multi task flow binding.

Example 23-17 Metadata Added to Page Definition to Create a Multi Task Flow Binding

<multiTaskFlow id="multiRegion1"              
    taskFlowList="${pageFlowScope.multiBean.taskFlowList}" activation="deferred"
    xmlns="http://xmlns.oracle.com/adf/controller/binding"/>

The taskFlowList attribute in the multi task flow binding metadata specifies the managed bean. The managed bean stores the list of objects describing the task flows that can be added to the page at runtime.

23.11.3 What You May Need to Know About Configuring a Page to Render an Unknown Number of Regions

  • Attempt to limit the number of ADF regions that you create in a page to 10.

  • Each task flow binding inherits attributes defined for the multi task flow binding unless you override this behavior using the methods exposed by TaskFlowBindingAttributes.

  • Each task flow binding inherits parameters defined in the multi task flow binding in addition to those defined using the parametersMap property, as described in Section 23.4, "Specifying Parameters for ADF Regions Using Parameter Maps."

23.12 Handling Access to Secured Task Flows by Unauthorized Users

A bounded task flow does not render in an ADF region if it is invoked by a user who does not have the security permissions to access it. The region renders a blank area in place of the requested task flow when this occurs. This may confuse your users as it does not provide feedback as to why the task flow that they attempted to invoke does not appear. To improve the user experience, you can specify an alternative bounded task flow to render when a user attempts to access a bounded task for which they do not have the required security permissions. You can, for example, configure the alternative bounded task flow to display a page to inform users that they do not have the necessary security permissions. A more complex approach may be to render a bounded task flow that takes the users step-by-step through the process to request the necessary permissions from their system administrator.

Configure the level of security for the alternative bounded task flow to make sure that users can view it should they fail to access a bounded task flow for which they do not have security permissions. This may involve making the alternative bounded task flow public, as described in Section 41.5.1, "How to Make an ADF Resource Public." For more information about securing your Fusion web application, including bounded task flows, see Section 41, "Enabling ADF Security in a Fusion Web Application."

23.12.1 How to Handle Access to Secured Task Flows by Unauthorized Users

You configure an alternative bounded task flow with the content that you want to display to users when they cannot access a bounded task flow because of a lack of security permissions. You specify the alternative bounded task flow as the value for the Unauthorized Region Taskflow property in your Fusion web application's adf-config.xml file.

Before you begin:

It may be helpful to have an understanding of why you may need to display a message to users without security permissions for a task flow. For more information, see Section 23.12, "Handling Access to Secured Task Flows by Unauthorized Users."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features. For more information, see Section 23.1.4, "Additional Functionality for Task Flows that Render in ADF Regions."

You will need to complete these tasks:

  1. Create an alternative bounded task flow to display to users when they cannot access a bounded task flow for which they do not have security permissions.

    For more information about creating a bounded task flow, see Section 20.2, "Creating a Task Flow."

  2. Configure this task flow so that users can access it.

    For more information, see Section 41.5.1, "How to Make an ADF Resource Public."

To display messages to users without security permissions for task flows:

  1. In the Application Resources panel, expand the Descriptors and ADF META-INF nodes, and then double-click the adf-config.xml file.

  2. In the overview editor, click the Controller navigation tab.

  3. In the Controller page, in the Unauthorized Region Taskflow field, enter the name of the bounded task flow to invoke or click Browse to select it.

23.12.2 What Happens When You Handle Access to Secured Task Flows by Unauthorized Users

JDeveloper writes the name of the bounded task flow that you selected as a value for the <unauthorized-region-taskflow> element in the adf-config.xml file, as illustrated in Example 23-18.

Example 23-18 Metadata Entry to Specify Task Flow Accessible Without Authentication

<?xml version="1.0" encoding="windows-1252" ?>
<adf-config xmlns="http://xmlns.oracle.com/adf/config"
    xmlns:config="http://xmlns.oracle.com/bc4j/configuration"
     xmlns:adf="http://xmlns.oracle.com/adf/config/properties">
...
<adf-controller-config xmlns="http://xmlns.oracle.com/adf/controller/config">
    <unauthorized-region-taskflow>/WEB-INF/task-flow-definition.xml
       </unauthorized-region-taskflow>
  </adf-controller-config>
...
</adf-config>

At runtime, the Fusion web application renders this alternative bounded task flow when users attempt to invoke a bounded task flow for which they do not have security permissions.

PKejpPKz$DOEBPS/deployment_topics.htm Deploying Fusion Web Applications

48 Deploying Fusion Web Applications

This chapter describes how to deploy Oracle ADF applications to a target application server. It describes how to create deployment profiles, how to create deployment descriptors, and how to load ADF runtime libraries. It includes instructions for running an application in the Integrated WebLogic Server as well as deploying to a standalone Oracle WebLogic Server.

This chapter includes the following sections:

48.1 About Deploying Fusion Web Applications

Deployment is the process of packaging application files as an archive file and transferring that file to a target application server. You can use JDeveloper to deploy Oracle ADF applications directly to the application server (such as Oracle WebLogic Server), or indirectly to an archive file as the deployment target, and then install this archive file to the target server. For application development, you can also use JDeveloper to run an application in Integrated WebLogic Server. JDeveloper supports deploying to server clusters, but you cannot use JDeveloper to deploy to individual Managed Servers that are members of a cluster.

Figure 48-1 shows the flow diagram that describes the overall deployment process. Note that preparing the target application server for deployment by installing the ADF runtime is described in Administering Oracle ADF Applications.

The following diagram contains clickable links.

Figure 48-1 Deployment Overview Flow Diagram

Deployment overview flow diagram Run and test using Integrated WebLogic ServerPrepare the ApplicationDeploy the ApplicationPostdeployment tasks


Note:

Normally, you use JDeveloper to deploy applications for development and testing purposes. If you are deploying Oracle ADF applications for production purposes, you can use Enterprise Manager or scripts to deploy to production-level application servers.

For more information about deployment to later-stage testing or production environments, see Administering Oracle ADF Applications.


ADF Java EE applications are based on standardized, modular components and can be deployed to the following application servers:

Deploying a Fusion web application is slightly different from deploying a standard Java EE application. JSF applications that contain ADF Faces components have a few additional deployment requirements:

You can use JDeveloper to:

The Summit sample application for Oracle ADF demonstrates the use of the Fusion web application technology stack to create transaction-based web applications. You can run the Summit sample application in JDeveloper using Integrated WebLogic Server. For more information about the Summit ADF sample applications, see Chapter 2, "Introduction to the ADF Sample Application."

48.1.1 Developing Applications with Integrated WebLogic Server

If you are developing an application in JDeveloper and you want to run the application in Integrated WebLogic Server, you do not need to perform the tasks required for deploying directly to Oracle WebLogic Server or to an archive file. JDeveloper has a default connection to Integrated WebLogic Server and does not require any deployment profiles or descriptors. Integrated WebLogic Server has a preconfigured domain that includes the ADF libraries, as well as the -Djps.app.credential.overwrite.allowed=true setting, that are required to run Oracle ADF applications. You can run an application by choosing Run from the JDeveloper main menu.

You debug the application using the features described in Chapter 42, "Testing and Debugging ADF Components."

48.1.2 Developing Applications to Deploy to Standalone Application Server

Typically, for deployment to standalone application servers, you test and develop your application by running it in Integrated WebLogic Server. You can then test the application further by deploying it to standalone Oracle WebLogic Server in development mode to more closely simulate the production environment.

In general, you use JDeveloper to prepare the application or project for deployment by:

  • Creating a connection to the target application server

  • Creating deployment profiles (if necessary)

  • Creating deployment descriptors (if necessary, and that are specific to the target application server)

  • Updating application.xml and web.xml to be compatible with the application server (if required)

  • Enabling the application for Real User Experience Insight (RUEI) in web.xml (if desired)

  • Migrating application level security policy data to a domain-level security policy store

  • Configuring the Oracle Single Sign-On (Oracle SSO) service and properties in the domain jps-config.xml file when you intend the web application to run using Oracle SSO

You must already have an installed application server. For Oracle WebLogic Server, you can use the Oracle 11g Installer or the Oracle Fusion Middleware 11g Application Developer Installer to install one. For other application servers, follow the instructions in the applications server documentation to obtain and install the server.

You must also prepare the application server for Fusion web application deployment. For more information, see the "Preparing the Standalone Application Server for Deployment" section of Administering Oracle ADF Applications.

  • Installing the ADF runtime into the application server installation:

    • For WebLogic Server

      • If you installed Oracle WebLogic Server together with JDeveloper using the Oracle 11g Installer for JDeveloper, the ADF runtime should already be installed.

      • If the ADF runtime is not installed and you want to use Oracle Enterprise Manager to manage standalone ADF applications (which are applications without Oracle SOA Suite or Oracle WebCenter Portal components), use the Oracle Fusion Middleware 11g Application Developer Installer. This installer will install the necessary Oracle Enterprise Manager components into the Oracle WebLogic installation.

      • If the ADF runtime is not installed and you do not need to install Enterprise Manager, use the Oracle 11g Installer for JDeveloper.

  • Extending Oracle WebLogic Server domains to be ADF-compatible using the ADF runtime

  • For WebLogic, setting the Oracle WebLogic Server credential store overwrite setting as required (-Djps.app.credential.overwrite.allowed=true setting).

  • Creating a global JDBC data source for applications that require a connection to a data source

After the application and application server have been prepared, you can:

  • Use JDeveloper to:

    • Directly deploy to the application server using the deployment profile and the application server connection.

    • Deploy to an EAR file using the deployment profile. For Oracle ADF applications, WAR and MAR files can be deployed only as part of an EAR file.

  • Use Enterprise Manager, scripts, or the application server's administration tools to deploy the EAR file created in JDeveloper. For more information, see Administering Oracle ADF Applications.

48.2 Running a Fusion Web Application in Integrated WebLogic Server

JDeveloper is installed with Integrated WebLogic Server which you can use to test and develop your application. For most development purposes, Integrated WebLogic Server will suffice. When your application is ready to be tested, you can select the run target and then choose the Run command from the main menu.


Note:

The first time you run an application in Integrated WebLogic Server, the Configure Default Domain dialog appears for you to define an administrative password for the new domain.


When you run the application target, JDeveloper detects the type of Java EE module to deploy based on artifacts in the projects and workspace. JDeveloper then creates an in-memory deployment profile for deploying the application to Integrated WebLogic Server. JDeveloper copies project and application workspace files to an "exploded EAR" directory structure. This file structure closely resembles the EAR file structure that you would have if you were to deploy the application to an EAR file. JDeveloper then follows the standard deployment procedures to register and deploy the "exploded EAR" files into Integrated WebLogic Server. The "exploded EAR" strategy reduces the performance overhead of packaging and unpackaging an actual EAR file.

In summary, when you select the run target and run the application in Integrated WebLogic Server, JDeveloper:


Note:

JDeveloper ignores the deployment profiles that were created for the application when you run the application in Integrated WebLogic Server.


The application will run in the base domain in Integrated WebLogic Server. This base domain has the same configuration as a base domain in a standalone WebLogic Server instance. In other words, this base domain will be the same as if you had used the Oracle Fusion Middleware Configuration Wizard to create a base domain with the default options in a standalone WebLogic Server instance.

JDeveloper will extend this base domain with the necessary domain extension templates, based on the JDeveloper technology extensions. For example, if you have installed JDeveloper Studio, JDeveloper will automatically configure the Integrated WebLogic Server environment with the ADF runtime template (JRF Fusion Middleware runtime domain extension template).

You can explicitly create a default domain for Integrated WebLogic Server. You can use the default domains to run and test your applications. Open the Application Servers window, right-click IntegratedWebLogicServer and choose Create Default Domain.

48.2.1 How to Run an Application in Integrated WebLogic Server

You can test an application by running it in Integrated WebLogic Server. You can also set breakpoints and then run the application within the ADF Declarative Debugger.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you run an application in the Integrated WebLogic Server. For more information, see Section 48.2, "Running a Fusion Web Application in Integrated WebLogic Server."

To run an application in Integrated WebLogic Server:

  1. In the Applications window, select the project, unbounded task flow, JSF page, or file as the run target.

  2. Right-click the run target and choose Run or Debug.

    The Configure Default Domain dialog appears for the first time you run your application and start a new domain in Integrated WebLogic Server. Use the dialog to define an administrator password for the new domain. Passwords you enter can be eight characters or more and must have a numeric character.

48.2.2 How to Run an Application with Metadata in Integrated WebLogic Server

When an application is running in Integrated WebLogic Server, the MAR (Metadata Archive) profile itself will not be deployed to a repository, but a simulated MDS repository will be configured for the application that reflects the metadata information contained in the MAR. This metadata information is simulated, and the application runs based on this location in source control.

Any customizations or documents created by the application that are not configured to be stored in other MDS repositories are written to this simulated MDS repository directory. For example, if you customize an object, the customization is written to the simulated MDS repository. If you execute code that creates a new metadata object, then this new metadata object is also written to the same location in the simulated MDS repository. You can keep the default location for this directory (ORACLE_HOME\jdeveloper\systemXX.XX\o.mds.dt\adrs\Application\AutoGeneratedMar\mds_adrs_writedir), or you can set it to a different directory. You also have the option to preserve this directory across different application runs, or to delete this directory before each application run.

If your workspace has different working sets, only the metadata from the projects defined in the working set and their dependent projects will be included in the MAR. You can view and change a project's dependencies by right-clicking the project in the Applications window, choosing Project Properties, and then selecting Dependencies. For instance, an application may have several projects but workingsetA is defined to be viewcontroller2 and viewcontroller5; and viewcontroller5 has a dependency on modelproject1. When you run or debug workingsetA, only the metadata for viewcontroller2, viewcontroller5, and modelproject1 will be included in the MAR for deployment.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you run an application with metadata in the Integrated WebLogic Server. For more information, see Section 48.2, "Running a Fusion Web Application in Integrated WebLogic Server."

You will need to complete this task:

Created a MAR profile, either manually or automatically by JDeveloper.

To deploy the MAR profile to Integrated WebLogic Server:

  1. In the Applications window, right-click the application and choose Application Properties.

  2. In the Application Properties dialog, expand Run and choose MDS.

  3. On the Run MDS page:

    • Select the MAR profile from the MAR Profile dropdown list

    • Enter a directory path in Override Location if you want to customize the location of the simulated MDS repository.

    • Select the Directory Content option. You can chose to preserve the customizations across application runs or delete customizations before each run.

    Select the MAR profile from the MAR Profile dropdown list. Figure 48-2 shows Demometadata1 selected as the MAR profile.

    Figure 48-2 Setting the Run MDS Options

    Application roperties Run MDS options

48.3 Preparing the Application

Before you deploy a Fusion web application to a standalone application server, you must perform prerequisite tasks within JDeveloper to prepare the application for deployment.

Figure 48-3 show the process flow to prepare the application for deployment. After the application has been prepared and the application server has been prepared as described in Administering Oracle ADF Applications, you can proceed to deploy the application as described in Section 48.4, "Deploying the Application."

The following diagram contains clickable links.

Figure 48-3 Preparing the Application for Deployment Flow Diagram

Preparing the application for deployment flow diagram. Create application server connectionCreate deployment profilesCreate deployment descriptorsEnable RUEI monitoring (optional)Enable ADF MBeans (optional)Enable ADF Security

48.3.1 How to Create a Connection to the Target Application Server

You can deploy applications to the application server via JDeveloper application server connections.

If your application involves customization using MDS, you should register your MDS repository with the application server:

For more information about registering MDS, see Administering Oracle Fusion Middleware.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you prepare an application for deployment. For more information, see Section 48.3, "Preparing the Application."

You will need to complete this task:

Installed an application server.

To create a connection to an application server:

  1. Launch the Application Server Connection wizard.

    You can:

    • In the Applications Servers window, right-click Application Servers and choose New Application Server.

    • In the New Gallery, expand General, select Connections and then Application Server Connection, and click OK.

    • In the Resources window, choose New > IDE Connections > Application Server.

  2. In the Create Application Server Connection dialog, on the Usage page, select Standalone Server and click Next.

  3. On the Name and Type page, enter a connection name.

  4. In the Connection Type dropdown list, choose:

    • WebLogic to create a connection to Oracle WebLogic Server

  5. Click Next.

  6. On the Authentication page, enter a user name and password for the administrative user authorized to access the application server.

  7. Click Next.

  8. On the Configuration page, enter the information for your server:

    For WebLogic:

    • The Oracle WebLogic host name is the name of the WebLogic Server instance containing the TCP/IP DNS where your application (.jar,.war,.ear) will be deployed.

    • In the Port field, enter a port number for the WebLogic Server instance on which your application (.jar,.war,.ear) will be deployed.

      If you don't specify a port, the port number defaults to 7001.

    • In the SSL Port field, enter an SSL port number for the WebLogic Server instance on which your application (.jar,.war,.ear) will be deployed.

      Specifying an SSL port is optional. It is required only if you want to ensure a secure connection for deployment.

      If you don't specify an SSL port, the port number defaults to 7002.

    • Select Always Use SSL to connect to the WebLogic Server instance using the SSL port.

    • Optionally enter a WebLogic Domain only if WebLogic Server is configured to distinguish non-administrative server nodes by name.

  9. Click Next.

  10. Click Next.

  11. If the SSl Signer Exchange Prompt dialog appears, click Y.

  12. On the Test page, click Test Connection to test the connection.

    JDeveloper performs several types of connections tests. The JSR-88 test must pass for the application to be deployable. If the test fails, return to the previous pages of the wizard to fix the configuration.

  13. Click Finish.

48.3.2 How to Create Deployment Profiles

A deployment profile defines the way the application is packaged into the archive that will be deployed to the target environment. The deployment profile:

  • Specifies the format and contents of the archive file that will be created

  • Lists the source files, deployment descriptors, and other auxiliary files that will be packaged

  • Describes the type and name of the archive file to be created

  • Highlights dependency information, platform-specific instructions, and other information

You need a WAR deployment profile for each web user interface project that you want to deploy in your application. If you want to package seeded customizations or place base metadata in the MDS repository, you need an application level metadata archive (MAR) deployment profile as well. For more information about seeded customizations, see Chapter 45, "Customizing Applications with MDS." If the application has customization classes, you need a JAR file for those classes and you need to add that JAR when you create the EAR file. Finally, you need an application level EAR deployment profile and you must select the projects (such as WAR and MAR profiles and customization classes JAR files) to include from a list. When the application is deployed, the EAR file will include all the projects that were selected in the deployment profile.


Note:

If you create your project or application using the ADF Fusion Web Application template, JDeveloper automatically creates default WAR, EAR, MAR, and JAR deployment profiles. Typically, you would not need to edit or create deployment profiles manually.


For Oracle ADF applications, you can deploy the application only as an EAR file. The WAR and MAR files that are part of the application should be included in the EAR file when you create the deployment profile.


Note:

If your Fusion web application has business services that you want to deploy, you will need to create a Business Component Service Interface deployment profile and deploy it. For more information about business services, see Section 15.2.21, "How to Deploy Web Services to Oracle WebLogic Server."


48.3.2.1 Creating a WAR Deployment Profile

You will need to create a WAR deployment profile for each web-based project you want to package into the application. Typically, the WAR profile will include the dependent data model projects it requires.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create a WAR deployment profile. For more information, see Section 48.3, "Preparing the Application."

You will need to complete this task:

Create web-based projects. If you used the ADF Fusion Web Application template, you should already have a default WAR deployment profile.

To create WAR deployment profiles for an application:

  1. In the Applications window, right-click the web project that you want to deploy and choose New > From Gallery.

    You will create a WAR profile for each web project.

  2. In the New Gallery, expand General, select Deployment Profiles and then WAR File, and click OK.

    If you don't see Deployment Profiles in the Categories tree, click the All Features tab.

  3. In the Create Deployment Profile -- WAR File dialog, enter a name for the project deployment profile and click OK.

  4. In the Edit WAR Deployment Profile Properties dialog, choose items in the left pane to open dialog pages in the right pane. Configure the profile by setting property values in the pages of the dialog.

    • If you have customization classes in your application, they must be loaded from the EAR-level application class loader and not from the WAR. You will later add these customization classes to the EAR.

      By default, customization classes are added to the data model project's WAR class path. So for each WAR, you must exclude the customization classes.

      If you created your customization classes in an extension project of the application, be sure to deselect any customization class archive on the Library Dependencies page of the WAR deployment profile for each user interface project.

      If you created your customization classes in the data model project of the application, deselect any customization classes in the Edit WAR Deployment Profiles Properties dialog Filters page for each user interface project. If you are using a customization.properties file, it should also be deselected.

    • You might also want to change the Java EE web context root setting. To do so, choose General in the left pane.

      By default, when Use Project's Java EE Web Context Root is selected, the associated value is set to the project name, for example, Application1-Project1-context-root. You need to change this if you want users to use a different name to access the application.

      If you are using custom JAAS LoginModule for authentication with JAZN, the context root name also defines the application name that is used to look up the JAAS LoginModule.

  5. Click OK to exit the Deployment Profile Properties dialog.

  6. Click OK again to exit the Project Properties dialog.

  7. Repeat Steps 1 through 7 for all web projects that you want to deploy.

48.3.2.2 Creating a MAR Deployment Profile

If you have seeded customizations or base metadata that you want to place in the MDS repository, you need to create a MAR deployment profile.

The namespace configuration under <mds-config> for MAR content in the adf-config.xml file is generated based on your selections in the MAR Deployment Profile Properties dialog.

Although uncommon, an enterprise application (packaged in an EAR) can contain multiple web application projects (packaged in multiple WARs), but the metadata for all these web applications will be packaged into a single metadata archive (MAR). The metadata contributed by each of these individual web applications can be global (available for all the web applications) or local to that particular web application.

To avoid name conflicts for metadata with global scope, make sure that all metadata objects and elements have unique names across all the web application projects that forms part of the enterprise application.

JDeveloper creates an auto-generated MAR when the Enable User Customizations and Across Sessions using MDS options are selected in the ADF View page of the Project Properties dialog or when you explicitly specify the deployment target directory in the adf-config.xml file.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create a MAR deployment profile. For more information, see Section 48.3, "Preparing the Application."

You will need to complete this task:

Create an MDS repository for your customization requirements to deploy metadata using the MAR deployment profile. For more information, see the section about managing the MDS repository in Administering Oracle Fusion Middleware. If you used the ADF Fusion Web Application template, you should already have a default MAR deployment profile.

To create a MAR deployment profile:

  1. In the Applications window, right-click the application in which you want to create a MAR profile and choose New > From Gallery.

    You will create a MAR profile if you want to include customizations.

  2. In the New Gallery, expand General, select Deployment Profiles and then MAR File, and click OK.

    If you don't see Deployment Profiles in the Categories tree, click the All Features tab.

  3. In the Create Deployment Profile -- MAR File dialog, enter a name for the MAR deployment profile and click OK.

  4. In the Edit MAR Deployment Profile Properties dialog, choose items in the left pane to open dialog pages in the right pane.

    Figure 48-4 shows a sample User Metadata directory tree.

    Figure 48-4 Selecting Items for the MAR Deployment Profiles

    MAR deployment profile dialog

    Note the following important points:

    • To include all customizations, you need only create a file group with the desired directories.

    • ADF Model and ADF view directories are added by default. No further action is required to package the ADF Model and ADF view customizations into the MAR. ADF view content is added to HTML Root dir, while ADF Model and Business Components content is added to User Metadata.

    • To include the base metadata in the MDS repository, you need to explicitly select these directories in the dialog.

      When you select the base document to be included in the MAR, you also select specific packages. When you select one package, all the documents (including subpackages) under that package will be used. When you select a package, you cannot deselect individual items under that package.

    • To include files from other than ADF Model and ADF view, users should create a new file group under User Metadata with the desired directories and explicitly select the required content in the Directories page.

    • If a dependent ADF library JAR for the project contains seeded customizations, they will automatically be added to the MAR during MAR packaging. They will not appear in the MAR profile.

    • If ADF Library customizations were created in the context of the consuming project, those customizations would appear in the MAR profile dialog by default.

  5. Click OK to exit the Deployment Profile Properties dialog.

  6. Click OK again to exit the Application Properties dialog.

48.3.2.3 Creating an Application Level EAR Deployment Profile

The EAR file contains all the necessary application artifacts for the application to run in the application server. If you used the ADF Fusion Web Application template, you should already have a default EAR deployment profile. For more information about the EAR file, see Section 48.4.5, "What You May Need to Know About EAR Files and Packaging."

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create an EAR deployment profile. For more information, see Section 48.3, "Preparing the Application."

You will need to complete these tasks:

  1. Add classes into a JAR file, as described in Section 48.3.2.4, "Adding Customization Classes into a JAR."

  2. Create the WAR deployment profiles, as described in Section 48.3.2.1, "Creating a WAR Deployment Profile."

To create an EAR deployment profile for an application:

  1. In the Applications window, right-click the application and choose New > From Gallery.

    You will create an EAR profile for the application.

  2. In the New Gallery, expand General, select Deployment Profiles and then EAR File, and click OK.

    If you don't see Deployment Profiles in the Categories tree, click the All Features tab.

  3. In the Create Deployment Profile -- EAR File dialog, enter a name for the application deployment profile and click OK.

  4. In the Edit EAR Deployment Profile Properties dialog, choose items in the left pane to open dialog pages in the right pane. Configure the profile by setting property values in the pages of the dialog.

    Be sure that you:

    • Select Application Assembly and then in the Java EE Modules list, select all the project profiles that you want to include in the deployment, including any WAR or MAR profiles.

    • Select Platform, select the application server you are deploying to, and then select the target application connection from the Target Connection dropdown list.


    Note:

    If you are using a custom JAAS LoginModule for authentication with JAZN, the context root name also defines the application name that is used to look up the JAAS LoginModule.


  5. If you have customization classes in your application, configure these classes so that they load from the EAR-level application class loader.

    1. In the Edit EAR Deployment Profile Properties dialog, select Application Assembly.

    2. Select the JAR deployment profile that contains the customization classes, and enter lib in the Path in EAR field at the bottom of the dialog.


      Note:

      You should have created this JAR as described in Section 48.3.2.4, "Adding Customization Classes into a JAR."


    The JAR file containing the customization classes is added to the EAR file's lib directory.


    Note:

    If you have customization classes in your application, you must also make sure they are not loaded from the WAR. By default, customization classes that are added to the data model project's libraries and class path are packaged to the WAR class path.

    To make sure customization classes from an extension project are not duplicated in the WAR, be sure to deselect any customization class archive on the Library Dependencies page for the WAR.

    If you created your customization classes in the data model project of the consuming application, deselect any customization classes in the Edit WAR Deployment Profile Properties dialog Filters page.


  6. Click OK again to exit the Edit EAR Deployment Profile Properties dialog.

  7. Click OK again to exit the Application Properties dialog.


Note:

To verify that your customization classes are put correctly in the EAR class path, you can deploy the EAR profile to file system. Then you can examine the EAR to make sure that the customization class JAR is available in the EAR class path (the EAR/lib directory) and not available in the WAR class path (the WEB-INF/lib and WEB-INF/classes directories).


48.3.2.4 Adding Customization Classes into a JAR

If your application has customization classes, create a JAR that contains only these customization classes. When you create your EAR, you can add the JAR to the EAR assembly. And when you create WAR profiles for your web projects, you must make sure they don't include the customization classes JAR.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you add customization classes. For more information, see Section 48.3, "Preparing the Application."

You will need to complete this task:

Make sure that your project has customization classes. You do not need to perform this procedure if the application does not have customization classes. For more information about customization classes, see Section 45.2.1, "How to Create Customization Classes."

To add customization classes into a JAR:

  1. In the Applications window, right-click the data model project that contains the customization classes for which you want to create a JAR, and choose New > From Gallery.

  2. In the New Gallery, expand General, select Deployment Profiles and then JAR File, and click OK.

    Alternatively, if you want to create a shared library, select Shared Library JAR File from the list of profile types, and click OK.


    Note:

    If you don't see Deployment Profiles in the Categories tree, click the All Features tab.


  3. In the Create Deployment Profile -- JAR File dialog, enter a name for the project deployment profile (for example, CCArchive) and click OK.

  4. In the Edit JAR Deployment Profile Properties dialog, select JAR Options.

  5. Enter the location for the JAR file.

  6. Expand Files Groups > Project Output > Filters to list the files that can be selected to be included in the JAR.

  7. In Filters page, in the Files tab, select the customization classes you want to add to the JAR file.

    If you are using a customization.properties file, it needs to be in the same class loader as the JAR file. You can select the customization.properties file to package it along with the customization classes in the same JAR.

  8. Click OK to exit the Edit JAR Deployment Profile Properties dialog.

  9. Click OK again to exit the Project Properties dialog.

  10. In the Applications window, right-click the project containing the JAR deployment profile, and choose Deploy > deployment profile > to JAR file.


    Note:

    If this is the first time you deploy to a JAR from this deployment profile, you choose Deploy > deployment profile and select Deploy to JAR in the wizard.


48.3.2.5 Delivering Customization Classes as a Shared Library

As an alternative to adding your customization classes to the EAR, as described in Section 48.3.2.3, "Creating an Application Level EAR Deployment Profile," you can also include the customization classes in the consuming application as a shared library.


Note:

This procedure describes how to create and use a shared library if you are deploying to Oracle Weblogic Server.


Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create and use a shared library for customization classes. For more information, see Section 48.3, "Preparing the Application."

You will need to complete this task:

Add customization classes into a JAR using JDeveloper in Studio Developer role. Follow the procedure described in Section 48.3.2.4, "Adding Customization Classes into a JAR," and make sure that you select Shared Library JAR File as the type of archive to create.

To create and use a shared library for your customization classes:

  1. In the Applications window, right-click the customization classes project, and choose Deploy > deployment-profile.

  2. In the Deploy wizard, select Deploy to Application Server and click Next.

  3. Select the appropriate application server, and click Finish.

    This makes the shared library available on the application server. You must now add a reference to the shared library from the consuming application.

  4. Open the application you want to customize in JDeveloper in the Studio Developer role.

  5. In the Application Resources panel of the Applications window, double-click the weblogic-application.xml file.

  6. In the overview editor, click the Libraries navigation tab.

  7. On the Libraries page, in the Shared Library References section, click the Add icon.

  8. In the Library Name field of the newly created row in the Shared Library References table, enter the name of the customization classes shared library you deployed, and save your changes.

48.3.2.6 Viewing and Changing Deployment Profile Properties

After you have created a deployment profile, you can view and change its properties.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you view deployment profiles. For more information, see Section 48.3, "Preparing the Application."

To view, edit, or delete a project's deployment profile:

  1. In the Applications window, right-click the project which you want to view or edit and choose Project Properties.

  2. In the Project Properties dialog, click Deployment.

    The Deployment Profiles list displays all profiles currently defined for the project.

  3. In the Deployment Profiles section, select a deployment profile.

  4. To edit or delete a deployment profile, click Edit or Delete.

48.3.3 How to Create and Edit Deployment Descriptors

Deployment descriptors are server configuration files that define the configuration of an application for deployment and that are deployed with the Java EE application as needed. The deployment descriptors that a project requires depend on the technologies the project uses and on the type of the target application server. Deployment descriptors are XML files that can be created and edited as source files, but for most descriptor types, JDeveloper provides dialogs or an overview editor that you can use to view and set properties. If you cannot edit these files declaratively, the XML file opens in the source editor for you to edit its contents.

In addition to the standard Java EE deployment descriptors (for example, application.xml and web.xml), you can also have deployment descriptors that are specific to your target application server. For example, if you are deploying to Oracle WebLogic Server, you can also have weblogic.xml, weblogic-application.xml, and weblogic-ejb-jar.xml.

For WebLogic Server, make sure that the application EAR file includes a weblogic-application.xml file that contains a reference to adf.oracle.domain, and that it includes an ADFApplicationStateListener to clean up application resources between deployment and undeployment actions. Example 48-1 shows a sample weblogic-application.xml file.

Example 48-1 Sample weblogic-application.xml

<weblogic-application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-application.xsd"
 xmlns="http://www.bea.com/ns/weblogic/weblogic-application">
  <listener>
    <listener-class>oracle.adf.share.weblogic.listeners.
          ADFApplicationStateListener</listener-class>
  </listener>
  <listener>
    <listener-class>oracle.mds.lcm.weblogic.WLLifecycleListener</listener-class>
  </listener>
  <library-ref>
    <library-name>adf.oracle.domain</library-name>
  </library-ref>
</weblogic-application>

If you are deploying web services, you may need to modify your weblogic-application.xml and web.xml files as described in Section 15.2.21, "How to Deploy Web Services to Oracle WebLogic Server."

If you want to enable the application for Real User Experience Insight (RUEI) monitoring, you must add a parameter to the web.xml file, as described in Section 48.3.3.5, "Enabling the Application for Real User Experience Insight and End User Monitoring."

During deployment, the application's security properties are written to the weblogic-application.xml file to be deployed with the application in the EAR file. For more information, see Section 41.8.2, "What Happens When You Configure Security Deployment Options."

Because Oracle WebLogic Server runs on Java EE 1.5, you may need to modify the application.xml and web.xml files to be compatible with the application server.

48.3.3.1 Creating Deployment Descriptors

JDeveloper automatically creates many of the required deployment descriptors for you. If they are not present, or if you need to create additional descriptors, you can use JDeveloper to create them.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create deployment descriptors. For more information, see Section 48.3, "Preparing the Application."

You will need to complete this task:

Check to see whether JDeveloper has already generated deployment descriptors.

To create a deployment descriptor:

  1. In the Applications window, right-click the project for which you want to create a descriptor and choose New > From Gallery.

  2. In the New Gallery, expand General, select Deployment Descriptors and then a descriptor type, and click OK.

    If you can't find the item you want, make sure that you chose the correct project, and then choose the All Features tab or use the Search field to find the descriptor. If the item is not enabled, check to make sure that the project does not already have a descriptor of that type. A project is allowed only one instance of a descriptor.

    JDeveloper starts the Create Deployment Descriptor wizard and then opens the file in the overview or source editor, depending on the type of deployment descriptor you choose.


Note:

For EAR files, do not create more than one deployment descriptor file of the same type per application or workspace. These files can be assigned to projects, but have application workspace scope. If multiple projects in an application have the same deployment descriptor, the one belonging to the launched project will supersede the others. This restriction applies to application.xml, weblogic-jdbc.xml, jazn-data.xml, and weblogic.xml.

The best place to create an application level descriptor is in the Descriptors node of the Application Resources panel in the Applications window. This ensures that the application is created with the correct descriptors.

Application level descriptors created in the project will be ignored at runtime. Only the application resources descriptors or descriptors generated at the EAR level will be used by the runtime.


48.3.3.2 Viewing or Modifying Deployment Descriptor Properties

After you have created a deployment descriptor, you can change its properties by using JDeveloper dialogs or by editing the file in the source editor. The deployment descriptor is an XML file (for example, application.xml) typically located under the Application Sources node.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you view deployment descriptors. For more information, see Section 48.3, "Preparing the Application."

To view or change deployment descriptor properties:

  1. In the Applications window or in the Application Resources panel, double-click the deployment descriptor.

  2. In the editor window, select either the Overview tab or the Source tab, and configure the descriptor by setting property values.

    If the overview editor is not available, the file opens in the source editor.

48.3.3.3 Configuring the application.xml File for Application Server Compatibility

You may need to configure your application.xml file to be compliant with your Java EE version.


Note:

Typically, your project has an application.xml file that is compatible and you would not need to perform this procedure.


Before you begin:

It may be helpful to have an understanding of the options that are available to you when you configure application.xml. For more information, see Section 48.3, "Preparing the Application."

To configure the application.xml file:

  1. In the Applications window, right-click the application and choose New > From Gallery.

  2. In the New Gallery, expand General, select Deployment Descriptors and then Java EE Deployment Descriptor Wizard, and click OK.

  3. In the Create Java EE Deployment Descriptor dialog, on the Select Descriptor page, select application.xml and click Next.

  4. On the Select Version page, select 5.0 to be compatible with Java EE 5.0 or higher, and click Next.

  5. On the Summary page, click Finish.

  6. Edit the application.xml file with the appropriate values.

48.3.3.4 Configuring the web.xml File for Application Server Compatibility

You may need to configure your web.xml file to be compliant with your Java EE version. For more information, see Section A.13, "web.xml."


Note:

Typically, your project has a web.xml file that is compatible and you would not need to perform this procedure. JDeveloper creates a starter web.xml file when you create a project.


Before you begin:

It may be helpful to have an understanding of the options that are available to you when you configure web.xml. For more information, see Section 48.3, "Preparing the Application."

To configure the web.xml file:

  1. In the Applications window, right-click the project in which you want to configure a web.xml file and choose New > From Gallery.

  2. In the New Gallery, expand General, select Deployment Descriptors and then Java EE Deployment Descriptor, and click OK.

  3. In the Create Java EE Deployment Descriptor dialog, on the Select Descriptor page, select web.xml and click Next.

  4. On the Select Version page, select the version you want to use and click Next.

    Version 3.0 is compatible with Java EE 6.0 or higher, and version 2.5 is compatible with Java EE 5.0.

  5. On the Summary page, click Finish.

48.3.3.5 Enabling the Application for Real User Experience Insight and End User Monitoring

Real User Experience Insight (RUEI) is a web-based utility to report on real-user traffic requested by, and generated from, your network. It measures the response times of pages and transactions at the most critical points in the network infrastructure. Session diagnostics allow you to perform root-cause analysis.

RUEI enables you to view server and network times based on the real-user experience, to monitor your Key Performance Indicators (KPIs) and Service Level Agreements (SLAs), and to trigger alert notifications on incidents that violate their defined targets. You can implement checks on page content, site errors, and the functional requirements of transactions. Using this information, you can verify your business and technical operations. You can also set custom alerts on the availability, throughput, and traffic of all items identified in RUEI.

For more information about RUEI, see the Oracle Real User Experience Insight documentation at http://www.oracle.com/technetwork/documentation/realuserei-091455.html.

To enable RUEI:

  1. In the Applications window, expand WEB-INF and double-click web.xml.

  2. In the overview editor, add the context-param tag to the web.xml file, as shown in Example 48-2.

Example 48-2 Enabling RUEI Monitoring for an Application in web.xml

<context-param>
  <description>This parameter notifies ADF Faces that the 
               ExecutionContextProvider service provider is enabled.
               When enabled, this will start monitoring and aggregating
               user activity information for the client initiated
               requests. By default this param is not set or is false.
  </description>
  <param-name>
         oracle.adf.view.faces.context.ENABLE_ADF_EXECUTION_CONTEXT_PROVIDER
  </param-name>
  <param-value>true</param-value>
</context-param>

If there is an EndUserMonitoringService service provider available, you can use it to log performance metrics and data by registering it in your application. The service provider should have been implemented by extending the EndUserMonitoringService class. For more information about this class, see the Javadoc.

Note that the context-parameter oracle.adf.view.faces.context.ENABLE_ADF_EXECUTION_CONTEXT_PROVIDER needs to be set when an EndUserMonitoringServive provider is used within an ADF application.

To enable End User Monitoring in an application:

  1. Verify that an EndUserMonitoringService service provider has been implemented.

  2. Navigate to the application's <application_home>/src/META-INF/services folder using your operating system tools.

    If the services folder does not exist, create one.

  3. In the <application_home>/src/META-INF/services folder, create a file named oracle.adf.view.rich.monitoring.EndUserMonitoringService

    where EndUserMonitoringService is the name of the service interface.

  4. Open the file in an editor and add this entry: <package>.MyEndUserMonitoringService

    where package is the Java package name where the service provider resides and MyEndUserMonitoringService is the name of the EndUserMonitoringService service provider.

48.3.4 How to Deploy Applications with ADF Security Enabled

If you are developing an application in JDeveloper using Integrated WebLogic Server, application security deployment properties are configured by default, which means that the application and security credentials and policies will be overwritten each time you redeploy for development purposes. However, the application security deployment properties are the same for Integrated WebLogic Server and the standalone WebLogic Server.

You can change the default behavior in the Application Properties dialog, as described in Section 41.8.1, "How to Configure, Deploy, and Run a Secure Application in JDeveloper."

48.3.4.1 Applications That Will Run Using Oracle Single Sign-On (SSO)

Before you can deploy and run the web application with ADF Security enabled on the application server, the administrator of the target server must configure the domain-level jps-config.xml file for the Oracle Access Manager (OAM) security provider. To complete this configuration task, you can use Oracle WebLogic Scripting Tool (WLST) provided with the JDeveloper install. For details about running WLST (with command addOAMSSOProvider(loginuri, logouturi, autologinuri)), see the section "Integrating Access Manager With Web Applications Using Oracle ADF Security and the OPSS SSO Framework" in Appendix A, "Integrating Oracle ADF Applications with Access Manager SSO" of the Administrator's Guide for Oracle Access Management.

Running the addOAMSSOProvider() command ensures that the ADF Security framework defers to the OAM service provider to clear the ObSSOCookie token. OAM uses this token to save the identity of authenticated users and, unless it is cleared during logout, the user will be unable to log out.

After the system administrator runs the command on the target server, the domain jps-config.xml file will contain the following security provider definition that is specific for ADF Security:

<propertySet name="props.auth.uri">
    <property name="login.url.FORM" value="/${app.context}/adfAuthentication"/>
    <property name="logout.url" value=""/>
</propertySet>

Additionally, the authentication type required by SSO is CLIENT-CERT. The web.xml authentication configuration for the deployed application must specify the <auth-method> element as one of the following CLIENT-CERT types.

WebLogic supports two types of authentication methods:

  • For FORM-type authentication method, specify the elements like this:

    <login-config>
      <auth-method>CLIENT-CERT,FORM</auth-method>
      <realm-name>myrealm</realm-name>
      <form-login-config>
         <form-login-page>/login.html</form-login-page>
         <form-error-page>/error.html</form-error-page>
      </form-login-config>
    </login-config>
    
  • For BASIC-type authentication method, specify the elements like this:

    <login-config>
       <auth-method>CLIENT-CERT,BASIC</auth-method>
       <realm-name>myrealm</realm-name>
    </login-config>
    

You can configure the web.xml file either before or after deploying the web application. For further details about setting up the authentication method for Single Sign-On, see Part IV, "Managing Access Manager SSO, Policies, and Testing" of the Administrator's Guide for Oracle Access Management.

48.3.4.2 Configuring Security for Weblogic Server

In a development environment, JDeveloper will automatically migrate application level credentials, identities, and policies to the standalone WebLogic Server instance only if the server is set up to be in development mode. Integrated WebLogic Server is set up in development mode by default. You can set up a standalone WebLogic Server to be in development mode during Oracle WebLogic Server domain creation using the Oracle Fusion Middleware Configuration Wizard. For more information about configuring Oracle WebLogic Server domains, see Creating WebLogic Domains Using the Configuration Wizard.

JDeveloper will not migrate application level security credentials to WebLogic Server set up in production mode. Typically, in a production environment, administrators will use Enterprise Manager or WLST to deploy an application, including its security requirements.

When you deploy an application to WebLogic Server, credentials (in the cwallet.sso file) and security policies (in the jazn-data.xml file) will either overwrite or merge with the WebLogic Server's domain-level credential store, depending on whether an option in weblogic-application.xml is set to OVERWRITE or MERGE. In production-mode WebLogic Server, to avoid security risks, only MERGE is allowed. For development-mode WebLogic Server, you can set to OVERWRITE to test user names and passwords. You can also set the option by running setDomainEnv.cmd or setDomainEnv.sh with the following option added to the command (usually located in ORACLE_HOME/user_projects/domains/MyDomain/bin).

For setDomainEnv.cmd:

set EXTRA_JAVA_PROPERTIES=-Djps.app.credential.overwrite.allowed=true 
    %EXTRA_JAVA_PROPERTIES%

For setDomainEnv.sh:

EXTRA_JAVA_PROPERTIES="-Djps.app.credential.overwrite.allowed=true
     ${EXTRA_JAVA_PROPERTIES}"
export EXTRA_JAVA_PROPERTIES

If the Administration Server is already running, you must restart it for this setting to take effect.

You can check to see whether WebLogic Server is in production mode by using the Oracle WebLogic Server Administration Console or by verifying the following line in WebLogic Server's config.xml file:

<production-mode-enabled>true</production-mode-enabled>

By default, JDeveloper sets the application's credential, identities, and policies to OVERWRITE mode. That is, the Application Policies, Credentials, and Users and Groups options are selected by default in the Application Properties dialog Deployment page. However, an application's credentials will be migrated only if the target WebLogic Server instance is set to development mode with -Djps.app.credential.overwrite.allowed=true

Policy migration only works in development-mode. Identity migration only works when using JDeveloper to directly deploy to WebLogic Server regardless of whether it is in development or production-mode.

When your application is ready for deployment to a production environment, you should remove the identities from the jazn-data.xml file or disable the migration of identities by deselecting Users and Groups from the Application Properties dialog. Application credentials must be manually migrated outside of JDeveloper.


Note:

Before you migrate the jazn-data.xml file to a production environment, check that the policy store does not contain duplicate permissions for a grant. If a duplicate permission (one that has the same name and class) appears in the file, the administrator migrating the policy store will receive an error and the migration of the policies will be halted. You should manually edit the jazn-data.xml file to remove any duplicate permissions from a grant definition.


For more information about migrating application credentials and other jazn-data user credentials, see the "Configuring the OPSS Security Store" chapter in Securing Applications with Oracle Platform Security Services.

48.3.4.2.1 Applications with JDBC URL for WebLogic

If your application has components that use JDBC URL connections, the connection user names and passwords are also stored in the application level credential and policy stores. For the deployed application to be able to connect to the database using the JDBC URL, these credentials and policies must be migrated. That is, if WebLogic Server is in production mode, system administrators must migrate this security information. If WebLogic Server is in development mode, it must have domain-level credential and policy stores set to OVERWRITE to allow the migration of security information.

48.3.4.2.2 Applications with JDBC Data Source for WebLogic

If your application uses application level JDBC data sources with password indirection for database connections, you may need to create credential maps in WebLogic Server to enable the database connection. For more information, see Administering Oracle ADF Applications.

48.3.5 How to Replicate Memory Scopes in a Clustered Environment

If you are deploying an application that is intended to run in a clustered environment, you need to ensure that all managed beans with a lifespan longer than one request are serializable, and that Oracle ADF is aware of changes to managed beans stored in ADF scopes (view scope and page flow scope).

For more information, see Section 26.4.3, "How to Set Managed Bean Memory Scopes in a Server-Cluster Environment."

48.3.6 How to Enable the Application for ADF MBeans

A Fusion web application uses many XML files for setting configuration information. Three of these configuration files have ADF MBean counterparts that are deployed with the application. After the application has been deployed, you can change configuration properties by accessing the ADF MBeans using the Enterprise Manager Fusion Middleware Control MBean browser.

To enable ADF MBeans, register them in the web.xml file. Example 48-3 shows a web.xml file with listener entries for connections, configuration, and business components.

Example 48-3 Enabling ADF MBeans in the web.xml File

<listener>
   <listener-class>
        oracle.adf.mbean.share.connection.ADFConnectionLifeCycleCallBack
   </listener-class>
</listener>
<listener>
   <listener-class>
        oracle.adf.mbean.share.config.ADFConfigLifeCycleCallBack</listener-class>
</listener>
<listener>
   <listener-class>
        oracle.bc4j.mbean.BC4JConfigLifeCycleCallBack</listener-class>
</listener>

Additionally, you must configure a writable MDS repository to enable post-deployment configuration of connections.xml using ADF Connections MBeans and bc4j.xcfg using ADF Business Components MBeans.

MDS configuration entries in the adf-config.xml file for a database-based MDS are shown in Example 48-4. For more information about configuring MDS, see Administering Oracle Fusion Middleware.

Example 48-4 MDS Configuration Entries in the adf-config.xml File

<adf-mds-config xmlns="http://xmlns.oracle.com/adf/mds/config">
   <mds-config xmlns="http://xmlns.oracle.com/mds/config" version="11.1.1.000">
      <persistence-config>
         <metadata-store-usages>
            <metadata-store-usage 
                default-cust-store="true" deploy-target="true" id="myStore">
            </metadata-store-usage>
         </metadata-store-usages>
      </persistence-config>
   </mds-config>
</adf-mds-config>

In a production environment, an MDS repository that uses a database is required. You can use JDeveloper, Enterprise Manager Fusion Middleware Control or scripts to switch from a file-based repository to a database MDS repository.

Additionally, if several applications are sharing the same MDS configuration, each application can achieve distinct customization layers by defining a adf:adf-properties-child property in the adf-config.xml file. JDeveloper automatically generates this entry when creating applications. If your adf-config.xml file does not have this entry, add it to the file with code similar to that of Example 48-5.

Example 48-5 Adding MDS Partition Code to the adf-config.xml File

<adf:adf-properties-child xmlns="http://xmlns.oracle.com/adf/config/properties">
     <adf-property name="adfAppUID" value="Application3-4434"/>
     <adf-property name="partition_customizations_by_application_id"
            value="true"/>
</adf:adf-properties-child> 

The value attribute is either generated by JDeveloper or you can set it to any unique identifier within the server farm where the application is deployed. This value can be set to the value attribute of the adfAppUID property.

When adf-property name is set to adfAppUid, then the corresponding value property should be set to the name of the application. By default, JDeveloper generates the value property using the application's package name. If the package name is not specified, JDeveloper generates the value property by using the workspace name and a four digit random number.

For more information about configuring ADF applications using ADF MBeans, see Administering Oracle ADF Applications.

48.3.7 What You May Need to Know About JDBC Data Source for Oracle WebLogic Server

ADF applications can use either a JDBC data source or a JDBC URL for database connections. You use the Oracle WebLogic Server Administration Console to configure a JDBC data source. For more information about database access, see Section 13.3, "Configuring Your Application Module Database Connection."


Best Practice:

Fusion web applications are not compatible with data sources defined with the JDBC XA driver. When creating a data source on Oracle WebLogic Server, be sure to change the Fusion web application data source's JDBC driver from “Oracle's Driver (Thin XA)” to “Oracle's Driver (Thin)”. Because XA data sources close all cursors upon commit, random JBO-27122 and closed statement errors may result when running the the Fusion web application with an XA data source.


The Fusion web application module in the data model project can be configured to use a JDBC URL connection type, a JDBC data source connection type, or a combination of both types. By default, Fusion web application modules use a JDBC URL connection. A component that uses a JDBC URL will attempt to connect directly to the database using the JDBC URL, and it will ignore any JDBC data sources (global or application level) that are available in WebLogic Server. For more information about migrating JDBC URL security information (user names and passwords) from the application to WebLogic Server, see Section 48.3.4, "How to Deploy Applications with ADF Security Enabled."

A Fusion web application can use a JDBC data source to connect to the database. A JDBC data source has three types: global, application level, and application level with password indirection. You generally set up a global JDBC data source in WebLogic Server. Any application that requires access to that database can use that JDBC data source. An application can also include application level JDBC data sources. When the application is packaged for deployment, if the Auto Generate and Synchronize weblogic-jdbc.xml Descriptor During Deployment option is selected, JDeveloper creates a connection_name-jdbc.xml file for each connection that was defined. Each connection's information is written to the corresponding connection_name-jdbc.xml file (entries are also changed in weblogic-application.xml and web.xml). When the application is deployed to WebLogic Server, the server looks for application level data source information before it looks for the global data source.

If the application is deployed with password indirection set to true, WebLogic Server will look for the connection_name-jdbc.xml file for user name information and it will then attempt to locate application level credential maps for these user names to obtain the password. If you are using JDeveloper to directly deploy the application to WebLogic Server, JDeveloper automatically creates the credential map and populates the map to the server using an MBean call.

However, if you are deploying to an EAR file, JDeveloper will not be able to make the MBean call to WebLogic Server. You must set up the credential maps using the Oracle WebLogic Administration Console. Even if you have a global JDBC data source set up, if you do not also have credential mapping set up, WebLogic Server will not be able to map the credentials with passwords and the connection will fail.

Once the data source has been created in Oracle WebLogic Server, it can be used by an application module. For more information, see the "Preparing the Standalone Application Server for Deployment" section of Administering Oracle ADF Applications.

48.4 Deploying the Application

You can use JDeveloper to deploy ADF applications directly to the standalone application server or you can create an archive file and use other tools to deploy to the application server.


Note:

Before you begin to deploy applications that use Oracle ADF to the standalone application server, you need to prepare the application server environment by performing tasks such as installing the ADF runtime and creating and extending domains or cells. For more information, see the "Preparing the Standalone Application Server for Deployment" section of Administering Oracle ADF Applications.


Figure 48-5 show the process flow for deploying an application and also for deploying customizations to the target standalone application server.

The following diagram contains clickable links.

Figure 48-5 Application Deployment Flow Diagram

Application Deployment Flow Diagram Deploy from JDeveloperPackage the application into an archiveDeploy customizations as a JARDeploy using commandsTesting and verifying deployment

Table 48-1 describes some common deployment techniques that you can use during the application development and deployment cycle. The deployment techniques are listed in order from deploying on development environments to deploying on production environments. It is likely that in the production environment, the system administrators deploy applications by using Enterprise Manager Fusion Middleware Control or scripts.

Table 48-1 Deployment Techniques for Development or Production Environments

Deployment TechniqueEnvironmentWhen to Use

Run directly from JDeveloper

Test or Development

When you are developing your application. You want deployment to be quick because you will be repeating the editing and deploying process many times.

JDeveloper contains Integrated WebLogic Server, on which you can run and test your application.

Use JDeveloper to directly deploy to the target application server

Test or Development

When you are ready to deploy and test your application on an application server in a test environment.

On the test server, you can test features (such as LDAP and Oracle Single Sign-On) that are not available on the development server.

You can also use the test environment to develop your deployment scripts, for example, using Ant.

Use JDeveloper to deploy to an EAR file, then use the target application server's tools for deployment

Test or Development

When you are ready to deploy and test your application on an application server in a test environment. As an alternative to deploying directly from JDeveloper, you can deploy to an EAR file and then use other tools to deploy to the application server.

On the test server, you can test features (such as LDAP and Oracle Single Sign-On) that are not available on the development server.

You can also use the test environment to develop your deployment scripts, for example, using Ant.

Use Enterprise Manager or WLST to deploy applications

Production

When your application is in a test and production environment. In production environments, system administrators usually use Enterprise Manager Fusion Middleware Control or run WLST to deploy applications.


Any necessary MDS repositories must be registered with the application server. If the MDS repository is a database, the repository maps to a data source with MDS-specific requirements.

If you are deploying the application to Oracle WebLogic Server, make sure to target this data source to the WebLogic Administration Server and to all Managed Servers to which you are deploying the application. For more information about registering MDS, see Administering Oracle Fusion Middleware.

If you are using the application server's administrative console or scripts to deploy an application packaged as an EAR file that requires MDS repository configuration in adf-config.xml, you must run the getMDSArchiveConfig command to configure MDS before deploying the EAR file. MDS configuration is required if the EAR file contains a MAR file or if the application is enabled for DT@RT (Design Time At RunTime).

For more information about WLST commands, see the WLST Command Reference for Infrastructure Components.

If you plan to configure ADF connection information, ADF Business Components information, or adf-config.xml using ADF MBeans after the application has been deployed, make sure that the application is configured with MDS and have the MBean listeners enabled in the web.xml file. For more information, see Section 48.3.6, "How to Enable the Application for ADF MBeans."


Note:

If your Fusion web application has business services that you want to deploy to WebLogic Server, see Section 15.2.21, "How to Deploy Web Services to Oracle WebLogic Server."


48.4.1 How to Deploy to the Application Server from JDeveloper

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you deploy an application. For more information, see Section 48.4, "Deploying the Application."

You will need to complete this task:

Create an application level deployment profile that deploys to an EAR file as described in Section 48.3.2.3, "Creating an Application Level EAR Deployment Profile."

Note:

When you are deploying to Oracle WebLogic Server from JDeveloper, ensure that the HTTP Tunneling property is enabled in the Oracle WebLogic Server Administration Console. This property is located under Servers > ServerName > Protocols. ServerName refers to the name of Oracle WebLogic Server.



Note:

JDeveloper does not support deploying applications to individual Managed Servers that are members of a cluster. You may be able to target one or more Managed Servers within a cluster using the Oracle WebLogic Server Administration Console or other Oracle WebLogic tools; however, the cluster can be negatively affected. For more information about deploying to Oracle WebLogic Server clusters, see Administering Oracle Fusion Middleware.


To deploy to the target application server from JDeveloper:

  1. In the Applications window, right-click the application and choose Deploy > deployment profile.

  2. In the Deploy wizard, on the Deployment Action page, select Deploy to Application Server and click Next.

  3. On the Select Server page, select the application server connection, and click Next.

  4. If you are deploying to a WebLogic Server instance, the WebLogic Options page appears. Select a deployment option and click Next.


    Note:

    If you are deploying an ADF application, do not use the Deploy to all instances in the domain option.


  5. Click Finish.

    During deployment, you can see the process steps displayed in the deployment Log window. You can inspect the contents of the modules (archives or exploded EAR) being created by clicking on the links that are provided in the log window. The archive or exploded EAR file will open in the appropriate editor or directory window for inspection.

    If the adf-config.xml file in the EAR file requires MDS repository configuration, the Deployment Configuration dialog appears for you to choose the target metadata repository or shared metadata repositories, as shown in Figure 48-6. The Repository Name dropdown list allows you to choose a target metadata repository from a list of metadata repositories registered with the Administration Server. The Partition Name dropdown list allows you to choose the metadata repository partition to which the application's metadata will be imported during deployment. You can use Oracle WebLogic Scripting Tool (WLST) and Oracle WebLogic Server Administration Tool to configure and register MDS. For more information about managing the MDS Repository, see Administering Oracle Fusion Middleware.

    Figure 48-6 MDS Configuration and Customization for Deployment

    MDS configuration

    Note:

    If you are deploying a Java EE application, click the application menu next to the Java EE application in the Applications window.


    For more information on creating application server connections, see Section 48.3.1, "How to Create a Connection to the Target Application Server."

48.4.2 How to Create an EAR File for Deployment

You can also use the deployment profile to create an archive file (EAR file). You can then deploy the archive file using Enterprise Manager, Oracle WebLogic Scripting Tool (WLST), or Oracle WebLogic Server Administration Console.

Although a Fusion web application is encapsulated in an EAR file (which usually includes WAR, MAR, and JAR components), it may have parts that are not deployed with the EAR. For instance, ADF Business Services can be deployed as a JAR. For more information about business services, see Section 15.2.21, "How to Deploy Web Services to Oracle WebLogic Server."

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you create an EAR file for deployment. For more information, see Section 48.4, "Deploying the Application."

You will need to complete this task:

Create an application level deployment profile that deploys to an EAR file as described in Section 48.3.2.3, "Creating an Application Level EAR Deployment Profile."

To create an EAR archive file:

  1. In the Applications window, right-click the application containing the deployment profile, and choose Deploy > deployment profile.

  2. In the Deploy wizard, on the Deployment Action page, select Deploy to EAR and click Finish.

    If an EAR file is deployed at the application level, and it has dependencies on a JAR file in the data model project and dependencies on a WAR file in the user interface project, then the files will be located in the following directories by default:

    • ApplicationDirectory/deploy/EARdeploymentprofile.EAR

    • ApplicationDirectory/ModelProject/deploy/JARdeploymentprofile.JAR

    • ApplicationDirectory/ViewControllerProject/deploy/WARdeploymentprofile.WAR


Tip:

Choose View >Log to see messages generated during creation of the archive file.


48.4.3 How to Deploy New Customizations Applied to ADF Library

If you have created new customizations for an ADF Library, you can use the MAR profile to deploy these customizations to any deployed application that consumes that ADF Library. For instance, suppose applicationA, which consumes ADFLibraryB, is deployed to a standalone application server. Later on, when new customizations are added to ADFLibraryB, you only need to deploy the updated customizations into applicationA. You do not need to repackage and redeploy the whole application nor do you need to manually patch the MDS repository.


Note:

This procedure is for applying ADF Library customizations changes to an application that has already been deployed to a standalone application server. It is not for the initial packaging of customizations into a MAR that will eventually be a part of an EAR. For information about initial packaging of the customization using a MAR, see Section 48.3.2.2, "Creating a MAR Deployment Profile."


To deploy ADF Library customizations, create a new MAR profile and only include the customizations to be deployed and then use JDeveloper to:

  • Deploy the customizations directly into the MDS repository in the standalone application server.

  • Deploy the customizations to a JAR. And then import the JAR into the MDS repository using tools such as the Fusion Middleware Control.

48.4.3.1 Exporting Customization to a Deployed Application

You can export the customizations directly from JDeveloper into the MDS repository for the deployed application on the standalone application server.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you export customizations directly into the application server. For more information, see Section 48.4, "Deploying the Application."

You will need to complete this task:

Create new customizations to the ADF Library. For more information on customizations, see Section 45.3.7, "How to Customize ADF Library Artifacts in JDeveloper."

To export the customizations directly into the application server:

  1. In the Applications window, right-click the application and choose Deploy > metadata.

  2. In the Deploy metadata dialog, on the Deployment Action page, select Export to a Deployed Application and click Next.

    If the MAR profile is included in the EAR profile of any application, Export to a Deployed Application will be dimmed and disabled.

  3. On the Application Server page, select the application server connection and click Next.

  4. For WebLogic Server, the Server Instance page appears. In this page, select the server instance where the deployed application is located and click Next.

  5. On the Deployed Application page, select the application you want to apply the customizations to and click Next.

  6. On the Sandbox Instance page, if you want to deploy to a sandbox, select Deploy to an associated sandbox, choose the sandbox instance, and click Next.

  7. On the Summary page, verify the information and click Finish.

48.4.3.2 Deploying Customizations to a JAR

When you deploy the ADF Library customizations to a JAR, you are packaging the contents as defined by the MAR profile.

Before you begin:

It may be helpful to have an understanding of the options that are available to you when you deploy customizations as a JAR. For more information, see Section 48.4, "Deploying the Application."

You will need to complete this task:

Create new customizations to the ADF Library. For more information on customizations, see Section 45.3.7, "How to Customize ADF Library Artifacts in JDeveloper."

To deploy the customizations as a JAR

  1. In the Applications window, right-click the application and choose Deploy > metadata.

  2. In the Deploy Metadata dialog, on the Deployment Action page, select Deploy to MAR.

  3. On the Summary page, click Finish.

  4. Use Enterprise Manager Fusion Middleware Control or the application server's administration tool to import the JAR into the MDS repository. For more information about Fusion Middleware Control, see Administering Oracle Fusion Middleware.

48.4.4 What You May Need to Know About ADF Libraries

An ADF Library is a JAR file that contains JAR services registered for ADF components such as ADF task flows, pages, or application modules. If you want the ADF components in a project to be reusable, you create an ADF Library deployment profile for the project and then create an ADF Library JAR based on that profile.

An application or project can consume the ADF Library JAR when you add it using the Resources window or manually by adding it to the library classpath. When the ADF Library JAR is added to a project, it will be included in the project's WAR file if the Deployed by Default option is selected.

For more information, see Chapter 44, "Reusing Application Components."

48.4.5 What You May Need to Know About EAR Files and Packaging

When you package a Fusion web application into an EAR file, it can contain the following:

  • WAR files: Each web-based view controller project should be packaged into a WAR file.

  • MAR file: If the application has customizations that are deployed with the application, it should be packaged into a MAR.

  • ADF Library JAR files: If the application consumes ADF Library JARs, these JAR files may be packaged within the EAR.

  • Other JAR files: The application may have other dependent JAR files that are required. They can be packaged within the EAR.

48.4.6 How to Deploy the Application Using Scripts and Ant

You can deploy the application using commands and automate the process by putting those commands in scripts. The ojdeploy command can be used to deploy an application without JDeveloper. You can also use Ant scripts to deploy the application. JDeveloper has a feature to help you build Ant scripts. Depending on your requirements, you may be able to integrate regular scripts with Ant scripts.

For more information about commands, scripts, and Ant, see Administering Oracle ADF Applications.

48.4.7 How to Deploy ADF Faces Library JARs with the Application

You can develop applications that only use ADF Faces without using ADF Model. In that case, you can deploy the ADF Faces JARs with the application into the application server.

Before you begin:

Create an application with a web-based project. If you used the Fusion Web Application (ADF) template, you should already have a default WAR deployment profile.

To deploy ADF Faces JARs as part of the application:

  1. In the Applications window, right-click the web project that you want to deploy and choose Project Properties.

  2. In the Project Properties dialog, select Deployment and then the deployment profile and click Edit.

    If your project does not have a WAR deployment profile, follow Steps 1 to 3 in Section 48.3.2.1, "Creating a WAR Deployment Profile," to create a new WAR deployment profile.

  3. Navigate to File Groups > WEB-INF/lib > Contributors and select ADF Faces Runtime 11.

  4. Click OK to exit the Deployment Profile Properties dialog.

  5. Click OK again to exit the Project Properties dialog.

  6. Deploy your application as described in this chapter either directly using JDeveloper or by creating a EAR and deploying it using the Enterprise Manager Fusion Middleware Control, the Oracle WebLogic Server Administration Console, or other methods.

    Make sure your application-level EAR contains the WAR file as described in Section 48.3.2.3, "Creating an Application Level EAR Deployment Profile."

48.4.8 What You May Need to Know About JDeveloper Runtime Libraries

When an application is deployed, it includes some of its required libraries with the application. The application may also require shared libraries that have already been loaded to WebLogic Server as JDeveloper runtime libraries. It may be useful to know which JDeveloper libraries are packaged within which WebLogic Server shared library. For a listing of the contents of the JDeveloper runtime libraries, see Administering Oracle ADF Applications.

48.5 Postdeployment Configuration

After you have deployed your application to WebLogic Server, you can perform configuration tasks.

48.5.1 How to Migrate an Application

If you want to migrate a Fusion web application from one WebLogic Server to another WebLogic Server, you may need to perform some of the same steps you did for a first time deployment.

In general, to migrate an application, you would:

48.5.2 How to Configure the Application Using ADF MBeans

If ADF MBeans were enabled and packaged with the deployed application, you can configure ADF properties using the Enterprise Manager MBean Browser. For instructions on how to enable an application for MBeans, see Section 48.3.6, "How to Enable the Application for ADF MBeans."

For information on how to configure ADF applications using ADF MBeans, see Administering Oracle ADF Applications.

48.6 Testing the Application and Verifying Deployment

After you deploy the application, you can test it from the application server. To test-run your ADF application, open a browser window and enter a URL:


Tip:

The context root for an application is specified in the user interface project settings by default as ApplicationName/ProjectName/context-root. You can shorten this name by specifying a name that is unique across the target application server. Right-click the user interface project, and choose Project Properties. In the Project Properties dialog, select Java EE Application and enter a unique name fo5r the context root.



Note:

/faces has to be in the URL for Faces pages. This is because JDeveloper configures your web.xml file to use the URL pattern of /faces in order to be associated with the Faces Servlet. The Faces Servlet does its per-request processing, strips out /faces part in the URL, then forwards the URL to the JSP. If you do not include the /faces in the URL, then the Faces Servlet is not engaged (since the URL pattern doesn't match). Your JSP is run without the necessary JSF per-request processing.


PKN5PKz$DOEBPS/appendix_designpat.htm< ADF Business Components Java EE Design Pattern Catalog

E ADF Business Components Java EE Design Pattern Catalog

This appendix summarizes the Java Platform, Enterprise Edition (Java EE) design patterns that the ADF Business Components layer implements for you.

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 E-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 Oracle Technology Network website at http://www.oracle.com/technetwork/java/index-jsp-136701.html.

Table E-1 Java EE Design Patterns Implemented by ADF Business Components

Pattern Name and DescriptionHow ADF Business Components Implements It

Model/View/Controller

Cleanly separates the roles of data and presentation, allowing multiple types of client displays to work with the same business information.

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 help you implement the view and controller layers.

Interface / Implementation Separation

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

ADF Business Components enforces a logical separation of client-tier accessible functionality (via interfaces) and its business tier implementation. JDeveloper handles the creation of custom interfaces and client proxy classes automatically.

Service Locator

Abstracts the technical details of locating a service so that the client can use it more easily.

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.

Inversion of Control

A containing component orchestrates the lifecycle of the components it contains, invoking specific methods that you can override at the appropriate times, so as to be able to focus more on what the code should do, instead of when it should be executed.

ADF components contain a number of easy-to-override methods that the framework invokes as needed during the course of application processing.

Dependency Injection

Simplifies application code, and increases configuration flexibility by deferring component configuration and assembly to the container.

ADF Business Components configures all its components from externalized XML metadata definition files. At runtime, the framework automatically injects dependent objects like view object instances into your application module service component and entity objects into your view rows, implementing lazy loading. It supports runtime factory substitution of components by any customized subclass of that component to simplify onsite application customization scenarios. Much of the ADF Business Components 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.

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.

ADF entity objects handle the database mapping functionality you use most frequently, including inheritance, association, and composition support, so you don't have to focus on object/relational mapping. They also provide a place to encapsulate both declarative business rules and one-off programmatic business domain.

Data Access Objects

Prevents unnecessary marshalling overhead by implementing dependent objects as lightweight, persistent classes instead of each as an individual enterprise bean. Isolates persistence details into a single, easy-to-maintain class.

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 requiring that you write any "application plumbing" code.

Session Facade

Prevents inefficient client access of entity beans and inadvertent exposure of sensitive business information by wrapping entity beans with a session bean.

ADF application modules are designed to implement a coarse-grained "service facade" architecture in any of their supported deployment modes. When deployed as a service interface, they provide an implementation of the Session Facade pattern automatically.

Value Object

Prevents unnecessary network roundtrips by creating one-off "transport" objects to group a set of related attributes needed by a client program.

ADF Business Components 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.

Page-by-Page Iterator

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

ADF Business Components provides an implementation of a generic RowSet interface which manages result sets produced by executing view object SQL queries. The RowSet interface allows you 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.

Fast-Lane Reader

Prevents unnecessary overhead for read-only data by accessing JDBC APIs directly. This allows an application to retrieve only the attributes that need to be displayed, instead of finding all of the attributes by primary key when only a few are required by the client. Typically, implementations of this pattern sacrifice data consistency for performance, since queries performed at the raw JDBC level do not "see" pending changes made to business information represented by enterprise beans.

ADF view objects read data directly from the database for best performance; however, they give you a choice regarding data consistency. If updateability and/or consistency with pending changes is desired, you need only associate your view object with the appropriate entity objects whose business data is being presented. If consistency is not a concern, view objects can simply perform the query with no additional overhead. In either case, you never have to write JDBC data access code. You need only provide appropriate SQL statements in XML descriptors.

(Bean) Factory

Allows runtime instantiation and configuration of an appropriate subclass of a given interface or superclass based on externally configurable information.

All ADF component instantiation is done based on XML configuration metadata through factory classes allowing runtime substitution of specialized components to facilitate application customization.

Entity Facade

Provides a restricted view of data and behavior of one or more business entities.

ADF view objects 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.

Value Messenger

Keeps client value object attributes in sync with the middle-tier business entity information that they represent in a bidirectional fashion.

The ADF Business Components 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.

Continuations

Gives you the simplicity and productivity of a stateful programming model with the scalability of a stateless web solution.

ADF Business Components application module pooling and state management functionality combine to deliver this value-add. Application module pooling eliminates the need to dedicate application server tier resources to individual users and supports a "stateless with user affinity" optimization that you can tune.


PKe<<PKz$DOEBPS/bcampool.htm Tuning Application Module Pools and Connection Pools

50 Tuning Application Module Pools and Connection Pools

This chapter describes how ADF Business Components application module pools work and how you can tune both application module pools and database connection pools to optimize application performance.

This chapter includes the following sections:

50.1 About Application Module Pooling

An application module pool is a collection of application module runtime instances of the same type. To provision a number of users visiting it, an application can be configured to provide one or more application module instances from the pool to service users at runtime.

Each application module instance in a pool is shared by multiple browser clients whose typical "think time" between submitting web pages allows optimizing the number of application module components to be effectively smaller than the total number of active users working on the system. For example, twenty users visiting the website from their browser might be able to be serviced by 5 or 10 application module instances instead of having as many application module instances as you have browser users. Therefore, not only can the pool service more users than the number of application modules available, but in addition the middle tier requires less memory to service this smaller set of application modules allowing ADF applications to scale further on limited hardware resources.

Through your design-time configuration, application modules can be used to support Fusion web application scenarios that are completely stateless, or they can be used to support a unit of work that spans multiple browser pages. As a performance optimization, when an instance of an application module is returned to the pool in "managed state" mode, the pool tracks session references to the application module. The application module instance is still in the pool and available for use, but it would prefer to be used by the same session that was using it the last time because maintaining this "session affinity" improves performance.

So, at any one moment in time, the instances of application modules in the pool are logically partitioned into three groups, reflecting their state:

Section 50.2.5, "What You May Need to Know About Configuration Property Scopes" describes the application module pool configuration parameters and how they affect the behavior of the pool.

50.1.1 Types of Pools Created When Running the Fusion Web Application

There are two kinds of pools in use when running a typical Fusion web application, application Module pools and database connection pools. Applications typically use application module pools, but rarely use connection pools. Connection pools are only used when your application defines the JDBC URL connection type, instead of the default JNDI data source connection type. You primarily need to understand how many of each kind of pool your application will create.

50.1.1.1 Application Module Pools

Application Module components can be used at runtime in two ways:

  • As an application module the client accesses directly

  • As a reusable component aggregated (or "nested") inside of another application module instance

When a client accesses it directly, an application module is called a root application module. Clients access nested application modules indirectly as a part of their containing application module instance. It's possible, but not common, to use the same application module at runtime in both ways. The important point is that ADF Business Components only creates an application module pool for a root application module.

The basic rule is that one application module pool is created for each root application module used by a Fusion web application in each Java VM where a root application module of that type is used by the ADF Controller layer. For advanced topics related to the number of application module pools your application may need, see Section 50.4, "Deployment Environment Scenarios and Pooling."

50.1.1.2 Database Connection Pools

The type of database connection pool the Fusion web application uses depends on the connection type that you configure for your application modules:

  • JDBC URL (e.g. jdbc:oracle:thin:@penguin:1521:ORCL)

  • JNDI name for a data source (e.g. java:comp/env/jdbc/YourConnectionDS)

JDeveloper configures the application module by default to use the data source connection type. A JDBC data source is a vendor-independent encapsulation of a database server connection. The JDBC data source offers advantages that the JDBC URL connection type does not. When you define a connection type based on a data source, you reconfigure the data source without changing the deployed application. The data source is also centrally defined at the application server level, whereas JDBC URL connections are not. In cases where a JDBC data source is not viable, at runtime, ADF Business Components will construct a default JDBC URL based on the data source connection information.

If you supply a JDBC URL connection while configuring your application module — which happens when you select a JDeveloper named connection which encapsulates the JDBC URL and username information — then the ADF database connection pool will be used for managing the connection pool.

If you use the default and supply the JNDI name of a JDBC data source then the ADF database connection pool will not be used and the configuration parameters described below relating to the ADF database connection pool are not relevant.


Note:

To configure the database connection pool for JDBC data sources looked-up by JNDI from your Java EE web and/or EJB container, consult the documentation for your Java EE container to understand the pooling configuration options and how to set them.


When using ADF database connection pooling, you have the following basic rule: One database connection pool is created for each unique <JDBCURL,Username> pair, in each Java VM where a <JDBCURL,Username> connection is requested by a root application used by the ADF Controller layer. For advanced topics related to the number of connection pools your application may need, see Section 50.4, "Deployment Environment Scenarios and Pooling."

50.2 Setting Pool Configuration Parameters

You control the runtime behavior of an application module pool by setting appropriate configuration parameters. You can set these declaratively in an application module configuration, supply them as Java System parameters, or set them programmatically at runtime.

50.2.1 How to Set Configuration Properties Declaratively

The Pooling and Scalability tab of the Edit Configuration dialog shown in Figure 50-1 is used for viewing and setting parameters.

Figure 50-1 Pooling and Scalability Tab of the Edit Configuration Dialog

Pooling and Scalability tab

Before you begin:

It may be helpful to have an understanding of connection pooling. For more information, see Section 50.2, "Setting Pool Configuration Parameters."

You may also find it helpful to understand functionality that can be added using other Oracle ADF features.

To edit your application module's pooling configuration:

  1. In the Applications window, double-click the application module.

  2. In the overview editor, click the Configurations navigation tab.

  3. In the Configurations page, double-click the configuration you want to edit.

  4. In the Edit Configuration dialog, click the Pooling and Scalability tab and edit the desired runtime properties and click OK to save the changes for your configuration.

50.2.2 What Happens When You Set Configuration Properties Declaratively

The values that you supply through the Edit Configuration dialog are saved in an XML file named bc4j.xcfg in the ./common subdirectory relative to the application module's XML document. All of the configurations for all of the application modules in a single Java package are saved in that same file. Typically, you do not modify the bc4j.xcfg file directly and use the Edit Configuration dialog to change configuration settings for the application module.

For example, if you look at the bc4j.xcfg file in the ./src/oracle/summit/model/services/common directory of the SummitADF application workspace, you will see the two named configurations for the BackOfficeAppModule application module, as shown in Example 50-1. In this case, The BackOfficeAppModuleLocal and the BackOfficeAppModuleShared configurations specify JDBC URL connections for use by the Oracle ADF Model Tester. The connection details for the JDBC connections appear in the connections.xml file located in the ./.adf/META-INF subdirectory relative to the project directory.

Example 50-1 Configuration Settings for the BackOfficeAppModule

<BC4JConfig version="11.1" xmlns="http://xmlns.oracle.com/bc4j/configuration">
...
   <AppModuleConfigBag
      ApplicationName="oracle.summit.model.services.BackOfficeAppModule">
      <AppModuleConfig 
            name="BackOfficeAppModuleLocal"
            jbo.project="oracle.summit.model.Model"
            ApplicationName="oracle.summit.model.services.BackOfficeAppModule"
            DeployPlatform="LOCAL" JDBCName="summit_adf">
         <Database jbo.TypeMapEntries="Java"/>
         <Security
            AppModuleJndiName="oracle.summit.model.services.BackOfficeAppModule"/>
      </AppModuleConfig>
      <AppModuleConfig
            name="BackOfficeAppModuleShared"
            jbo.project="oracle.summit.model.Model"
            ApplicationName="oracle.summit.model.services.BackOfficeAppModule"
            DeployPlatform="LOCAL" JDBCName="summit_adf">
         <AM-Pooling jbo.ampool.maxpoolsize="1"
                     jbo.ampool.isuseexclusive="false"/>
         <Database jbo.TypeMapEntries="Java"/>
         <Security
            AppModuleJndiName="oracle.summit.model.services.BackOfficeAppModule"/>
      </AppModuleConfig>
   </AppModuleConfigBag>
</BC4JConfig>

Note that attributes of child elements of the <AppModuleConfig> tag have names beginning with jbo that match the names of their ADF Business Components properties (for example, the <AM-Pooling> tag defines the attribute jbo.ampool.maxpoolsize that corresponds to the property jbo.ampool.maxpoolsize). It's also important to understand that if a property is currently set to its runtime default value in the Edit Configuration dialog, then JDeveloper does not write the entry to the bc4j.xcfg file.

50.2.3 How to Set 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.

It may be useful to set configuration properties as Java VM system parameters when all ADF applications running on a particular Java VM require the same configuration value setting for particular parameters. In this case, you must not set the configuration properties in the bc4j.xcfg file and you should confirm that the Edit Configuration dialog displays no value for the desired property, as described in Section 50.2.1, "How to Set Configuration Properties Declaratively."

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 database Connection Pool are displayed and edited in this dialog as a number of seconds, but are saved to the configuration file in milliseconds. If you provide a value for any of these four parameters as a Java System parameter — or if you hand-edit the bc4j.xcfg file — make sure to provide these time interval values in milliseconds!


50.2.4 How to Programmatically Set Configuration Properties

When your application requires control over application module configuration properties at runtime, you can dynamically set these properties using ADF Business Components API. For example, in a typical ADF application, your application module may configure a static JDBC data source. However, when the application needs to display data, depending upon the user, from various databases, you might set the data source name and application module pool parameters at runtime.

You can set configuration properties programmatically by creating a Java class that implements the EnvInfoProvider interface in the oracle.jbo.common.ampool package. In your class, you override the getInfo() method and call put() to put values into the environment Hashtable passed in as shown in Example 50-2.

Example 50-2 Setting Environment Properties with a Custom EnvInfoProvider

package devguide.advanced.customenv.view;
import java.util.Hashtable;
import oracle.jbo.common.ampool.EnvInfoProvider;
/**
 * Custom EnvInfoProvider implementation to set
 * environment properties programmatically
 */
public class CustomEnvInfoProvider implements EnvInfoProvider {
  /**
   * Overridden framework method to set custom values in the
   * environment hashtable.
   * 
   * @param string - ignore
   * @param environment Hashtable of config parameters
   * @return null - not used
   */
  public Object getInfo(String string, Object environment) {
    Hashtable envHashtable = (Hashtable)environment;
    envHashtable.put("some.property.name","some value");
    return null;
  }
  /* Required to implement EnvInfoProvider */
  public void modifyInitialContext(Object object) {}
  /* Required to implement EnvInfoProvider */
  public int getNumOfRetries() {return 0;}
}

When creating an application module for a stateless or command-line-client, with the createRootApplicationModule() method of the Configuration class, you can pass the custom EnvInfoProvider as the optional second argument. In order to use a custom EnvInfoProvider in an ADF web-based application, you need to implement a custom session cookie factory class as shown in Example 50-3. To use your custom session cookie factory, set the jbo.ampool.sessioncookiefactoryclass configuration property to the fully qualified name of your custom session cookie factory class.

Example 50-3 Custom SessionCookieFactory to Install a Custom EnvInfoProvider

package devguide.advanced.customenv.view;
import java.util.Properties;
import oracle.jbo.common.ampool.ApplicationPool;
import oracle.jbo.common.ampool.EnvInfoProvider;
import oracle.jbo.common.ampool.SessionCookie;
import oracle.jbo.http.HttpSessionCookieFactory;
/**
 * Example of custom http session cookie factory
 * to install a custom EnvInfoProvider implementation
 * for an ADF web-based application.
 */
public class CustomHttpSessionCookieFactory
       extends HttpSessionCookieFactory {
  public SessionCookie createSessionCookie(String appId,
                                           String sessionId, 
                                           ApplicationPool pool,
                                           Properties props) {
    SessionCookie cookie =
      super.createSessionCookie(appId, sessionId,pool, props);
    EnvInfoProvider envInfoProv = new CustomEnvInfoProvider();
    cookie.setEnvInfoProvider(envInfoProv);
    return cookie;
  }
}

50.2.5 What You May Need to Know About Configuration Property Scopes

Each runtime configuration property used by ADF Business Components has a scope. The scope of each property indicates when the property's value is evaluated and whether its value is effectively shared (i.e. static) in a single Java VM, or not. The ADF Business Components PropertyManager class is the registry of all supported properties. It defines the property names, their default values, and their scope. This class contains a main() method so that you can run the class from the command line to see a list of all the configuration property information.

Assuming JDEVHOME is the JDeveloper installation directory, to see this list of settings for reference, do the following:

$ java -cp JDEVHOME/BC4J/lib/bc4jmt.jar oracle.jbo.common.PropertyManager

Issuing this command will send all of the ADF Business Components configuration properties to the console. It also lists a handy reference about the different levels at which you can set configuration property values and remind you of the precedence order these levels have:

---------------------------------------------------------------
Properties loaded from following sources, in order:
1. Client environment [Provided programmatically
                       or declaratively in bc4j.xcfg]
2. Applet tags
3. -D flags (appear in System.properties)
4. bc4j.properties file (in current directory)
5. /oracle/jbo/BC4J.properties resource
6. /oracle/jbo/commom.jboserver.properties resource
7. /oracle/jbo/common.Diagnostic.properties resource
8. System defined default
---------------------------------------------------------------

You'll see each property is listed with one of the following scopes:

  • MetaObjectManager

    Properties at this scope are initialized once per Java VM when the ADF PropertyManager is first initialized.

  • SessionImpl

    Properties at this scope are initialized once per invocation of ApplicationModule.prepareSession().

  • Configuration

    Properties at this scope are initialized when the ApplicationModule pool is first created and the application module's configuration is read the first time.

  • Diagnostic

    Properties at this scope are specific to the built-in ADF Business Components diagnostic facility.

At each of these scopes, the layered value resolution described above is performed when the properties are initialized. Whenever property values are initialized, if you have specified them in the Client Environment (level 1 in the resolution order) the values will take precedence over values specified as System parameters (level 3 in the resolution order).

The Client Environment is a hashtable of name/value pairs that you can either programatically populate, or which will be automatically populated for you by the Configuration object when loaded, with the name/value pairs it contains in its entry in the bc4j.xcfg file. The implication of this is that for any properties scoped at MetaObjectManager level, the most reliable way to ensure that all of your application modules use the same default value for those properties is to do both of the following:

  1. Make sure the property value does not appear in any of your application module's bc4j.xcfg file configuration name/value pair entries.

  2. Set the property value using a Java system property in your runtime environment.

If, instead, you leave any MetaObjectManager-scoped properties in your bc4j.xcfg files, you will have the undesirable behavior that they will take on the value specified in the configuration of the first application module whose pool gets created after the Java VM starts up.

50.2.6 What You May Need to Know About How Database and Application Module Pools Cooperate

How ADF application module pools use the database connection pool depends on the setting of the jbo.doconnectionpooling application module configuration parameter. In the Pooling and Scalability page of the Edit Configuration dialog shown in Figure 50-1, you set this parameter using the checkbox labelled Disconnect Application Module Upon Release.


Note:

The notion of disconnecting the application module upon release to the pool better captures what the actual feature is doing than the related configuration parameter name (jbo.doconnectionpooling) does. The setting of jbo.doconnectionpooling=false does not mean that there is no database connection pooling happening. What it means is that the application module is not disconnected from its JDBC connection upon check in back to the application module pool.


If the default setting of jbo.doconnectionpooling=false is used, then when an application module instance is created in any pool it acquires a JDBC connection from the appropriate connection pool (based on the JDBC URL in the ADF case, or from the underlying JDBC data source implementation's pool in the case of a JNDI data source name). That application module instance holds onto the JDBC connection object that it acquired from the pool until the application module instance is removed from the application module pool. During its lifetime, that application module instance may service many different users, and ADF worries about issuing rollbacks on the database connection so that different users don't end up getting pending database state confused. By holding onto the JDBC connection, it allows each application module instance to keep its JDBC PreparedStatement objects cached and reusable across subsequent accesses by clients, thereby providing the best performance.

If jbo.doconnectionpooling=true, then each time a user session finishes using an application module (typically at the end of each HTTP request), the application module instance disassociates itself with the JDBC connection it was using on that request and it returns it to the JDBC connection pool. The next time that application module instance is used by a user session, it will reacquire a JDBC connection from the JDBC connection pool and use it for the span of time that application module is checked out of the application module pool (again, typically the span of one HTTP request). Since the application module instance "unplugs" itself from the JDBC connection object used to create the PreparedStatements it might have used during the servicing of the current HTTP request, those PreparedStatements are no longer usable on the next HTTP request because they are only valid in the context of the Connection object in which they were created. So, when using the connection pooling mode turned on like this, the trade-off is slightly more JDBC overhead setup each time, in return for using a smaller number of overall database connections.

The key difference is seen when many application module pools are all using the same underlying database user for their application connection.

  • If 50 different application module pools each have even just a single application module instance in them, with jbo.doconnectionpooling=false there will be 50 JDBC application connections in use. If the application module pooling parameters are set such that the application module pools are allowed to shrink to 0 instances after an appropriate instance idle timeout by setting jbo.ampool.minavailablesize=0, then when the application module is removed from its pool, it will put back the connection its holding onto.

  • In contrast, if 50 different application module pools each have a single application module instance and jbo.doconnectionpooling=true, then the amount of JDBC connections in use will depend on how many of those application modules are simultaneously being used by different clients. If an application module instance is in the pool and is not currently being used by a user session, then with jbo.doconnectionpooling=true it will have released its JDBC connection back to the connection pool and while the application module instance is sitting there waiting for either another user to need it again, or to eventually be cleaned up by the application module pool monitor, it will not be "hanging on" to a JDBC connection.


Performance Tip:

Leave the jbo.doconnectionpooling configuration parameter set to false for best performance without sacrificing scalability and reliability. Database connection pooling is still achieved through application module pooling. The only exception is when multiple application module pools (and therefore a large number of application module instances) share the same database, making the total available database connections the highest priority.


Highest performance is achieved by not disconnecting the application module instance from its database connection on each check in to the application module pool. Accordingly, the default setting of the jbo.doconnectionpooling configuration parameter is false. The pooling of application module instances is already an effective way to optimize resource usage, and the Oracle ADF runtime is more efficient when you do not have to disconnect application module instances from their associated JDBC connection after each release to the pool. Effectively, by pooling the application modules which are related one-to-one with a JDBC connection, you are already achieving a pooling of database connections that is optimal for most Fusion web applications.

However, when minimizing the total overall number of database sessions is a priority, one situation in which it might be appropriate to use database connection pooling is when you have a large number of application module pools all needing to use database connections from the same underlying application user at the database level. In this case, the many application module pools can economize on the total overall database sessions by sharing a single, underlying database connection pool of JDBC connections, albeit at a loss of efficiency of each one. This choice would be favored only if total overall database sessions is of maximum priority. In this scenario, if a user scrolls through some, but not all rows of a view object's row set, then with jbo.doconnectionpooling=true, Oracle ADF will automatically passivate the pending application module state (including current row information) so that the next time the application module is used, the queried view object can be put back into the same current row with the same initial rows fetched. This passivation behavior may reduce performance.

To achieve a more ideal balance between conserving JDBC connections and keeping all application modules connected to the database, you can configure jbo.ampool.connection_threshold. This runtime property specifies the maximum number of connections that application modules in all application module pools combined may hold onto without releasing back to the connection pool upon checkin. Setting the maximum number of connections implies disconnecting application modules upon release is desired and automatically enables jbo.doconnectionpooling=true. For more details about optimizing the jbo.doconnectionpooling property, see Section 50.3.2, "What You May Need to Know About Optimizing Connection Pooling."

50.2.7 What You May Need to Know About Application Module Pool Parameters

The application module pool configuration parameters fall into three logical categories relating to pool behavior, pool sizing, and pool cleanup behavior.

50.2.7.1 Pool Behavior Parameters

Table 50-1 lists the application module configuration parameters that affect the behavior of the application module pool.

Table 50-1 Application Module Pool Behavior Configuration Parameters

Pool Configuration ParameterDescription

Failover Transaction State Upon Managed Release

(jbo.dofailover)

Specifies whether to disable or enable failover. By default, failover is disabled. To enable failover, set the parameter to true. When enabled, the Oracle ADF framework performs eager passivation of the pending transaction state each time an application module is released to the pool in "Managed State" mode. See Section 49.2.2.2, "How Passivation Changes When Optional Failover Mode is Enabled" for more information.

The failover feature is disabled by default (jbo.dofailover=false) as a performance optimization when there is only one web server instance configured, thus reducing the need for passivation and activation. This allows for application module affinity to a specific user session.

Note: When enabling application module state passivation, a failure can occur when Oracle WebLogic Server is configured to forcibly release connections back into the pool. A failure of this type produces a SQLException (Connection has already been closed.) that is saved to the server log. The exception is not reported through the user interface.

To ensure that state passivation occurs and users' changes are saved, set an appropriate value for the weblogic-application.xml deployment descriptor parameter inactive-connection-timeout-seconds on the <connection-check-params> pool params element.

Setting the deployment descriptor parameter to several minutes, in most cases, should avoid forcing the inactive connection timeout and the resulting passivation failure. Adjust the setting as needed for your environment.

Row-Level Locking Behavior Upon Release

(jbo.locking.mode)

Specifies the locking mode (optimistic or pessimistic). The default is optimistic, which forces the application module pool not to create a pending transaction state on the database with row-level locks each time the application module is released to the pool. See Section 49.11.1, "How to Confirm That Applications Use Optimistic Locking" for more information.

Fusion web applications should leave the locking mode set to the default value optimistic to avoid creating the row-level locks.

This parameter is not configurable in the Edit Configuration dialog. To edit the jbo.locking.mode parameter, open the Business Components page of the overview editor for the adf-config.xml file, located in the ADF META-INF folder in the Application Resources pane of the Applications window.

This feature is enabled by default and set to optimistic.

Disconnect Application Module Upon Release

(jbo.doconnectionpooling)

Note: This parameter's name is misleading and is better understood by the name Disconnect Application Module Upon Release, as shown in the Edit Configuration dialog.

Specifies whether the application module instance can be disconnected from the database connection when the application module instance is returned to the application module pool. This enables an application to size the application module pool larger than the database connection pool. The default is false, which means that an application module instance can retain its database connection when the application module instance is returned to the application module pool. When set to true, the application module can release the database connection back to the database connection pool when the application module instance is returned to the application module pool. Note that before an application module is disconnected from the database connection, a rollback can be issued on that database connection to revert any pending database state.

See also jbo.ampool.connection_threshold to achieve an ideal balance between conserving connections and using in-memory application module passivation. See Section 50.2.6, "What You May Need to Know About How Database and Application Module Pools Cooperate" for more information.

This feature is disabled by default (false).

Disconnect Application Module Upon Reaching Maximum Connection Threshold

(jbo.ampool.connection_threshold)

Specifies whether to force application modules to hold onto their JDBC connections so they do not release back to the connection pool upon checkin until a maximum number of JDBC connections is reached for all application modules in all application module pools combined. The default is to disable this feature (jbo.ampool.connection_threshold=0) which avoids the overhead associated with normal connection pooling.

Setting a connection threshold to a limit greater than 0 enables this feature. When the threshold is reached, connections will be released on the next pool cleanup cycle starting with least recently used, available application modules.

Setting a non-zero connection threshold implies disconnecting application modules upon release is desired and automatically enables jbo.doconnectionpooling=true. See Section 50.3.2, "What You May Need to Know About Optimizing Connection Pooling" for more information.

Setting a non-zero connection threshold releases JDBC connections during application module pool cleanup instead of during application module checkin. To ensure JDBC connections are released efficiently, configure jbo.ampool.monitorsleepinterval to shorten the monitor sleep period.

This feature is disabled by default (jbo.ampool.connection_threshold=0).

Transaction Memory State Upon Release

(jbo.txn.disconnect_level)

Specifies whether the application module, view objects and row sets remain in memory and stay valid but allow their corresponding references to JDBC objects to be dropped. Passivation in memory is enabled by default (jbo.txn.disconnect_level=1). Upon activation, the framework reexecutes and synchronizes the cursor positions.

When used in conjunction with jbo.doconnectionpooling=true or jbo.ampool.connection_threshold, improves performance and reduces the memory overhead associated with this situation. See Section 50.3.2, "What You May Need to Know About Optimizing Connection Pooling" for more information.

Setting jbo.txn.disconnect_level=0, changes the application module passivation behavior so that the view objects and their row sets are closed and removed. In this case, view objects and their row sets will be re-created and reverted to their original state upon activation. Configuring jbo.txn.disconnect_level to 1 can prevent this behavior to avoid the passivation costs for this situation.

This feature is enabled by default (jbo.txn.disconnect_level=1).

Enable Application Module Pooling

(jbo.ampool.doampooling)

Specifies whether to enable application module pooling. By default application pooling is enabled (true).

Whenever you deploy your application in a production environment the default setting of jbo.ampool.doampooling set to true is the way you will run your application. But, as long as you run your application in a test environment, setting the property to false can play an important role in your testing. When this property is false, there is effectively no application pool. See Section 49.10, "Testing to Ensure Your Application Module is Activation-Safe" for more information.

This feature is enabled by default (true).

Support Dynamic JDBC Credentials

(jbo.ampool.dynamicjdbccredentials)

Specifies whether to enable additional pooling lifecycle events to allow developer-written code to change the database credentials (username/password) each time a new user session begins to use the application module.

This feature is enabled by default (true), however this setting is a necessary but not sufficient condition to implement the feature. The complete implementation requires additional developer-written code.

Reset Non-Transactional State Upon Unmanaged Release

(jbo.ampool.resetnontransactionalstate))

Specifies whether the application module resets any nontransactional state like view object runtime settings, JDBC prepared statements, bind variable values, etc. when the application module is released to the pool in unmanaged or "stateless" mode. By default application module reset is enabled (true).

Disabling this feature can improve performance, however since it does not clear bind variable values, your application needs to ensure that it systemically sets bind variable values correctly. Failure to do so with this feature disabled can mean one user might see data with another users bind variable values.)

This feature is enabled by default (true).


50.2.7.2 Pool Sizing Parameters

Table 50-2 lists the application module configuration parameters that affect the sizing of the application module pool.

Table 50-2 Application Module Pool Sizing Configuration Parameters

Pool Configuration ParameterDescription

Initial Pool Size

(jbo.ampool.initpoolsize)

Specifies the number of application module instances to create when the pool is initialized. The default is 0 (zero) instances.

Creating application module instances during initialization reduces the cost of CPU processing by creating application module instances during the initialization instead of on-demand when additional application module instances are required.

A general guideline is to configure this to 10% more than the anticipated number of concurrent application module instances required to service all users.

When configuring jbo.initpoolsize, realize that any pre-initialized application module instances that are not used and that exceed the limit specified by jbo.ampool.maxinactiveage will be freed from the pool. Coordinate this parameter with jbo.ampool.minavailablesize to prevent the initialized instances from being reclaimed.

Maximum Pool Size

(jbo.ampool.maxpoolsize)

Specifies the maximum number of application module instances that the pool can allocate. The pool will never create more application module instances than this limit imposes. The default is 4096 instances.

Referenced Pool Size

(jbo.recyclethreshold)

Specifies the maximum number of application module instances in the pool that may attempt to preserve session affinity for the next request made by the session which used them last before releasing them to the pool in managed-state mode. User session affinity mechanism attempts to give back the same application module instance from the pool that the user session was using on the last request. If the application module pool is sized correctly for your typical application load, then most of the time a user session will be reunited with the application module instance it was using.

The default is to allow 10 available instances to try and remain "loyal" to the affinity they have with the most recent session that released them in managed state mode. The referenced pool size should always be less than or equal to the maximum pool size.

Configure this value to maintain the application module instance's affinity to a user's session. A general guideline is to configure this to the expected number of concurrent users that perform multiple operations with short think times. If there are no users expected to use the application with short think times, then this can be configured to 0 zero to eliminate affinity.

Maintaining this affinity as much as possible will save the CPU processing cost of needing to switch an application module instance from one user session to another.


50.2.7.3 Pool Cleanup Parameters

A single application module pool monitor per Java VM runs in a background thread and wakes up every so often to do resource reclamation. The pool monitor uses the following two, independent strategies to identify which application module instances are candidates to be removed from the pool and reclaimed as a potential new resource.

  1. The application module pool monitor removes application module instances from the pool that have not been used for more than 3600000 milliseconds (which is the default value and is exactly one hour). These unused application module instances will be reclaimed regardless of the minimum available size for the pool. To override the maximum time to live for an application module, you can set the jbo.ampool.timetolive parameter. However, for most Fusion web applications, you will not need to reclaim unused application module instance and can set this parameter value to -1.

  2. The application module pool monitor removes application module instances that have remained idle for 600000 milliseconds (which is the default value and is exactly 10 minutes). This cleanup stops when the number of instances in the pool reaches the minimum available size. You can override the idle timeout for application module instances using the jbo.ampool.maxinactiveage parameter.

Table 50-3 lists the parameters that affect how resources are reclaimed when the pool monitor does one of its resource cleanup passes.


Best Practice:

When you specify the length of time between application module pool cleanup passes, set all application modules to use the same Pool Polling Interval value. Since there is only a single application monitor pool monitor per Java VM, the value that will effectively be used for the application module pool monitor polling interval will be the value found in the application module configuration read by the first application module pool that gets created. Setting all application modules to use the same value ensures that this value is set in a predictable way.


Table 50-3 Application Module Resource Management Configuration Parameters

Pool Configuration ParameterDescription

Pool Polling Interval

(jbo.ampool.monitorsleepinterval)

Specifies the length of time in milliseconds between pool resource cleanup. Configuring a higher interval results in less frequent resource cleanups.

The default is to have the application module pool monitor wake up every 600000 milliseconds (which is 600 seconds, or ten minutes). Configuring a lower interval results in inactive application module instances being removed more frequently to save memory.

While the number of application module instances in the pool will never exceed the maximum pool size, available instances which are candidates for getting removed from the pool do not get "cleaned up" until the next time the application module pool monitor wakes up to do its job.

Maximum Available Size

(jbo.ampool.maxavailablesize)

Specifies the ideal maximum number of available application module instances in the pool when the server is under load.

The default maximum available size is 25 instances. A lower value generally results in more application module instances being removed from the pool on a cleanup. Configure this to leave the maximum number of available instances desired after a resource cleanup.

A general guideline is to configure this to 20% more than the pool size under normal load to allow for some additional growth. If this is set too low, then some users may see an error accessing the application if no application module instances are available.

When the pool monitor wakes up to do resource cleanup, it will try to remove available application module instances to bring the total number of available instances down to this ideal maximum. Instances that have been not been used for a period longer than the idle instance time-out will always get cleaned up at this time, then additional available instances will be removed if necessary to bring the number of available instances down to this size.

While application module pool tuning allows different values for the jbo.ampool.maxavailablesize | jbo.ampool.minavailablesize parameters, in most cases it is fine to set these minimum and maximum tuning properties to the same value

Minimum Available Size

(jbo.ampool.minavailablesize)

Specifies the minimum number of available application module instances that the pool monitor should leave in the pool during a resource cleanup operation, when the server is under light load.

The default is 5 instances.

Set to 0 (zero) if you want the pool to shrink to contain no instances when all instances have been idle for longer than the idle time-out after a resource cleanup.

While application module pool tuning allows different values for the jbo.ampool.minavailablesize | jbo.ampool.maxavailablesize parameters, in most cases it is fine to set these minimum and maximum tuning properties to the same value.

Idle Instance Timeout

(jbo.ampool.maxinactiveage)

Specifies the number of milliseconds after which to consider an idle application module instance in the pool as a candidate for removal during the next resource cleanup.

The default is 600000 milliseconds of idle time (which is 600 seconds, or ten minutes). A lower value results in more application module instances being marked as a candidate for removal at the next resource cleanup. A higher value results in fewer application module instances being marked as a candidate for removal at the next resource cleanup.

Maximum Instance Time to Live

(jbo.ampool.timetolive)

Specifies the number of milliseconds after which to consider an unused application module instance in the pool as a candidate for removal during the next resource cleanup regardless of whether it would bring the number of instances in the pool below minavailablesize.

The default is 3600000 milliseconds of total time to live (which is 3600 seconds, or one hour). A lower value reduces the time an unused application module instance can exist before it must be removed at the next resource cleanup. The default value is sufficient for most applications. A higher value increases the time an application module instance can exist before it must be removed at the next cleanup.

Alternatively, set the parameter value to -1 when you want to prevent removal of unused application modules by the application module pool monitor.


50.2.8 What You May Need to Know About Data Source Configuration

When you specify a JDBC data source as your application module's connection type, any configuration parameters that you have configured for the database connection pool will be ignored. To configure the connection pool for your data source, you must use the means provided by your Java EE container. In the case of Oracle WebLogic Server, you configure the data source using the Oracle WebLogic Server Administration Console.

The main steps for configuring JDBC data sources are:

  1. Create a data source for each data base that you want to connect to. When you create the data source, specify the configuration options to match the ones for ADF Business Components database connection pools described in Table 50-4. The configuration settings that you specify will depend on your database and the capacity planning that you need anticipate for your application.

    For details about configuring JDBC data sources and connection pool capacity planning, see Administering JDBC Data Sources for Oracle WebLogic Server.

  2. Optionally, configure transaction options for the data source.

  3. Optionally, configure connection testing options for the data source.

  4. Optionally, target the data source to additional servers and clusters.

For detailed procedures for each of these steps, see the topic "Configure JDBC data sources" in the Administration Console Online Help.

Table 50-4 Equivalent Oracle WebLogic Server Data Source Parameters

ADF Business Components Parameter\Oracle WebLogic Server Parameter

Initial Pool Size

(jbo.initpoolsize)

Initial Capacity

Maximum Pool Size

(jbo.maxpoolsize)

Maximum Capacity

Pool Polling Interval

(jbo.poolmonitorsleepinterval)

No equivalent for Oracle WebLogic Server.

Maximum Available Size

(jbo.poolmaxavailablesize)

Maximum Capacity

Minimum Available Size

(jbo.poolminavailablesize)

Maximum Capacity

Idle Instance Timeout

(jbo.poolmaxinactiveage)

Shrink Frequency Seconds


50.2.9 What You May Need to Know About Database Connection Pool Parameters

If you are using a JDBC URL for your connection information so that the ADF database connection pool is used, then configuration parameters listed in Table 50-5 can be used to tune the behavior of the database connection pool. A single "database connection pool monitor" per Java VM runs in a background thread and wakes up every so often to do resource reclamation. The parameters in Table 50-3 include the ones that affect how resources are reclaimed when the pool monitor does one of its resource cleanup passes.


Note:

The configuration parameters for database connection pooling have MetaObjectManager scope (described in Section 50.2.5, "What You May Need to Know About Configuration Property Scopes" earlier). This means their settings are global