Skip Headers
Oracle® Application Development Framework Developer's Guide
10g Release 3 (10.1.3.0)

Part Number B28967-02
Go to Documentation Home
Home
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

1 Introduction to Oracle ADF Applications

This chapter describes the architecture and key functionality of the Oracle Application Development Framework and highlights the typical development process for using JDeveloper 10g Release 3 (10.1.3) to build web applications using Oracle ADF, Enterprise JavaBeans, Oracle TopLink, and JSF.

This chapter includes the following sections:

1.1 Overview of Oracle Application Development Framework

The Oracle Application Development Framework (Oracle ADF) is an end-to-end application framework that builds on J2EE standards and open-source technologies to simplify and accelerate implementing service-oriented applications. If you develop enterprise solutions that search, display, create, modify, and validate data using web, wireless, desktop, or web services interfaces, Oracle ADF can simplify your job. Used in tandem, Oracle JDeveloper 10g and Oracle ADF give you an environment that covers the full development lifecycle from design to deployment, with drag-and-drop data binding, visual UI design, and team development features built-in.

1.1.1 Framework Architecture and Supported Technologies

In line with community best practices, applications you build using Oracle ADF achieve a clean separation of concerns by adhering to a model, view, controller architecture. Figure 1-1 illustrates where each ADF module fits in this architecture. The core module in the framework is Oracle ADF Model, a declarative data binding facility that implements the JSR-227 specification. The Oracle ADF Model layer enables a unified approach to bind any user interface to any business service with no code. The other modules Oracle ADF comprises are:

  • Oracle ADF Controller integrates Struts and JSF with Oracle ADF Model

  • Oracle ADF Faces offers a library of components for web applications built with JSF

  • Oracle ADF Swing extends Oracle ADF Model to desktop applications built with Swing

  • Oracle ADF Business Components simplifies building business services for developers familiar with 4GL tools like Oracle Forms.

Figure 1-1 Simple ADF Architecture

Figure shows simple ADF architecture.

1.1.1.1 View Layer Technologies Supported

In the view layer of your application, where you design the web user interface, you can develop using either classic JavaServer Pages (JSP) or the latest JavaServer Faces (JSF) standard. Alternatively, you can choose the polish and interactivity of a desktop UI, and develop using any off-the-shelf Swing components or libraries to ensure just the look and feel you need. Whatever your choice, you work with WYSIWYG visual designers and drag-and-drop data binding. One compelling reason to choose JSF is the comprehensive library of nearly one hundred JSF components that the ADF Faces module provides.

ADF Faces components include sophisticated features like look and feel "skinning" and the ability to incrementally update only the bits of the page that have changed using the latest AJAX programming techniques. The component library supports multiple JSF render kits to allow targeting users with web browsers and roaming users with PDA telnet devices. In short, these components dramatically simplify building highly attractive and functional web and wireless UIs without getting your hands "dirty" with HTML and JavaScript.

1.1.1.2 Controller Layer Technologies Supported

In the controller layer, where handling page flow of your web applications is a key concern, Oracle ADF integrates both with the popular Apache Struts framework and the built-in page navigation functionality included in JSF. In either case, JDeveloper offers visual page flow diagrammers to design your page flow, and the ADF Controller module provides appropriate plug-ins to integrate the ADF Model data binding facility with the controller layer's page processing lifecycle.

1.1.1.3 Business Services Technologies Supported by ADF Model

In the model layer, Oracle ADF Model implements the JSR-227 service abstraction called the data control and provides out-of-box data control implementations for the most common business service technologies. Whichever ones you employ, JDeveloper and Oracle ADF work together to provide you a declarative, drag-and-drop data binding experience as you build your user interfaces. Supported technologies include:

  • Enterprise JavaBeans (EJB) Session Beans

    Since most J2EE applications require transactional services, EJB session beans are a logical choice because they offer declarative transaction control. Behind the EJB session bean facade for your business service, you use plain old Java objects (POJOs) or EJB entity beans to represent your business domain objects. JDeveloper offers integrated support for creating EJB session beans, generating initial session facade implementations, and creating either Java classes or entity beans. You can also use Oracle TopLink in JDeveloper to configure the object/relational mapping of these classes.

  • JavaBeans

    You can easily work with any Java-based service classes as well, including the ability to leverage Oracle TopLink mapping if needed.

  • Web Services

    When the services your application requires expose standard web services interfaces, just supply Oracle ADF with the URL to the relevant Web Services Description Language (WSDL) for the service endpoints and begin building user interfaces that interact with them and present their results.

  • XML

    If your application needs to interact with XML or comma-separated values (CSV) data that is not exposed as a web service, this is easy to accomplish, too. Just supply the provider URL and optional parameters and you can begin to work with the data.

  • ADF Application Modules

    These service classes are a feature of the ADF Business Components module, and expose an updateable dataset of SQL query results with automatic business rules enforcement.

1.1.1.4 Recommended Technologies for J2EE Enterprise Developers

The remainder of this guide focuses attention on using Oracle ADF with the technologies Oracle recommends to J2EE developers building new web applications: JavaServer Faces for the view and controller layers, and the combination of an EJB session bean with mapped Java classes for the business service implementation. However, this chapter begins with a very simple Oracle ADF application built with these technologies to acquaint you with typical development process.

Note:

If you are a developer coming to J2EE development with experience in 4GL tools like Oracle Forms, Oracle Designer, Visual Basic, PowerBuilder, and so on, Oracle recommends that you take advantage of the additional declarative development features offered by the Oracle ADF Business Components module. Oracle ADF Developer's Guide for Forms/4GL Developers covers using Oracle ADF with additional framework functionality in the business services tier using this module. You can access the developer's guide for Forms/4GL developers from http://www.oracle.com/technology/products/adf/learnadf.html.

1.1.2 Declarative Development with Oracle ADF and JavaServer Faces

For seasoned Java developers, choosing to develop declaratively instead of coding admittedly takes some getting used to. However, most developers will acknowledge a true time-saver, and they are also likely to have some exposure to declarative techniques through their experience with frameworks like Spring or Apache Struts and tag libraries like the JSP Standard Tag Library (JSTL). JavaServer Faces incorporates similar declarative functionality and Oracle ADF complements it by adding declarative data binding to the mix.

1.1.2.1 Declarative J2EE Technologies You May Have Already Used

Using the Spring Framework, developers configure the instantiation of JavaBeans through a beans XML file, declaratively specifying dependencies between them. At runtime, generic framework code reads the XML file, instantiates the beans as directed, and resolves the dependencies between beans. This design pattern is commonly known as dependency injection, and Spring provides a declaratively configured way to leverage its generic implementation to set up your application's beans.

Using the Struts struts-config.xml file, developers configure the mapping of HTTP requests to action handler classes and other page flow information. At runtime, the generic Struts front-controller servlet uses the information contained in the configuration XML file to route the requests as directed. When you use Struts, you leave the request routing to the declaratively configured Struts infrastructure, and concentrate on writing the interesting code that will handle particular requests.

Using the JSTL tag library, developers indicate the model data to iterate over and present on the page using declarative expressions, as shown in this snippet:

<c:when test="${not empty UserList}">
  <c:forEach var="user" items="${UserList.selectedUsers}">
    <tr>
      <td><c:out value="${user.name}"/></td>
      <td><c:out value="${user.email}"/>
    </tr>
  </c:forEach>
</c:when>

Rather than resorting to an unmaintainable mix of Java scriptlet code and tags in their page, developers embed expressions like ${not empty UserList}, ${UserList.selectedUsers}, and ${user.name} into tag attributes. At runtime a generic expression evaluator returns the boolean-, List- and String-valued results, respectively, performing work to access beans and their properties without writing code. This same declarative expression language, nicknamed "EL," that originally debuted as part of the JSTL tag library has been improved and incorporated into the current versions of the JSP and JSF standards.

1.1.2.2 JSF Offers Dependency Injection, Page Handling, EL and More

JavaServer Faces simplifies building web user interfaces by introducing web UI components that have attributes, events, and a consistent runtime API. Instead of wading knee-high through tags and script, you assemble web pages from libraries of off-the-shelf, data-aware components that adhere to the JSF standard. As part of fulfilling their mission to simplify web application building, the industry experts who collaborated to design the JavaServer Faces standard incorporated numerous declarative development techniques. In fact, JSF supports all three of the facilities discussed above: instantiation and dependency injection for beans, page request handling and page navigation, and use of the standard expression language.

At runtime, the value of a JSF component is determined by its value attribute. While a component can have static text as its value, typically the value attribute will contain an EL expression that the runtime infrastructure evaluates to determine what data to display. For example, an outputText component that displays the name of the currently logged-in user might have its value attribute set to the expression #{UserInfo.name} to accomplish this. Since any attribute of a component can be assigned a value using an EL expression, it's easy to build dynamic, data-driven user interfaces. For example, you could hide a component when a collection of beans you need to display is empty by setting the component's rendered attribute to a boolean-valued EL expression like #{not empty UserList.selectedUsers}. If the list of selected users in the bean named UserList is empty, then the rendered attribute evaluates to false and the component disappears from the page.

To simplify maintenance of controller-layer application logic, JSF offers a declarative bean creation mechanism similar to the Spring Framework. To use it, you configure your beans in the JSF faces-config.xml file. They are known as "managed beans" since the JSF runtime manages instantiating them on demand when any EL expression references them for the first time. JSF also offers a declarative dependency injection feature. Managed beans can have managed properties whose runtime value is assigned by the JSF runtime based on a developer-supplied EL expression. Managed properties can depend on other beans that, in turn, also have managed properties of their own, and the JSF runtime will guarantee that the "tree" of related beans is created in the proper order.

As illustrated in Figure 1-2, JSF managed beans serve two primary roles.

Figure 1-2 Basic Architecture of a JSF Application

Figure shows basic architecture of a JSF application.

Request-scoped managed beans that are tightly related to a given page are known colloquially as "backing" beans, since they support the page at runtime with properties and methods. The relationship between a UI component in the page and the backing bean properties and methods is established by EL expressions in appropriate attributes of the component like:

  • value="#{expr}"

    References a property with data to display or modify

  • action="#{expr}"

    References a method to handle events

  • binding="#{expr}"

    References a property holding a corresponding instance of the UI component that you need to manipulate programmatically — show/hide, change color, and so on.

Think of managed beans that aren't playing the role of a page's backing bean simply as "application logic beans." They contain code and properties that are not specific to a single page. While not restricted to this purpose, they sometimes function as business service wrappers to cache method results in the controller layer beyond a single request and to centralize pre- or post-processing of business service methods that might be used from multiple pages.

In addition to using managed beans, you can also write application code in a so-called PhaseListener class to augment any of the standard processing phases involved in handling a request for a JSF page. These standard steps that the JSF runtime goes through for each page are known as the "lifecycle" of the page. Most real-world JSF applications will end up customizing the lifecycle by implementing a custom phase listener of some kind, typically in order to perform tasks like preparing model data for rendering when a page initially displays, among other things.

1.1.2.3 Oracle ADF Further Raises the Level of Declarative Development for JSF

The Oracle ADF Model layer follows the same declarative patterns as other J2EE technologies, by using XML configuration files to drive generic framework facilities. The only interesting difference is that ADF Model focuses on adding value in the data binding layer. It implements the two concepts in JSR-227 that enable decoupling the user interface technology from the business service implementation: data controls and declarative bindings.

Data controls abstract the implementation technology of a business service by using standard metadata interfaces to describe its public interface. This includes information about the properties, methods, and types involved. At design time, visual tools leverage the service metadata to let you bind your UI components declaratively to any public member of a data control. At runtime, the generic Oracle ADF Model layer reads the information describing your data controls and bindings from appropriate XML files and implements the two-way "wiring" that connects your user interface to your service. This combination enables three key benefits:

  • You write less code, so there are fewer lines to test and debug.

  • You work the same way with any UI and business service technologies.

  • You gain useful runtime features that you don't have to code yourself.

There are three basic kinds of binding objects that automate the key aspects of data binding that all enterprise applications require:

  • Action bindings invoke business service methods to perform a task or retrieve data.

  • Iterator bindings keep track of the current row in a data collection.

  • Attribute bindings connect UI components to attributes in a data collection.

Typically UI components like hyperlinks or buttons use action bindings. This allows the user to click on the component to invoke a business service without code. UI components that display data use attribute bindings. Iterator bindings simplify building user interfaces that allow scrolling and paging through collections of data and drilling-down from summary to detail information.

The group of bindings supporting the UI components on a page are described in a page-specific XML file called the page definition file. Generic bean factories provided by ADF Model use this file at runtime to instantiate the page's bindings. These bindings are held in a request-scoped Map called the binding container accessible during each page request using the EL expression #{bindings}. This expression always evaluates to the binding container for the current page. Figure 1-3 shows how EL value binding expressions relate the UI components in a page to the binding objects in the binding container.

Figure 1-3 Bindings in the Binding Container Are EL Accessible at Runtime

Bindings in binding container are EL accessible at runtime

Figure 1-4 illustrates the architecture of a JSF application when leveraging ADF Model for declarative data binding. When you combine Oracle ADF Model with JavaServer Faces, it saves you from having to write a lot of the typical managed bean code that would be required for real-world applications. In fact, many pages you build won't require a "backing bean" at all, unless you perform programmatic controller logic that can't be handled by a built-in action or service method invocation (which ADF Model can do without code for you). You can also do away with any application logic beans that wrap your business service, since the ADF Model's data control implements this functionality for you. And finally, you can often avoid the need to write any custom JSF phase listeners because ADF Model offers a generic JSF phase listener that performs most of the common operations you need in a declarative way based on information in your page definition metadata.

Figure 1-4 Architecture of a JSF Application Using ADF Model Data Binding

JSF application Architecture using ADF Model data binding

1.1.3 Key ADF Binding Features for JSF Development

With the fundamentals of ADF Model data binding for JSF applications described, it's time to describe the full breadth of added-value functionality that ADF Model brings to the table. The following sections give an overview of the key functional areas that further improve your development productivity.

1.1.3.1 Comprehensive JDeveloper Design-Time Support

JDeveloper's comprehensive design- time support for ADF Model declarative data binding includes:

  • Data Control Wizards

    Quickly create a data control for EJB session beans, Java service classes, web services, XML or CSV data from a URL, and ADF application modules. When additional information is required, helpful wizards guide you step by step.

  • Data Control Palette

    Visualize all business services that you have exposed as data controls and drag service properties, methods, method parameters, and method results to create appropriate bound user interface elements. Easily create read-only and editable forms, tables, master/detail displays, and individual bound UI components including single and multiselect lists, checkboxes, radio groups, and so on. Creating search forms, data creation pages, and parameter forms for invoking methods is just as easy. If your process involves collaboration with page designers in another team, you can drop attributes onto existing components in the page to bind them after the fact. In addition to the UI components created, appropriate declarative bindings are created and configured for you in the page definition file with robust undo support so you can experiment or evolve your user interface with confidence that your bindings and UI components will stay in sync.

  • Page Definition Editor

    Visualize page definition metadata in the Structure window and configure declarative binding properties using the appropriate editor or the Property Inspector. Create new bindings by inserting them into the structure where desired.

  • Binding Metadata Code Insight

    Edit binding metadata with context-sensitive, XML schema-driven assistance on the structure and valid values. Visualize page definition metadata in the Structure window and configure declarative binding properties using the appropriate editor or the Property Inspector.

1.1.3.2 More Sophisticated UI Functionality Without Coding

The JSF reference implementation provides a bare-bones set of basic UI components that includes basic HTML input field types and a simple table display, but these won't take you very far when building real-world applications. The ADF Model layer implements several features that work hand-in-hand with the more sophisticated UI components in the Oracle ADF Faces library to make quick work of the rich functionality your end users crave, including:

  • More Sophisticated Table Model

    Tables are a critical element of enterprise application UIs. By default, JSF doesn't support paging or sorting in tables. The ADF Faces table and the ADF Model table binding cooperate to display pageable, editable or read-only, tables with sorting on any column.

  • Key-Based Current Selection Tracking

    One of the most common tasks of web user interfaces is presenting lists of information and allowing the user to scroll through them or to select one or more entries in the list. The ADF Model iterator binding simplifies tracking the selected row in a robust way, using row keys instead of relying on positional indicators that can change when data is refreshed and positions have changed. In concert with the ADF Faces table and multiselection components, it's easy to work with single or multiple selections, and build screens that navigate master/detail information.

  • Declarative Hierarchical Tree Components and Grids

    Much of the information in enterprise applications is hierarchical, but JSF doesn't support displaying or manipulating hierarchical data out of the box. The ADF Model layer provides hierarchical bindings that you can configure declaratively and use with the ADF Faces tree or hierarchical grid components to implement interactive user interfaces that present data in the most intuitive way to your users.

  • More Flexible Models for Common UI Components

    Even simple components like the checkbox can be improved upon. By default, JSF supports binding a checkbox only to boolean properties. ADF Model adds the ability to map the checkbox to any combination of true or valid values your data may present. List components are another area where ADF Model excels. The valid values for the list can come from any data collection in a data control and the list can perform updates or be used for row navigation, depending on your needs. The ADF Model list binding also makes null-handling easy by optionally adding a translatable "<No Selection>" choice to the list.

1.1.3.3 Centralize Common Functionality in Layered Model Metadata

ADF Model can improve the reuse of several aspects of application functionality by allowing you to associate layered metadata with the data control structure definitions that can be reused by any page presenting their information. Examples of functionality that ADF Model allows you to reuse includes:

  • Translatable Prompts, Tooltips, and Format Masks

    JSF supports a simple mechanism to reference translatable strings in resource bundles, but it has no knowledge about what the strings are used for and no way to associate the strings with specific business domain objects. With ADF Model, you can associate translatable prompts, tooltips, and format masks with any attribute of any data type used in the data control service interface so that the attribute's data is presented in a consistent, locale-sensitive way on every page where it appears.

  • Declarative Validation

    JSF supports validators that can be associated with a UI component; however, it offers no mechanism to simplify validating the same business domain data in a consistent way on every screen where it's used. With ADF Model, you can associate an extensible set of validator objects with the data control structure definition metadata so that the validations will be enforced consistently, regardless of which page the user employs to enter or modify the object's data.

  • Declarative Security

    JSF has no mechanism for integrating authorization information with UI components. With ADF Model, you can associate user or role authorization information with each attribute in the data control structure definition metadata so that pages can display the information consistently only to users authorized to see it.

1.1.3.4 Simplified Control Over Page Lifecycle

JSF rigorously defines the page processing lifecycle, but for some very common tasks it requires you to write code in your own phase listener to implement it. What's more, until a future version of the JSF specification, phase listeners are global in nature, requiring you to write conditional code based on the current page's name when the functionality applies only to a specific page. The ADF Model and ADF Controller layers cooperate to simplify per-page control over the most common things you would typically code in a custom phase listener, including:

  • Declarative Method Invocation

    Configure business service method invocations with EL expression-based parameter passing, and bind to method results with options to cache results until method parameters change to avoid unnecessary requerying of data. You can have methods invoked by the press of a command component like a link or button, or configure your page definition to automatically invoke the method at an appropriate phase of the JSF lifecycle

  • Declarative Page Lifecycle Control

    Declaratively configure an iterator binding to refresh its data during a specific JSF lifecycle phase, and optionally provide a conditional EL expression for finer control over when that refresh is desired. You have the same control over when any automatic method invocation should invoke its method as well.

  • Centralized Error Reporting

    Customize the error reporting approach for your application in a single point instead of on each page.

1.2 Development Process with Oracle ADF and JavaServer Faces

In this section, describes a simple example to acquaint you with the typical development process of building an Oracle ADF application with JavaServer Faces. This information is intended as a high-level overview of the basic workflow of J2EE application building with Oracle ADF.

1.2.1 Overview of the Steps for Building an Application

Our example is based on a highly-simplified version of the Service Request tracking system (the SRDemo sample), the real-world sample application used throughout the remainder of this guide. In the Service Request tracking system, external users log requests for technical assistance with products they've purchased. Internal users try to assist the customers in the area in which they have expertise. This introduction focuses on the basics, and examines a small slice of the system's functionality related to users and their areas of technical expertise.

You'll examine the steps involved in building a simple JSF page like the one you see in Figure 1-5 that allows the end user to browse for users by name, scroll through the results, and for each user found, see their areas of technical expertise.

Figure 1-5 Simple Browse Users Page with Search and Master/Detail Data

Simple browse users page with search and master/detail data

1.2.1.1 Starting by Creating a New Application

The first step in building a new application is to assign it a name and to specify the directory where its source files will be saved. Selecting Application from the JDeveloper New Gallery launches the Create Application dialog shown in Figure 1-6. Here you give the application a name, set a working directory, and provide a package prefix for the classes you'll create in the application. Suppose that you enter a package prefix of oracle.srdemo so that, by default, all of the classes will be created in packages whose names will begin with oracle.srdemo.*. Since you will be building a web application using JSF, EJB, and TopLink, Figure 1-6 shows the corresponding application template selected from the list. This application template is set up to create separate projects named Model and ViewController with appropriate technologies selected to build the respective layers of the application.

Figure 1-6 Creating a New Application Using an Application Template

creating a new application using an application template

1.2.1.2 Building the Business Service in the Model Project

You will typically start by building your business service interface, which by default is done in the project named Model. Your Model project will comprise an EJB 3.0 session bean to function as the service facade, and Java classes that represent the business domain objects you need to work with. The model doesn't need to be functionally complete to proceed on to the subsequent steps of developing the UI, but defining the service interface forces you to think about the data the view layer will need and the information it may need to supply as parameters to your service methods to complete the job. Since you'll want to work with users and areas of expertise, the Java classes named User and ExpertiseArea are created. Each class will contain properties to reflect the data needed to represent users and areas of expertise.

Based on the requirements, suppose the business service needs to support finding users by name. For this purpose, you can use the EJB Session Bean wizard to create a stateless EJB 3.0 session bean using a container-managed transaction. Next you can add a method called findUsersByName() to its local interface that accepts the matching pattern as a parameter called name. To clearly communicate the type of the result and obtain the best compile-time type checking possible, it is best practice to declare the return type of the method to be List<User>, a strongly typed list of User beans. Finally, you can write the method in the SRServiceBean class that implements the service interface. Figure 1-7 shows what the service and its classes look like in the Java class diagram in JDeveloper. You can see that the class also contains the useful findAllUsers() method to return all users if needed.

Figure 1-7 SRService Session Bean Facade and Supporting Domain Classes

SRService Session Bean Façade and supporting domain classes

Because of the clean separation that ADF Model affords between the service and the user interface, the remaining steps to build the page depend only on the service interface, not its implementation. You can begin with a service that returns static test data, but eventually you will want to map the User and ExpertiseArea classes to appropriate tables in your database. This is where Oracle TopLink excels, and JDeveloper's integrated support for configuring your TopLink session and mappings makes quick work of the task. If you already have database tables with similar structure to your classes, Oracle TopLink can "automap" the classes to the tables for you, and then you can adjust the results as needed. If the database tables do not exist yet, you can use JDeveloper's database diagrammer to design them before performing the mapping operation. To implement the findUsersByName() method, you will create a named query as part of the User mapping descriptor and provide the criteria required to retrieve users matching a name supplied as a parameter. At runtime, the Oracle TopLink runtime handles retrieving the results of the parameterized query from the database based on XML-driven object/relational mapping information.

1.2.1.3 Creating a Data Control for Your Service to Enable Data Binding

With the business service in place, you can begin to think about building the user interface. The first step in enabling drag-and-drop data binding for the business service is to create a data control for it. Creating the data control publishes the service interface to the rest of the Oracle ADF Model design time using JSR-227 service and structure descriptions. To create a data control, you just drag the SRServiceBean class onto JDeveloper's Data Control Palette. Figure 1-8 shows the Data Control Palette following this operation. You can see it reflects all of the service methods, any parameters they expect, and the method return types. For the findUsersByName() method, you can see that it expects a name parameter and that its return type contains beans of type User. The nested email, lastName, and expertiseAreas properties of the user are also displayed. Since expertiseAreas is a collection-typed property (of type List<ExpertiseArea>), you also see its nested properties. The Operations folder, shown collapsed in the figure, contains the built-in operations that the ADF Model layer supports on collections like Previous, Next, First, Last, and so on.

Figure 1-8 Data Control Palette Displays Services Declarative Data Binding

Data Control Palette shows services declarative data binding

As you build your application, when you add additional methods on your service interface or change existing ones, simply drag and drop the SRServiceBean class again on to the Data Control Palette and the palette—as well as its underlying data binding metadata—will be refreshed to reflect your latest changes. The data control configuration information resides in an XML file named DataControls.dcx that JDeveloper adds to your Model project when you create the first data control. If you create multiple data controls, the information about the kind of data control they are (for example EJB, JavaBean, XML, web service, and so on.) and how to construct them at runtime lives in this file. In addition, JDeveloper creates an XML structure definition file for each data type involved in the service interface in a file whose name matches the name of that data type. For an EJB service interface, this means one structure definition file for the service class itself, and one for each JavaBean that appears as a method return value or method argument in the service interface.

These structure definition files drive the Data Control Palette display and come into play when you leverage the declarative, model-layer features like validators, prompts, tooltips, format masks, and declarative security. Since you defined these features at the model layer in these structure definition files, all your pages that present information related to these types display and validate the information in a consistent way. Figure 1-9 shows all of these files in the Model project in the Application Navigator after the data control for SRServiceBean has been created.

Figure 1-9 Service Classes and Data Control Metadata Files in Model Project

service classes, data control metadata in model project

1.2.1.4 Dragging and Dropping Data to Create a New JSF Page

With the data control created, you can begin doing drag-and-drop data binding to create your page. Since you'll be using ADF Faces components in your page, you first ensure that the project's tag libraries are configured to use them. Double-clicking the ViewController project in the Application Navigator brings up the Project Properties dialog where you can see what libraries are configured on the JSP Tag Libraries page. If the ADF Faces Components and ADF Faces HTML libraries are missing, you can add them from here. Figure 1-10 shows the Project Properties dialog with the correction libraries for the ViewController project.

Figure 1-10 Configuring ViewController Project Tag Libraries to Use ADF Faces

configure ViewController project tag libraries for ADF Faces

Next, you use the Create JSF JSP wizard to create a page called browseusers.jspx. You may be more familiar working with JSP pages that have a *.jsp extension, but using a standard XML-based JSP "Document" instead is a best practice for JSF development since it:

  • Simplifies treating your page as a well-formed tree of UI component tags

  • Discourages you from mixing Java code and component tags

  • Allows you to easily parse the page to create documentation or audit reports

When the Create JSF JSP wizard completes, JDeveloper opens the new page in the visual editor. From there, creating the databound page shown in Figure 1-11 is a completely drag-and-drop experience. As you drop elements from the Data Control Palette onto the page, a popup menu appears to show the sensible options for UI elements you can create for that element.

Figure 1-11 Browse Users JSF Page in the Visual Designer

browse users JSF page in the visual designer

The basic steps to create this page are:

  1. Drop a panelForm component from the ADF Faces Core page of the Component Palette onto the page and set its text attribute in the Property Inspector to "Browse Users and Expertise Areas".

  2. Drop the findUsersByName() method from the Data Control Palette to create an ADF parameter form. This operation creates a panelForm component containing the label, field, and button to collect the value of the name parameter for passing to the method when the button is clicked.

  3. Drop the User return value of the findUsersByName() node from the Data Control Palette to create an ADF read-only form. This operation creates a panelForm component containing the label and fields for the properties of the User bean.

  4. Expand the Operations folder child of the User return value in the Data Control Palette and drop the built-in Previous operation to the page as a command button. Repeat to drop a Next button to the right of it.

  5. Drop the expertiseAreas property nested inside the User return value in the Data Control Palette as an ADF read-only table. Select Enable Sorting in the Edit Table Columns dialog that appears to enable sorting the data by clicking on the column headers.

At any time you can run or debug your page to try out the user interface that you've built.

1.2.1.5 Examining the Binding Metadata Files Involved

The first time you drop a databound component from the Data Control Palette on a page, JDeveloper will create the page definition file for it. Figure 1-12 shows the contents of the browseusersPageDef.xml file in the Structure window. You can see that an action binding named findUsersByName will be created to invoke the service method of the same name. Iterator bindings named findUsersByNameIter and expertiseAreasIterator will be created to handle the collection of User beans returned from the service method and to handle the nested collection of ExpertiseArea beans. Action bindings named Next and Previous will be created to support the buttons that were dropped. And finally, attribute bindings of appropriate names will be created to support the read-only outputText fields and the table.

Figure 1-12 Page Definition XML File for browseusers.jsp

page definition XML file for browseusers.jsp.

The very first time you perform Oracle ADF Model data binding in a project, JDeveloper creates one additional XML file called DataBindings.cpx that stores information about the mapping between page names and page definition names and lists the data controls that are in use in the project. Figure 1-13 shows what the DataBindings.cpx file looks like in the Structure window. At runtime, this file is used to create the overall Oracle ADF Model binding context. In addition, page map and page definition information from this file are used to instantiate the binding containers for pages as they are needed by the pages the user visits in your application.

Figure 1-13 Structure of DataBindings.cpx

structure of DataBindings.cpx.

Note:

For complete details on the structure and contents of the DataControls.dcx, DataBindings.cpx, and PageDef.xml metadata files, see Appendix A, "Reference ADF XML Files".

1.2.1.6 Understanding How Components Reference Bindings via EL

As you perform drag-and-drop data binding operations, JDeveloper creates the required ADF Model binding metadata in the page definition and creates the JSF components you've requested. Importantly it also ties the two together by configuring various properties on the components to have EL expression values that reference the bindings. Figure 1-14 summarizes how the components on the page reference the bindings from the page's binding container at runtime.

Figure 1-14 EL Expressions Related Page Components to Bindings

EL expressions related page components to bindings

As a simple example, take the Previous button. When you drop this built-in operation as a button, an action binding named Previous is created in the page definition file, and two properties of the commandButton component are set:

  • actionListener="#{bindings.Previous.execute}"

  • disabled="#{!bindings.Previous.enabled}"

These two EL expressions "wire" the button to invoke the built-in Previous operation and to automatically disable the button when the Previous operation does not make sense, such as when the user has navigated to the first row in the collection.

Studying another example in the page, like the read-only outputText field that displays the user's email, you would see that JDeveloper sets up the following properties on the component to refer to its binding:

  • value="#{bindings.email.inputValue}"

  • label="#{bindings.email.label}"

The combination of these two binding attribute settings tells the component to pull its value from the email binding, and to use the email binding's label property as a display label. Suppose you had configured custom prompts for the User and ExpertiseArea beans in the Model project, the bindings can then expose this information at runtime allowing the prompts to be referenced in a generic way by components on the page.

The drag-and-drop data binding steps above did not account for how the current record display (for example "N of M") appeared on the page. Since information about the current range of visible rows, the starting row in the range, and the total number of rows in the collection are useful properties available for reference on the iterator binding, to create this display, just drop three outputText components from the Component Palette and set each's value attribute to an appropriate expression. The first one needs to show the current row number in the range of results from the findUsersByName method, so it is necessary to set its value attribute to an EL expression that references the (zero-based!) rangeStart property on the findUsersByNameIter binding.

#{bindings.findUsersByNameIter.rangeStart + 1}

The second outputText component just needs to show the word "of", so setting its value property to the constant string "of" will suffice. The third outputText component needs to show the total number of rows in the collection. Here, just a reference to an attribute on the iterator binding called estimatedRowCount is needed.

1.2.1.7 Configuring Binding Properties If Needed

Any time you want to see or set properties on bindings in the page definition, you can select Go to Page Definition in the context menu on the page. For example, you would do this to change the number of rows displayed per page for each iterator binding by setting its RangeSize property. In the example shown in Figure 1-14, after visiting the page definition, the Property Inspector was used to set the RangeSize of the findUsersByNameIter iterator binding to 1 and the same property of the expertiseAreasIterator to 2. Setting the RangeSize property for each iterator causes one user and two expertise areas to display at a time on the page.

1.2.1.8 Understanding How Bindings Are Created at Runtime

The final piece of the puzzle to complete your basic understanding of Oracle ADF Model involves knowing how your data controls and declarative bindings are created at runtime based on the XML configuration files you've created. As part of configuring your project for working with Oracle ADF data binding, JDeveloper registers a servlet filter called ADFBindingFilter in the web.xml file of your ViewController project and maps this filter by default to URLs matching the pattern *.jsp and *.jspx.

This ADFBindingFilter servlet filter is responsible for finding your DataBindings.cpx file, based on the information in the web.xml file and creating the ADF binding context. The binding context is a Map that contains all binding containers, data controls, and the mapping of page names to page definition files. You can reference it at any time in your application using the EL expression #{data}. It's also the place where the centralized error handler is registered, and APIs are provided to set a custom error handler if needed (together with numerous other useful APIs).

When the page request is received the application invokes both the JSF lifecycle and the ADF lifecycle. Specifically, during execution of the ADF lifecycle execution, another object, the ADFPhaseListener, lazily instantiates the bindings in a binding container and data controls the first time they are needed to service a page request. The ADFPhaseListener references the information in the page map on the binding context to know which binding container to use for which page; it also references information in the DataControls.dcx file to know what data control factory to use. On each request, it ensures that the binding container of the current page being requested is available for reference via EL using the expression #{bindings}. Figure 1-15 summarizes the relationships between these metadata files.

Figure 1-15 How ADF Binding Metadata Is Used at Runtime

how ADF binding metadata is used at runtime

Once the binding container is set up for a given page, the ADFPhaseListener integrates the JSF page handling lifecycle with the bindings. It coordinates the per-page execution of the iterators and service methods based on information in the appropriate page definition file. The iterators and method invocation bindings are known as "executable" bindings for this reason.

1.2.2 Making the Display More Data-Driven

After you have a basic page working, you will likely notice some aspects that you'd like to make more sophisticated. For example, you can use the properties of ADF bindings to hide or show groups of components or to toggle between alternative sets of components.

1.2.2.1 Hiding and Showing Groups of Components Based on Binding Properties

If the application user enters a last name in the browseusers.jspx page that matches a single user, it doesn't look very nice to show disabled Next and Previous navigation buttons and a "1 of 1" record counter. Instead, you might want a result like what you see in Figure 1-16, where these components disappear when only a single row is returned.

Figure 1-16 Hiding Panel with Navigation Buttons When Not Relevant

hiding panel with navigation buttons when not relevant

Luckily, this is easy to accomplish. You start by organizing the navigation buttons and the record counter display into a containing panel component like panelHorizontal. After creating the panel to contain them, you can drag and drop in the visual editor, or drag and drop in the Structure window to place the existing controls inside another container. Then, to hide or show all the components in the panel, you just need to set the value of the panel's rendered attribute to a data-driven EL expression.

Recall that the number of rows in an iterator binding's collection can be obtained using its estimatedRowCount property. Figure 1-17 shows the EL picker dialog that appears when you select the panelHorizontal component, click in the Property Inspector on its rendered attribute, and click the ... button. If you expand the bindings for the current page you will see the findUsersByNameIter iterator binding. You can then expand it further to see the most common properties that developers reference in EL. By picking estimatedRowCount and clicking the > button, you can then change the expression to a boolean expression by introducing a comparison operator to compare the row count to see if it is greater than one. When you set such an expression, the panel will be rendered at runtime only when there are two or more rows in the result.

Figure 1-17 Setting a Panel's Rendered Attribute Based on Binding Properties

setting panel rendered attribute based on binding properties

1.2.2.2 Toggling Between Alternative Sets of Components Based on Binding Properties

Consider another situation in the sample page. When no rows are returned, by default the read-only form would display its prompts next to empty space where the data values would normally be, and the table of experience areas would display the column headings and a blank row containing the words "No rows yet". To add a little more polish to the application, you might decide to display something different when no rows are returned in the iterator binding's result collection. For example, you might simply display a "No matches. Try again" message as shown in Figure 1-18.

Figure 1-18 Alternative Display If Search Produces Empty Collection

alternative display if search produces empty collection

JSF provides a basic feature called a "facet" that allows a UI component to contain one or more named, logical groups of other components that become rendered in a specific way at runtime. ADF Faces supplies a handy switcher component that can evaluate an EL expression in its FacetName attribute to determine which of its facets becomes rendered at runtime. Using this component effectively lets you switch between any groups of components in a dynamic and declarative way. If you group the components that present the user information and experience area table into a panel, then you can use the switcher component to switch between showing that panel and a simple message depending on the number of rows returned.

Figure 1-19 shows the Structure window for the browseusers.jsp page reflecting the hierarchical containership of JSF components after the switcher component is introduced. First, you would set up two JSF facets and give them meaningful names like found and notfound. Then you can organize the existing components into the appropriate facet using drag and drop in the Structure window. In the found facet, you want a panel containing all of the components that show the user and experience area information. In the notfound facet, you want just an outputText component that displays the "No matches. Try again" message.

Figure 1-19 Structure Window View of browseusers.jsp

structure window view of browseusers.jsp.

By setting the facetName attribute of switcher to the EL expression, the found facet will be used when the row count is greater than zero, and the notfound facet will be used when the row count equals zero:

#{bindings.findUsersByNameIter.estimatedRowCount > 0 ?'found':'notfound'}

The combination of Oracle ADF declarative bindings, ADF Faces components, and EL expressions demonstrates another situation that previously required tedious, repetitive coding which now can be handled with ease.

This concludes the introduction to building J2EE applications with Oracle ADF. The rest of this guide describes the details of building a real-world sample application using Oracle ADF, EJB, and JSF.