4 Creating and Configuring Bean Data Controls

This chapter describes how to create data controls for JavaBeans components that are based on the Java Persistence API (JPA) and plain Java objects (also known as "POJOs").

This chapter includes the following sections:

4.1 About Bean 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 on data controls, see Section 1.1, "About ADF Model."

You use the bean data control type to create data controls for plain Java objects (POJOs) and JPA-based Java service facade classes.

4.1.1 About JPA-Based Bean Data Controls

Similar to EJB data controls, JPA-based bean data controls enable you to work with persistent data. Such data controls are based on POJO service facade classes that provide accessor methods to JPA entity classes. The main difference in JPA-based bean data controls is that you must provide the code to manage the persistence instead of being able to rely on an EJB container. For more information on EJB data controls, see Section 3.1, "About EJB Data Controls."

4.1.2 About non-JPA Bean Data Controls

You can also create bean data controls for Java classes that do not work with JPA functions. Such data controls do not provide persistence functionality or named criteria support, but they do include other features of adapter data controls such as the ability to add declarative validation rules on attributes and support for UI control hints.

Unlike JPA-based bean data controls, non-JPA data controls do not have built-in implementations for handling transactions or updating of data sources. However, you can code your own implementation for that functionality in your bean class within specific methods whose signatures the data control recognizes. For more information, see Section 4.7, "Adding Transactional Behavior to a non-JPA Bean Data Control" and Section 4.6, "Enabling Custom CRUD Operations in a Bean Data Control."

Non-JPA data controls have support for scrollable paging and range paging, but require some manual coding. For more information, see Section 4.4.1, "How To Manually Implement Pagination Support in a Data Control."

You can also create a custom data control type that extends bean data controls. For more information, see Section 4.9, "Creating Custom Bean Data Controls."

4.2 Preparing a Bean to Expose with a Data Control

A bean data control serves as a metadata wrapper for a bean class and exposes the bean's code elements as data control objects, which can then be used to bind those code elements to UI components.

4.2.1 Supported Types and Constructs in Bean Data Controls

Bean data controls support the same Java types and constructs as EJB data controls. For more information, see Section 3.2.1, "Supported Types and Constructs in EJB Data Controls."

4.2.2 Bean Data Control Objects

When you create a data control based on a bean, the data control exposes several different types of objects, each of which you can bind to a variety of UI components. Bean data controls exposes the same types of objects as EJB data controls. For more information, see Section 3.2.2, "EJB Data Control Objects.".

4.2.3 Bean Data Control Prerequisites and Considerations

Bean data controls are based on classes that meet the JavaBeans specification. For example, for a class to be a valid data control source, it needs to have a public default constructor.

In order to take advantage of the full functionality of JPA-based data controls, you need to include some elements in your classes that the data controls can use to present the structure of the services. These elements are largely the same as for EJB data controls. The main difference is that you use a Java service facade class for bean data controls instead of an EJB session bean. For more information, see Section 3.2.4, "EJB Data Control Prerequisites and Considerations."

4.2.4 How to Create a Service Facade for a JPA-Based Bean Data Control

You can create a bean data control based on a POJO class that contains service methods to access Java entity classes. JDeveloper has a wizard that helps you create this facade class that contains all of the necessary methods to work with the data control.

Before you begin:

It may be helpful to have a general understanding of the code conventions that the service facade and the data control will rely on. For more information, see Section 4.2, "Preparing a Bean to Expose with a Data Control."

You need to complete this task:

  • Create an application workspace that contains a project with JPA entities as described in "How to Create JPA Entities" in Developing Applications with Oracle JDeveloper.

To create a service facade for a JPA-based Bean Data Control:

  1. Right-click the package that contains the JPA entity classes and choose Java Service Facade.

  2. In the Java Service Class page of the Create Java Service Facade wizard, do the following:

    • Specify a name for the service class.

    • Specify the persistence unit on which to base the service facade.

    • Select the Implicit or Explicit radio button to determine commit behavior.

      If you select Explicit, transactional methods are generated into the class, which are in turn exposed as Commit and Rollback operations if you later create a data control based on the class.

      If you select Implicit, you can use the persistEntity(), mergeEntity(), and removeEntity() methods that are generated by the wizard to act as the methods for adding and removing rows from the data source.

  3. In the Java Service Facade Methods page, select the methods which you want to generate.

    Note:

    If you subsequently plan to create a data control and you want to use the built-in pagination and JPA querying support, be sure to select the queryByRange() method.

  4. Click Finish to exit the wizard.

4.3 Exposing Java Collections and Methods With Bean Data Controls

Once you have your bean in place, you can use JDeveloper to create data controls that provide the objects needed to declaratively bind UI components to the bean's services as well as any built-in operations provided by the data control.

4.3.1 How to Create a JPA-Based Bean Data Control

You create JPA-based bean data controls from within the New Gallery or the Applications window.

Before you begin:

It may be helpful to have a general understanding of bean data controls. For more information, see Section 4.3, "Exposing Java Collections and Methods With Bean 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 4.2, "Preparing a Bean to Expose with a Data Control."

You need to complete this task:


Create a Java service facade class, as described in Section 4.2.4, "How to Create a Service Facade for a JPA-Based Bean Data Control."

To create a bean data control:

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

    For a JPA-based data control, use the Java service facade class as the base for the data control.

  2. In the Choose Bean Class page of the Create Bean 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 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. Methods will be added to the bean to implement the data control features.

  4. Optionally, click the New Wrapper Class icon (to the right of the Implementation Class field) to generate a separate class that extends the bean class and holds the custom methods created on this page of the wizard.

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

4.3.2 How to Create a non-JPA-Based Bean Data Control

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

Before you begin:

It may be helpful to have a general understanding of bean data controls. For more information, see Section 4.3, "Exposing Java Collections and Methods With Bean 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 4.2, "Preparing a Bean to Expose with a Data Control."

You need to complete these tasks:

  1. Create an application workspace and a project. For more information, see "Creating Applications and Projects" in Developing Applications with Oracle JDeveloper.

  2. Create a bean class in the project. For more information, see "How to Create a New Java Class or Interface" in Developing Applications with Oracle JDeveloper.

To create a non-JPA bean data control:

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

  2. In the Choose Bean Class page of the Create Bean 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 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. For each feature that you select, methods with signatures that are recognized by the data control will be added to the bean. Within those methods, you can write your implementation for the respective data control features.

  4. Optionally, click the New Wrapper Class icon (to the right of the Implementation Class field) to generate a separate class that extends the bean class and holds the methods created on this page of the wizard.

  5. In the Bean 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 4.4, "Paginated Fetching of Data in Bean Data Controls." The Support Named Criteria option must be selected for you to be able to select an access mode.

    • 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."

4.3.3 What Happens in Your Project When You Create a Bean Data Control

When you create a data control based on a JavaBeans component, JDeveloper does the following:

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

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

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 JPA-based data controls, see Section 3.3.3, "How EJB and Bean Data Controls Appear in the IDE."

If you have selected any features on the ADF Data Controls Features page, methods to implement those features are added to the bean (or to the wrapper class if you have chosen to generate one).

If the bean has accessor methods that query collections and you have selected Support Named Criteria in the wizard, the data control will be generated to use oracle.adf.model.adapter.bean.jpa.JPQLDataFilterHandler, which provides support in the data control for declarative named criteria and paginated queries.

If the bean doesn't have accessor methods that query collections, the data control will be generated to use oracle.adf.model.adapter.bean.DataFilterHandler. Besides not supporting named criteria, oracle.adf.model.adapter.bean.DataFilterHandler also does not have paging functionality fully implemented. However, you can add a method to your bean to implement paging. For more information, see Section 4.4.1, "How To Manually Implement Pagination Support in a Data Control."

If the bean has accessor methods that query collections and you deselected Support Named Criteria in the wizard, the data control is generated to use the more limited oracle.adf.model.adapter.bean.BeanDCHandler handler and thus disables even basic paging support. For more information, see Section 3.3.4, "What You May Need to Know About the Support Named Criteria Option."

4.3.4 What You May Need to Know About Primary Keys for Non-JPA Bean Data Controls

Even when you are creating non-JPA beans, you can use the @Id annotation to mark a field as a primary key column.

However, for performance reasons, you might find it preferable to designate the primary key at the data control level so that you do not introduce a dependency on the JPA runtime library. For more information, see Section 7.3.1, "How to Designate an Attribute as Primary Key."

4.4 Paginated Fetching of Data in Bean Data Controls

When you create a 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.

Paging support for bean data controls generally follows the same principals as paging for EJB data controls. For more information, see Section 3.4, "Paginated Fetching of Data in EJB Data Controls." However, especially for non-JPA-based data controls, you might want or need to fill in part of the implementation yourself.

4.4.1 How To Manually Implement Pagination Support in a Data Control

With non-JPA data controls (or any EJB or bean data control that uses the oracle.adf.model.adapter.bean.jpa.DataFilterHandler handler), you need to add three methods for each collection in the session or service facade in order for the ADF Model runtime to implement scrollable paging and range paging. The method signatures should take the following form:

List<EntityBeanName> getEntityBeanNameList()
List<EntityBeanName> getEntityBeanNameList(int firstResult, int maxResults)
long getEntityBeanNameListSize()

Note:

JPA-based data controls typically use the oracle.adf.model.adapter.bean.jpa.JPQLDataFilterHandler handler and thus do not require manual implementation of these methods. However, a data control can get assigned the oracle.adf.model.adapter.bean.jpa.DataFilterHandler handler if the bean it is based on does not contain the queryByRange(String jpqlStmt, int firstResult, int maxResults) method. For more information, see Section 3.2.4.2, "Recommended Session Facade Elements."

4.4.2 How to Implement a Custom Handler for Querying and Pagination

If the built-in querying and paging options are not sufficient for your application, you can implement your own custom paging and querying behavior by providing your own data handler class for your data control.

To implement a custom handler for querying and pagination:

  1. Write a custom data control handler class and add it to the data control's project.

    You can sub-classes an existing handler, such as oracle.adf.model.adapter.bean.jpa.JPQLDataFilterHandler or oracle.adf.model.adapter.bean.DataFilterHandler. See Example 4-1 for an outline of a custom handler class.

  2. In the Source view of the DataControls.dcx file, type the fully-qualified class name of the handler as the value for the DataControlHandler attribute of each data control.

    DataControlHandler is an attribute of the ejb-definition element of EJB data controls and an attribute of the bean-definition element for bean data controls.

Example 4-1 Custom Data Control Handler

public class MyJPQLDataFilterHandler  extends JPQLDataFilterHandler
{
 public boolean invoke(Map bindingContext,
                                 OperationBinding action,
                                 DataFilter filter)
 {
    /** TODO: Users provide custom criteria. */
 }
 
 public Object invoke(RowContext rowCtx, String name,
                               DataFilter filter)
 {
    /** TODO: Users provide custom criteria. */
 } 
 
}

4.5 Enabling Failover in a Bean Data Control

You can configure bean data controls to have their state managed by the ADF runtime. This can be particularly useful if your application will run in a high availability or cluster environment. If the application is running on a server node that fails, the most recent snapshot of the data control's session state can be restored to another node in the cluster. Likewise, if a user's session is interrupted, the failover support can be used to restore the data control's state when the session is resumed.

You enable failover by implementing methods for saving and restoring the state of the data control. The ADF Model runtime manages the calling of these methods and handles the details of distributing the states of the data control. EJB and bean data control support for failover requires the following three methods, which you can add to your bean class through the data control wizard or manually:

  • public Serializable createSnapshot(). Saves the state of the data control and underlying bean as a serialized object and returns a handle for that object. The ADF runtime calls this method whenever the user submits any changes to a component bound via the data control (or when the user merely refreshes the page).

    In this method you need to add the logic that determines what gets saved and return the corresponding Serializable handle.

  • public void restoreSnapshot(Serializable handle). Restores the session state based on the most recently created snapshot. This method is called whenever the ADF Model runtime needs to restore a session that has been interrupted for whatever reason, such as a broken connection, a server failure, etc.

    In this method you need to fill in the implementation for restoring the data control from the handle returned by createSnapshot().

  • public void removeSnapshot(Serializable handle). Removes the snapshot that is associated with the handle returned by the createSnapshot() method.

4.5.1 What You May Need to Know About Calling PageFlowScope from the Constructor

In bean data controls that implement failover, you should not call PageFlowScope from the bean's constructor. During application failover, the data control objects are re-instantiated with a call to the constructor. Because that call happens outside of the ADF lifecycle, FacesContext is not available, nor is anything that depends upon it for its implementation.

4.6 Enabling Custom CRUD Operations in a Bean Data Control

JPA-based data controls are tightly integrated with the CRUD (create/read/update/delete) support in JPA. For example, built-in data control operations such as Create and Delete use the corresponding JPA persistence methods to carry out those operations when invoked at runtime.

However, if your data control is not JPA-based, you can provide your own implementation to integrate your bean's CRUD model with the data control.

The following are the method stubs that are added to your bean data control class when you use the Create Bean Data Control wizard to create a bean data control and enable custom CRUD support:

  • public Object createRowData(RowContext p0). Used to create a new row of data. At runtime, this method is called when the Create operation is invoked. You can provide your own implementation of this method to customize how a new row is persisted.

  • public boolean removeRowData(RowContext p0). Used to remove a row of data. At runtime, this method is called when the Delete operation is invoked.

  • public boolean setAttributeValue(oracle.binding.AttributeContext p0, Object p1). This method is called by the ADF Model runtime when a new value is to be set on an attribute in a bean.

  • public Object registerDataProvider(oracle.binding.RowContext p0). This method is called by the data binding facility before the object is modified or marked as removed, so the row can be marked dirty by the data control.

    This method needs to be present if you are implementing custom CRUD functionality, though typically you do not need to provide your own implementation.

  • public void validate(). Validates a transaction if it is dirty.

    This method needs to be present if you are implementing custom CRUD functionality, though typically you do not need to provide your own implementation of this method.

For information on creating a non-JPA data control, see Section 4.3.2, "How to Create a non-JPA-Based Bean Data Control."

4.7 Adding Transactional Behavior to a non-JPA Bean Data Control

When you create a JPA-based bean with the Create Java Service Facade wizard, you can generate code to support an explicit commit model. When a data control is based on such a class, the bean's transactional methods are exposed as Commit and Rollback operations in the data control.

For non-JPA bean data controls, you can generate stub methods when you create the data control to support the Commit and Rollback operations. Within those stub methods, you can write your own implementation of transactional behavior. At runtime, when the Commit and Rollback operations are invoked those methods are called.

The following are the method stubs that are added to your bean data control class when you use the Create Bean Data Control wizard to create a bean data control and enable transactional support:

  • public boolean isTransactionDirty(). Used to mark whether there are any pending changes to be committed (or rolled back).

  • public void commitTransaction(). Commits all pending changes to the data source.

  • public void rollbackTransaction(). Rolls back pending changes.

Note:

In order to implement transaction support in a non-JPA data control, you must also implement custom CRUD methods. For more information, see Section 4.6, "Enabling Custom CRUD Operations in a Bean Data Control"

For information on creating a non-JPA data control, see Section 4.3.2, "How to Create a non-JPA-Based Bean Data Control."

4.8 Using Annotations to Declare Metadata for Non-JPA Data Controls

The Adapter Data Control Framework provides several Java annotations that you can use to specify metadata for bean data controls.

  • oracle.adf.model.adapter.bean.annotation.AccessMode. Use to override the AccessMode flag in the DataControls.dcx file. You can use this annotation to control the paging feature in a JPA-based data control at the level of the accessor method, thus making it possible to use different access modes in a single data control.

    // AccessModeType can be either NO_PAGING, RANGE_PAGING or SCROLLABLE)@AccessMode(type = AcessModeType.RANGE_PAGING)
    public Collection<EmpBean> getListEmpBean() {}
    public Collection<EmpBean> getListEmpBean(int firstResult, int maxResults) {}
    public int getListEmpBeanSize() {}
    }
    

    For more information, see Section 3.4.4, "How to Specify Access Mode for Individual Objects in the Data Control."

  • oracle.adf.model.adapter.bean.annotation.AccessModeType. Must also be imported when using the oracle.adf.model.adapter.bean.annotation.AccessMode annotations in a class.

  • oracle.adf.model.adapter.bean.annotation.ElementType. Use to define the type for the collection. For example, an element type of EmpBean can be defined with @ElementType(name = "model.EmpBean". This is a substitute for using a generic collection (for example, Collection<EmpBean>) and is recommended only if you are using JDK 1.4 or before or if you need to override the element type of the collection.

    @ElementType(name = "model.EmpBean")
    public Collection getListEmpBean() {}
    
  • oracle.adf.model.adapter.bean.annotation.Id. Use to define the primary key for the attribute. For example:

    @Id
    public int getPrimaryKey() {}
    
  • oracle.adf.model.adapter.bean.annotation.Property. Use to specify a property for an attribute. For example:

    @Property(name = AttributeHints.ATTRIBUTE_LABEL, value = "Employee No.")
    public Long getEmpno() {}
    
  • oracle.adf.model.adapter.bean.annotation.Properties. Use to specify multiple properties for an attribute. For example:

    @Properties( {
      @Property(name = AttributeHints.FMT_FORMATTER, value = "oracle.jbo.format.DefaultDateFormatter"),
      @Property(name = AttributeHints.FMT_FORMAT, value = "dd-mmm-yyyy"),
      @Property(name = AttributeHints.ATTRIBUTE_LABEL, value = "Hire Date"),
      @Property(name = AttributeHints.ATTRIBUTE_TOOLTIP, value = "My Tooltip"),
      @Property(name = AttributeHints.ATTRIBUTE_CTL_TYPE, value = AttributeHints.CTL_DEFAULT),
      @Property(name = AttributeHints.ATTRIBUTE_CTL_DISPLAYWIDTH, value = "40"),
      @Property(name = AttributeHints.ATTRIBUTE_CTL_DISPLAYHEIGHT,  value = "20"),
      @Property(name = AttributeHints.ATTRIBUTE_CTL_FORMTYPE, value = AttributeHints.ATTRIBUTE_FORM_TYPE_DETAIL),
      @Property(name = AttributeHints.ATTRIBUTE_CTL_FIELD_ORDER, value =""),
      @Property(name = AttributeHints.ATTRIBUTE_CTL_CATEGORY, value = "")
      })
    public Timestamp getHiredate() {}
    

4.9 Creating Custom Bean Data Controls

You can modify or enhance the functionality on the bean data control type by extending the definition and implementation classes for the bean data control type to create a custom data control.

Creating a custom bean-based data control consists of a combination of the following main steps:

  • (Optionally) extending oracle.adf.model.adapter.bean.BeanDataControl in order to customize the way the data control handles filtering, failover, updating data sources, and other data control features.

  • (Optionally) extending oracle.adf.model.adapter.bean.BeanDCDefinition to create a new implementation class.

    If you create a new implementation class, you need to register that implementation class in the DataControls.dcx file. In the source view of the file, replace the value of the data control's ImplDef property (oracle.adf.model.adapter.bean.BeanDataControl) with the fully-qualified name of the new implementation class.

  • (Optionally) creating new structure definition types for the types of data structures that will be represented by your data control.

  • (Optionally), in the data control class, implement some of the existing supported features (such as failover or custom CRUD support).

For API documentation of the classes used by the bean data control and other data control types, see theJava API Reference for Oracle ADF Model.