Skip Headers
Oracle® Application Development Framework Developer's Guide For Forms/4GL Developers
10g Release 3 (10.1.3.0)

Part Number B25947-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

2 Overview of Development Process with Oracle ADF and JSF

This chapter highlights the typical development process for using Oracle JDeveloper 10g Release 3 (10.1.3) to build web applications using Oracle ADF and JSF, using Oracle ADF Business Components to implement the business service layer.

This chapter includes the following sections:

2.1 Introduction to the Development Process

The simplest way to appreciate how easy J2EE development can be using JDeveloper and Oracle ADF is to walk through a typical, end-to-end development process. Using Oracle ADF, enterprise J2EE application development can be a visual, code free experience. Of course, you eventually write code in a real-world application, but importantly Oracle ADF allows you to focus your efforts on the code that is directly related to your application's business requirements.

In the Service Request tracking system used as the real-world example application throughout the remainder of this guide, external users log service 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 walkthrough highlights the typical steps involved in implementing a solution for one small use case related to that overall system's functionality. In the walkthrough you'll create a small system to managing the profiles of technician users and their areas of technical expertise.

While this overview tries to give you the essence of the typical development process with Oracle ADF, it doesn't provide the click-by-click guidance of a tutorial. For a list of all the available Oracle ADF tutorials, go to the Oracle ADF product center on OTN at http://otn.oracle.com/products/adf.

Note:

After reading the chapter, if you want to experiment with a completed version of the small application described here, download the ADFIntro workspace from the Example Downloads page at http://otn.oracle.com/documentation/jdev/b25947_01/.

2.2 Creating an Application Workspace to Hold Your Files

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 2-1. Here you give the application a name like ADFInfo, set a working directory, and provide a package prefix for the classes you'll create in the application. You'll typically enter a package prefix like oracle.srdemo so that, by default, all of the components comprising the application will be created in packages whose names will begin with oracle.srdemo.*. Since you will be building a web application using JSF and ADF Business Components, Figure 2-1 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 2-1 Creating an Application Workspace to Hold Your Files

Image of Create Application dialog

If you want to inspect the default technologies included in each project, you can open the Technology Scope page in the Project Properties dialog. Figure 2-2 shows what this page looks like after you add additional Database and UML technologies to the list in the Model project. By specifying exactly which technologies you intend to use in each project, you help JDeveloper simplify the available choices presented to the developer in the New Gallery and other dialogs to only those relevant to the current project's technologies.

Figure 2-2 The Technology Scope Defines the Technologies Used in That Project

Image of Technology Scope dialog

2.3 Thinking About the Use Case and Page Flow

After creating an application workspace, you might begin the development process by doing some use case modeling to capture and communicate end-user requirements for the system to be built. Figure 2-3 shows a simple diagram created the use case diagrammer, one of a number of built-in UML diagramming tools. The diagram represents the simple technician management system that your managers are asking you to build. It consists of two related use cases: "Search for Technician by Name" and "Update Technician Profile." Using diagram annotations, you can capture particular requirements about what end users might need to see on the screens that will implement the use case. For example, you might note that managers want to see product names and technician expertise levels while browsing the search results.

Figure 2-3 Use Case Diagram for a Simple Technician Management System

Image of use case diagram

By modeling the use cases, you begin to understand the kinds of user interface pages that will be required to implement end-user requirements. As shown in Figure 2-4, using the JSF page flow diagrammer, you can create a skeleton page flow for the system. Since the page flow is related to the user interface, this work happens in the context of the ViewController project in the workspace.

Using the Component Palette, you drop pages and named navigation rules to connect them. You should be able to implement the requirements using the combination of a searchtechnicians page and an updateprofile page. After using the searchtechnicians page to find the technician to update, the manager will proceed to updateprofile page to modify that technician's profile. After saving the changes, she'll return back to the searchtechnicians page. The navigation lines on the page diagram reflect this flow. The warning symbols you see are no reason for alarm. They indicate that you still have to create the page that the page icon represents. You'll see that in a later step of the walkthrough.

Figure 2-4 Skeleton JSF Page Flow Diagram in the ViewController Project

Image of skeleton JSF page flow in a project

Note:

JDeveloper supports the ability to do "UI first" development to mock up web page displays using unbound UI components, and then bind them to data later. However, in this walkthrough you'll be following a more traditional bottom up approach that is most similar to the way traditional 4GL tools attack the problem. Both styles of development are possible, or you can develop simultaneously and meet in the middle.

2.4 Designing the Database Schema

If you already have the database tables for USERS, PRODUCTS, and EXPERTISE_AREAS that store information about users with a technician role and the expertise they have for particular products, you can begin working with them immediately. Seeing them in a data diagram can help you understand whether the schema might require any changes to support the new use case.

After creating a named connection in the Connection Navigator to browse your database schema objects, you can see your existing tables under a Tables folder. Using the New Gallery, you can create a new database diagram, select the USERS, PRODUCTS, and EXPERTISE_AREAS tables from the Connection Navigator, and drop them onto the diagram. Figure 2-5 shows what the database diagram would look like.

Of course, if the tables didn't already exist, you could use the same diagrammer to design them and generate the DDL scripts to create the tables from scratch.

Figure 2-5 Database Diagram Showing Schema for Technician Management System

Image of diagram for database schemas

2.5 Creating a Layer of Business Domain Objects for Tables

With the database tables in place, you can create a set of Java components that represents them and simplifies modifying the data they contain. Using entity objects to encapsulate data access and validation related to the tables, any pages you build today or in the future that work with these tables get consistently validated. Since this task is related to the data access and business logic for your application, you'll do it in the context of the Model project. As you work, JDeveloper automatically configures your project to reference any necessary Oracle ADF libraries your application will need at runtime.

2.5.1 Dragging and Dropping to Reverse-Engineer Entity Objects for Tables

You can create business components by using wizards or a diagram. On one hand, the wizards can be faster to use since you can create many components at the same time. For example, in a single step you can create entity objects, related view objects, and an application module to use as your business service with the Business Components from Tables wizard. On the other hand, creating business components on a diagram is often more intuitive and allows you to understand the roles each different kind of business component plays. Since creating business components using the wizards is covered in later chapters, for this walkthrough it is best to take things one steps at a time and work in a visual way.

To create a business components diagram, open the New Gallery and select Business Components Diagram. After creating a new diagram, just drop the tables from the Connection Navigator onto the diagram surface to create entity objects for them. By default, the entity objects get named Users, ExpertiseAreas, and Products based on the names of the tables. Since an entity object represents a single element of business domain data, it's best practice to name them with singular names. You can use the diagram's in-place editing support to rename the entity objects to User, ExpertiseArea, and Product. JDeveloper has extensive support for refactoring to automate changing any related files to use the new names. In addition to the entity objects that were created, the tool also created associations that reflect the foreign keys relating the underlying tables. To help communicate how your entity objects are related to the tables, you can add the tables themselves to the same diagram and draw dependency lines between them, as shown in Figure 2-6.

Figure 2-6 Business Components Diagram Showing Entity Objects and Related Tables

Image shows diagram of entity objects and related tables

2.5.2 Adding Business Validation Rules to Your Entity Object

Your set of associated entity objects represents a reusable layer of business domain components. Any business validation rules you enforce at this level are enforced consistently throughout any applications you build that satisfy use cases related to Users, ExpertiseAreas, and Products. This applies regardless of the user interface technology that you use. This guide focuses attention on developing web applications with JSF, but validation rules encapsulated in your business domain layer work the same whether used through web, wireless, or Swing user interfaces, as well as through web services. The validation rules can range from the simplest syntactic value-checking to the most complicated enterprise database-backed programmatic rules.

By double-clicking the Users entity object in the diagram, you can access the Entity Object Editor to define declarative validation rules for users. Open the Validation page of the editor to add validation rules. Click New to add a new rule, and add a UniqueKey Validator that will ensure that the primary key for new User rows is unique. As shown in Figure 2-7, you can enter a validation error message that the manager will see if she enters a new user whose ID is already taken. JDeveloper saves the error message in a standard Java message bundle to simplify localizing it for different languages.

Figure 2-7 Adding a New UniqueKey Validator

Image of Add Validation Rule dialog for new user

Next, you could add a regular expression validator on the Email attribute to ensure that managers only enter email address in the expected 8-character, lowercase format. Selecting the Email attribute in the Declarared Validation Rules tree and clicking New again, you can add a Regular Expression Validator. Figure 2-8 shows the regular expression to match from three to eight lowercase characters, and the error message that will appear if the manager enters an email in the wrong format.

Figure 2-8 The Regular Expression Validator Ensures That Email Address Is Correctly Formatted

Image of Add Validation Rule dialog for email address

Select the UserRole attribute and click New to add a List Validator as shown in Figure 2-9 to ensure that the role of a new user can only be user, technician, or manager. Again, you can enter the error message the manager will see if she enters the data incorrectly.

Figure 2-9 The List Validator Ensures That UserRole Has One of Three Legal Values

Image of Add Validation Rule dialog for UserRole

After doing this, you can see, as shown in Figure 2-10, that all the validation rules in effect are summarized on the Validation page of the Entity Object Editor.

Figure 2-10 The Validation Page Provides One Place to See All Validation Rules in Effect

Image of Validation dialog

In a real-world application, you would go on to add a number of method validators that invoke custom validation event handlers that you write in Java. Like the built-in validations, these can be attribute-level rules if they are related just to one specific attribute, or entity-level validation rules if they are more complex and involve consulting multiple attribute values or other entities to determine validity. The code you would write inside the validation events can easily access the properties of any entity object in your business domain layer, or easily perform any SQL query, as part of determining if the method-based validation rule should succeed or fail the validation check.

If you notice a pattern in the kind of custom Java-based validations your team is performing, you can extend the set of built-in validation rules in JDeveloper with custom, parameter-driven rules of your own. Custom rules allow other developers on your team to reuse the common validation patterns in their future work without writing code themselves. Instead they pick your custom validation rule from a list and set a few properties. Either way, whether business rules are implemented declaratively or using validation event handlers written in Java, they all appear in the Validation page of the Entity Object Editor, so that you have a single place to see all business rules in effect for that object.

2.5.3 Defining UI Control Hints for Your Entity Objects

In addition to business rules, other useful resources you can centralize in your entity object layer are the standard UI labels and format masks that your business information will use throughout all applications you build. By opening the Entity Object Editor and selecting individual attributes, you can use the Control Hints tab to define the Label Text, Tooltip Text, Format Type, Format mask and other hints. Since these user-visible labels and format masks need to be sensitive to the preferred language of the end user, JDeveloper manages them for you in a standard Java resource bundle. This way, they are straightforward to translate into other locales for creating multilingual applications.

Assume you've edited the User, ExpertiseArea, and Product entities to define label text hints for all the attributes. You'll see later in the walkthrough how these centralized UI label hints are automatically leveraged in the pages you build that work with data related to these entity objects.

2.6 Building the Business Service to Handle the Use Case

Once the reusable layer of entity objects is created, you can implement the specific business service to satisfy the needs of the use case at hand. Since this task is related to the data access and business logic for your application, you'll do it in the context of the Model project.

2.6.1 Creating a Application Module to Manage Technicians

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

After adjusting the diagram's visual properties to turn off the grid display, you can use the Component Palette to drop a new application module onto the business component diagram, as shown in Figure 2-11. Since it will be a service concerned with technicians, you could call it TechnicianService to reflect this role.

Figure 2-11 Creating a New Application Module on the Business Components Diagram

Image shows how to use business components diagram

The application module's data model is composed of SQL queries that define what data the end user will see on the screen. To work with SQL query results, you'll define view object components that encapsulate the necessary queries. When the end user needs to update the data, your view objects reference entity objects in your reusable business domain layer. These entity objects ensure any data the end user modifies is validated and saved in a consistent way.

2.6.2 Creating View Objects to Query Appropriate Data for the Use Case

Start by considering the data required by the "Search for Technician by Name" use case. For certain, you'll need a query that involves User information, since technicians are a kind of user whose data resides in the USERS table. So, drop a new view object component onto the diagram and name it SearchTechniciansByName. Drag the User entity object and drop it onto the new SearchTechniciansByName view object component in the diagram. By creating a view object in this manner, JDeveloper updates the view object's SQL query to include all of that entity object's data.

For the search page, imagine that you only need to display the UserId, Email, FirstName, and LastName attributes. You can use the diagram to select the other attributes in the SearchTechniciansByName view object and remove them using the Delete key. By including only the data you need in the query, you make your application more efficient by retrieving only the information required by the task at hand.

To save space, you can display a view object in standard mode, and you can adjust the colors to distinguish different types of business components on the diagram. Figure 2-12 shows how a well organized business components diagram might look for the steps you've seen so far.

Figure 2-12 Business Components Diagram Including SearchTechniciansByName View Object

Image of business components diagram with search

You want the SearchTechniciansByName view object to:

  • Only find users with the 'technician' role

  • Be searchable by a user-supplied name parameter

To accomplish this you need to edit the view object to configure these features. Double-clicking the view object on the diagram to opens the View Object Editor.

To add a bind variable to support searching technicians by name, you can open the Bind Variables page of the editor as shown in Figure 2-13, and define one called TechName of type String with null as its default value. On the Control Hints tab you can define a Label Text hint for the bind variable of "Name Contains". This label will appear in any pages you build using this bind variable for searching.

Figure 2-13 Adding a Named Bind Variable to Search by Name

Image of Bind Variables dialog

Next, you can open the SQL Statement page and fine-tune the SELECT statement. As shown in Figure 2-14, you can enter an appropriate WHERE clause to search only for technicians whose first name or last name matches the value of the TechName bind variable in a case-insensitive way. You can also enter an ORDER BY clause to sort the results first by last name, then by first name.

Figure 2-14 Adjusting the Query's Where and Order By Clauses

Image of SQL Statement page and search for WHERE

Recall from the use case diagram that the managers asked to see the related set of technician expertise information while browsing search results. They also indicated that they wanted to see the product name information related to the expertise level. You can drop a second view object onto the diagram and call it TechnicianSkills. Since it will need to include information from both the ExpertiseArea and Product entity objects, you can multiselect both of these entities and drop them together onto the new view object. Double-clicking the TechnicianSkills view object, you can see that the join query has been automatically determined, and you can use the Attributes page to remove the attributes you don't need.

Lastly, since you'll need a master/detail display between the results in the SearchTechniciansByName query and the TechnicianSkills query, you can use the View Link tool in the palette to connect the master view object to the detail view object. Figure 2-15 shows the results of having created the new detail TechnicianSkills view object and linking it master/detail with SearchTechniciansByName.

Figure 2-15 Master/Detail View Objects in the Business Components Diagram

Image of master/detail objects in diagram

2.6.3 Using View Objects in the Application Module's Data Model

The last step to complete the TechnicianService application module is to use your view objects to define its data model. Like entity objects, view objects are reusable components that you can use in multiple application modules when their queries make sense in multiple use cases. Selecting both the SearchTechniciansByName and TechnicianSkills view objects in the diagram and dropping them onto the application module accomplishes the task. You can rename the view object instances used in the data model to have shorter names. These names will be used by the client to identify the data collections produced by the view object's queries at runtime. In Figure 2-16, you can see what it would look like if you chose the shorter names Technicians and Skills to name the master/detail collections in the TechnicianService's data model. The dotted lines are dependency lines you can add to further clarify how components on a UML diagram depend on each other.

Figure 2-16 TechnicianService Application Module Containing Named Instances of Two View Objects

Image of application module with named view objects

Whether you use wizards and editors or the visual diagrammers to work on your application components, as shown in Figure 2-17, the Application Navigator displays all of the components you've created. Selecting a particular component like the TechnicianService application module, you can see additional information about it in the Structure window.

You'll notice in the Structure window that the TechnicianService component has only an XML file in its Sources folder. Using ADF Business Components for your business service layer, each component has a related XML component definition file. If you don't have any need to write custom Java code to extend the behavior of a given component or to handle its events, you can just use the component in an XML-only mode. A class provided by the base framework gets used at runtime instead, and its behavior is determined by the metadata in its XML component definition file.

Figure 2-17 The Application Navigator Displays the Components Comprising Your Application

Image of Application Navigator displaying components

2.6.4 Testing Your Service

Even before building a user interface, you can interactively test your TechnicianService component using the integrated Business Components Browser. To launch this testing tool, select the application module in either the Application Navigator or the diagram and choose Test... from the context menu. When the Business Components Browser Connect dialog appears, click Connect.

As shown in Figure 2-18, the Technicians and Skills master/detail view object instances that comprise the data model of the TechnicianService component appear in the tree at the left. Double-click the ViewLink11 node that links the two in the tree and a Bind Variables dialog appears to prompt you for a value for the TechName bind variable. Entering a value like "an" and clicking OK executes the Technicians view object query, and the tester tool shows you the results. Any technicians whose first name or last name contains the letters "an" in the name appear. Notice that the UI controls appear with the labels that you defined in the UI control hints for the entity objects in your business domain layer.

Figure 2-18 Interactively Testing the TechnicianService Application Module

Image of Business Components Browser

Using the toolbar buttons you can scroll through the master data to observe the automatic master/detail coordination. If you try updating the email address of Alexander Hunold to ahunold@srdemo.com and click into a different field, you'll receive the validation exception shown in Figure 2-19. Recall that this was one of the business rules that you encapsulated inside your User entity object in the business domain layer. The exception verifies the automatic coordination that occurs between updatable rows in view objects and the underlying entity objects that they reference.

Figure 2-19 The Business Components Browser Showing Failed Entity Object Validation Rule

Image of Business Components Browser with test failure

While doing development with Oracle ADF, you will find the Business Components Browser is very useful. It allows you to exercise all of the data model of your business service component without having to build — or without having to use — your end-user UI pages. This can save you a lot of time when trying to diagnose problems, or just test out the latest queries or business rules you've added to your business service layer.

2.6.5 The Data Control for Your Application Module Enables Data Binding

With the business service in place, it's time to think about creating the user interface. Application modules you build are automatically exposed as JSR-227-compliant data controls to enable drag-and-drop data binding using JDeveloper's rich design-time support for this specification. Figure 2-20 shows the Data Control Palette and the TechnicianServicesDataControl that is automatically kept in sync with your application module definition as you create and modify it. You can see the Technicians and Skills data collections that represent the view object instances in the TechnicianService's data model. The Skills data collection appears as a child of Technicians, reflecting the master/detail relationship you set up while building the business service. The attributes available in each row of the respective data collections appear as child nodes. The data collection level Operations folders, shown collapsed in the figure, contains the built-in operations that the ADF Model layer supports on data collections like Previous, Next, First, Last, and so on.

Figure 2-20 The Data Control Palette Displays Business Services for Declarative Data Binding

Image of Data Control Palette and setting data bindings

Note:

If you create other kinds of data controls for working with web services, XML data retrieved from a URL, JavaBeans, or EJBs, they would also appear in the Data Control Palette with an appropriate display. The first time you create one of these data controls in a project, JDeveloper creates a DataControls.dcx file that contains configuration information about them. In addition, it creates XML structure definition files for each data type involved in the service interface.

These additional files are not needed when you are working with application modules since application modules are already metadata-driven components whose XML component definition files contain all the information necessary to be exposed automatically as JSR 227 data controls.

2.7 Dragging and Dropping Data to Create a New JSF Page

Now that you're familiar with the basics of the Data Control Palette, you can begin doing drag-and-drop data binding to create your page. Since you'll be using ADF Faces components in your page, 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, as shown in Figure 2-21. If the ADF Faces Components and ADF Faces HTML libraries are missing, you can add them from here.

Figure 2-21 Configuring ViewController Project Tag Libraries to Use ADF Faces

Image of Project Properties page for ADF tag libraries

Next, you can select the ViewController project in the Application Navigator and choose Open JSF Navigation from the context menu to return to the skeleton JSF page flow you created earlier. Double-click the /searchtechnicians.jspx page icon in the diagram to launch the Create JSF JSP wizard shown in Figure 2-22, which you use to create the file representing the searchtecnicians.jspx web page.

Figure 2-22 Creating a New JSF JSP Page

Image of step 1 of the Create JSF/JSP wizard

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:

You can click Finish on the first page of the wizard, taking all defaults. After completing the Create JSF JSP wizard, a new page opens in the visual editor. From there, creating the databound page shown in Figure 2-23 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 2-23 Browse Users JSF Page in the Visual Designer

Image of JSF page in Visual Designer

The basic steps to create this page are:

  1. Drop a panelHeader component from the ADF Faces Core page of the Component Palette onto the page and set its text attribute in the Property Inspector to "Search Technicians".

  2. Drop the ExecuteWithParams built-in operation for the Technicians data collection in the Data Control Palette to create an ADF parameter form. This step creates a panelForm component containing the label, field, and button to collect the value of the TechName bind variable and pass it to the view object when the button is clicked. Use the Property Inspector to set the text on the command button created to "Go".

  3. Drop the Technicians data collection 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 attributes in a row of the Technicians data collection. In the Edit Form Fields dialog that appears, you can delete the UserId attribute from the list so that it doesn't appear on the page.

  4. Again from the Operations folder of the Technicians data collection, drop the built-in Previous operation to the page as a command button. Repeat to drop a Next button to the right of it for the built-in Next operation.

  5. Drop the detail Skills data collection in the Data Control Palette as an ADF read-only table. In the Edit Table Columns dialog that appears, include columns in the table only for the ExpertiseLevel and Name attributes, and use the Up and Down buttons to reorder them so that Name comes first. Select the Enable sorting checkbox to enable sorting the data by clicking the column headers.

  6. Drop a commandButton from the Component Palette at the bottom of the page and change its Text property to "Update Profile". Set its Action property to "UpdateProfile" by picking it from the list to have the button follow the "UpdateProfile" navigation rule you created in the JSF page flow diagram earlier.

Note:

Producing the exact look of the page in Figure 2-23 involves a few additional drags and drops to group the default components, add an object separator between them, and dropping some read-only text fields bound to the current row count and total rows using EL. These steps are explained in a later section of this walkthrough.

At any time you can run or debug your page to try out the user interface that you've built. Notice that the UI control hints you set up on your entity object attributes in the business domain layer automatically appear in the user interface. Searching by name finds technicians whose last name or first name contains the string you've entered (case-insensitively). The Previous and Next buttons navigate among the technicians found by the search, and each technician's related set of skills display, along with the product name to which the expertise applies. A simple master/detail search page is illustrated in Figure 2-24.

Figure 2-24 Simple Search Technicians Page with Master/Detail Data

Image of web page with master/detail data

2.8 Examining the Binding Metadata Files Involved

The group of bindings supporting the UI components on a page are described in a page-specific XML file called the page definition file. 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 2-25 shows the contents of the searchtechniciansPageDef.xml file in the Structure window. Each time you add components to the page using the Data Control Palette JDeveloper adds appropriate declarative binding entries into this page definition file.

For example, after performing the steps in the previous section to create the databound UI components on the searchtechnicians.jspx page, you can see in the figure that JDeveloper added an action binding named ExecuteWithParams to invoke the built-in data control operation of the same name. Iterator bindings named TechniciansIterator and SkillsIterator were added to handle the data collection of rows from the Technicians and Skills view object instances, respectively. Action bindings named Next and Previous were added to support the buttons that were dropped. And, finally, value bindings of appropriate names were added to support the read-only outputText fields and the table.

Figure 2-25 Page Definition XML File for searchtechnicians.jspx

Image shows Structure window with page definition XML

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 that lists the data controls that are in use in the project. Figure 2-26 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 2-26 Structure of DataBindings.cpx

Image of Structure window for DataBindings.cpx file

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

2.9 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 file and creates tags representing the JSF UI 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 2-27 summarizes how the page's UI components reference the bindings in its page definition. At runtime, these bindings are contained in a binding container related to the page.

Figure 2-27 EL Expressions Relate UI Components in a Page to Bindings

Image shows EL expressions, UI components, and bindings flow

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:

The first EL expression "wires" the button to execute the action binding named Previous in the binding container bound to the built-in Previous operation of the related data collection. The second EL expression automatically disables the button when the Previous operation does not make sense, such as when the user has navigated to the first row in the data collection.

Studying another example in the page, like the read-only outputText field that displays the user's email address and the panelLabelAndMessage component that contains it, you would see that JDeveloper sets up the following properties on these components to refer to the Email value binding:

The combination of these settings "wires" the outputText component to pull its value from the Email binding, and the panelLabelAndMessage component to use the Email binding's label property as a display label. Since you configured UI controls hints for the attributes of your entity objects in the business domain layer, the control hints are inherited by the view object's attributes. The bindings expose this information at runtime so that components can easily refer to the control hints, such as labels and format masks using EL expressions.

The drag-and-drop data binding just completed did not account for how the current record display (for example "N of M") appeared on the page. To create it, you will need to reference properties for:

Since the bindings expose properties for these, it is easy to create a current record display like this. Just drop three outputText components from the Component Palette and set each component's value attribute to an appropriate EL expression. The first one needs to show the current row number in the range of results from the Technicians data collection, so set its value attribute to an EL expression that references the (zero-based) rangeStart property on the TechniciansIterator binding.

#{bindings.TechniciansIterator.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, make a reference to the iterator binding's estimatedRowCount property:

#{bindings.TechniciansIterator.estimatedRowCount}

2.10 Configuring Binding Properties If Needed

Any time you want to see or set properties on bindings in the page definition, you can choose 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. As shown in Figure 2-27, after opening the page definition, the Property Inspector was used to set the RangeSize of the TechniciansIterator binding to 1 and the same property of the SkillsIterator to 2. Setting the RangeSize property for each iterator this way causes one user and two expertise areas to display at a time on the page.

2.11 Understanding How Bindings Are Created at Runtime

To round out this basic introduction of ADF Model binding for JSF pages, it is good to understand how your data controls and declarative bindings are created at runtime. As part of configuring your project for working with Oracle ADF data binding, JDeveloper registers an additional handler that is triggered whenever a client requests a JSP page. This handler is listed in the standard J2EE web application configuration file (web.xml) of your ViewController project. It sets up the correct binding container for the current page based on the related ADF Model XML configuration files, and makes it accessible using the EL expression #{bindings}. During the subsequent handling of the web page request, the JSF standard dictates a predictable set of processing steps known as the page "lifecycle". Oracle ADF uses standard mechanisms to plug into these processing steps to automate preparing data for display, invoking built-in operations or custom service methods, as well as updating and validating data against the view objects in your application module's data model.

Note:

If your curiosity already craves step-by-step details on how a page request is handled when using JSF and Oracle ADF, see the annotated sequence diagram in Section 29.2, "Lifecycle of a Web Page Request Using Oracle ADF and JSF"

2.12 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 reference the properties of ADF bindings to hide or show groups of components or to toggle between alternative sets of components.

2.12.1 Hiding and Showing Groups of Components Based on Binding Properties

If the manager enters a name in the searchtechnicians.jspx page that matches a single user, the disabled Next and Previous navigation buttons the "1 of 1" record counter are superfluous. Instead, you might want a result like what you see in Figure 2-28, where these components disappear when only a single row is returned.

Figure 2-28 Hiding Panel with Navigation Buttons When Not Relevant

Image shows information in displayed result set to be hidden

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 in the Structure window to place the existing controls inside the new container component. 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 data collection can be obtained using its estimatedRowCount property. Figure 2-29 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 ADF Bindings folder as well as the bindings node to see the bindings in the current page's binding container, you will see the TechniciansIterator. You can then expand this iterator binding 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 2-29 Setting a Panel's Rendered Attribute Based on Binding Properties

Image shows Rendered Attribute dialog

2.12.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 2-30.

Figure 2-30 Alternative Display If Search Produces Empty Collection

Image of alternate display to use with empty result set

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, you can use the switcher component to switch between showing that panel and a simple message, depending on the number of rows returned.

Figure 2-31 shows the Structure window for the searchtechnicians.jspx 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 technician and experience area information. In the notfound facet, you want just an outputText component that displays the "No matches. Try again" message. Finally, you set the DefaultFacet property on the switcher component to found so that facet displays by default.

Figure 2-31 Switcher Component Containing 'found' and 'notfound' Facets

Image of Structure window for switcher component

Set the facetName attribute of switcher to the following EL expression so that 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.TechniciansIterator.estimatedRowCount > 0 ? 'found' : 'notfound'}

The combination of Oracle ADF declarative bindings, ADF Faces components, and EL expressions is another situation in which tedious, repetitive coding can be handled with ease.

2.13 Adding the Edit Page and Finishing the Use Case

With the page for the "Search Technicians by Name" use case implemented, you can turn your attention to the "Update Technician Profile" use case. Assuming you want the manager to be able to view all the attributes of the technician user when they go to update the profile, you'll need to create a view object that includes all the User entity object's attributes to support the updateprofile.jspx page. Once you add this new view object to the TechnicianService's data model, you'll see it appear in the Data Control Palette, from where you can then drop it onto the updateprofile.jspx page to create an edit form in one step.

2.13.1 Adding Another View Object to the Data Model

To add a view object with all of the User entity object's attribute, open the business component diagram again in the Model project and drop a new view object from the Component Palette. Name the new view object Technicians since it will be used to show all the data about technicians. Drop the User entity object onto the new view object in the diagram, and double-click the view object to open the View Object Editor. Using the editor you can:

  • Add the same WHERE clause you did for the SearchTechniciansByName view object to query rows only where user_role = 'technician'

  • Set the UserId attribute to be Updatable only While New to prevent the end user from updating the values of UserId values in existing rows.

Back on the diagram drop the Technicians view object onto the TechnicianService to use it in the data model, and name the view object instance UpdateProfile. Figure 2-32 shows the updated business service model. You'll notice that the corresponding UpdateProfile data collection appears immediately in the Data Control Palette.

Figure 2-32 Updated Business Service Diagram

Image of updated business service diagram

2.13.2 Creating the Edit Page

To open the visual editor for the updateprofile.jspx page, open the JSF page flow diagram, double-click the /updateprofile.jspx page and click Finish in the Create JSF JSP wizard.

You can build the edit form shown in Figure 2-33 with the following steps:

  • Drop a panelHeader component from the ADF Faces Core page of the Component Palette onto the page and set its text attribute in the Property Inspector to "Update Technician Profile".

  • Drop the UpdateProfile data collection from the Data Control Palette and drop it onto the page as an ADF Form.

  • Expand the Operations folder of the TechnicianService data control in the Data Control Palette and drop its Commit built-in operation in the "footer" facet folder of the panelForm in the Structure window. Change its Text property to "Save". Set its Disabled property to "false". Set its Action property to "BackToSearch" by picking it from the list to have the button follow the "BackToSearch" navigation rule you created in the JSF page flow diagram earlier.

  • Drop a Rollback built-in operation to the "footer" facet of the panelForm in the Structure window. Change its Text property to "Cancel". Set its Disabled property to "false". As with the Save button, set this button's Action property to "BackToSearch".

Figure 2-33 Update Technician Profile

Image of Update Technician Profile in Visual Designer

2.13.3 Synchronizing the Search and Edit Page

When a manager finds the technician whose profile she wants to update, clicking the UpdateProfile button will take her to the updateprofile.jspx page. In order for the updateprofile.jspx page to know which technician to edit, you can use a declarative technique to set an attribute to the value of key that represents the current technician's row. Figure 2-34 shows the Structure window after a declarative setActionListener component is added as a child of the Update Profile command button. This setActionListener component evaluates one EL expression to determine the value to copy and another EL expression to determine the property to which to assign this value. The Property Inspector shows the EL expressions indicating that it should copy the value from the rowKeyStr property of the Email binding, and set it into the value of an attribute named rowKeyStr in the request scope.

Figure 2-34 Declaratively Setting a Request Attribute

Image of attribute in Structure window and Property Palette

In the page definition of the updateprofile.jspx page, you can use another declarative technique to invoke an action binding for the built-in setCurrentRowWithKey operation whenever the page is rendered. This action binding accepts a parameter whose value you can provide using the #{requestScope.rowKeyStr} expression. In this way, without writing code you can use the key of the current row from the browse page to set the current row for editing in the UpdateProfile data collection. These steps allow you to synchronize the two pages without writing code.

2.13.4 Controlling Whether Data Appears Initially

For a page like searchtechnicians.jspx, sometimes you want the end user to immediately see results from the view object's query when they see the page for the first time. On other occasions, you might want the user to first have a chance to enter some search criteria before performing the query. Assuming you want the searchtechnicians.jspx page to behave like this, you can conditionalize the initial display of data based on an EL expression. The expression that will come in handy for this tasks allows you to detect whether the page is being displayed for the first time, or whether the end-user has subsequently clicked a button or link on the page, causing the browser to post a request back to the server to handle the event. As shown in Figure 2-35, by setting the RefreshCondition property on the TechniciansIterator binding to the EL expression:

${adfFacesContext.postback == true}

you cause the iterator to present data only after the user has interacted with the page. When the page first renders, this postback property will be false, and the related data collection will be empty.

Figure 2-35 Declaratively Controlling When an Iterator Displays Data

Image of iterator in Stucture window and Property Palette

2.13.5 Running the Final Result

If you run the pages now you will see that they are working. A manager can search for technicians, browse their skills, update a technician's profile, and save changes. If the manager accidentally updates a piece of data that violates a business rule that you've encapsulated inside your domain business layer of entity objects, she will automatically see the error messages. Figure 2-36 shows the results of trying to update the email address to a value that contains the domain name. Similar errors would appear if you tried to violate the other business rules you added to the User entity, or if you had additional view objects that referenced the same entity objects. When multiple managers use the application simultaneously, the ADF components comprising the business service automatically handle multi-user concurrency through row locking, lost-update protection, and application module pooling.

Figure 2-36 Automatic Presentation of Failed Entity Object Business Rules

Image of web page for failed rule validation

2.14 Considering How Much Code Was Involved

In this walkthrough, you've seen the steps to build a simple, yet complete J2EE application with an MVC architecture using:

The experience was both visual and declarative: you didn't have to write any Java code to achieve the results shown here. In fact, if you were to search the workspace directory for all *.java files created during the course of the walkthrough, you would see the results shown in Figure 2-37. Assuming you follow the recommended practices for ADF beginners of only generating Java code when you need it, you see that JDeveloper only created four *.java files. And these files don't even count as "code", since all they contain are the translatable strings related to your ADF business components.

Figure 2-37 Only Java Files Required for This Walkthrough Are Java Message Bundles

Image of Java files listing in command prompt

If you were to peek into one of the message bundle files like UserImplMsgBundle.java, Example 2-1 shows what you would see. It contains the UI control hints you defined for the attributes of the User entity object, along with the error message strings for the business rule validators. By automatically maintaining these standard Java message bundle files for you, JDeveloper simplifies creating multilingual applications. JavaServer Faces provides a similar mechanism to cleanly separate your translatable strings into separate resource files. At runtime, both JSF and ADF use the most appropriate version of the message resources based on the user's browser language settings.

Example 2-1 UserImplMsgBundle Translatable Control Hints and Errors Messages

public class UserImplMsgBundle extends JboResourceBundle {
  static final Object[][] sMessageStrings = {
    { "UserRole_LABEL", "Role" },
    { "PostalCode_TOOLTIP", "Zip" },
    { "UserRole_Rule_0", 
       "Role must be user, technician, or manager" },
    { "Email_Rule_0", 
      "Please use the 8-character username without the domain name" },
    { "User_Rule_0", 
      "This user id is already taken. Please choose another." },
    { "CountryId_TOOLTIP", "Country" },
    { "City_TOOLTIP", "City" },
    { "LastName_LABEL", "Last Name" },
    { "StateProvince_TOOLTIP", "State" },
    { "FirstName_LABEL", "First Name" },
    { "Email_LABEL", "Email Address" },
    { "StreetAddress_TOOLTIP", "Address" },
    { "UserId_LABEL", "User Id" }
  };
// etc.
}

So discounting these message bundle files, you developed the entire walkthrough without writing or generating a line of Java code. This is a testament to the depth and breadth of declarative functionality that the combination of JSF and Oracle ADF can offer you, especially when using the ADF Business Components technology for your business service layer. 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, ADF Business Components, and JSF.