As Published In
Oracle Magazine
January/February 2005

DEVELOPER: Frameworks


Forms Functionality in J2EE

By Steve Muench Oracle ACE

Leverage your Oracle Forms skills in J2EE frameworks.

If you are a veteran Oracle Forms user, you're already well versed in leveraging a visual, declarative, framework-based tool to get your job done. Without thinking twice, you use the Oracle Forms Builder to create instances of application-building objects—forms, data blocks, relations, list of values (LOVs), RecordGroups, and so on—and use wizards and a property palette to configure the declarative settings that control their behavior. Oracle Forms runtime provides a ready-to-use implementation of all these base components; configures each component from relevant FMX-file metadata at runtime; and invokes, as appropriate, the PL/SQL triggers you've written to augment or change the declaratively configured default behavior.

You never write code to implement low-level details such as parsing and executing SQL statements, fetching data as it's needed, creating WHERE clauses to implement query by example, locking rows, detecting lost updates, or coordinating master/detail relations. The Oracle Forms framework implements all of that for you. You just work on code the framework cannot provide automatically: your application-specific business logic and desired user interface interactions.

Oracle JDeveloper 10g and Oracle Application Development Framework (ADF) exactly mirror this style of framework-based development that you've already mastered. You use the Oracle JDeveloper 10g Integrated Development Environment (IDE) as your builder tool to create instances of application building objects, and you use wizards and a property palette to configure the declarative settings that control their behavior. Oracle ADF runtime provides a ready-to-use implementation of all these base components, configures each component from relevant XML metadata at runtime, and triggers the invocation of the custom Java methods you've written to augment or change the declaratively configured default behavior.

As with Oracle Forms Runtime, when you use Oracle ADF for your J2EE development, you focus on business logic and user interface handling but not on low-level implementation details. The Oracle ADF components you use to build your solution already cooperate to implement all of the best-practice J2EE design patterns required to build a real-world J2EE business application that can be deployed to any J2EE-compliant application server.

Separating UI and Application Data

In Oracle Forms, each form contains visual objects, such as canvases, windows, alerts, and LOVs, as well as nonvisual objects, such as data blocks, relations, and record groups. Individual data block items have visual properties, such as Foreground Color and Bevel , as well as nonvisual properties, such as Data Type and Maximum Length . Even the various event-handling triggers that Oracle Forms defines fall into visual and nonvisual categories. For example, it's clear that triggers such as WHEN-BUTTON-PRESSED and WHEN-MOUSE-CLICKED are visual in nature, relating to the front-end UI, and that triggers such as WHEN-VALIDATE-ITEM and ON-INSERT are related more closely to back-end data processing.

Although having visual and nonvisual aspects merged in application objects and triggers simplifies the learning curve, 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 back-end business logic and easier to repurpose back-end business logic in multiple forms.

In order to understand this separation of UI and data, imagine cutting an Oracle Forms-created form as you know it today in half, keeping only its nonvisual, data-related aspects. What's left would simply be 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. This part of the original form would be a kind of a smart data service or a generic application module , exposing a data model of business information and enforcing business logic but containing no user interface elements. The goal of separating this application module from anything visual would be to allow any kind of user interface you need in the future to use it.

Let's focus 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 us that we need to filter, join, order, and group data for our end users in many different ways, depending on the task at hand. On the other hand, the validation rules we apply to our 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 data is manipulated by users in our applications.

Enabling this flexibility requires further factoring of our data block functionality. We need one kind of object to represent each of the many different SQL queries defining the views of data we require. We also need an object to represent a business entity that enforces business rules and communicates changes to our base table in a consistent way. By splitting things like this, we can have multiple different query objects interact with the same underlying business entity when their SQL queries present the same business data.

Meet the ADF Business Components

Oracle ADF breathes life into this UI/data separation, by providing ready-to-use Java components for your J2EE applications that implement the Oracle Forms-inspired functionality you're familiar with, with responsibilities divided along cleanly separated functional lines:

  • The ApplicationModule component is the data-only part of the form we considered above. An application module is a smart data service containing a data model of master/detail-related queries your client interface needs to work with. It also provides a transaction and database connection used by the components it contains.

  • The EntityObject component implements both the validation and database changes parts of the data block functionality we considered above. Related to an underlying base table, an entity object is a component that represents your business domain entity and gives you a single place to encapsulate business logic related to validation, defaulting, and database modification behavior for that business object.

  • The ViewObject component handles the data-retrieval part 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 happens automatically. While defining a view object, you can link any of its query columns to underlying entity objects. The view object and entity object can then cooperate automatically for you at runtime to enforce your domain business logic, regardless of the business data needed by the user for the task at hand.

To get you off to a running start, you can use Oracle JDeveloper to generate Oracle ADF business components from existing Oracle Designer module component definitions or simply point the Business Components from Tables Wizard at a schema and pick the tables you want to work with. In no time, you can have an application module with a default master/detail data model of view objects related to underlying entity objects. Using the UML modelers, Oracle ADF object editors, or property palette, you can then begin to evolve these components, through a combination of declarative settings and additional custom Java code, into exactly what you need for implementing your business application functionality.

Even before you embark on creating your ideal application user interface with Oracle JDeveloper's various visual editors and diagrammers, you test your application module by using the built-in Business Components Tester tool. Anytime you need it, this tool visualizes your application module's data model in a tree control and, on demand, builds basic dynamic data entry forms you can use to exercise all of your application module's data blocks—that is, its view object queries and their underlying entity objects—working against your real application data. Using this tool helps you quickly appreciate how your application module, view object, and entity object components cooperate to provide the basic features of Oracle Forms Runtime without requiring any user-written code.

Familiar Tasks with a Java Twist

As you use Oracle JDeveloper to create your own application modules, view objects, and entity objects, the builder creates the necessary Java class files and XML metadata that store their declarative settings. Each component in your application is a class that inherits its default behavior from an appropriate Oracle ADF framework component. You customize the default inherited behavior by writing Java code in your component's own class file that augments or overrides the default component behavior.

Because Java classes support inheritance of both properties and behavior, writing a Java "trigger" to customize the behavior of your own Oracle ADF components boils down to overriding a well-defined method name from the component's superclass —the class from which your application module, view object, or entity object component inherits its behavior. Instead of having special do-the-right-thing built-in routines—as Oracle Forms has—in Java, an overridden method simply invokes its superclass's method to have it perform the behavior it would have performed if your overridden method had not been present. Accordingly, overriding an Oracle ADF component's method to augment or change its default behavior ends up looking like the code in Listing 1.

Code Listing 1: Java code overriding an Oracle ADF component's method

 

/**
 * Your entity object class extends the base
 * ADF entity class EntityImpl to inherit its
 * default functionality. Methods of the same
 * signature in your class override those in
 * the superclass.
 */ 
public class YourBusinessEntityImpl extends EntityImpl {
  /**
   * Example of an overridden framework method.
   *
   * ADF invokes (or "triggers") the create()
   * method on an entity object just after a
   * new instance is created.
   */
   public void create(AttributeList attrs) {
    /* "pre-create"
     *  Do something before calling the superclass
     *  For example "peeking" at or "poking" values
     *  into the initial attribute list.
     */
                         /* "on-create"
    super.create(attrs);  * Avoid calling the superclass 
                          * to change default behavior
                          */ 
    /* "post-create"
     *  Do something after calling the superclass
     *  For example, complex defaulting logic
     */
  }
}


The create() method in Listing 1 is just one of several useful methods in an entity object class. In Java, each class is responsible for its own actions and encapsulates the implementation of several useful operations it can perform.

 

Next Steps


READ
more about Oracle JDeveloper 10g and Oracle ADF
 oracle.com/technology/products/jdev
 amazon.com/exec/obidos/ASIN/0072255838

 DOWNLOAD Oracle JDeveloper 10g

Instead of a library of built-in routines that run the gamut from ABORT_QUERY and GO_BLOCK to SET_ITEM_PROPERTY and WRITE_IMAGE_FILE , your application functionality breaks down naturally into separate objects in Java, with each object offering only its own relevant methods. For example, you would write code in Oracle Forms to set a property of a data block at runtime like this:

 

 
SET_BLOCK_PROPERTY('blockname', MAX_RECORDS_FETCHED,25);


Using an Oracle ADF view object in Java, you would call a similar method directly on an instance of the view object like this: 

someViewObject.setMaxFetchSize(25);


Neatly packaging our application functionality into distinct classes that each focus on doing a particular task well and can be extended to address new requirements demonstrates that Java-based development can be seriously empowering.

What's Next?

Now that you understand the basics of how Oracle ADF components deliver a reusable Java implementation of the familiar data-handling functionality you love in Oracle Forms, I'll cover the most commonly used framework features in my next column and delve a bit farther beneath the surface to explore some of the unique benefits of working with a Java-based application-building framework. In the meantime, if you haven't already downloaded Oracle JDeveloper 10g, visit oracle.com/technetwork/products/jdev for software, tutorials, and samples. If you prefer the company of a good third-party book to help you as you start out, I recommend the Oracle JDeveloper 10 g Handbook , by Faderman, Koletzke, and Dorsey (Oracle Press, 2004), ISBN: 0072255838.


Steve Muench is a consulting product manager for Oracle JDeveloper. In his more than 15 years at Oracle, he has supported and developed Oracle tools and XML technologies and continues to evangelize them. He authored Building Oracle XML Applications (O'Reilly & Associates, 2000) and shares tips and tricks on OTN and his "Dive into BC4J and ADF" Weblog.


Send us your comments