Oracle® Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework 11g Release 1 (11.1.1) B31974-03 |
|
![]() Previous |
![]() Next |
This chapter provides an overview of the ADF Business Components layer of Oracle ADF, including a description of the key features they provide for building your business services.
This chapter includes the following sections:
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.
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:
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 domain object layer
Automatically validate and save any changes to the database
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
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
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
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
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.
ADF Business Components provides components that implement functionality similar to that offered by enterprise 4GL tools. Several key components in ADF Business Components map to concepts that you may be familiar with in other 4GL tools.
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 ADF addresses the UI/data split above 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
JDeveloper includes comprehensive design time support for ADF Business Components. Collectively, these facilities let you create, edit, diagram, test, and refactor the business components.
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 or to create a new application resource connection by copying an existing IDE-level connection.
Since this dialog appears before you create your first business component, you also use it to globally control the SQL flavor that the view objects will use to formulate SQL statements. Although the default for an Oracle database connection is always the Oracle SQL flavor, other SQL flavors 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.
The dialog also 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 Type Map setting to the Oracle type map and will use the optimized types in the oracle.jbo.domain
package. You can change this setting to globally use only the basic Java data types.
Note: If you plan to have your application run against both Oracle and non-Oracle databases, you should select the SQL92 SQL flavor when you begin building your application, not later. While this sacrifices using some of the Oracle-specific optimizations that are inherent in using the Oracle SQL flavor, it makes the application portable to both Oracle and non-Oracle databases. |
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.
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.
Once a component exists, you can edit it using the respective overview editor that you access either by double-clicking on 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.
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.
Once you have created an application module component, you can test it interactively using the built-in Business Component Browser. To launch the Business Component Browser, 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 Business Component Browser 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.
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.
One of the key simplifying benefits of using ADF Business Components for your business service implementation is the application module's support for a "UI-aware 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 "UI aware" because your UI components will automatically update to reflect any changes to the row sets of these business objects
Thus, the UI-aware data model represents a solution that works across application technology layers to ensure that the UI and data model remain synchronized.
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. This active data notification also extends to custom business service methods that happen to produce changes to the data model.
Under the covers, the application module component implements a set of generic service methods that allow users to leverage its UI-aware 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. Because the data model is UI-aware, your UI components will be bound declaratively to view objects in the data model and to custom business service methods.
Without a UI-aware data model, you would need to write more code in the client 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 UI-aware 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 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 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.
Because the application module supports the UI-aware 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.
Before you begin implementing specific ADF business components, it is a good idea to have some familiarity with the Oracle ADF business services layer's design and implementation.
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 the ADF Business Components layer, 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 30.5, "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 36.3, "Customizing Framework Behavior with Extension Classes".
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 Flavor, and Type Map". However, applications that target Oracle databases will find numerous optimizations built into ADF Business Components.
The ADF Business Components layer 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 F, "ADF Business Components Java EE Design Pattern Catalog".
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
Figure 3-3 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
.
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-4, 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
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 correct number for the optimal number of components in a package. However, with experience, you'll realize that the correct 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 package in ADF Business Components 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 36.7, "Working with Libraries of Reusable Business Components".
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-5 shows how the Application Navigator displays the XML component definition and optional custom Java class for an application module.
Figure 3-6 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.
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.
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-7 illustrates what occurs when you enable a custom Java class for the YourService
application module considered above. 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.
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 Business Components: Class Naming page of the JDeveloper Preferences dialog. Changes you make only affect newly created components. |
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. To work with string-based data, by default ADF Business Components uses the regular java.lang.String
type.
Table 3-1 Basic Data Types in the oracle.jbo.domain and oracle.ord.im Packages
Data Type | Package | Represents |
---|---|---|
|
|
Any numerical data |
|
|
Date with optional time |
|
|
Sequential integer assigned by a database trigger |
|
|
Oracle database ROWID |
|
|
Timestamp value |
|
|
Timestamp value with time zone information |
|
|
Timestamp value with Local time zone information |
|
|
Binary File (BFILE) object |
|
|
Binary Large Object (BLOB) |
|
|
Character Large Object (CLOB) |
|
|
Oracle Intermedia Image (ORDIMAGE) |
|
|
Oracle Intermedia Audio (ORDAUDIO) |
|
|
Oracle Intermedia Video (ORDVIDEO) |
|
|
Oracle Intermedia Document (ORDDOC) |
|
|
User-defined object type |
|
|
User-defined collection type (e.g. |
Note: Theoracle.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 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 when you begin to write more custom code of your own, you'll learn to recognize compiler or runtime errors related to "Number is an abstract class" as indicating that you are inadvertently 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 |
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.
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 domain layer to coordinate validating and saving data that the user changes. For more information about this runtime interaction, see Section 6.3.8, "What Happens at Runtime: When View Objects and Entity Objects Cooperate".
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
When you begin adding custom code to your Oracle 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.
Groovy is a scripting language for the Java platform with Java-like syntax. Because it is dynamically compiled, Groovy script can be stored inline in XML files to enable customization after deployment. And the Groovy language simplifies the authoring of code by employing dot-separated notation.
For example, with Groovy you can use simplified syntax like:
PromotionDate > HireDate
rather than:
((Date)getAttribute("PromotionDate")).compareTo((Date)getAttribute("HireDate")) > 0
in a validation rule.
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
.
There is one top-level object named adf
that allows you access to objects that the framework makes available to the Groovy script. 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)
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
Other accessible member names come from the context in which the Groovy script is applied.
Bind variable: The context is the variable object itself. 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.
Transient attribute: 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.
Script Expression validation rule: The context is the validator object (JboValidatorContext
) merged with the entity on which the validator is applied. You can reference keywords like the following:
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
source
: to access the entity on which the validator is applied in order to invoke methods on it (accessing the value of an attribute in the entity does not require the source
keyword)
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 rowset as the aggregate is being computed. The Groovy expression must return a numeric value (or number domain). For example:
employeesInDept.sum("Sal")
or
employeesInDept.sum("Sal!=0?Sal:0 + Comm!=0?Comm:0")
The ADF Business Components framework provides support for the use of Groovy to perform the following tasks:
Define an Script Expression validator or Compare validator (see Section 7.5, "Using Groovy Expressions For Validation and Business Rules")
Define error message tokens for handling validation failure (see Section 7.7.4, "How to Embed a Groovy Expression in an Error Message")
Handle conditional execution of validators (see Section 7.7.3, "How to Conditionally Raise Error Messages Using Groovy")
Set the default value of a bind variable in the view object query statement (see Section 5.10, "Working with Bind Variables")
Set the default value of a bind variable that specifies a criteria item in the view criteria statement (see Section 5.11, "Working with Named View Criteria").
Define the default value for an entity object attribute (see Section 4.10.6, "How to Define a Static Default Value")
Calculate the value of a transient attribute of an entity object or view object (see Section 4.14, "Adding Transient and Calculated Attributes to an Entity Object" and Section 5.14, "Adding Calculated and Transient Attributes to a View Object")
For more information about the Groovy language, refer to the following websites: