3 Creating and Configuring EJB Data Controls

This chapter describes how to create data controls for EJB session beans and also includes information on paging and failover support.

This chapter includes the following sections:

3.1 About EJB Data Controls

Data controls are an abstraction provided by ADF Model than enable you to work with data and business services in a declarative manner and easily create UI components. For more general information, see Section 1.1, "About ADF Model."

You can create data controls for EJB session beans to simplify the creation of web applications that rely on database access. In addition to the features that are common for all adapter data controls (such as declarative UI hints and validation rules), EJB data controls have the following features built in:

  • Range paging in order to improve performance of queries to large data sets

  • Declarative named criteria to simplify creation of search-by-example forms

  • Transactional operations (based on transactional business methods in the session bean)

  • Failover support (based on failover methods that you implement)

3.1.1 EJB Data Control Use Cases and Examples

You can use EJB data controls to do the following kinds of things:

  • Create highly functional web pages that are bound to an EJB session facade, without manually writing any binding code

  • Create an application that integrates existing EJB business services with ADF features such as ADF Model data binding, ADF Faces, and ADF task flows

  • Take advantage of UI hints, validation rules, and other declarative metadata to provide consistent application of prompts, tooltips, format masks, and error messages throughout the application

  • Take advantage of ADF Model features to declaratively add query-by-example forms and list-of-value (LOV) components to pages

  • Enable MDS customization on the application, which allows customers to customize an application without modifying the source code

3.1.2 Additional Functionality for EJB Data Controls

You may find it helpful to understand other ADF and JDeveloper features before you implement your data controls. Following are links to other sections that may be useful.

  • ADF Model and data binding: When you create forms in an ADF web application, you use ADF Model and data binding. For more information, see "Using ADF Model in a Fusion Web Application" in Developing Fusion Web Applications with Oracle Application Development Framework and Java API Reference for Oracle ADF Model

  • ADF Faces: When you create databound UI components, they are likely to be from the ADF Faces component set. For more information, see "Creating a Databound Web User Interface" in Developing Fusion Web Applications with Oracle Application Development Framework.

  • ADF task flows: Task flows extend JSF page flows to provide a modular and transaction-aware approach to navigation and application control. For more information, see "Creating ADF Task Flows" in Developing Fusion Web Applications with Oracle Application Development Framework.

  • Java EE support in JDeveloper: JDeveloper provides support for creating Java EE components in a way that is optimized for use with EJB data controls. For more information, see "Developing with EJB and JPA Components"

3.2 Preparing a Session Bean to Use With a Data Control

An EJB data control encapsulates an EJB session bean and exposes the bean's code elements as data control objects, which can then be used to bind those code elements to UI components. When you create a data control based on an EJB session bean, the data control relies on coding patterns in the bean. This section shows the mapping between given code patterns and data control objects and shows patterns that you can use in your beans to maximize the data control features.

Note:

The data control does not replace the bean code. Rather, it serves as a thin adapter layer between the bean and the binding layer. The methods in your bean are used at runtime as you have coded them. Any declarative metadata that you specify in the data control, such as UI hints or validation rules, augments the session bean's business logic. Likewise, if you add or change methods after you have created the data control, the data control works with those new or revised methods.

3.2.1 Supported Types and Constructs in EJB Data Controls

EJB (and bean) data controls are compatible with classes that use the following Java types and constructs:

  • Java primitive types and arrays

  • Complex Java types, such as your own beans

  • Java scalar types, including types from the java.math, java.sql, and java.util packages

  • Collection types encompassed by the java.util.Collection, java.util.List, and java.util.Map packages

  • Generics, strongly-typed collections, and wildcards

  • Java Persistence API (JPA) features such as:

    • @Id annotations to determine primary keys

    • @NamedQuery annotations and the full range of JPQL syntax for named queries

    • @JoinColumn annotations to denote master-detail and list-of-value (LOV) relationships.

3.2.2 EJB Data Control Objects

When you create a data control based on an EJB session bean (or a POJO bean), the data control exposes several different types of objects, each of which you can bind to a variety of UI components.

For EJB and bean data controls, data control objects are exposed for collections, complex types, and primitives that are returned by any public method starting with get. In these cases, the name of the data control object typically matches the name of the get method, but with the leading get removed from the name.

If a returned object has a relationship to another object defined through a JoinColumn annotation, then a child object is displayed in the Data Controls panel.

If the fields of a bean are exposed with public get methods, those fields are exposed as child attributes of the collection or structured attribute in the Data Controls panel. For get methods that return arrays and simple collections composed of primitives or strings, a child attribute node called element is exposed the Data Controls panel.

For methods that are not pre-pended with get, the methods are exposed as method objects in the Data Controls panel. Returns of these methods are exposed as method return objects.

In addition, built-in data control operations become available for many of those objects. See Section 2.2.4, "Data Control Built-in Operations" for the full list of those operations.

Note:

EJB and bean data controls also expose bean constructors, which you can use to create buttons in the UI for creating new instances of the bean. This provides an alternative to using the data control's Create operation for creating instances. Buttons created from constructor nodes in the Data Controls enable the user to create a new object instance without adding that object to the persistence context (which using the Create operation does). You can declaratively access that object instance by binding to the result property of the binding object for the constructor.

Table 3-1 shows how the various data control objects map to the elements of EJB classes. For information on using these objects, see Section 2.3, "Creating Databound UI Components from the Data Controls Panel."

Table 3-1 Important EJB and Bean Data Control Objects

Icon Name Description

icon for collection

Collection

Is exposed for any public get method that returns a collection (any object implementing java.util.Collection).

The children under a collection may be attributes of the collection, related collections, custom methods that return a value from the collection, or built-in operations that can be performed on the collection.

icon for structured attribute

Structured Attribute

Is exposed for any public get method that returns a complex Java type that is not a collection.

icon for attribute

Attribute

Is exposed for any public get method that returns a Java primitive or String, such as a column in an entity bean).

icon for key attribute

Key Attribute

Is exposed for any attribute that is marked as the primary key (or which is part of a composite primary key). A key attribute can be designated with an @Id annotation in the entity bean class or in the data control structure file for a bean. For more information, see Section 3.2.4.1, "Recommended Entity Bean Elements" and Section 7.3.1, "How to Designate an Attribute as Primary Key."

icon for method

Method

Represents methods that are not pre-pended with get. These methods may return single values, structures, or collections.

icon for method return

Method Return

Represents an object that is returned by a method or other operation. The returned object can be a single value or a collection.

A method return appears as a child under the method that returns it. The objects that appear as children under a method return can be attributes of the collection, other methods that perform actions related to the parent collection, or operations that can be performed on the parent collection.

icon for operation

Operation

Represents a built-in data control operation that performs actions on the parent object. Data control operations are located in an Operations node under collections or method returns, and also under the root data control node. The operations that are children of a particular collection or method return operate on those objects only, while operations under the data control node operate on all the objects in the data control.

If an operation requires one or more parameters, they are listed in a Parameters node under the operation.

icon for parameter

Parameter

Represents a parameter value that is declared by the method or operation under which it appears. Parameters appear in the Parameters node under a method or operation.

icon for named criteria

Named criteria

Represents a metadata-based query from which you can create a user search form.

You can create custom view criteria and add them to the Data Controls panel. See Section 7.6, "Filtering Result Sets with Named Criteria."

icon for constructor

Constructor

Represents a constructor for one of the creatable types encompassed by a bean or EJB data control. You can use this data control object to create a command control that the user can click to create a new instance of that type.


3.2.3 About the Session Facade Pattern

EJB data controls are based on the EJB session facade design pattern, in which a session bean mediates access to individual entity beans, which contain the code to query database tables. When you create a data control based on a session bean, the data control exposes top-level objects based on the session bean's methods and lower level objects based on the detail in the entity beans that is retrieved by the session bean's accessor methods.

3.2.4 EJB Data Control Prerequisites and Considerations

In order to take advantage of the full functionality of EJB data controls, you need to include some elements in your classes that the data controls can use to present the structure of the services.

Your project should contain the following types of classes:

  • JPA entity classes for every database table that your application needs to query.

  • One or more session beans that contain accessor methods to the entity beans and other business methods. EJB data controls are based on sessions beans.

  • Optionally, (POJO) service facade classes that mirror the structure of the session beans. These service facade classes are useful for testing the services without having to run them in an application server container. You can also create data controls for service facade classes in order to test the services with the data control.

3.2.4.1 Recommended Entity Bean Elements

Your entity beans should contain the following elements:

  • @NamedQuery annotations containing queries that return each row of the collection. You can also take advantage of the constructs of the Java Persistence Query Language (JPQL) to add more selective queries. For more information on JPQL, see http://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html.

  • @JoinColumn annotations for any columns that reference other tables (or other columns in the same table) by foreign key. The generated data control will then expose these joined columns as master-detail relationships and simplify the creation of UI components that rely on those relationships.

  • addEntityBeanName(CollectionType collectionParam) and removeEntityBeanName(CollectionType collectionParam) methods for each of the collections represented by the entity beans. The data control's Create and Delete operations rely on these methods to add and remove rows in a collection.

  • Primary keys designated for each entity bean. This is necessary for the Create operation to function properly when creating new rows at runtime.

    You can designate primary key columns in entity beans by adding (or generating) @Id annotations for the appropriate columns.

  • A strategy for generating primary key values when creating new records. This is particularly important when you are using explicit commit models where you need to persist a new record upon its creation but before the user fills in the details for the other fields. For more information, see Section 3.2.8, "About Generating IDs for Primary Keys with the @GeneratedValue Annotation."

3.2.4.2 Recommended Session Facade Elements

It is recommended that your session beans (and/or Java service facade classes) contain the elements in the following list in order to integrate with data control features. If you use JDeveloper's wizards to create your classes, these elements are generated for you by default.

  • Getter methods that return the results of named queries specified in the entity beans. For example, the method shown in Example 3-1 would return the results of a named query called Customer.findById.

    When you create a query that includes named parameters, the data control object that is created for that query includes the ExecuteWithParams built-in operation, which you can use to quickly create forms that are based on parameters that are supplied at runtime.

    Tip:

    If you have multiple named queries for an entity bean, you can create a getter method for each named query to create distinct data control collection objects for each query.

  • The queryByRange(String jpqlStmt, int firstResult, int maxResults) method, in order to take advantage of built-in support for JPA named queries, named criteria metadata, scrollable access mode, and range paging access mode. The data control will use this method to perform all named queries, instead of invoking the getter methods for the queries in the session bean.

    Example 3-2 shows the code that is generated for the queryByRange(String jpqlStmt, int firstResult, int maxResults) method when you use JDeveloper to generate a session bean (or a plain Java facade using the Java Service Facade wizard). You can change the implementation of this method, but you need to keep the signature as is, since that's what the ADF Model runtime looks for.

  • (If your bean has transactional behavior), the following methods with these exact signatures:

    • public boolean isTransactionDirty()

    • public void rollbackTransaction()

    • public void commitTransaction()

    These methods are used to implement the data control's commit and rollback operations. When you use the JDeveloper wizards for creating Java service facade classes and EJB stateful container-managed session beans, working implementations of these three methods are generated in the classes by default.

Example 3-1 Getter Method That Returns the Results of a Named Query

/** <code>select o from Customer o where o.id = :custId</code> */
public List<Customer> getCustomerFindById(BigDecimal custId) {
    if (custId != null) {
        Long custIdLong = new Long(String.valueOf(custId));
        return em.createNamedQuery("Customer.findById").setParameter("custId", custIdLong).getResultList();
    } else {
        return getCustomerFindAll();
    }

Example 3-2 Code Listing for queryByRange() Method

public Object queryByRange(String jpqlStmt, int firstResult, int maxResults) {
    Query query = em.createQuery(jpqlStmt);
    if (firstResult > 0) {
        query = query.setFirstResult(firstResult);
    }
    if (maxResults > 0) {
        query = query.setMaxResults(maxResults);
    }
    return query.getResultList();
}
 

3.2.5 Creating EJBs for a Data Control in JDeveloper

JDeveloper's wizards enable you to create EJB entity classes and session beans that are optimized for use with data controls. For more information, see "How to Work with an EJB Business Services Layer" in Developing Applications with Oracle JDeveloper.

3.2.6 What You May Need to Know About How EJB and Bean Data Controls Use Getter Methods

When you use the queryByRange(String jpqlStmt, int firstResult, int maxResults) in your session bean (and the data control uses the oracle.adf.model.adapter.bean.jpa.JPQLDataFilterHandler handler), the data control will use this method to perform all named queries, instead of invoking the getter methods for the queries in the session bean. If you have custom logic that you have added to the getter methods, it will not be called when the query is run. If you need that custom logic to run, you can incorporate it into the queryByRange(String jpqlStmt, int firstResult, int maxResults) method.

When you do not include the queryByRange(String jpqlStmt, int firstResult, int maxResults) in your session bean, the data control based on that bean is generated with the oracle.adf.model.adapter.bean.DataFilterHandler handler. In this case, the data control will invoke the session bean's getter methods directly, but you will not be able to use declarative named criteria on objects in the data control and you will need to manually implement methods for scrollable and range paging to work. For more information on the use of named criteria, see Section 7.6, "Filtering Result Sets with Named Criteria." For more information on paging, see Section 3.4, "Paginated Fetching of Data in EJB Data Controls."

3.2.7 About Commit Models for EJB Session Beans

EJB data controls can be used for different varieties of EJB session beans, whether they are bean-managed or container managed or whether they are stateful or stateless. JDeveloper's Create Session Bean wizard can generate code for the following types of session beans on which you can create a data control for updating data:

  • stateless container-managed transactions (CMT) with implicit commit

  • stateless bean-managed transactions (BMT) with implicit commit

  • stateful CMT with implicit commit

  • stateful BMT with implicit commit

  • stateful CMT with explicit commit

  • stateful BMT with explicit commit

3.2.7.1 Implicit Commit Models

For data controls based on any of the implicit commit variants, the transactional operations Commit and Rollback are not provided. For these beans, any use of the persistEntity or mergeEntity methods update the data in the underlying data source.

3.2.7.2 Explicit Commit Models

When you work with beans with an explicit commit model, the underlying data source is not updated until the Commit operation is called. This enables a user to create or make changes to multiple rows in multiple tables and then later commit them all to the data source with one click.

For data controls based on any of the explicit commit variants, you still might need to add steps to merge or persist changes to the persistence context before those changes can be committed. For example, you might need to have the user click buttons both to persist new rows and to commit the group of changes.

However, for some session beans, it is possible to configure the data control so that its Create operation automatically calls the entity's persist method when it is invoked. This is the default behavior for data controls for session beans created with JDeveloper's Create Session Bean wizard that are configured as stateful with container-managed transactions and an explicit commit model. For more information, see Section 3.3.8, "About Automatically Persisting New Rows."

Where it is not possible to persist new rows immediately upon their creation, you can use a managed bean to override or combine operations and methods. For more information, see "Overriding Declarative Methods" in Developing Fusion Web Applications with Oracle Application Development Framework.

Also for many beans, and particularly for stateful CMT beans with explicit commit, you need to implement ID generation for the primary key columns. For more information, see Section 3.2.8, "About Generating IDs for Primary Keys with the @GeneratedValue Annotation."

3.2.8 About Generating IDs for Primary Keys with the @GeneratedValue Annotation

In general it is convenient to let JPA auto-generate primary key values when you create a new instance of an entity. For many data models, you must generate values to populate the primary key columns of your tables to avoid constraint violation errors when the user tries to persist a new row. In JPA entity classes that use a simple primary key type (like Integer, long, String, etc.), you can use @GeneratedValue annotation for an entity's primary key column to designate how and from where the new record obtains that value. You then need to ensure that those values are generated by the database.

The Create Entities from Tables wizard in JDeveloper can help you configure your entities to have their primary key values automatically generated and assigned. This option is available to entities which use a simple primary key type, such as Integer, String, long, int, etc. When this option is enabled, the entity's primary key field is annotated with @GeneratedValue, which indicates how the key value should be generated. The wizard enables you to choose between the SequenceGenerator and TableGenerator strategies.

Once your classes have the @GeneratedValue annotation, you need to make sure that the values are generated by the database upon creation of a new row and passed to the entity. You can do this in one of the following ways:

  • Update the persistence unit for the entities to have the schema objects automatically created upon deployment by setting the eclipselink-ddl-generation property to create-tables or drop-and-create-tables. For more information, see Section 3.2.9, "How to Change a Persistence Unit's Schema Generation Behavior."

  • Manually update the online database schema to incorporate the ID generation objects specified in the @GeneratedValue annotations.

    When you use the Create Entities from Tables wizard in JDeveloper, schema objects for any sequence or table generators are created and displayed under the Offline Database Sources node for the data model project in the Applications window. You can add the object to the online schema by right-clicking the node for the object, choosing Generate to > ConnectionName, and completing the ensuing Generate Database Objects from Database wizard.

  • If you already have ID generation objects in the live database schema, manually change the annotation attributes to refer to those objects. For example, for the @SequenceGenerator annotation, you would change the sequenceName attribute.

3.2.9 How to Change a Persistence Unit's Schema Generation Behavior

By default, when you use the Create Entities from Tables wizard to create entities, it creates a persistence unit with the eclipselink-ddl-generation property configured to use its default value (none). This means that EclipseLink, which is the default persistence provider for the generated entities, will not generate any Data Definition Language (DDL) statements or schema changes at runtime.

However, when you are developing the application, it might be useful to configure this property so that schema objects are created or re-created in the database schema each time that you test deploy the application. That will save you from having to manually keep the database schema in sync with incremental changes that you make as you develop the data model. For example, if you set the eclipselink-ddl-generation property to create-tables, EclipseLink will try to generate any schema objects that are specified by the entities and which do not yet exist in the schema, including sequences and tables for ID generation.

To change a persistence unit's schema generation behavior:

  1. In the Applications window, expand the data model project and double-click the persistence unit file (which is located at Application Sources > META-INF > persistence.xml by default).

  2. If there are multiple persistence units, in the overview editor for the persistence unit file, select the persistence unit for your project and click the Go to the Persistence Unit icon.

  3. In the overview editor for the persistence unit, select the Schema Generation page.

  4. From the Generation Type dropdown list, select the type of schema generation that you want.

For more information on the eclipselink-ddl-generation options, see the EclipseLink documentation at http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/p_ddl_generation.htm.

WARNING:

Before deploying your finished application to a production environment, the database schema should be finalized, and you should change the eclipselink-ddl-generation property back to none.

3.2.10 How to Automatically Update a Session Facade

If you change an entity bean, you can use JDeveloper to quickly update the session bean and, if applicable, its remote and local interfaces. The Edit Session Facade wizard enables you to generate code in the session bean to expose named queries and methods that have been added to your entity classes. If you have a data control based on that session bean, any newly added methods become available to you in the Data Controls panel immediately after you refresh the panel.

To update a session facade based on updated entity beans:

  1. In the Applications window, right-click the session bean and choose Edit Session Facade.

  2. In the Specify Session Facade Options dialog, select any methods that you would like generated in the session bean.

3.2.11 What You May Need to Know About Refreshing JPA Queries

By default, when a JPA query is run, the results of the query are cached and that cache is used if the query is re-issued from the same session. Therefore, if a change occurs to the database from a second user's session after the first user's initial query, the first user might not see the changes made by the second user when re-running the query (e.g. when refreshing a page).

To make sure that a fresh JPA query is always run, you can use a hint on the query to refresh the cache.

In JPA 2.0, you can apply the following hint to the query:

setHint("javax.persistence.cache.storeMode", "REFRESH")

For the getCustomerFindAll() method, this would look like the following:

public List<Customer> getCustomerFindAll() {
    return em.createNamedQuery("Customer.findAll").                 
        setHint("javax.persistence.cache.storeMode", "REFRESH").
        getResultList();
}

In JPA 1.0, you can apply the following hint (assuming TopLink is your persistence provider):

setHint("eclipselink.refresh", "true")

3.3 Exposing Session Bean Services with ADF Data Controls

Once you have your application's services in place, you can use JDeveloper to create data controls that provide the information needed to declaratively bind UI components to those services.

In a standard Java EE application, you normally create entity beans that represent tables in a database and then create a session facade over all the EJBs. This facade provides a unified interface to the underlying entities. You then would typically use other classes to coordinate the interaction between the user interface and the services exposed by the session facade.

In an Oracle ADF application, you can eliminate the need to programmatically coordinate the model and view layers by creating a data control to encapsulate the services represented by the service facade and enable declarative data binding between the layers. You then create UI components that are declaratively bound to the services through the data control. The bindings take the form of EL expressions that reference the data control. Figure 3-1 illustrates the coordination between UI components and data control objects that is possible with declarative bindings.

Figure 3-1 Binding Between View and Service

shows mapping from data control objects to UI components

Data controls consist of one or more XML metadata files that define the capabilities of the services that the bindings can work with at runtime. The data controls work in conjunction with the underlying beans without changing the implementation of the beans.

For example, Figure 3-2 shows an EJB data model project in the Applications window. The project has a number of entity beans that represent database tables, such as the Customer bean, the Product bean, the Order bean, and so on. The project also contains a session bean, OrdersSessionEJBBean, which is used to access the beans created from tables. This session bean also contains service methods for persisting, merging, and removing records. There is a data control for the session bean, which allows developers to declaratively create UI pages based on the methods of the session bean and the entity beans that the session bean encapsulates. In addition, there are XML files in the persdef.model package that correspond with the Customer, Product, and Order beans that contain additional metadata such as UI hints and validation rules. These additional XML files are only needed if you are adding metadata for a given data collection.

Figure 3-2 EJB Model Project

Applications window showing beans and data control files

3.3.1 How to Create EJB Data Controls

You create data controls from within the New Gallery or the Applications window.

Before you begin:

It may be helpful to have a general understanding of using EJB data controls. For more information, see Section 3.3, "Exposing Session Bean Services with ADF Data Controls".

You may also find it helpful to understand the code patterns and constructs in your session bean that the data control uses. For more information, see Section 3.2, "Preparing a Session Bean to Use With a Data Control."

You need to complete this task:


Create an application workspace, JPA/EJB 3.0 entities, and one or more session beans for the entities. For more information, see "How to Work with an EJB Business Services Layer" in Developing Applications with Oracle JDeveloper.

To create an EJB data control:

  1. In the Applications window, right-click the session bean for which you want to create a data control and choose Create Data Control.

  2. In the Choose Session EJB page of the Create EJB Data Control wizard, specify a name for the data control instance.

    Note:

    You can create multiple data control instances with different behavior for the same bean. For more information, see Section 3.3.11, "How to Create Different Data Controls for a Single Bean."

  3. In the Choose Session EJB Business Interface page of the wizard, choose Local or Remote. For web applications, typically you would choose Local.

  4. In the Choose ADF Data Controls Features page, select any of the following checkboxes for additional data control features that you would like to use in your application. (This page of the wizard only appears when you are creating the data control over a stateful session bean.)

    Methods will be added to the session bean to implement the selected data control features.

    • Transactions. Selecting this feature generates the commitTransaction(), rollbackTransaction(), and isTransactionDirty() methods in your session bean and maps them with the data control's commit and rollback operations. If you have used JDeveloper to create a stateful and container-managed session bean, these methods should already be implemented, in which case the Transactions checkbox would be selected by default.

    • Custom CRUD. This feature enables you to provide your own implementation of persistence behavior. EJB data controls already have CRUD functionality from JPA, so you would only select this feature if you want to override JPA's functionality. For more information, see Section 3.3.5, "What You May Need to Know About CRUD Operations in an EJB Data Control."

    • Failover. For more information, see Section 3.5, "Enabling Failover in an EJB Data Control."

  5. In the EJB Data Control Options page, select any additional options.

  6. Click Finish.

Note:

If you later rename the bean on which a data control is based, you must again use the Create Data Control command in order to regenerate the data control's metadata. When doing so, you can keep the same data control instance name.

If you merely make changes to a bean after the data control is created, you do not have to regenerate the data control. The data control incorporates any changes made to the bean. However, you might need to close and reopen the project in order for the data control to incorporate the changes to the underlying beans.

3.3.2 What Happens in Your Project When You Create an EJB Data Control

When you create a data control based on an EJB session bean, JDeveloper does the following things:

  • Creates the data control definition file (DataControls.dcx) and opens the file in the overview editor.

    Depending on the configuration of the bean on which the data control is based and the options that you have chosen in the wizard, various elements and properties are configured in the DataControls.dcx file and can be seen in its source view. These elements and properties include:

    • <CreatableTypes>, which specifies the entities that are encompassed by the facade class and for which declarative metadata can be created.

    • DataControlHandler, which specifies a handler class that implements various features for the data control, including support for paging and named criteria.

    • AccessMode, which determines how the data control fetches data in the running application. For more information, see Section 3.4, "Paginated Fetching of Data in EJB Data Controls."

    • EagerPersist, which determines whether new rows are added to the persistence context when created. For more information, see Section 3.3.8, "About Automatically Persisting New Rows."

  • Displays the hierarchy of the resulting data control objects in the Data Controls panel.

  • If you have selected any features on the ADF Data Controls Features page, adds methods to implement those features to the session bean.

  • If you have selected Generate Metadata, generates XML data control structure files for the high-level data control objects. These files hold any declarative metadata, such as UI hints and validation rules, that you define for given data control objects. If you have not selected this option, the data control structure files are created on demand when you use the DataControls.dcx overview editor to add declarative metadata to data control objects. For more information, see Chapter 7, "Adding Business Logic to Data Controls."

For general information on the overview editor and Data Controls panel, see Section 2.2.2, "What Happens in Your Project When You Create a Data Control." For information specific to EJB and bean data controls, see Section 3.3.3, "How EJB and Bean Data Controls Appear in the IDE."

3.3.3 How EJB and Bean Data Controls Appear in the IDE

Once you have created an EJB or bean data control, you can use the overview editor for the DataControls.dcx file to further configure the data control, and you can use the Data Controls panel to create databound UI components.

3.3.3.1 DataControls.dcx Overview Editor for EJB and Bean Data Controls

The overview editor for the DataControls.dcx file provides a view of the master-detail hierarchies of your data model as well as methods from the session facade. When you select a node, you can view the fields that can be mapped to database columns in the corresponding entity class in the Attributes tab. In the Accessors tab, you can view fields for the corresponding entity class that have entity relationships defined (such as OneToMany and ManyToOne). In the Operations tab for collections, you can view entity methods that the data control uses for standard operations, such as the add and remove methods of the collection accessors.

See Table 2-1 for a description of the icons that are used in the overview editor and Data Controls panel.

You can change the settings for a data control by selecting an element and clicking the Edit icon. For more information about editing a data control, see Chapter 7, "Adding Business Logic to Data Controls."

3.3.3.2 Data Controls Panel for EJB and Bean Data Controls

The Data Controls panel serves as a palette, from which you can create databound UI components by dragging nodes from the Data Controls panel to the design editor for a web page. For information on the contents of the Data Controls panel, see Section 2.2.3, "Display of Business Services in the Data Controls Panel."

In addition for EJB and JPA-based bean data controls, nodes for named criteria appear, as shown in Table 2-1. Named criteria are used to create quick search forms. By default, an implicit named criteria called All Queriable Attributes appears for each queriable collection when you create the data control. You can create additional declarative named criteria for each collection as described in Section 7.6, "Filtering Result Sets with Named Criteria."

For information on creating databound UI components from a data control, see Section 2.3, "Creating Databound UI Components from the Data Controls Panel."

3.3.3.3 EJB and Bean Data Control Built-in Operations

EJB data controls also provide standard built-in data control operations that you can use to create command components in your user interface for page navigation and data operations.

For information on all of the operations available to data controls, see Section 2.2.4, "Data Control Built-in Operations."

3.3.4 What You May Need to Know About the Support Named Criteria Option

The Support Named Criteria option that is offered when you create an EJB or JPA-based bean data control affects more than named criteria. In addition, selecting this option enables support for the scrollable and range paging access modes as described in Section 3.4, "Paginated Fetching of Data in EJB Data Controls." If you deselect this option, the data control is generated to use the oracle.adf.model.adapter.bean.BeanDCHandler handler class, which does not contain support for either the paginated or scrollable access modes.

3.3.5 What You May Need to Know About CRUD Operations in an EJB Data Control

When you create an EJB data control, CRUD (Create/Read/Update/Delete) features rely on the session bean's service methods and the entity beans encompassed by the session bean.

For example, a session bean's persist and merge methods are represented in the Data Controls panel and you can use them to create buttons that allow the user to persist and merge the current instance of the object.

There are also built-in data control operations available that you can use to bind data operations to the UI. These operations in turn call the appropriate methods in the session facade and entity classes. In addition, they may update the state of the ADF iterator. For example, when invoked, the Create operation for a data collection calls the constructor of the entity class that represents that collection to create the instance and then calls the appropriate persist method in the session bean to add the new instance to the JPA persistence context. Then the newly created instance is added to the ADF iterator.

Tip:

Where applicable, it is generally best to use these built-in operations, because they handle communication with both the JPA entity manager and the ADF iterators, keeping the two in sync.

You can also implement your own logic for CRUD (Create/Read/Update/Delete) operations if you do not wish to rely on JPA for these features. For more information on implementing custom CRUD operations, see Section 4.6, "Enabling Custom CRUD Operations in a Bean Data Control."

3.3.6 What You May Need to Know About the Merge and Persist Methods

If, when you created your session bean, you chose to expose merge and persist methods, then those methods appear in the Data Controls panel and you can use them to create buttons that allow the user to merge and persist the current instance of the object. Which you use depends on whether the page will need to interact with the instance once updates are made. If you want to be able to continue to work with the instance, then you need to use the persist method.

The merge methods are implementations of the JPA EntityManager.merge method. This method takes the current instance, copies it, and passes the copy to the PersistenceContext. It then returns a reference to that persisted entity and not to the original object. This means that any subsequent changes made to that instance will not be persisted unless the merge method is called again.

The persist methods are implementations of the JPA EntityManager.persist method. Like the merge method, this method passes the current instance to the PersistenceContext. However, the context continues to manage that instance so that any subsequent updates will be made to the instance in the context.

3.3.7 What You May Need to Know About Remove Methods

When you have a data control that is based on a session bean or a Java service facade that contains remove methods (to remove objects from the JPA persistence context), those methods are exposed in the Data Controls panel along with other facade methods. However, when deleting an entity from a form or table bound to an ADF iterator, you should generally use the Delete operation instead of a remove method. The Delete operation calls the remove method on the facade and also notifies the ADF iterator of the changes, ensuring that the iterator and the persistence context stay in sync. If you call the remove methods directly in order to take advantage of any custom behavior that you have coded within them, you also need to provide the code to refresh the ADF iterator.

3.3.8 About Automatically Persisting New Rows

For most variants of EJB (and JPA-based bean) data controls, the Create operation creates a new row and inserts it into the row set. However, it does not add the newly created object to the persistence context. That is generally the desired behavior for stateless and implicit-commit data models, since attempting to persist the instance immediately upon creating it may violate constraint violations due to mandatory fields being empty.

However, some models support the option of calling the persist method during the Create operation, because the underlying DML to persist the row is deferred until commit time. When the Create Session Bean wizard in JDeveloper is used to generate a stateful session bean using CMT and explicit commit behavior, it generates a model that supports this eager persist behavior. The advantage this model has in a conversational web application is that the application can combine these steps of create and persist into a single gesture (typically a button). After creating multiple instances, the user can click a commit button to apply all of the pending changes, at which point a transaction is begun and the DML statements are executed in the database to perform any pending INSERT, UPDATE or REMOVE operations.

When you create a data control for an EJB or a bean, the class is scanned to see if it is a candidate for this "eager persist" behavior. If so, the data control's EagerPersist property is set to true. You can override the initial value to enable or disable this option as you wish.

Calling an entity's persist method eagerly is generally desirable only when the following conditions are met:

  • The session bean has explicit commit behavior (since implicit commit behavior would mean that the object would be committed as soon as it was created).

  • The model does not attempt to execute SQL right away when the persist method is called.

  • You have set up ID generation for the primary key column. For more information, see Section 3.2.8, "About Generating IDs for Primary Keys with the @GeneratedValue Annotation."

  • The EJB session been is stateful and uses the following:

    • container-managed transactions

    • the @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) annotation for the session bean class,

    • the @TransactionAttribute(TransactionAttributeType.REQUIRED for the commit method

If you use JDeveloper's Create Session Bean wizard to create a stateful session bean with container-managed transactions and an explicit commit model, any data control that you create for this bean will be generated with the EagerPersist property set to true. Otherwise, EagerPersist is set to false.

3.3.9 How to Change the EagerPersist Property

If your bean meets the conditions to work with eager persist behavior (as described in Section 3.3.8, "About Automatically Persisting New Rows") but it is not turned on (which might be the case if you did not use the Create Entities from Tables wizard to create the entity classes), you can manually set the EagerPersist property to true. Likewise, if the property is set to true but you do not want eager persist behavior, you can change it to false.

To change the value of the EagerPersist property for a data control:

  1. In the Data Controls panel, right-click the data control's root node and choose Edit Definition.

  2. In the ejb-definition Properties dialog, change the value of the EagerPersist property.

3.3.10 What You May Need to Know About the Persistence Context and Resubmitting Queries

When you have a data control based on a stateful container-managed session bean, pre-commit changes made in a session are not reflected in any subsequent query that is made to the data source. So, if a user is in the middle of a transaction and performs an operation that requeries the data source, the subsequent refresh of the data on the page will not include changes made in the session.

3.3.11 How to Create Different Data Controls for a Single Bean

You can create multiple instances of a data control for a single bean, which can be useful if you need to make contrasting data control features available to the UI developer. For example, you may want to make it possible for a UI developer to create some UI components with scrollable paging and others with range paging.

Before you begin:

It may be helpful to have a general understanding of using EJB data controls. For more information, see Section 3.3, "Exposing Session Bean Services with ADF Data Controls".

You may also find it helpful to understand the code patterns and constructs in your session bean that the data control uses. For more information, see Section 3.2, "Preparing a Session Bean to Use With a Data Control."

You need to complete this task:


Create a data control as shown in Section 3.3.1, "How to Create EJB Data Controls."

To create an additional data control instance for a bean:

  1. Right-click the bean for which you want to create the additional data control instance and choose Create Data Control.

  2. In the Choose Session EJB page (or Choose Bean Class) page of the wizard, specify a unique name for the data control instance (different from any previous data control instances that you have created).

  3. Complete the wizard with the options that you want for that instance of the data control.

3.3.12 What Happens When You Create an Additional Data Control Instance

When you create an additional data control instance for a bean, an additional high-level node appears in the overview editor for the DataControls.dcx file, as shown in Figure 3-3 and in the Data Controls panel.

Figure 3-3 Data Control Overview Editor with Two Data Control Instances

EmpDeptSessionBean and EmpDeptSessionBeanPaging instances

Note:

When you add declarative metadata such as UI hints and validators to a data control, the different data control instances for a bean use that same metadata. For more information on adding declarative metadata, see Chapter 7, "Adding Business Logic to Data Controls."

3.4 Paginated Fetching of Data in EJB Data Controls

When you create an EJB or bean data control, you can use the wizard's Access Mode dropdown list to determine how records are accessed from the database and whether to limit the number of records that are held in memory at a time.

In EJB and bean data controls, there are the following possibilities for fetching and storing data in memory:

  • Scrollable access mode.

    If you accept the defaults when creating the data control, the data access mode is set to scrollable. This means that the data that your application needs to display is retrieved from the database as needed (in increments equal to the range size specified by the UI component's iterator) and stored in memory. Then, when the user scrolls forward through the application, additional rows are fetched as needed and stored in memory. All rows that have been fetched remain in memory.

    For example, if the running application contains a table that displays rows 1 through 20 on a web page and the table's iterator has a range size of 25 (the default), the data control will fetch the first 25 rows. If the user scrolls down to display rows 477 through 496 of the result set, the data will be fetched in sets of 25 as the user scrolls until rows 26 through 500 are fetched. At that point, a total of 500 rows will be stored in memory.

    This is the default mode for data controls using oracle.adf.model.adapter.bean.DataFilterHandler and oracle.adf.model.adapter.bean.jpa.JPQLDataFilterHandler. However, for data controls using oracle.adf.model.adapter.bean.DataFilterHandler, you still need to add paging methods to your data control to implement the access mode. For more information, see Section 4.4.1, "How To Manually Implement Pagination Support in a Data Control."

  • Range paging access mode

    To limit the amount of records that are fetched and stored in memory at a time, you can use the rangePaging access mode. As with scrollable mode, range paging mode allows your applications to fetch data in increments. The main difference in range paging mode is that only the most recently fetched increment is retained in memory. So, for example, if the accessor iterator's rangeSize attribute is set to 25, no more than 25 records will be held in memory at any given time.

    In a range paging version of the scrollable example above, the data control would fetch rows 1 through 25 and hold them in memory in order to display rows 1 through 20. If the user scrolled down, the data control would fetch data in increments of 25 as the user was scrolling but release the previous 25 records from memory as it fetched a new range. By the time the user reached rows 477 through 496 as in the example above, only rows 476 through 500 would be in memory.

    When scrolling to a position that displays data from multiple increments, only the data from the increment last fetched is held in memory.

    You can set page ranging when creating the data control by selecting Range Paging in the Access Mode dropdown of the Create EJB Data Control wizard.

    Note:

    When you use range paging in a data control, the built-in navigation operation Last does not work on databound UI components created from that data control.

  • No pagination. When there is no pagination, all available data for a UI component is fetched. No pagination is implemented when the data control does not implement a data control handler, such as oracle.adf.model.adapter.bean.DataFilterHandler ororacle.adf.model.adapter.bean.jpa.JPQLDataFilterHandler. You can also use annotations to turn off paging for specific collections. For more information, see Section 3.4.4, "How to Specify Access Mode for Individual Objects in the Data Control."

  • Custom pagination. If the built-in pagination options do not suit your needs, you can implement your own pagination by implementing a custom handler class. For more information, see Section 4.4.2, "How to Implement a Custom Handler for Querying and Pagination."

For more information about access mode and data control handlers, see Section 3.4.3, "What You May Need to Know About the Scrollable and Range Paging Modes."

3.4.1 How to Change Paging Mode for a Data Control

If you want to change the paging mode for a data control, you can do so in the Data Controls panel.

Note:

For data controls using the oracle.adf.model.adapter.bean.DataFilterHandler ororacle.adf.model.adapter.bean.jpa.JPQLDataFilterHandler handler, the default access mode is scrollable.

Before you begin:

It may be helpful to have a general understanding of access modes for EJB and bean data controls. For more information, see Section 3.4, "Paginated Fetching of Data in EJB Data Controls."

You need to complete this task:


Create an EJB or bean data control. For more information, see Section 3.3.1, "How to Create EJB Data Controls."

To change paging mode for a data control:

  1. In the Data Controls panel, right-click the data control's node and choose Edit Definition.

  2. In the ejb-definition Properties or the bean-definition Properties dialog, select rangePaging or scrollable from the AccessMode dropdown list.

  3. If you are changing the data control to use range paging, make sure that the data control's FactoryClass property is specified as oracle.adf.model.adapter.bean.BeanDCFactoryImpl.

    You can access the FactoryClass property in the source editor for the DataControls.dcx file or in the Properties window that appears when you open DataControls.dcx in the source editor or overview editor.

3.4.2 How to Set Range Size for a Data Control that Uses Range Paging

When you set a data control's access mode to rangePaging, the data control determines the range size by reading the rangeSize property of the accessor iterator of each component that is bound to a collection in the data control.

To set the range size for a component:

  1. In the Applications window, select the page containing the component that is bound to the data control.

  2. In the Structure window, select the component that is bound to the data control collection.

  3. In the Properties window, expand the Behavior node, and set the rangeSize property to the desired value.

For more information on iterator bindings, see "Iterator Bindings Created in the Page Definition File" in Developing Fusion Web Applications with Oracle Application Development Framework.

3.4.3 What You May Need to Know About the Scrollable and Range Paging Modes

Data controls that support scrollable and range paging modes rely on methods in the bean class to implement that functionality. The method that the data control uses depends on the data control handler class that the data control uses.

For JPA-based data controls, typically the JPQLDataFilterHandler handler is specified. JPQLDataFilterHandler relies on the presence of JPA queries and a queryByRange() method in the bean. For more information, see Section 3.2.4, "EJB Data Control Prerequisites and Considerations."

For non-JPA bean data controls (and for EJB and JPA-based bean data controls that do not have a queryByRange() method), DataFilterHandler is specified. To implement range paging in data controls that use this handler, you need to add code to your bean class as shown in Section 4.4.1, "How To Manually Implement Pagination Support in a Data Control."

For data controls that do not have either of these handler classes (such as EJB data controls where you have explicitly turned off named criteria support), there is no built-in support for scrollable or range paging. However, you can write your own handler class to implement paging support. For more information, see Section 4.4.2, "How to Implement a Custom Handler for Querying and Pagination."

3.4.4 How to Specify Access Mode for Individual Objects in the Data Control

If your data control encompasses multiple collections of different sizes, you may wish to set different access modes for some of the collections. You can do so by placing annotations on the accessor methods in the bean that the data control represents.

For the methods on which the annotations are used, the annotations override the access mode set for the data control. If an accessor method does not have such an annotation, it inherits its access mode from the one that is defined for the data control.

To specify access mode for individual objects in a bean or EJB data control:

  1. Open the class on which the data control is based. For EJB data controls, this is the remote or local interface, depending on which you specified in the wizard when creating the data control.

  2. Add annotations for the methods for which you want a different access mode than that generally specified for the data control.

    Note:

    These annotations only work on getter methods.

    Example 3-3 shows the necessary import statements and the available annotations and how they can be used on a collection.

Example 3-3 Access Mode Annotations

import oracle.adf.model.adapter.bean.annotation.AccessMode;
import oracle.adf.model.adapter.bean.annotation.AccessModeType;

...
   * List with scrollable access
   */  
  @AccessMode(type=AccessModeType.SCROLLABLE)
  public List<Employees> getEmployeesScrollable();
 ...
   * List with range paging.
   */  
  @AccessMode(type=AccessModeType.RANGE_PAGING)
  public List<Employees> getEmployeesRangePaging();
 ...
   * List with no paging.
   */  
  @AccessMode(type=AccessModeType.NO_PAGING)
  public List<Employees> getEmployeesNoPaging();

3.4.5 What You May Need to Know About Sorting Tables Based on Range Paginated Collections

By default, if a user sorts a table that is bound to a JPA-based data control, the ADF Model runtime forces the iterator to return all rows into memory for sorting, even if the back-end JPQL queries have already done the sort at the database level, which can cause memory problems if collection is too large. If you are using range paging for a collection, you can disable the ADF Model runtime full in-memory sort and have the data control handle it instead, based on just the currently selected range.

To use the data control to handle the sort for range paginated collections:

  1. In the Applications window, double-click the DataControls.dcx file to open it in the overview editor.

  2. In the overview editor, select the node for the data control that you want to edit.

  3. In the Properties window, set the ImplementsSort property to true.

3.5 Enabling Failover in an EJB Data Control

You can configure EJB data controls that are based on stateful session beans to have their state managed by the ADF Model runtime and enable failover of the objects encapsulated by the data control. Failover support for EJB data controls works in the same way as it does for bean data controls.

For information on generating method stubs in the session bean for this failover support, see Section 3.3.1, "How to Create EJB Data Controls." For more information on implementing those methods, see Section 4.5, "Enabling Failover in a Bean Data Control."