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:
Section 3.2, "Preparing a Session Bean to Use With a Data Control"
Section 3.3, "Exposing Session Bean Services with ADF Data Controls"
Section 3.4, "Paginated Fetching of Data in 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)
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
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"
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.
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.
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 |
---|---|---|
|
Collection |
Is exposed for any public 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. |
|
Structured Attribute |
Is exposed for any public |
|
Attribute |
Is exposed for any public |
|
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 |
|
Method |
Represents methods that are not pre-pended with |
|
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. |
|
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. |
|
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. |
|
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." |
|
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. |
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.
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.
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.
add
EntityBeanName(CollectionType collectionParam)
and remove
EntityBeanName(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."
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(); }
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.
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."
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
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.
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."
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.
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:
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).
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.
In the overview editor for the persistence unit, select the Schema Generation page.
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
.
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:
In the Applications window, right-click the session bean and choose Edit Session Facade.
In the Specify Session Facade Options dialog, select any methods that you would like generated in the session bean.
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")
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.
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.
You create data controls from within the New Gallery or the Applications window.
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:
To create an EJB data control:
In the Applications window, right-click the session bean for which you want to create a data control and choose Create Data Control.
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."
In the Choose Session EJB Business Interface page of the wizard, choose Local or Remote. For web applications, typically you would choose Local.
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."
In the EJB Data Control Options page, select any additional options.
Access Mode. Enables you to set how the data control fetches and stores data in memory. For more information, see Section 3.4, "Paginated Fetching of Data in EJB Data Controls." The Support Named Criteria option must be selected for you to be able to select an access mode.
Support Named Criteria. When selected, the data control includes built-in support for declarative named criteria, which can be used to create quick search forms. For more information, see Section 7.6, "Filtering Result Sets with Named Criteria."
WARNING:
If you deselect this option, built-in options for scrollable paging and range paging access modes are also turned off. For more information, see Section 3.3.4, "What You May Need to Know About the Support Named Criteria Option."
The Support Named Criteria option is only available for JPA-based beans that also contain a queryByRange()
method. The data control uses the bean's queryByRange()
method to handle all queries that otherwise would be carried out by individual getter methods on the bean. For more information, see Section 3.2.6, "What You May Need to Know About How EJB and Bean Data Controls Use Getter Methods."
Generate Metadata. You can select this option to automatically generate metadata files for all of the beans represented by the data control upon the creation of the data control. This option is not necessary, since metadata files are created on demand when you edit a data control. However, this option might be useful if you plan to make the application available for MDS customization. For more information, see Section 7.2.4, "What You May Need to Know About MDS Customization of Data Controls."
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.
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."
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.
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."
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."
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."
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.
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."
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.
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.
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
.
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:
In the Data Controls panel, right-click the data control's root node and choose Edit Definition.
In the ejb-definition Properties dialog, change the value of the EagerPersist
property.
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.
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.
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:
To create an additional data control instance for a bean:
Right-click the bean for which you want to create the additional data control instance and choose Create Data Control.
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).
Complete the wizard with the options that you want for that instance of the data control.
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.
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."
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."
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
.
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:
To change paging mode for a data control:
In the Data Controls panel, right-click the data control's node and choose Edit Definition.
In the ejb-definition Properties or the bean-definition Properties dialog, select rangePaging
or scrollable
from the AccessMode dropdown list.
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.
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:
In the Applications window, select the page containing the component that is bound to the data control.
In the Structure window, select the component that is bound to the data control collection.
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.
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."
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:
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.
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();
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:
In the Applications window, double-click the DataControls.dcx
file to open it in the overview editor.
In the overview editor, select the node for the data control that you want to edit.
In the Properties window, set the ImplementsSort
property to true.
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."