3 Getting Started with ADF Business Components

This chapter provides an overview of ADF Business Components, including a description of the key features they provide for building your business services.

This chapter includes the following sections:

3.1 About ADF Business Components

ADF Business Components and JDeveloper simplify the development, delivery, and customization of business applications for the Java EE platform. With ADF Business Components, developers aren't required to write the application infrastructure code required by the typical Java EE application to:

  • Connect to the database

  • Retrieve data

  • Lock database records

  • Manage transactions

ADF Business Components addresses these tasks through its library of reusable software components and through the supporting design time facilities in JDeveloper. Most importantly, developers save time using ADF Business Components since the JDeveloper design time makes typical development tasks entirely declarative. In particular, JDeveloper supports declarative development with ADF Business Components to:

  • Author and test business logic in components which automatically integrate with databases

  • Reuse business logic through multiple SQL-based views of data, supporting different application tasks

  • Access and update the views from browser, desktop, mobile, and web service clients

  • Customize application functionality in layers without requiring modification of the delivered application

The goal of ADF Business Components is to make the business services developer more productive.

3.1.1 ADF Business Components Features

ADF Business Components provides a foundation of Java classes that allow your business-tier application components to leverage the functionality provided in the following areas:

Simplifying Data Access
  • Design a data model for client displays, including only necessary data

  • Include master-detail hierarchies of any complexity as part of the data model

  • Implement end-user Query-by-Example data filtering without code

  • Automatically coordinate data model changes with business services layer

  • Automatically validate and save any changes to the database

Enforcing Business Domain Validation and Business Logic
  • Declaratively enforce required fields, primary key uniqueness, data precision-scale, and foreign key references

  • Easily capture and enforce both simple and complex business rules, programmatically or declaratively, with multilevel validation support

  • Navigate relationships between business domain objects and enforce constraints related to compound components

Supporting Sophisticated UIs with Multipage Units of Work
  • Automatically reflect changes made by business service application logic in the user interface

  • Retrieve reference information from related tables, and automatically maintain the information when the user changes foreign-key values

  • Simplify multistep web-based business transactions with automatic web-tier state management

  • Handle images, video, sound, and documents without having to use code

  • Synchronize pending data changes across multiple views of data

  • Consistently apply prompts, tooltips, format masks, and error messages in any application

  • Define custom metadata for any business components to support metadata-driven user interface or application functionality

  • Add dynamic attributes at runtime to simplify per-row state management

Implementing High-Performance Service-Oriented Architecture
  • Support highly functional web service interfaces for business integration without writing code

  • Enforce best-practice interface-based programming style

  • Simplify application security with automatic JAAS integration and audit maintenance

  • "Write once, run anywhere": use the same business service as plain Java class, EJB session bean, or web service

Streamlining Application Customization
  • Extend component functionality after delivery without modifying source code

  • Globally substitute delivered components with extended ones without modifying the application

  • Deliver application upgrades without losing or having to reapply downstream customizations manually

3.1.2 ADF Business Components Core Objects

ADF Business Components implements the business service through the following set of cooperating components:

  • Entity object

    An entity object represents a row in a database table and simplifies modifying its data by handling all data manipulation language (DML) operations for you. It can encapsulate business logic for the row to ensure that your business rules are consistently enforced. You associate an entity object with others to reflect relationships in the underlying database schema to create a layer of business domain objects to reuse in multiple applications.

  • View object

    A view object represents a SQL query. You use the full power of the familiar SQL language to join, filter, sort, and aggregate data into exactly the shape required by the end-user task. This includes the ability to link a view object with others to create master-detail hierarchies of any complexity. When end users modify data in the user interface, your view objects collaborate with entity objects to consistently validate and save the changes.

  • Application module

    An application module is the transactional component that UI clients use to work with application data. It defines an updatable data model and top-level procedures and functions (called service methods) related to a logical unit of work related to an end-user task.

While the base components handle all the common cases through built-in behavior, customization is always possible and the default behavior provided by the base components can be easily overridden or augmented.

3.2 Comparison to Familiar 4GL Tools

ADF Business Components provides components that implement functionality similar to that offered by enterprise 4GL tools. Several key components in ADF Business Components have concepts you may be familiar with in other 4GL tools.

3.2.1 Familiar Concepts for Oracle Forms Developers

ADF Business Components implements all of the data-centric aspects of the familiar Oracle Forms runtime functionality, but in a way that is independent of the user interface. In Oracle Forms, each form contains both visual objects (like canvases, windows, alerts, and LOVs), as well as nonvisual objects (like data blocks, relations, and record groups). Individual data block items have both visual properties like Foreground Color and Bevel, as well as nonvisual properties like Data Type and Maximum Length. Even the different event-handling triggers that Forms defines fall into visual and nonvisual categories. For example, it's clear that triggers like WHEN-BUTTON-PRESSED and WHEN-MOUSE-CLICKED are visual in nature, relating to the front-end UI, while triggers like WHEN-VALIDATE-ITEM and ON-INSERT are more related to the backend data processing. While merging visual and nonvisual aspects definitely simplifies the learning curve, the flip side is that it can complicate reuse. With a cleaner separation of UI-related and data-related elements, it would be easier to redesign the user interface without disturbing backend business logic and easier to repurpose back-end business logic in multiple different forms.

In order to imagine this separation of UI and data, consider reducing a form as you know it to only its nonvisual, data-related aspects. This reduces the form to a container of data blocks, relations, and record groups. This container would continue to provide a database connection for the data blocks to share and would be responsible for coordinating transaction commits or rollbacks. Of course, you could still use the nonvisual validation and transactional triggers to augment or change the default data-processing behavior as well. This nonvisual object you are considering is a kind of a "smart data model" or a generic application module, with data and business logic, but no user interface elements. The goal of separating this application module from anything visual is to allow any kind of user interface you need in the future to use it as a data service.

Focus a moment on the role the data blocks would play in this application module. They would query rows of data from the database using SQL, coordinate master/detail relationships with other data blocks, validate user data entry with WHEN-VALIDATE-RECORD and WHEN-VALIDATE-ITEM triggers, and communicate valid user changes back to the database with INSERT, UPDATE, and DELETE statements when you commit the data service's transaction.

Experience tells you that you need to filter, join, order, and group data for your end-users in a variety of ways to suit the many different tasks. On the other hand, the validation rules that you apply to your business domain data remain basically the same over time. Given these observations, it would be genuinely useful to write business entity validation exactly once, and leverage it consistently anywhere that data is manipulated by users in your applications.

Enabling this flexibility requires further "factoring" of your data block functionality. You need one kind of "SQL query" object to represent each of the many different views of data your application requires, and you need another kind of "business entity" object to enforce business rules and communicate changes to your base table in a consistent way. By splitting things like this, you can have multiple "view objects" with specific SQL queries that present the same business data yet each working with the same underlying "entity object."

Oracle Application Development Framework (Oracle ADF) addresses the UI/data split by providing ready-to-use Java components that implement typical Forms functionality. Responsibilities between the querying and entity-related functions are cleanly separated, resulting in better reuse.

3.2.1.1 Similarities Between the Application Module and a "Headless" Form Module

The application module component is the "data portion" of the form. The application module is a smart data service containing a data model of master-detail-related queries that your client interface needs to work with. It also provides a transaction and database connection used by the components it contains. It can contain form-level procedures and functions, referred to as service methods, that are encapsulated within the service implementation. You can decide which of these procedures and functions should be private and which ones should be public.

3.2.1.2 Similarities Between the Entity Object and a Forms Record Manager

The entity object component implements the "validation and database changes" portion of the data block functionality. In the Forms runtime, this duty is performed by the record manager. The record manager is responsible for keeping track of which of the rows in the data block have changed, for firing the block-level and item-level validation triggers when appropriate, and for coordinating the saving of changes to the database. This is exactly what an entity object does for you. The entity object is a component that represents your business domain entity through an underlying database table. The entity object gives you a single place to encapsulate business logic related to validation, defaulting, and database modification behavior for that business object.

3.2.1.3 Similarities Between the View Object and a Data Block

The ViewObject component performs the "data retrieval" portion of the data block functionality. Each view object encapsulates a SQL query, and at runtime each one manages its own query result set. If you connect two or more view objects in master-detail relationships, that coordination is handled automatically. While defining a view object, you can link any of its query columns to underlying entity objects. By capturing this information, the view object and entity object can cooperate automatically for you at runtime to enforce your domain business logic, regardless of the "shape" of the business data required by the user's task.

3.2.2 Familiar Concepts for PeopleTools Developers

If you have developed solutions in the past with PeopleTools, you are familiar with the PeopleTools component structure. ADF Business Components implement the data access functionality you are familiar with from PeopleTools.

3.2.2.1 Similarities Between the Application Module and a "Headless" Component

Oracle ADF adheres to an MVC pattern and separates the model from the view. Pages, which you are familiar with in the PeopleTools Component, are defined in the view layer, using standard technologies like JSF and ADF Faces components for web-based applications or Swing for desktop-fidelity client displays.

The ADF application module defines the data structure, just like the PeopleTools Component Buffer does. By defining master-detail relationships between ADF query components that produce row sets of data, you ensure that any application module that works with the data can reuse the natural hierarchy as required, similar to the scroll levels in the Component Buffer.

Similar to the Component Interface you are familiar with, the application module is a service object that provides access to standard methods, as well as additional developer-defined business logic. In order to present a "headless" data service for a particular user interface, the Component Interface restricts a number of PeopleTools functions that are related to UI interaction. The application module is similar to the Component Interface in that it provides a "headless" data service, but in contrast it does not do this by wrapping a restricted view of an existing user interface. Instead, the application module is designed to deal exclusively with business logic and data access. Rather than building a Component Interface on top of the component, with ADF Business Components you first build the application module service that is independent of user interface, and then build one or more pages on top of this service to accomplish some end-user task in your application.

The application module is associated with a transaction object in the same way that the PeopleTools Component Buffer is. The application module also provides a database connection for the components it contains. Any logic you associate today with the transaction as Component PeopleCode, in ADF Business Components you would define as logic on the application module.

Logic associated with records in the transaction, that today you write as Component Record PeopleCode or Component Record Field PeopleCode, should probably not be defined on the application module. ADF Business Components has view objects that allow for better re-use when the same record appears in different components.

In summary, PeopleTools uses the component for the container concept, whereas ADF Business Components uses the application module. That is where the similarity ends. Do not assume that all of your component code will migrate to an application module. First, understand the concept of the view object, which is the layer between the entity object and the application module. Then, decide which of your component code is suitable for an application module and which is suitable for view objects.

3.2.2.2 Similarities Between the Entity Object and a Record Definition

The entity object is the mapping to the underlying data structure, just like the PeopleTools Record Definition maps to the underlying table or view. You'll often create one entity object for each of the tables that you need to manipulate your application.

Similar to how you declare a set of valid values for fields like "Customer Status" using PeopleTools' translate values, in ADF Business Components you can add declarative validations to the individual attributes of an entity object. Any logic you associate with the record that applies throughout your applications, which today you write as Record PeopleCode or Record Field PeopleCode, can be defined in ADF Business Components on the entity object.

3.2.2.3 Similarities Between the View Object and a Row Set

Just like a PeopleTools row set, a view object can be populated by a SQL query. Unlike a row set, a view object definition can contain business logic.

Any logic which you would find in Component Record PeopleCode is a likely candidate to define on the view object. Component Record PeopleCode is directly tied to the component, but a view object can be associated with different application modules. Whereas you can use the same record definition in many PeopleTools components, Oracle ADF allows you to reuse the business logic across multiple applications.

The view object queries data in exactly the "shape" that is useful for the current application. Many view objects can be built on top of the same entity object.

You can define relationships between view objects to create master-detail structures, just as you find them in the scroll levels in the PeopleTools component.

3.2.3 Familiar Concepts for Siebel Tools Developers

If you have developed solutions in the past with Siebel Tools version 7.0 or earlier, you will find that ADF Business Components implements all of the familiar data access functionality you are familiar with, with numerous enhancements.

3.2.3.1 Similarities Between the entity Object and a Table Object

Like the Siebel Table object, the ADF entity object describes the physical characteristics of a single table, including column names and physical data types. Both objects contain sufficient information to generate the DDL (data definition language) statements to create the physical tables in the database. In ADF Business Components you define associations between entity objects to reflect the foreign keys present in the underlying tables. These associations allow view object queries used by user interface pages to automatically join business information. ADF Business Components handles list of values (LOV) objects that you reference from data columns through a combination of declarative entity-level validation rules and view object attribute-level LOV definitions. You can also encapsulate other declarative or programmatic business logic with these entity object "table" handlers that is automatically reused in any view of the data you create.

3.2.3.2 Similarities Between the View Object and a Business Component

Like the Siebel Business Component, the ADF view object describes a logical mapping on top of the underlying physical table representation. Both the Siebel Business Component and the ADF view object allow you to provide logical field names, data, and calculated fields that match the needs of the user interface. As with the Siebel Business Component, with the ADF view object you can define view objects that join information from various underlying tables. The related ADF view link is similar to the Siebel Link object and allows you to define master-detail relationships. In ADF Business Components, your view object definitions can exploit the full power of the SQL language to shape the data as required by the user interface.

3.2.3.3 Similarities Between the Application Module and a Business Object

The Siebel Business Object lets you define a collection of business components. The ADF application module performs a similar task, allowing you to create a collection of master-detail view objects that act as a "data model" for a set of related user interface pages. In addition, the application module provides a transaction and database connection context for this group of data views. You can make multiple requests to objects obtained from the application module and these participate in the same transaction.

3.2.4 Familiar Functionality for ADO.NET Developers

If you have developed solutions in the past with Visual Studio 2003 or 2005, you are familiar with using the ADO.NET framework for data access. ADF Business Components implements all of the data access functionality you are familiar with from ADO.NET, with numerous enhancements.

3.2.4.1 Similarities Between the Application Module and a Data Set

The application module component plays the same role as the ADO.NET data set. It is a strongly typed service component that represents a collection of row sets called view object instances, which are similar to ADO.NET data tables. An application module exposes a service interface that surfaces the rows of data in a developer-configurable set of its view instances as an SDO-compatible service (accessible as a web service, or as an SCA composite). The application module works with a related transaction object to provide the context for the SQL queries that the view objects execute. The application module also provides the context for modifications saved to the database by the entity objects, which play the role of the ADO.NET data adapter.

3.2.4.2 Similarities Between the Entity Object and a Data Adapter

The entity object component is like a strongly-typed ADO.NET data adapter. It represents the rows in a particular table and handles the find-by-primary-key, insert, update, delete, and lock operations for those rows. In ADF Business Components, you don't have to specify these statements yourself, but you can override them if you need to. The entity object encapsulates validation or other business logic related to attributes or entire rows in the underlying table. This validation is enforced when data is modified and saved by the end user using any view object query that references the underlying entity object. One difference in ADF Business Components is that the arbitrary, flexible querying is performed by SQL statements at the view object instance level, but the view objects and entity objects coordinate automatically at runtime.

3.2.4.3 Similarities Between the View Object and a Data Table

The view object component encapsulates a SQL query and manages the set of resulting rows. It can be related to an underlying entity object to automatically coordinate validation and saving of modifications made by the user to those rows. This cooperation between a view object's queried data and an entity object's encapsulated business logic offers all of the benefits of the data table with the clean encapsulation of business logic into a layer of business domain objects. Like ADO.NET data tables, you can easily work with a view object's data as XML or have a view object read XML data to automatically insert, update, or delete rows based on the information it contains.

3.3 Overview of Design Time Facilities

JDeveloper includes comprehensive design time support for ADF Business Components. Collectively, these facilities let you create, edit, diagram, test, and refactor the business components.

3.3.1 Choosing a Connection, SQL Platform, and Data Type Map

The first time you create a component, you'll see the Initialize Business Components Project dialog shown in Figure 3-1. You use this dialog to select a design time application resource connection to use while working on your business components in this data model project (the term used in this guide for a project created for ADF Business Components) or to create a new application resource connection by copying an existing IDE-level connection.

Figure 3-1 Initialize Business Components Project Dialog

Initialize Business Components Project dialog

Since this dialog appears before you create your first business component, you also use it to globally control the SQL platform that the view objects will use to formulate SQL statements. Although the default for an Oracle database connection is always the Oracle SQL platform, other SQL platforms you can choose include OLite (for the Oracle Lite database), SQLServer for a Microsoft SQLServer database, DB2 for an IBM DB2 database, and SQL92 for any other supported SQL92- compliant database.

Note:

If you plan to have your application run against both Oracle and non-Oracle databases, you should select the SQL92 SQL platform when you begin building your application, not later. While this sacrifices some of the Oracle-specific optimizations that are inherent in using the Oracle SQL platform, it makes the application portable to both Oracle and non-Oracle databases.

Additionally, the dialog lets you determine which set of data types that you want the data model project to use. If JDeveloper detects you are using an Oracle database driver, it defaults the Data Type Map setting to the Java Extended for Oracle type map which uses standard Java types and the optimized types in the oracle.jbo.domain package for common data types. When you create a SQL92-compliant application that will run on a non-Oracle database, you can change the data type map to the Java setting to globally use only the basic Java data types.

The Java Extended for Oracle type map and the Oracle Domains type map handle numeric data differently. When you create a new application the default type map Java Extended for Oracle maps numeric data to the java.math.BigDecimal class, which inherits from java.math.Number. The java.math.BigDecimal default matches the way the Fusion web application view layer, consisting of ADF Faces components, preserves alignment of numeric data (such as numeric values displayed by ADF Faces input fields in a web page). Whereas the Oracle Domains type map, which maps numeric data to the oracle.jbo.domain.Number class, may not display the data with the alignment expected by certain ADF Faces components. Aside from this alignment issue, the Oracle Domains type map remains a valid choice and applications without ADF Faces components will function without issue.

New Fusion web applications should use the default Java Extended for Oracle type. The Oracle Domains type map is provided for backward compatibility and for applications that do not use ADF Faces as the view layer technology. Please note that when you migrate an application developed with JDeveloper version 11.1.1.4.0 or earlier, your application will continue to use the Oracle Domains type map and will not change to the current default type map Java Extended for Oracle.

Note that you cannot change the data type map after you've initialized a data model project. After you have initialized a data model project, you can you can override the SQL platform in the overview editor for the adf-config.xml file. Specifying the database type in the adf-config.xml file supports generating SQL statements during runtime that can require the actual database type. You can locate the file in the Application Resources panel by expanding the Descriptors > ADF META-INF node.

3.3.2 Creating New Components Using Wizards

In the New Gallery in the ADF Business Components category, JDeveloper offers a wizard to create each kind of business component. Each wizard allows you to specify the component name for the new component and to select the package into which you'd like to organize the component. If the package does not yet exist, the new component becomes the first component in that new package.

The wizard presents a series of panels that capture the necessary information to create the component type. When you click Finish, JDeveloper creates the new component by saving its XML component definition file. If you have set your Java generation options to generate classes by default, JDeveloper also creates the initial custom Java class files.

3.3.3 Creating New Components Using the Context Menu

Once a package exists in the Application Navigator, you can quickly create additional business components of any type in the package by selecting it in the Application Navigator and using one of the options on the context menu shown in Figure 3-2.

Figure 3-2 Context Menu Options on a Package to Create Any Kind of Business Component

Context menu options in Application Navigator

3.3.4 Editing Components Using the Component Overview Editor

Once a component exists, you can edit it using the respective overview editor that you access either by double-clicking the component in the Application Navigator or by selecting it and choosing the Edit option from the context menu. The overview editor presents the same editing options that you see in the wizard but it may arrange them differently. The overview editor allows you to change any aspect of the component. When you click OK, JDeveloper updates the components XML component definition file and, if necessary, any of its related custom Java files. Because the overview editor is a JDeveloper editor window, rather than a modal dialog, you can open and view the overview editor for as many components as you require.

3.3.5 Displaying Related Components Using Diagrams

As the number of business components that your project defines increases, you may decide to refactor components to change the relationships that you originally created. To help you understand the relationship between components in the data model project, open any component in the editor window and click the Diagram tab. The relationship diagram in the editor identifies the component you are editing in bold text. Related components appear as link text that you can click to display the relationship diagram for the component identified by the link. For example, Figure 3-3 displays the Diagram tab in the editor for the view object ProductsVO. The diagram identifies the list of entity objects that ProductsVO can access (for example, ProductBaseEO and ProductTranslationEO and so on), the view link (ProductsToWarehouseStockLevels) that defines the view object's relationship to a related view object, and the related view object (WarehouseStockLevelsVO) named by the view link. Each of these related components displays as a link that you can click to open the component in the Diagram tab for its editor. By clicking on related component links, you can use the diagrams to navigate the component relationships that your project defines.

Figure 3-3 Relationship Diagram Displays Main Object and All Related Components in Component Editor's Diagram Tab

Diagram tab in overview editor

3.3.6 Visualizing, Creating, and Editing Components Using UML Diagrams

JDeveloper offers extensive UML diagramming support for ADF Business Components. You can drop components that you've already created onto a business components diagram to visualize them. You can also use the diagram to create and modify components. The diagrams are kept in sync with changes you make in the editors.

To create a new business components diagram, use the Business Components Diagram item in the ADF Business Components category of the JDeveloper New Gallery. This category is part of the Business Tier choices.

3.3.7 Testing Application Modules Using the Oracle ADF Model Tester

Once you have created an application module component, you can test it interactively using the built-in Oracle ADF Model Tester. To launch the Oracle ADF Model Tester, select the application module in the Application Navigator or in the business components diagram and choose either Run or Debug from the context menu.

The Oracle ADF Model Tester presents the view object instances in the application module's data model and allows you to interact with them using a dynamically generated user interface. The tool also provides a list of the application module's client interface methods that you can test interactively by double-clicking the application module node. This tool is invaluable for testing or debugging your business service both before and after you create the web page view layer.

3.3.8 Refactoring Components

At any time, you can select a component in the Application Navigator and choose Refactor > Rename from the context menu to rename the component. The Structure window also provides a Rename context menu option for details of components, such as view object attributes or view instances of the application module data model, that do not display in the Application Navigator. You can also select one or more components in the navigator by using Ctrl + click and then choosing Refactor > Move from the context menu to move the selected components to a new package. References to the old component names or packages in the current data model project are adjusted automatically.

3.4 Overview of the Oracle ADF Active Data Model

One of the key simplifying benefits of using ADF Business Components for your business service implementation is the application module's support for an "active data model" of row sets. The data model defines the business objects specific to your application, while the row sets of each business object contain the data. In the UI portion of the application, the UI components interact with these business objects to perform retrieve, create, edit, and delete operations. When you use ADF Business Components in combination with the ADF Model layer and ADF Faces UI components, the data model is "active" because your UI components will automatically update to reflect any changes to the row sets of these business objects.

Thus, the active data model represents a solution that works across application technology layers to ensure that the UI and data model remain synchronized.

3.4.1 A More Generic Business Service Solution

Using a typical Java EE business service implementation makes the client developer responsible for:

  • Invoking service methods to return data to present

  • Tracking what data the client has created, deleted, or modified

  • Passing the changes back to one or more different service methods to validate and save them

Retrieving, creating, editing, deleting, and saving is a typical sequence of tasks performed during application development. As a result, the ADF application module represents a smarter, more generic solution. Using the application module for your business service, you simply bind client UI components like fields, tables, and trees to the active view object instances in the application module's data model. Your UI components in JSP or JSF pages for the web or mobile devices (as well as desktop-fidelity UIs comprising windows and panels that use Swing) automatically update to reflect any changes to the rows in the view object row sets of the data model. Additionally, if you define custom business service methods for the application module that happen to produce changes to the data model view instances, those changes will also be automatically reflected in the UI components.

Under the covers, the application module component implements a set of generic service methods that allow users to leverage its active data model in a service-oriented architecture (SOA). Both web service and UI clients can easily access an application module's data model using simple APIs. These APIs enable you to search for and modify any information that the application module makes available.

When you build UIs that take advantage of the ADF Model layer for declarative data binding, you generally won't need to write client-side code. The active data model supports declaratively binding UI components in your web pages to view objects in the data model and to custom business service methods. Additionally, when you create web services in a SOA environment they can be bound declaratively to the data model through the data model's web service interface.

3.4.2 Typical Scenarios for an Active Data Model

Without an active data model, you would need to write more code in the client or web service to handle the straightforward, everyday CRUD-style operations. In addition, to keep pages up to date, you would need to manage "refresh flags" that clue the controller layer in to requesting a "repull" of data from the business service to reflect data that might have been modified. When using an ADF application module to implement your business service, you can focus on the business logic at hand, instead of the plumbing to make your business work as your end users expect.

Consider the following three simple, concrete examples of the active data model:

  • New data appears in relevant displays without requerying

    A customer logs into the Fusion Order Demo application and displays a list of items in their shopping cart. Then if the customer visits some product pages and creates a new order item, when they return back to display their shopping cart, the new item appears in their list without requiring the application to requery the database.

  • Changes caused by business domain logic automatically reflected

    A back office application causes an update to the order status. Business logic encapsulated in the Orders entity object in the business domain layer contains a simple rule that updates the last update date whenever the order status attribute is changed. The user interface updates to automatically reflect the last update date that was changed by the logic in the business domain layer.

  • Invocation of a business service method by the ADF Model layer binding requeries data and sets current rows

    In a tree display, the user clicks on a specific node in a tree. This action declaratively invokes a business service method by the ADF tree binding on your application module that requeries master-detail information and sets the current rows to an appropriate row in the row set. The display updates to reflect the new master-detail data and current row displayed.

3.4.3 Active Data Model Support for Custom Code

Because the application module supports the active data model, your client user interface will remain up to date. This means you will not need to write code in the client that is related to setting up or manipulating the data model.

Another typical type of client-side code you no longer have to write using ADF Business Components is code that coordinates detail data collections when a row in the master changes. By linking the view objects, you can have the coordination performed automatically for you.

However, when you do need to write custom code, encapsulate that code inside custom methods of your application module component. For example, whenever the programmatic code that manipulates view objects is a logical aspect of implementing your complete business service functionality, you should encapsulate the details by writing a custom method in your application module's Java class. This includes, but is not limited to, code that:

  • Configures view object properties to query the correct data to display

  • Iterates over view object rows to return an aggregate calculation

  • Performs any kind of multistep procedural logic with one or more view objects

By centralizing these implementation details in your application module, you gain the following benefits:

  • You make the intent of your code more clear to clients.

  • You allow multiple client pages to easily call the same code if needed.

  • You simplify regression-testing of your complete business service functionality.

  • You keep the option open to improve your implementation without affecting clients.

  • You enable declarative invocation of logical business functionality in your pages.

3.5 Overview of the ADF Business Components Implementation

Before you begin implementing specific ADF business components, it is a good idea to have some familiarity with ADF Business Components design and implementation.

3.5.1 Standard Java and XML

As is the case with all Oracle ADF technologies, ADF Business Components is implemented in Java. The working, tested components in the framework provide generic, metadata-driven functionality from a rich layer of robust code. ADF Business Components follows the Java EE community best practice of using cleanly separated XML files to store metadata that you define to configure each component's runtime behavior.

Since ADF Business Components is often used for business critical applications, it's important to understand that the full source for Oracle ADF, including ADF Business Components, is available to supported customers through Oracle Worldwide Support. The full source code for Oracle ADF can be an important tool to assist you in diagnosing problems, as described in Section 36.8, "Using the ADF Declarative Debugger." Working with the full source code for Oracle ADF also helps you understand how to correctly extend the base framework functionality to suit your needs, as described in Section 12.4, "Customizing Framework Behavior with Extension Classes."

3.5.2 Application Server or Database Independence

Applications built using ADF Business Components can run on any Java-capable application server, including any Java EE-compliant application server. Because business components are implemented using plain Java classes and XML files, you can use them in any runtime environment where a Java Virtual Machine is present. This means that services built using ADF Business Components are easy to use both inside a Java EE server — known as the "container" of your application at runtime — and outside.

Customers routinely use application modules in such diverse configurations as command-line batch programs, web services, custom servlets, JSP pages, and desktop-fidelity clients built using Swing.

You can also build applications that work with non-Oracle databases, as described in Section 3.3.1, "Choosing a Connection, SQL Platform, and Data Type Map." However, applications that target Oracle databases will find numerous optimizations built into ADF Business Components.

3.5.3 Java EE Design Pattern Support

ADF Business Components implements all of the popular Java EE design patterns that you would normally need to understand, implement, and debug yourself to create a real-world enterprise Java EE application. If it is important to you to cross-reference the names of these design patterns from the Java EE specifications with their ADF Business Components counterparts, you can refer to Appendix E, "ADF Business Components Java EE Design Pattern Catalog."

3.5.4 Source Code Organization

Since ADF Business Components is implemented in Java, its classes and interfaces are organized into packages. Java packages are identified by dot-separated names that developers use to arrange code into a hierarchical naming structure.

The classes and interfaces that comprise the source code provided by ADF Business Components reside in the oracle.jbo package and numerous subpackages. However, in day to day work with ADF Business Components, you'll work typically with classes and interfaces in these two key packages:

  • The oracle.jbo package, which contains all of the interfaces that are designed for the business service client to work with

  • The oracle.jbo.server package, which contains the classes that implement these interfaces

Note:

The term client here refers to any code in the model, view, or controller layers that accesses the application module component as a business service.

Figure 3-4 shows a concrete example of the application module component. The client interface for the application module is the ApplicationModule interface in the oracle.jbo package. This interface defines the names and signatures of methods that clients can use while working with the application module, but it does not include any specifics about the implementation of that functionality. The class that implements the base functionality of the application module component resides in the oracle.jbo.server package and is named ApplicationModuleImpl.

Figure 3-4 ADF Business Components Separate Interface and Implementation

Separation of interface and implementation

3.5.5 Package Naming Conventions

Since ADF Business Components is implemented in Java, the components of your application (including their classes, interfaces, and metadata files) will also be organized into packages.

To ensure that your components won't clash with reusable components from other organizations, choose package names that begin with your organization's name or web domain name. So, for example, the Apache organization chose org.apache.tomcat for a package name related to its Tomcat web server, while Oracle picked oracle.xml.parser as a package name for its XML parser. Components you create for your own applications might reside in packages with names like com.yourcompany.yourapp and subpackages of these.

As a specific example, the ADF Business Components that make up the main business service for the Fusion Order Demo application are organized into the oracle.fodemo.storefront package and its subpackages. As shown in Figure 3-5, these components reside in the StoreFrontService project in the StoreFrontModule application, and are organized broadly as follows:

  • oracle.fodemo.storefront.account.queries contains the view objects used in the customer registration process

  • oracle.fodemo.storefront.client contains test client .java files

  • oracle.fodemo.storefront.entities contains the entity objects

  • oracle.fodemo.storefront.lookups contains static data view objects and the LookupServiceAM shared application module

  • oracle.fodemo.storefront.store.queries contains the view objects used to manage the storefront

  • oracle.fodemo.storefront.store.service contains the StoreServiceAM application module

Figure 3-5 Organization of ADF Business Components in the Fusion Order Demo Application

Application Navigator and model layer

In your own applications, you can choose any package organization that you believe best. In particular, keep in mind that you are not constrained to organize components of the same type into a single package.

Because JDeveloper supports component refactoring, you can easily rename components or move them to a different package at any time. This flexibility allows you to easily incorporate inevitable changes into the application as your application evolves.

There is no optimal number of components in a package. However, with experience, you'll realize that the best structure for your team falls somewhere between the two extremes of placing all components in a single package and placing each component in its own, separate package.

One thing to consider is that the project is the unit of granularity that JDeveloper supports for reuse in other data model projects. So, you might factor this consideration into how you choose to organize components. For more information, see Section 38.3, "Packaging a Reusable ADF Component into an ADF Library."

3.5.6 Metadata with Optional Custom Java Code

Each kind of component in ADF Business Components comes with built-in runtime functionality that you control through declarative settings. These settings are stored in an XML component definition file with the same name as the component that it represents. When you need to write custom code for a component, for example to augment the component's behavior, you can enable an optional custom Java class for the component in question. Figure 3-6 shows how the Application Navigator displays the XML component definition and optional custom Java class for an application module.

Figure 3-6 Application Navigator Displays Component XML File and Optional Class Files

Application Navigator with component files

3.5.6.1 Example of an XML-Only Component

Figure 3-7 illustrates the XML component definition file for an application-specific component like an application module named YourService that you create in a package named com.yourcompany.yourapp. The corresponding XML component definition resides in a ./com/yourcompany/yourapp subdirectory of the data model project's source path root directory. That XML file records the name of the Java class it should use at runtime to provide the application module implementation. In this case, the XML records the name of the base oracle.jbo.server.ApplicationModuleImpl class provided by Oracle ADF.

Figure 3-7 XML Component Definition File for an Application Module

Component definition file for application module

When used without customization, your component is completely defined by its XML component definition and it will be fully functional without custom Java code or even a Java class file for the component. If you have no need to extend the built-in functionality of a component in ADF Business Components, and no need to write any custom code to handle its built-in events, you can use the component in this XML-only fashion.

3.5.6.2 Example of a Component with Custom Java Class

When you need to add custom code to extend the base functionality of a component or to handle events, you can enable a custom Java class for any of the key types of ADF Business Components you create. You enable the generation of custom classes for a component on the Java page of its respective overview editor in JDeveloper. When you enable this option, JDeveloper creates a Java source file for a custom class related to the component whose name follows a configurable naming standard. This class, whose name is recorded in the component's XML component definition, provides a place where you can write the custom Java code required by that component. Once you've enabled a custom Java class for a component, you can navigate to it using a corresponding Go To componentName Class option in the component's Application Navigator context menu.

Figure 3-8 illustrates what occurs when you enable a custom Java class for the YourService application module. A YourServiceImpl.java source code file is created in the same source path directory as your component's XML component definition file. The YourServiceImpl.xml file is updated to reflect the fact that at runtime the component should use the com.yourcompany.yourapp.YourServiceImpl class instead of the base ApplicationModuleImpl class.

Figure 3-8 Component with Custom Java Class

Component with custom Java class

Note:

The examples in this guide use default settings for generated names of custom component classes and interfaces. If you want to change these defaults for your own applications, use the ADF Business Components: Class Naming page of the JDeveloper Preferences dialog. Changes you make only affect newly created components.

3.5.7 Basic Data Types

The Java language provides a number of built-in data types for working with strings, dates, numbers, and other data. When working with ADF Business Components, you can use these types, but by default you'll use an optimized set of types in the oracle.jbo.domain and oracle.ord.im packages. These types, shown in Table 3-1, allow data accessed from the Oracle database to remain in its native, internal format. You will achieve better performance using the optimized data types provided by ADF Business Components by avoiding costly type conversions when they are not necessary.

There are two cases where an optimized data type is not used by default and a Java built-in data type is used instead. To work with string-based data, by default ADF Business Components uses the regular java.lang.String type. Additionally, to work with numeric data, by default ADF Business Components uses the java.math.BigDecimal type, which formats numerals in a way that is consistent with the alignment expected by ADF Faces components. For backward compatibility, and for applications that do not use ADF Faces components, the optimized data type oracle.jbo.domain.Number provided in previous releases remains an alternative data type for numeric data.

Table 3-1 Basic Data Types in the oracle.jbo.domain and oracle.ord.im Packages

Data Type Package Represents

Number (not used by default)

oracle.jbo.domain

Any numerical data. By default, ADF Business Components uses the java.math.BigDecimal type to support formatting of numeric values with the alignment expected by ADF Faces components. The java.math.BigDecimal type should be used whenever ADF Faces is the chosen view layer technology.

Date

oracle.jbo.domain

Date with optional time

DBSequence

oracle.jbo.domain

Sequential integer assigned by a database trigger

RowID

oracle.jbo.domain

Oracle database ROWID

Timestamp

oracle.jbo.domain

Timestamp value

TimestampTZ

oracle.jbo.domain

Timestamp value with time zone information

TimestampLTZ

oracle.jbo.domain

Timestamp value with local time zone information retrieved from JavaVM or from the ADF Context when configured in the application's adf-config.xml with an EL expression:

<user-time-zone-config xmlns=
  "http://xmlns.oracle.com/adf/usertimezone/config">
  <user-timezone expression= "EL exp" />
</user-time-zone-config>

The EL expression will be evaluated to determine the time zone of the current user; otherwise, the value defaults to the time zone of the JavaVM.

BFileDomain

oracle.jbo.domain

Binary File (BFILE) object

BlobDomain

oracle.jbo.domain

Binary Large Object (BLOB)

ClobDomain

oracle.jbo.domain

Character Large Object (CLOB)

OrdImageDomain

oracle.ord.im

Oracle Intermedia Image (ORDIMAGE)

OrdAudioDomain

oracle.ord.im

Oracle Intermedia Audio (ORDAUDIO)

OrdVideoDomain

oracle.ord.im

Oracle Intermedia Video (ORDVIDEO)

OrdDocDomain

oracle.ord.im

Oracle Intermedia Document (ORDDOC)

Struct

oracle.jbo.domain

User-defined object type

Array

oracle.jbo.domain

User-defined collection type (e.g. VARRAY)


Note:

If you are not using ADF Faces as your view layer technology, you may use either the java.math.BigDecimal type or the oracle.jbo.domain.Number type. Be aware, however, that the oracle.jbo.domain.Number class has the same class name as the built-in java.lang.Number type. Since the Java compiler implicitly imports java.lang.* into every class, you will need to explicitly import the oracle.jbo.domain.Number class into any class that references it. Typically, JDeveloper will follow this practice for you, but if you receive compiler or runtime errors related to "Number is an abstract class" it means you are using java.lang.Number instead of oracle.jbo.domain.Number. Adding the:
import oracle.jbo.domain.Number;

line at the top of your class, after the package line, prevents these kinds of errors.

3.5.8 Generic Versus Strongly-Typed APIs

When working with application modules, view objects, and entity objects, you can choose to use a set of generic APIs or you can have JDeveloper generate code into a custom Java class to enable a strongly-typed API for that component. For example, when working with an view object, if you wanted to access the value of an attribute in any row of its result, the generic API would look like this:

Row row = ordersVO.getCurrentRow();
Date shippedDate = (Date)row.getAttribute("OrderShippedDate");

Notice that using the generic APIs, you pass string names for parameters to the accessor, and you have to cast the return type to the expected type, as with Date shown in the example.

Alternatively, when you enable the strongly typed style of working you can write code like this:

OrdersRow row = (OrdersRow)ordersVO.getCurrentRow();
Date shippedDate = row.getOrderShippedDate();

In this case, you work with generated method names whose return type is known at compile time, instead of passing string names and having to cast the results. Typically, it is necessary to use strongly typed accessors when you need to invoke the methods from the business logic code without sacrificing compile-time safety. This can also be useful when you are writing custom validation logic in setter methods, although in this case, you may want to consider using Groovy expressions instead of generating entity and view row implementation classes for Business Components. Subsequent chapters explain how to enable this strongly typed style of working by generating Java classes for business logic that you choose to implement using Java.

3.5.9 Custom Interface Support for Client-Accessible Components

Only these components of the business service as visible to the client:

  • Application module, representing the service itself

  • View objects, representing the query components

  • View rows, representing each row in a given query component's results

The entity objects in the business service implementation is intentionally not designed to be referenced directly by clients. Instead, clients work with the data queried by view objects as part of an application module's data model. Behind the scenes, the view object cooperates automatically with entity objects in the business services layer to coordinate validating and saving data that the user changes. For more information about this runtime interaction, see Section 6.3.9, "What Happens at Runtime: How View Objects and Entity Objects Cooperate."

3.5.9.1 Framework Client Interfaces for Components

The Java interfaces of the oracle.jbo package provide a client-accessible API for your business service. This package intentionally does not contain an Entity interface, or any methods that would allow clients to directly work with entity objects. Instead, client code works with interfaces like:

  • ApplicationModule, to work with the application module

  • ViewObject, to work with the view objects

  • Row, to work with the view rows

3.5.9.2 Custom Client Interfaces for Components

When you begin adding custom code to your ADF business components that you want clients to be able to call, you can "publish" that functionality to clients for any client-visible component. For each of your components that publishes at least one custom method to clients on its client interface, JDeveloper automatically maintains the related Java interface file. So, assuming you were working with an application module like StoreServiceAM in the Fusion Order Demo application, you could have custom interfaces like:

  • Custom application module interface

    StoreServiceAM extends ApplicationModule
    
  • Custom view object interface

    OrderItemsInfo extends ViewObject
    
  • Custom view row interface

    OrderItemsInfoRowClient extends Row
    

Client code can then cast one of the generic client interfaces to the more specific one that includes the selected set of client-accessible methods you've selected for your particular component.

3.6 Overview of Groovy Scripting Language Support

Groovy is a scripting language with Java-like syntax for the Java platform. The Groovy scripting language simplifies the authoring of code by employing dot-separated notation, yet still supporting syntax to manipulate collections, Strings, and JavaBeans. Groovy language expressions in ADF Business Components differs from the Java code that you might use in a Business Components custom Java class because Groovy expressions are executed at runtime, while the strongly typed language of Java is executed at compile-time. Additionally, because Groovy expressions are dynamically compiled, they are stored in the XML definition files of the business components where you use it.

ADF Business Components supports the use of the Groovy scripting language in places where access to entity object and view object attributes is useful, including attribute validators (for entity objects), attribute default values (for either entity objects or view objects), transient attribute value calculations (for either entity objects or view objects), bind variable default values (in view object query statements and view criteria filters), and placeholders for error messages (in entity object validation rules). Additionally, ADF Business Components provides a limited set of built-in keywords that can be used in Groovy expressions.

Specifically, the ADF Business Components framework provides support for the use of Groovy language expressions to perform the following tasks:

To perform these tasks in JDeveloper, you use expression editor dialogs that are specific to the task. For example, when you want to create a default value for a transient view object attribute, you use the attribute's Edit Expression Editor dialog to enter an expression that determines a runtime value for the attribute. The same dialog also lets you specify when the value should be calculated (known as a recalculate condition), as shown in Figure 3-9.

Figure 3-9 Dialog to Edit Expression for Default Attribute Values

Expression editor for attribute value

Additionally, the overview editor that you use to edit entity objects and view objects displays the Business Rules page, where you can view and edit all expressions used by a single business component. For example, the Business Rules page that you display for a view object lets you view all expressions that the view object uses on its view accessors, bind variables, and attributes. You can filter the display to show only those items with Groovy expressions defined, as shown in Figure 3-10. Although expressions cannot be verified at design time, all expression editors let you test the syntax of the expression before you save it.

Figure 3-10 Overview Editor's Business Rules Page Shows All Expressions Used by a Business Component

Business Rules page for a view object

For more information about the Groovy language, refer to the following web site:

3.6.1 Referencing Business Components Objects in Groovy Expressions

There is one top-level object named adf that allows you access to objects that the framework makes available to the Groovy script. When you reference an Oracle ADF object in a Groovy expression, the Oracle ADF runtime returns wrapper objects that do not correspond to the actual concrete type of the classes. These wrapper objects support all of the method and field types of the wrapped object. Your expressions can use wrapped objects as if they were the actual object. Note, however, any attempt to cast wrappered objects to its concrete type will fail with a ClassCastException. In general, when working with the Groovy language it is not necessary to use explicit casting, and in the case of these wrapped ADF Business Components objects, doing so will cause an exception.

The accessible Oracle ADF objects consist of the following:

  • adf.context - to reference the ADFContext object

  • adf.object - to reference the object on which the expression is being applied (which can also be referenced using the keyword object, without the adf prefix). Other accessible member names come from the context in which the Groovy script is applied.

    • Entity object attributes: The context is an instance of the entity implementation class. Through this object you can reference custom methods of the custom entity implementation class, any methods defined by the base implementation class as specified by the JavaDoc for EntityImpl, and you can reference the attributes of the entity instance.

    • Entity object script validation rules: The context is the validator object (JboValidatorContext) merged with the entity on which the validator is applied. For details about keywords that you can use in this context, see Section 3.6.2.1, "Referencing Members of the Same Business Component."

    • View object attributes: The context is an instance of the view row implementation class. Through this object, you can reference custom methods of the custom view row implementation class, any methods defined by the base implementation class as specified by the JavaDoc for ViewRowImpl, and you can reference the attributes of the view row instance as defined by the query row set.

    • Bind variable in view objects: The context is the variable object itself not the view row. You can reference the structureDef property to access other information as well as the viewObject property to access the view object in which the bind variable participates. However, access to view object attributes is not supported.

    • Bind variable in view accessors: The context is the current view row. The view accessor with bind variable is used to create a cascading List of Value (LOV). The view accessor can derive Groovy-driven values from the current view row in the view accessor view object used to formulate the list of valid choices.

    • Transient attributes: The context is the current entity or view row. You can reference attributes by name in the entity or view row in which the attribute appears, as well as public methods on that entity or view row. To access methods on the current object, you must use the object keyword to reference the current object (for example, object.methodName( )). The object keyword is equivalent to the this keyword in Java. Without it, in transient expressions, the method will be assumed to exist on the dynamically compiled Groovy script object itself.

  • adf.error - in validation rules, to access the error handler that allows the validation expression to generate exceptions or warnings

  • adf.userSession - returns a reference to the ADF Business Components user session (which you can use to reference values in the userData hashmap that is part of the session)

You can also reference the current date (time truncated) or current date and time using the following expressions:

  • adf.currentDate

  • adf.currentDateTime

3.6.2 Referencing Custom Business Components Methods and Attributes in Groovy Expressions

Groovy script language simplifies the authoring of code that you might write to access methods and attributes of your entity object and view objects.

3.6.2.1 Referencing Members of the Same Business Component

The simplest example of referencing business component members, including methods and attributes that the entity object and view object define, is to reference attributes that exist in the same entity object or view object as the attribute that you apply the expression.

For example, you could define a Groovy expression to calculate the value of a transient attribute AnnualSalary on an entity object with an attribute Sal that specifies the employee's monthly salary:

Sal * 12

Or, with Groovy you can write a simple validation rule to compare the attributes of a single view object using syntax like:

PromotionDate > HireDate

Using Java, this same comparison would look like:

((Date)getAttribute("PromotionDate")).compareTo((Date)getAttribute("HireDate")) > 0

Note that the current object is passed in to the script as the this object, so you can reference an attribute in the current object by simply using the attribute name. For example, in an attribute-level or entity-level Script Expression validator, to refer to an attribute named "HireDate", the script can simply reference HireDate.

Similar to referencing attributes, when you define custom methods in an entity implementation class, you can invoke those methods as part of your expression. For example, to define an attribute default value:

adf.object.getDefaultSalaryForGrade()

A method reference requires the prefix adf.object which allows you to reference the same entity that defines the attribute on which the expression is applied. This same prefix also allows you to reference the methods of the base class of the entity implementation class (EntityImpl.java) that your custom implementation class extends.

Note that when you want to reference the method of an entity implementation class in a validation rule, you use the source prefix:

source.getDefaultSalaryForGrade()

Use of the source prefix is necessary in validators because the object keyword implies the validation rule object instead of the entity object (where the method is defined).

To allow you to reference members of the validator object (JboValidatorContext), you can use these keywords in your validation rule expression:

  • newValue: in an attribute-level validator, to access the attribute value being set

  • oldValue: in an attribute-level validator, to access the current value of the attribute being set

For example, you might use the following expression to specify a dynamic validation rule check of the salary for a salesman.

if (Job == "SALESMAN")
{
  return newValue < source.getMaxSalaryForGrade(Job)
}
else
return true

3.6.2.2 Referencing Members of Other Business Components

You can also reference the methods and attributes that entity objects and view objects defines in the expressions you apply to a different entity object attribute or validation rule. This is accomplished by referencing the accessor in the entity association.

For example, if you define an entity with a master-detail association for Dept and Emp, by default the accessor for the entity association will be named Dept and Emp, to identity the source and destination data source. Using that accessor in a Groovy expression to set the default value for a new employee's salary based on the location of their department:

adf.object.getDefaultSalaryForGrade(Dept.Loc)

This expression does not reference the entity even though it has the same name (Dept) as the accessor for the association. Instead, assuming a master-detail relationship between departments and employees, referencing the accessor allows the Groovy expression for the employee entity object to walk back to the master department entity and pass in the value of Loc from that master.

3.6.3 Manipulating Business Component Attribute Values in Groovy Expressions

You can use the following built-in aggregate functions on Oracle Business Components RowSet objects:

  • rowSetAttr.sum(GroovyExpr)

  • rowSetAttr.count(GroovyExpr)

  • rowSetAttr.avg(GroovyExpr)

  • rowSetAttr.min(GroovyExpr)

  • rowSetAttr.max(GroovyExpr)

These aggregate functions accept a string-value argument that is interpreted as a Groovy expression that is evaluated in the context of each row in the row set as the aggregate is being computed. The Groovy expression must return a numeric value (or number domain).

For example, in a Dept entity object you could add a transient attribute that displays the sum of all employee salaries that is calculated by this expression:

EmployeesInDept.sum("Sal")

To reference the employees of a specific department, the expression supplies the name of the master-detail association's accessor for the destination Emp entity. In this case, the accessor is EmployeesInDept and salary is interpreted for each record of the Emp entity object.

Or, assume that you want the calculation of the salary total for specific departments to include each employee's benefits package, which varies with job role:

EmployeesInDept.sum("Sal + adf.object.getBenefitsValue(Job)")