UIX Developer's Guide
Go to Table of Contents
Contents
Go to previous page
Previous
Go to next page
Next

16. Business Components for Java Integration

Oracle's Business Components for Java (BC4J) leverages Java Database Connectivity (JDBC) to provide an optimized and scalable Object-Relational mapping of information stored in the Oracle9i Database. It allows business logic to be centralized at the middle tier while leaving presentation related activities to the web tier.

The BC4J UIX technology integration allows the developer to declaratively specify a UIX page containing elements with attributes bound to BC4J data sources. In addition, the UIX developer can declaratively specify how to validate and update those data sources when events are sent to the web tier by the user.

As we work through the various sections, we'll be building up our understanding of the integration, allowing us to put it all together at the end by building a fully functional declarative Employee Database web application.

This chapter contains the following sections:

Introduction

The BC4J UIX technology integration allows the developer to declaratively define an entire BC4J web application without needing to write any custom Java code. By making it straightforward to leverage the features of BC4J from UIX, the web application developer can focus the majority of her effort on meeting the needs of her customers rather than on the complexities of integrating these two technologies.

BC4J introduces a number of object-oriented concepts to describe information stored in an Oracle9i Database. The top level concept is a root Application Module, which is the logical container for coordinated objects related to a particular task, with optional business logic. Typically, the root Application Module is accessed via a BC4J SessionCookie , allowing the user to find with the same Application Module over many interactions with the web tier. Each root Application Module has a connection to the Oracle9i Database, which is configured via the BC4J concept of a Configuration, which is simply referenced by name.

Each Application Module can contain nested Application Modules, as well as named View Objects. A View Object defines the structural aggregation of one or more Entity Objects selected from the Oracle9i Database by a SQL statement. An ORDER BY clause or WHERE clause may be optionally included in the SQL statement. Each Entity Object provides an object-oriented representation of the data it retrieves from a database object, such as a table or view.  Database foreign key relationships between tables are captured as named Associations between Entity Objects.

Having executed the View Object, the results can be accessed by iterating over each Row in turn and retrieving its Attributes by name. These Attribute names are determined at design time when defining the structure of the View Object. The structural definition of each Attribute in a ViewObject is called an AttributeDef.  In certain cases, the contents of a detail View Object will be dependent on the current Row of a master View Object.  The relationship between these two View Object queries at runtime is captured by a named View Link, which can be defined in terms of an Association between two Entity Objects, one from each View Object.

There may be a business logic need to execute a View Object more than once with a different ORDER BY clause or WHERE clause, but still making both sets of rows available simultaneously. This is achieved by the BC4J concept of a RowSet, which is accessed by name and is logically contained by the View Object.

Now that you have a basic understanding of the object-oriented mapping provided by BC4J, we are ready to create the business components for our example.

Preparing the Business Components

Our Employee Database example uses BC4J components defined in the oracle.cabo.data.jbo.demo.employee Java package. These components can be created using the Oracle JDeveloper9i Business Components wizard on the DEPT and EMP tables of the SCOTT schema to generate the following:

Business Component Description
EmployeeModule the Employee Database Application Module
DeptView the Department View Object
EmpView the Employee View Object
EmpForeignKeyLink the View Link from DeptView to EmpView by department number
EmpSelfKeyLink the View Link from EmpView to EmpView by manager number
Dept the Department Entity Object
Emp the Employee Entity Object
EmpForeignKeyAssoc the Association from Dept to Emp by department number
EmpSelfKeyAssoc the Association from Emp to Emp by manager number

By default, the usage names for each reference to a View Object of type EmpView are EmpView, EmpView1 and EmpView2. We can edit the EmployeeModule to make these usage names a little more meaningful as shown below.

The changes are highlighted in bold.

Our Employee Database enforces that its employees cannot change their Employee number over time, so we must edit the Emp Entity Object, to make the Empno attribute updatable "While New". This will allow us to define the Employee number for a new hire, but protect against accidental update of the Employee number later.

Now that we have prepared all the necessary BC4J business components, we are ready to create our UIX pages.

Associating the Business Components

When creating any UIX page that leverages the BC4J UIX technology integration, you will need to define the corresponding namespace as shown below:

<page xmlns="http://xmlns.oracle.com/uix/controller"
      xmlns:bc4j="http://xmlns.oracle.com/uix/bc4j" >
  ...
</page>

The preferred namespace short prefix is bc4j, which is what we shall use for all of the examples in this chapter.

As you have already seen, a BC4J project can contain a number of different business components. However, not every page in a web application will need to use all of the available business components. A new section, <bc4j:registryDef>, is introduced to define which business components are used by a particular page.

<page xmlns="http://xmlns.oracle.com/uix/controller"
      xmlns:bc4j="http://xmlns.oracle.com/uix/bc4j" >
  <bc4j:registryDef>
    ...
  </bc4j:registryDef>
</page>

The <bc4j:registryDef> section contains a list of the root Application Modules used by the page, as well as the relevant nested Application Modules and View Objects. Each root Application Module is checked out from a pool before rendering begins and is released again after rendering completes. If the release mode is not stateless, then a cookie is written in the response before any user interface content is generated. This cookie will enable the same Application Module to be found when the user makes a subsequent request to the web tier.

Our Employee Database web application consists of three pages.

The page definitions for createEmp.uix and modifyEmp.uix are very similar because they only use the DeptEmpsVO View Object.

<bc4j:registryDef>
 <bc4j:rootAppModuleDef name="EmpAppModule"
                          defFullName="oracle.cabo.data.jbo.demo.employee.EmployeeModule"
                          configName="EmployeeModuleLocal"
                          releaseMode="stateful" >
   <bc4j:viewObjectDef name="CurrentDeptEmpsVO"
                           defFullName="oracle.cabo.data.jbo.demo.employee.EmpView" >
      <bc4j:rowDef name="CreateEmp" >
        <bc4j:propertyKey name="key" />
      </bc4j:rowDef>
    </bc4j:viewObjectDef>
  </bc4j:rootAppModuleDef>
</bc4j:registryDef>

The name attribute will be used to reference the root Application Module (or View Object, Row) from the UINode tree, as well as from the event handlers.  The root Application Module name also serves as an application identifier which should be consistent across all pages in the same application.  The defFullName indicates the type of the Application Module or View Object, the configName attribute tells the BC4J runtime engine which Configuration to use when connecting to the Oracle9i Database, and the releaseMode attribute indicates how state and resources should be managed.

The viewEmps.uix page uses both the AllDeptsVO and the CurrentDeptEmpsVO, so it has the following page definition.

<bc4j:registryDef>
  <bc4j:rootAppModuleDef name="DeptEmpApp"
                          defFullName="oracle.cabo.data.jbo.demo.employee.EmployeeModule"
                          configName="EmployeeModuleLocal"
                          releaseMode="stateful" >
    <bc4j:viewObjectDef name="AllDeptsVO"
                          defFullName="oracle.cabo.data.jbo.demo.employee.DeptView" >
       <bc4j:rowDef name="CurrentDept" />
    </bc4j:viewObjectDef>
    <bc4j:viewObjectDef name="CurrentDeptEmpsVO"
                        defFullName="oracle.cabo.data.jbo.demo.employee.EmpView" /> 
</bc4j:rootAppModuleDef>
</bc4j:registryDef>

Now that we have created our page definitions, we are ready to use them to define the user interface content and to handle events generated by user interactions.

Defining the User Interface

The BC4J UIX technology integration support for defining the user interface falls into three categories.

  1. Each business component concept is represented using a scoping UINode, such that its indexed children are in the scope of that business component. One example is a <bc4j:attrScope>.

  2. The properties of the currently scoped business component can be accessed using a BC4J bound value, such as <bc4j:attrProperty>.

  3. Finally, standard templates are provided which already bind the corresponding BC4J metadata to the appropriate attributes for each of the form elements. An example is <bc4j:inlineMessage> which derives attribute values such as required from the underlying mandatory property of the currently scoped Attribute.

Scopes

During rendering, the BC4J UIX integration represents each business component concept using a scoping UINode. For example, indexed children of a root Application Module scope UINode are in the context of the specified root Application Module. The name must match a root Application Module in the BC4J registry definition. A nested Application Module scope can be established within the context of a <bc4j:rootAppModuleScope> or another <bc4j:appModuleScope>. The name should match an Application Module at the same level in the BC4J registry definition.

For example:

<bc4j:rootAppModuleScope name="root" >
 <contents>
    ...
    <!-- indexed children scoped by the root Application Module
             named "root" -->
    ...
   <bc4j:appModuleScope name="alpha" >
     <contents>
        ...
       <bc4j:appModuleScope name="beta" >
         <contents>
            ...
            <!-- indexed children scoped by nested Application Module "alpha"
                 in nested Application Module "beta", in the root Application 
                 Module named "root" -->
             ...
          </contents>
        </bc4j:appModuleScope>
         ...
      </contents>
    </bc4j:appModuleScope>
    ...
  </contents>
</bc4j:rootAppModuleScope>

A View Object scope can be established within the context of either a <bc4j:rootAppModuleScope> or a <bc4j:appModuleScope>, identified by usage name, whereas a Row Set scope can only be established in the context of a <bc4j:viewObjectScope>, referenced by name. Since a BC4J View Object is also a Row Set, establishing a View Object scope will effectively establish a <bc4j:rowSetScope> for the View Object itself. The Row scope establishes the current Row using the named RowDef from the BC4J registry definition.  By default, first enclosing <bc4j:viewObjectScope> or <bc4j:rowSetScope> automatically puts its current row into scope.

For example:

<bc4j:appModuleScope name="alpha" >
 <contents>
   <bc4j:viewObjectScope name="beta" >
     <contents>
        ...
        <!-- indexed children scoped by View Object "beta", 
             in Application Module "alpha". -->
        ...
       <bc4j:rowSetScope name="gamma" >
         <contents>
            ...
            <!-- indexed children scoped by Row Set "gamma", of
                 View Object "beta", in Application Module "alpha". -->
            ...
           <bc4j:rowScope name="delta" >
             <contents>
                ...
                <!-- indexed children scoped by Row "delta" of
                     Row Set "gamma", of View Object "beta", 
                     in Application Module "alpha". -->
                ...
             </contents>
           </bc4j:rowScope>
         </contents>
       </bc4j:rowSetScope>
     </contents>
   </bc4j:viewObjectScope> 
 </contents></bc4j:appModuleScope>

The structural information of a BC4J View Object is described by the BC4J concept of an AttributeDef. By now you will probably be able to anticipate the syntax for establishing the currently scoped attribute definition. Some BC4J metadata, such as the updatability of an Attribute, depends not only on the AttributeDef but also on the current row. If the AttributeDef is marked as being updatable "While New", then updating this Attribute in a new row will succeed, but updating this Attribute in an existing row will fail. For cases such as these it is necessary to place the current Attribute of the current row into scope. This will also implicitly place the corresponding AttributeDef into scope too.

For example:

<bc4j:viewObjectScope name="alpha" >
 <contents>
   <bc4j:attrDefScope name="beta" >
     <contents>
        ...
        <!-- indexed children scoped by AttributeDef "beta", 
             in View Object "alpha". -->
        ...
     </contents>
   </bc4j:attrDefScope>
   <bc4j:rowScope>
     <contents>
       <bc4j:attrScope name="gamma" >
         <contents>
            ...
            <!-- indexed children scoped by both Attribute "gamma"
                 in the current Row and AttributeDef "gamma" in
                 View Object "alpha". -->
            ...
         </contents>
       </bc4j:attrScope>
     </contents>
   </bc4j:rowScope>
 </contents>
</bc4j:viewObjectScope>

When an attribute is structured, such as an Address attribute having City, Street and Zip code attributes, these can be placed into scope using nested <bc4j:attrScope> elements, as shown below:

...
<bc4j:rowScope>
 <contents>
   <bc4j:attrScope name="Address" >
     <contents>
       <bc4j:attrScope name="City" >
         <contents>
            ...
            <!-- indexed children scoped by Attribute and AttributeDef "City"
                 in structured attribute "Address" in the current Row. -->
            ...
         </contents>
       </bc4j:attrScope>
     </contents>
   </bc4j:attrScope>
 </contents>
</bc4j:rowScope>
...

Of course, this could be cumbersome if there are many structured attributes in the current Row, so a simplified dot notation is also supported:

...
<bc4j:rowScope>
 <contents>
   <bc4j:attrScope name="Address.City" >
     <contents>
        ...
        <!-- indexed children scoped by Attribute and AttributeDef "City"
             in structured attribute "Address" in the current Row. -->
        ...
     </contents>
   </bc4j:attrScope>
 </contents>
</bc4j:rowScope>
...

We have now managed to establish the corresponding scopes in our user interface. The following section describes how information about the current scope can be used to assign the attribute value of any UIX Component.

Form Elements

Now that you are able to establish scopes for each of the BC4J concepts, you will want to be able to use these scopes to bind attribute values for various UIX elements. This is achieved using standard UIX Data Binding. The BC4J UIX integration provides standard bound value elements to access properties of each scope, such as whether the current AttributeDef is mandatory, whether the current Attribute is updatable, or the currently scoped Attribute value.

For example:

<bc4j:viewObjectScope name="alpha" >
 <contents>
   <bc4j:attrScope name="beta" >
     <contents>
       <messageTextInput prompt="Beta" >
          <!-- bind the required attribute to the BC4J 
               "mandatory" AttributeDef metadata. -->
         <boundAttribute name="required" >
           <bc4j:attrDefProperty name="mandatory" />
         </boundAttribute>

          <!-- bind the readOnly attribute to the inverse 
               of the BC4J "updatable" Attribute metadata. -->
         <boundAttribute name="readOnly" >
           <not>
             <bc4j:attrProperty name="updatable" />
           </not>
         </boundAttribute>

          <!-- bind the text attribute to the 
               BC4J "value" Attribute metadata. -->
         <boundAttribute name="text" >
           <bc4j:attrProperty name="value" />
         </boundAttribute>
       </messageTextInput>
     </contents>
   </bc4j:attrScope>
 </contents>
</bc4j:viewObjectScope>

While <bc4j:attrProperty> is very flexible, it can be a bit tedious repeatedly establishing attribute scopes. A <bc4j:attrValue> element both puts the attribute in scope and retrieves a value in one step:


<bc4j:viewObjectScope name="alpha" >
 <contents>
   <messageTextInput prompt="Beta" >
      <!-- bind the text attribute to the value of the
           "beta" attribute. -->
     <boundAttribute name="text" >
       <bc4j:attrValue name="beta" />
     </boundAttribute>
   </messageTextInput>
 </contents>
</bc4j:viewObjectScope>

This is more than just a convenience, though. A <bc4j:attrValue> can go places that a <bc4j:attrScope> can't. In particular, you can't put <bc4j:attrScope> inside a <boundAttribute>, which makes it difficult to bind two values of a bean to two different Attributes. <bc4j:attrValue> solves this. For example, you can bind the "text" of a link to one Attribute and the "destination" to another:


<bc4j:viewObjectScope name="alpha" >
 <contents>
   <link>
      <!-- bind the text attribute to the value of the
           "someText" attribute. -->
     <boundAttribute name="text" >
       <bc4j:attrValue name="someText" />
     </boundAttribute>

      <!-- bind the destination attribute to the value of the
           "someURL" attribute. -->
     <boundAttribute name="destination" >
       <bc4j:attrValue name="someURL" />
     </boundAttribute>
   </messageTextInput>
 </contents>
</bc4j:viewObjectScope>

The flexibility of UIX Data Binding allows you to bind any UIX attribute value to any scoped business component property. However, binding each UIX attribute value individually would become tedious and error prone, so standard BC4J templates have been provided for the common cases. From the UIX developer's perspective, these templates look just like UIX elements in the BC4J namespace.

For example:

<bc4j:viewObjectScope name="alpha" >
 <contents>
   <bc4j:messageTextInput prompt="Beta" attrName="beta" />
 </contents>
</bc4j:viewObjectScope>

Each UIX Components form element, such as <textInput>, <dateField>, <choice> as well as the <messageXXX> equivalents all have corresponding BC4J UIX elements with an attrName attribute.  This internally sets a <bc4j:attrScope> with the specified attrName and binds the BC4J metadata to the relevant attributes of the form element.

Automatic Mode

The <bc4j:table> template adds the capability to derive the set of columns from the currently scoped BC4J View Object attribute metadata. This is called "automatic" mode. The columnStamp named child typically contains a <bc4j:column>. The column header is rendered in the context of the current AttributeDef, while the column contents are rendered once per row in the context of the current Attribute. Another <bc4j:table> named child, <bc4j:keyStamp> is rendered once per row to identify the row.  The <bc4j:rowKey> can be used here to output a form element with the externalized BC4J Row Key as its value.

For example:

<bc4j:table name="alpha" automatic="true" >
  <!-- the key identifying the current row in the table -->
 <bc4j:keyStamp>
   <bc4j:rowKey name="key" />
 </bc4j:keyStamp>
  <!-- the column rendered for each attribute -->
 <bc4j:columnStamp>
    <!-- the attrScope is automatic -->
   <bc4j:column>
     <columnHeader>
        <!-- the sortableHeader defaults its attrName
             from the current attrScope -->
       <bc4j:sortableHeader/>
     </columnHeader>
     <contents>
        <!-- renders the current attribute as read only -->
       <bc4j:input readOnly="true" />
     </contents>
   </bc4j:column>
 </bc4j:columnStamp>
</bc4j:table>

When in automatic mode, the column stamp must contain a component capable of rendering the each BC4J Attribute value, which may not be the same for every column. For this reason, the BC4J UIX integration introduces two new form elements <bc4j:input> and <bc4j:messageInput> which use BC4J metadata about the Attribute type to switch between the various form elements, such as <bc4j:dateField> or <bc4j:textInput>.

Automatic mode is not restricted to tables.  Another new element, <bc4j:region>, adds the capability to repeat an attrStamp named child for each AttributeDef in the currently scoped BC4J View Object. This is typically used for automating the fields displayed in a form. A key named child is rendered before the repeated attrStamp named child.

For example:

<bc4j:region automatic="true" >
  <!-- the key identifying the current row -->
 <bc4j:key>
   <bc4j:rowKey name="key" />
 </bc4j:key>
  <!-- the stamp for each attribute -->
 <bc4j:attrStamp>
   <bc4j:messageInput/>
 </bc4j:attrStamp>
</bc4j:region>

We will use the automatic mode feature for our Employee Database user interface.  The summary page contains a Department and its Employees, with links to create a new hire, update an existing Employee's details or to remove an employee who no longer works for the company.

The first section of the summary page uses a region for the current Department row, in automatic mode, with the attrStamp containing a read only messageInput, as shown below.

<bc4j:rootAppModuleScope name="EmpAppModule" >
 <contents>
   <bc4j:viewObjectScope name="AllDeptsVO" >
     <contents>
       <bc4j:region automatic="true" >
         <bc4j:attrStamp>
           <bc4j:messageInput readOnly="true" />
         </bc4j:attrStamp>
       </bc4j:region>
     </contents>
   </bc4j:viewObjectScope>
 </contents>
</bc4j:rootAppModuleScope>

A similar <bc4j:region> is needed for both the create and modify Employee pages, changing the scope to the CurrentDeptEmpsVO View Object and without the readOnly attribute set on messageInput.

The table of employees in the current Department uses a <bc4j:table> in automatic mode, with the contents of the column in the columnStamp set to read only.

<bc4j:rootAppModuleScope name="EmpAppModule" >
 <contents>
   <bc4j:viewObjectScope name="CurrentDeptEmpsVO" >
     <contents>
       <bc4j:table name="emps" automatic="true" >
         <bc4j:keyStamp>
           <bc4j:rowKey name="key" />
         </bc4j:keyStamp>
         <bc4j:columnStamp>
           <bc4j:column>
             <columnHeader>
              <bc4j:sortableHeader/>
             </columnHeader>
             <contents>
               <bc4j:input readOnly="true" />
             </contents>
           </bc4j:column>
         </bc4j:columnStamp>
       </bc4j:table>
     </contents>
   </bc4j:viewObjectScope>
 </contents>
</bc4j:rootAppModuleScope>

This will render a table with a separate column for each attribute, defaulting the column header text to the attribute name and the contents displayed as read only.  Each column will be sortable by the user clicking on the header text.  The navigation bar will also be presented to allow the user to navigate the CurrentDeptEmpsVO view object.

Now that we have defined our user interface, we must also define the behavior for each UIX Controller event triggered by our page.

Handling Events

Although UIX makes it extremely straightforward to declaratively define UIX Components, even reusable composite components via UIX Templates, as well as UIX Pages with event handlers, there is currently only limited support for declaratively defining event handler behavior. Usually, developers are forced to write their own event handling Java code, referencing it via the <method/> or <instance/> elements. The BC4J UIX technology integration provides standard event handler elements, eliminating the need for custom Java code for common cases.

For example:

<handlers>
 <event name="goto" >
   <bc4j:findRootAppModule name="root" >
     <bc4j:findViewObject name="alpha" >
       <bc4j:goto/>
     </bc4j:findViewObject>
   </bc4j:findRootAppModule>
 </event>
</handlers>

The same technique of first establishing scope applies for event handling as well. The <bc4j:goto> event handler understands the structure of the UIX Components goto event, and applies it to the currently scoped BC4J Row Set (or View Object since this is also a Row Set).  Similarly, the <bc4j:sort> event handler understands and applies the UIX Components sort event.

Our Employee Database summary page, which contains a <bc4j:table>, needs entries for both sort and goto events, as shown below.

<handlers>
 <event source="emps" name="goto" >
   <bc4j:findRootAppModule name="EmpAppModule" >
     <bc4j:findViewObject name="CurrentDeptEmpsVO" >
       <bc4j:goto/>
     </bc4j:findViewObject>
   </bc4j:findRootAppModule>
 </event>

 <event source="emps" name="sort" >
   <bc4j:findRootAppModule name="EmpAppModule" >
     <bc4j:findViewObject name="CurrentDeptEmpsVO" >
       <bc4j:sort/>
     </bc4j:findViewObject>
   </bc4j:findRootAppModule>
 </event>
  ...
</handlers>

The create employee page, which contains an automatic region of all attributes, needs an entry to handle the form submission and apply each parameter value to the corresponding BC4J Row.

<bc4j:registryDef>
 <bc4j:rootAppModuleDef name="EmpAppModule"
                         defFullName="oracle.cabo.data.jbo.demo.employee.EmployeeModule"
                         configName="EmployeeModuleLocal"
                         releaseMode="stateful" >
   <bc4j:viewObjectDef name="CurrentDeptEmpsVO"
                        defFullName="oracle.cabo.data.jbo.demo.employee.EmpView" >
    <!-- setting the "autoCreate" attribute allows a default Row
          to be created when the Key does not locate an existing
          Row. -->
       <bc4j:rowDef name="CreateEmp" autoCreate="true" >
     <bc4j:propertyKey name="key" />
    </bc4j:rowDef>
   </bc4j:viewObjectDef>
 </bc4j:rootAppModuleDef>
</bc4j:registryDef>
...
<handlers>
 <event name="apply" >
   <bc4j:findRootAppModule name="EmpAppModule" >
     <bc4j:findViewObject name="CurrentDeptEmpsVO" >
       <!-- find the row identified by the RowDef "CreateEmp" above, then
             set the region automatically, insert the row and commit the 
             changes. If no validation errors occur, navigate to the 
             "viewEmps" summary page -->
       <bc4j:findRow name="CreateEmp" >
        <!-- the Row Key can change during form submission
              specifically when the Row is automatically created.
              transfer current key value to page property
              for "CreateEmp" RowDef above -->
        <bc4j:setPageProperty name="key" >
          <bc4j:stringKey/>
        </bc4j:setPageProperty>
         <bc4j:setRegion automatic="true" />
         <bc4j:insertRow/>
         <bc4j:commit/>
         <ctrl:go name="viewEmps" />
       </bc4j:findRow>
     </bc4j:findViewObject>
   </bc4j:findRootAppModule>                      
 </event>
  ...
</handlers>

The modify employee page, which also contains an automatic region of all attributes, needs a similar entry, however it obtains the current row key from a page property when the page is first accessed.  This key does not change during form submission so there is no need to render the row key as a form parameter.

Now that we have defined our BC4J event handlers, we are ready to complete our Employee Database application by adding the page navigation logic.

Completing the Web Application

The final phase of the Employee Database application is to add navigation logic between the pages.  The summary page contains a button linking directly to the create employee page, as well as an update button which navigates to the modify employee page, passing the key of the selected BC4J Row as a page property.

Both the create and modify pages contain a button to apply the changes, as well as a cancel button which will rollback the current changes and navigate back to the summary page.

The UIX Controller must be configured to register the BC4J UIExtension before any BC4J UIX elements will be recognized.  This is achieved by adding the UI extension to your uix-config.xml file:


 <?xml version="1.0" encoding="ISO-8859-1"?> 
 <configurations xmlns="http://xmlns.oracle.com/uix/config">
   <application-configuration>
     <ui-extensions>
       <ui-extension>oracle.cabo.data.jbo.ui.JboUIExtension</ui-extension>
     </ui-extensions>
   </application-configuration>
 </configurations>

For more information on uix-config.xml, see the Configuration chapter.

The full source for the Employee Database application is included below.

Display Employees for Department  (viewEmps.uix)

<?xml version="1.0" encoding="UTF-8" ?>

<page xmlns="http://xmlns.oracle.com/uix/controller"
      xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
      xmlns:ui="http://xmlns.oracle.com/uix/ui"
      xmlns:bc4j="http://xmlns.oracle.com/uix/bc4j" >

<bc4j:registryDef>
 <bc4j:rootAppModuleDef name="EmpAppModule"
                         defFullName="oracle.cabo.data.jbo.demo.employee.EmployeeModule"
                         configName="EmployeeModuleLocal"
                         releaseMode="stateful" >
  <bc4j:viewObjectDef name="AllDeptsVO"
                       defFullName="oracle.cabo.data.jbo.demo.employee.DeptView" />
  <bc4j:viewObjectDef name="CurrentDeptEmpsVO"
                       defFullName="oracle.cabo.data.jbo.demo.employee.EmpView"
                       rangeSize="3" />
 </bc4j:rootAppModule>
</bc4j:registryDef>

<content>

 <pageLayout xmlns="http://xmlns.oracle.com/uix/ui"
              xmlns:data="http://xmlns.oracle.com/uix/ui"
              title="View Emps" >
  <contents>
    <!-- include the view source link -->
   <link text="View Source" ctrl:event="viewSource" />

    <!-- this will contain any validation errors after form
         submission -->
   <messageBox automatic="true" />

   <form name="emp" >
    <contents>
     <tableLayout>
      <contents>
       <bc4j:rootAppModuleScope name="EmpAppModule" >
        <contents>
         <bc4j:viewObjectScope name="AllDeptsVO" >
          <contents>
            <!-- placing the region in automatic mode will cause the key
                 named child to be rendered, followed by each attribute 
                 in the ViewObject using the attrStamp named child. -->
           <bc4j:region automatic="true" >
             <!-- the stamp for each attribute -->
            <bc4j:attrStamp>
             <bc4j:messageInput readOnly="true" />
            </bc4j:attrStamp>
           </bc4j:region>

           <bc4j:viewObjectScope name="CurrentDeptEmpsVO" >
            <contents>
              <!-- placing the table in automatic mode will cause the table
                   to contain the keyStamp named child followed by the 
                   columnStamp named child for each attribute in the 
                   ViewObject. -->
             <bc4j:table name="emps" automatic="true" width="80%" >
              <tableSelection>
                <!-- single selection for each row in the table -->
               <singleSelection>
                <contents>
                  <!-- the update button causes the currently selected
                       row to be sent to the update page -->
                 <submitButton text="Update"
                                ctrl:event="update" />
                  <!-- the delete button causes the currently selected
                       row to be removed -->
                 <submitButton text="Delete"
                                ctrl:event="delete" />
                </contents>
               </singleSelection>
              </tableSelection>
               <!-- the key identifying the current row in the table -->
              <bc4j:keyStamp>
               <bc4j:rowKey name="key" />
              </bc4j:keyStamp>
               <!-- the column rendered for each attribute -->
              <bc4j:columnStamp>
                <!-- the attrScope is automatic -->
               <bc4j:column>
                <columnHeader>
                  <!-- the sortableHeader defaults its attrName
                       from the current attrScope -->
                 <bc4j:sortableHeader/>
                </columnHeader>
                <contents>
                  <!-- renders the current attribute as read only -->
                 <bc4j:input readOnly="true"/>
                </contents>
               </bc4j:column>
              </bc4j:columnStamp>
             </bc4j:table>
            </contents>
           </bc4j:viewObjectScope>
          </contents>
         </bc4j:viewObjectScope>
        </contents>
       </bc4j:rootAppModuleScope>
      </contents>
     </tableLayout>
    </contents>
   </form>    
  </contents>
   
  <contentFooter>
    <!-- the create button redirects to the create page -->
   <button text="Create" ctrl:event="create" />
  </contentFooter>
 </pageLayout>
</content>

<handlers>

 <event name="sort" source="emps" >
   <!-- finding the ApplicationModule causes it to be checked out from the
        ApplicationPool.  It is released after rendering completes. -->
  <bc4j:findRootAppModule name="EmpAppModule" >
    <!-- establish the ViewObject scope -->
   <bc4j:findViewObject name="CurrentDeptEmpsVO" >
     <!-- sort by the submitted attribute name -->
    <bc4j:sort/>
   </bc4j:findViewObject>
  </bc4j:findRootAppModule>
 </event>

 <event name="goto" source="emps" >
   <!-- finding the ApplicationModule causes it to be checked out from the
        ApplicationPool.  It is released after rendering completes. -->
  <bc4j:findRootAppModule name="EmpAppModule" >
    <!-- establish the ViewObject scope -->
   <bc4j:findViewObject name="CurrentDeptEmpsVO" >
     <!-- navigate to the submitted range -->
    <bc4j:goto/>
   </bc4j:findViewObject>
  </bc4j:findRootAppModule>
 </event>

 <event name="create" >
   <!-- forward to the create page -->
  <go name="createEmp" />
 </event>

 <event name="update" >
   <!-- forward to the update page, passing the selected key
        as a page property -->
  <go name="modifyEmp" >
   <property name="key" >
    <selection name="emps" key="key" />
   </property>
  </go>
 </event>

 <event name="delete" >
   <!-- finding the ApplicationModule causes it to be checked out from the
        ApplicationPool.  It is released after rendering completes. -->
   <bc4j:findRootAppModule name="EmpAppModule" >
     <!-- establish the ViewObject scope -->
    <bc4j:findViewObject name="CurrentDeptEmpsVO" >
      <!-- find the selected ViewObject row -->
     <bc4j:findRowByKey>
      <bc4j:keyBinding>
       <bc4j:selectionKey name="emps" key="key" />
      </bc4j:keyBinding>
      <bc4j:handlers>
        <!-- remove the selected ViewObject row -->
       <bc4j:removeRow />
        <!-- execute the query to eliminate dead row access -->
       <bc4j:executeQuery/>
      </bc4j:handlers>
     </bc4j:findRowByKey>
    </bc4j:findViewObject>

    <!-- commit the transaction, forwards to self automatically -->
   <bc4j:commit/>
  </bc4j:findRootAppModule>                      
 </event>
                         
</handlers>

</page>

Create a New Employee  (createEmp.uix)

<?xml version="1.0" encoding="UTF-8" ?>

<page xmlns="http://xmlns.oracle.com/uix/controller"
      xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
      xmlns:ui="http://xmlns.oracle.com/uix/ui"
      xmlns:bc4j="http://xmlns.oracle.com/uix/bc4j" >

<bc4j:registryDef>
 <bc4j:rootAppModuleDef name="EmpAppModule"
                         defFullName="oracle.cabo.data.jbo.demo.employee.EmployeeModule"
                         configName="EmployeeModuleLocal"
                         releaseMode="stateful" >
  <bc4j:viewObjectDef name="CurrentDeptEmpsVO"
                       defFullName="oracle.cabo.data.jbo.demo.employee.EmpView" >
   <!-- setting the "autoCreate" attribute allows a default Row
         to be created when the Key does not locate an existing
         Row. -->
   <bc4j:rowDef name="CreateEmp" autoCreate="true" >
    <bc4j:propertyKey name="key" />
   </bc4j:rowDef>
  </bc4j:viewObjectDef>
 </bc4j:rootAppModuleDef>
</bc4j:registryDef>

<content>

 <pageLayout xmlns="http://xmlns.oracle.com/uix/ui"
              xmlns:data="http://xmlns.oracle.com/uix/ui"
              title="Create Emp" >
  <contents>
    <!-- include the view source link -->
   <link text="View Source" ctrl:event="viewSource" />

    <!-- this will contain any validation errors after form
         submission -->
   <messageBox automatic="true" />
    
   <form name="emp" >
    <contents>
      <!-- we cannot implicitly determine that events
           will be triggered because submit buttons are 
           outside the form scope, so add the placeholder
           explicitly -->
     <formParameter name="event" />
      <!-- layout the fields in two columns -->      
     <tableLayout>
      <contents>
       <bc4j:rootAppModuleScope name="DeptEmpApp" >
        <contents>
         <bc4j:viewObjectScope name="CurrentDeptEmpsVO" >
          <contents>
           <bc4j:rowScope name="CreateEmp" >
            <contents> 
              <!-- placing the region in automatic mode will cause the key
                   named child to be rendered, followed by each attribute 
                   in the ViewObject using the attrStamp named child. -->
             <bc4j:region automatic="true" >
               <!-- the key identifying this region -->
              <bc4j:key>
               <bc4j:rowKey name="key" />
              </bc4j:key>
               <!-- the stamp for each attribute -->
              <bc4j:attrStamp>
                <!-- the attrScope is automatic -->
               <bc4j:messageInput/>
              </bc4j:attrStamp>
             </bc4j:region>
            </contents>
           </bc4j:rowScope>
          </contents>
         </bc4j:viewObjectScope>
        </contents>
       </bc4j:rootAppModuleScope>
      </contents>
     </tableLayout>
    </contents>
   </form>  
  </contents>

  <contentFooter>
    <!-- place a row of buttons below the content -->
   <pageButtonBar>
    <contents>
      <!-- the cancel button performs a transaction rollback -->
     <button text="Cancel" ctrl:event="cancel" />
      <!-- the create button submits the user-entered
           form data -->
     <submitButton text="Create" formName="emp"
                    ctrl:event="apply" />
    </contents>
   </pageButtonBar>
  </contentFooter>
   
 </pageLayout>

</content>

<handlers>

 <event name="cancel" >
   <!-- finding the ApplicationModule causes it to be checked out from the
        ApplicationPool.  It is released after rendering completes. -->
  <bc4j:findRootAppModule name="EmpAppModule" >
    <!-- rollback the current transaction -->
   <bc4j:rollback/>
    <!-- forward to the summary page -->
   <go name="viewEmps" />
  </bc4j:findRootAppModule>
 </event>

 <event name="apply" >
   <!-- finding the ApplicationModule causes it to be checked out from the
        ApplicationPool.  It is released after rendering completes. -->
  <bc4j:findRootAppModule name="EmpAppModule" >
    <!-- establish the ViewObject scope -->
   <bc4j:findViewObject name="CurrentDeptEmpsVO" >
    <!-- find the row identified by the RowDef "CreateEmp" above, then
          set the region automatically, insert the row and commit the 
          changes. If no validation errors occur, navigate to the 
          "viewEmps" summary page -->
    <bc4j:findRow name="CreateEmp" >
     <!-- the Row Key can change during form submission
           specifically when the Row is automatically created.
           transfer current key value to page property
           for "CreateEmp" RowDef above -->
     <bc4j:setPageProperty name="key" >
      <bc4j:stringKey/>
     </bc4j:setPageProperty>
     <bc4j:setRegion automatic="true" />
     <bc4j:insertRow/>
     <bc4j:commit/>
     <ctrl:go name="viewEmps" />
    </bc4j:findRow>
    </bc4j:findViewObject>
  </bc4j:findRootAppModule>
 </event>

</handlers>

</page>

Modify an Existing Employee  (modifyEmp.uix)

<?xml version="1.0" encoding="UTF-8" ?>

<page xmlns="http://xmlns.oracle.com/uix/controller"
      xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
      xmlns:ui="http://xmlns.oracle.com/uix/ui"
      xmlns:bc4j="http://xmlns.oracle.com/uix/bc4j" >

<bc4j:registryDef>
 <bc4j:rootAppModuleDef name="EmpAppModule"
                         defFullName="oracle.cabo.data.jbo.demo.employee.EmployeeModule"
                         configName="EmployeeModuleLocal"
                         releaseMode="stateful" >
  <bc4j:viewObjectDef name="CurrentDeptEmpsVO"
                       defFullName="oracle.cabo.data.jbo.demo.employee.EmpView" >
     <!-- the current row is keyed by the key page property -->
    <bc4j:rowDef name="CurrentEmp" >
     <bc4j:propertyKey name="key" />
    </bc4j:rowDef>
  </bc4j:viewObjectDef>
 </bc4j:rootAppModuleDef>
</bc4j:registryDef>

<content>

 <pageLayout xmlns="http://xmlns.oracle.com/uix/ui"
              xmlns:data="http://xmlns.oracle.com/uix/ui"
              title="Update Emp" >
  <contents>
    <!-- include the view source link -->
   <link text="View Source" ctrl:event="viewSource" />

    <!-- this will contain any validation errors after form
         submission -->
   <messageBox automatic="true" />
    
   <form name="edit" >
    <contents>
      <!-- we cannot implicitly determine that events
           will be triggered because submit buttons are 
           outside the form scope, so add the placeholder
           explicitly -->
     <formParameter name="event" />
      <!-- layout the fields in two columns -->      
     <tableLayout>
      <contents>
       <bc4j:rootAppModuleScope name="EmpAppModule" >
        <contents>
         <bc4j:viewObjectScope name="CurrentDeptEmpsVO" >
          <contents>
           <bc4j:rowScope name="CurrentEmp" >
            <contents>
              <!-- placing the region in automatic mode will cause the key
                   named child to be rendered, followed by each attribute 
                   in the ViewObject using the attrStamp named child. -->
             <bc4j:region automatic="true" >
               <!-- the key identifying the current row -->
              <bc4j:key>
               <bc4j:rowKey name="key" />
              </bc4j:key>
               <!-- the stamp for each attribute -->
              <bc4j:attrStamp>
                <!-- the attrScope is automatic -->
               <bc4j:messageInput/>
              </bc4j:attrStamp>
             </bc4j:region>
            </contents>
           </bc4j:rowScope>
          </contents>
         </bc4j:viewObjectScope>
        </contents>
       </bc4j:rootAppModuleScope>
      </contents>
     </tableLayout>
    </contents>
   </form>  
  </contents>

  <contentFooter>
    <!-- place a row of buttons below the content -->
   <pageButtonBar>
    <contents>
      <!-- the cancel button performs a transaction rollback -->
     <button text="Cancel" ctrl:event="cancel" />
      <!-- the update button submits the user-entered
           form data -->
     <submitButton text="Update" formName="edit"
                    ctrl:event="apply" />
    </contents>
   </pageButtonBar>
  </contentFooter>
   
 </pageLayout>

</content>

<handlers>

 <event name="cancel" >
   <!-- finding the ApplicationModule causes it to be checked out from the
        ApplicationPool.  It is released after rendering completes. -->
  <bc4j:findRootAppModule name="EmpAppModule" >
    <!-- rollback the current transaction -->
   <bc4j:rollback/>
    <!-- forward to the summary page -->
   <go name="viewEmps" />
  </bc4j:findRootAppModule>
 </event>

 <event name="apply" >
   <!-- finding the ApplicationModule causes it to be checked out from the
        ApplicationPool.  It is released after rendering completes. -->
  <bc4j:findRootAppModule name="EmpAppModule" >
    <!-- establish the ViewObject scope -->
   <bc4j:findViewObject name="CurrentDeptEmpsVO" >
     <!-- find the row by key -->
    <bc4j:findRow name="CurrentEmp" >
      <!-- set the region of attributes automatically -->
     <bc4j:setRegion automatic="true" />
      <!-- commit the transaction -->
     <bc4j:commit/>
      <!-- forward to the summary page -->
     <ctrl:go name="viewEmps" />
    </bc4j:findRow>
   </bc4j:findViewObject>
  </bc4j:findRootAppModule>                      
 </event>

</handlers>

</page>

Controlling the Choice of Columns and Fields In Your ViewObjects

In the examples we've shown so far, we've used the "automatic" property of <bc4j:table> and <bc4j:region>. This is great for demonstration code and quick applications, since it automatically iterates through all of your ViewObject's attributes. But it's also limiting. You can't hide columns or fields. You can't reorder the fields or columns, or change the layout. You also don't have access to any of the special properties on our specific component types, since you're using nothing but <bc4j:messageInput> and <bc4j:input>. To get at all these features, you'll have to turn off automatic mode and explicitly state which columns you want.

Let's start with the "viewEmps.uix" example. First, we'll turn off automatic mode on the table. You can either set "automatic" to false or just get rid of it altogether. With automatic mode off, the <bc4j:columnStamp> will be ignored, and you have to use a <contents> section:


              <!-- Our table; automatic mode is off -->
              <bc4j:table name="emps"
                          width="80%" alternateText="No Employees found" >
               <tableSelection>
                <!-- single selection for each row in the table -->
                <singleSelection>
                 <contents>
                  <submitButton text="Update"
                                ctrl:event="update" />
                  <submitButton text="Delete"
                                ctrl:event="delete" />
                 </contents>
                </singleSelection>
               </tableSelection>
               <bc4j:keyStamp>
                <bc4j:rowKey name="key" />
               </bc4j:keyStamp>

               <contents>
                 <!-- We'll add the columns explicitly -->
               </contents>
              </bc4j:table>

We've turned automatic mode off, but now we've got an empty table. Let's add two columns:


              <!-- Our table; automatic mode is off -->
              <bc4j:table name="emps"
                          width="80%" alternateText="No Employees found" >

                 .......

               <bc4j:keyStamp>
                <bc4j:rowKey name="key" />
               </bc4j:keyStamp>

               <contents>
                 <!-- We'll add the columns explicitly -->
                 <bc4j:column attrName="Job">
                    <columnHeader>Job</columnHeader>
                    <contents>
                      <bc4j:styledText styleClass="OraDataText"/>
                    </contents>
                 </bc4j:column>

                 <bc4j:column attrName="Ename"/>
                   <columnHeader>
                    <!-- the sortableHeader defaults its attrName
                         from the current attrScope -->
                    <bc4j:sortableHeader text="Employee Name"/>
                    <contents>
                      <bc4j:styledText/>
                    </contents>
                   </columnHeader>
                 </bc4j:column>

               </contents>
              </bc4j:table>

We've added back just two of the columns of this table. All the other columns will be completely hidden. But we've done a lot more, just to show the added flexibility in this scenario:

You can also add columns that are unrelated with any of the rows in your ViewObject, or are derived in more complicated ways than any of the built-in component table code allows.

This is all you need to do for tables or uneditable regions. For editable regions, you should do a little bit more to ensure that only the attributes that are being edited are written back to the ViewObject. Let's take the "apply" event handler of "modifyEmp.uix":


 <event name="apply" >
   <!-- finding the ApplicationModule causes it to be checked out from the
        ApplicationPool.  It is released after rendering completes. -->
  <bc4j:findRootAppModule name="EmpAppModule" >
    <!-- establish the ViewObject scope -->
   <bc4j:findViewObject name="CurrentDeptEmpsVO" >
     <!-- find the row by key -->
    <bc4j:findRow name="CurrentEmp" >
      <!-- set the region of attributes automatically -->
     <bc4j:setRegion automatic="true" />
      <!-- commit the transaction -->
     <bc4j:commit/>
      <!-- forward to the summary page -->
     <ctrl:go name="viewEmps" />
    </bc4j:findRow>
   </bc4j:findViewObject>
  </bc4j:findRootAppModule>                      
 </event>

Instead of using <bc4j:setRegion automatic="true"/>, we'll need to remove that and use one <bc4j:setAttribute< for every attribute in use:


 <event name="apply" >
  <bc4j:findRootAppModule name="EmpAppModule" >
   <bc4j:findViewObject name="CurrentDeptEmpsVO" >
    <bc4j:findRow name="CurrentEmp" >
      <!-- set two attributes explicitly -->
     <bc4j:setAttribute name="Job" />
     <bc4j:setAttribute name="Ename" />

     <bc4j:commit/>
     <ctrl:go name="viewEmps" />
    </bc4j:findRow>
   </bc4j:findViewObject>
  </bc4j:findRootAppModule>                      
 </event>

Accessing BC4J Objects in Java

Once your application becomes sufficiently complicated, you'll inevitably reach the day that you can't quite accomplish everything declaratively. When you have to write Java code, BC4J UIX lets you get at all the BC4J objects from your standard UIX DataProviders and EventHandlers. In this example, we'll walk through creating a custom DataObjectList out of the EMP database.

Let's start by writing the DataObjectList itself. It'll be a very simple, almost featureless class. It operates strictly on the current range of a RowIterator (remember that ViewObjects are a subclass of RowIterator), and maps attribute names directly to DataObject keys:


import oracle.cabo.ui.RenderingContext;
import oracle.cabo.ui.data.DataObject;
import oracle.cabo.ui.data.DataObjectList;

import oracle.jbo.NoDefException;
import oracle.jbo.Row;
import oracle.jbo.RowIterator;

public class JBODataObjectList implements DataObjectList
{
  /**
   * Create a data object list based on the current range of 
   * this row iterator.
   */
  public JBODataObjectList(RowIterator iterator)
  {
    this(iterator, Integer.MAX_VALUE);

  }


  /**
   * Create a data object list based on the current range of 
   * this row iterator, with a restricted size.
   */
  public JBODataObjectList(RowIterator iterator, int maxSize)
  {
    _iterator = iterator;
    _size     = Math.min(_iterator.getRowCountInRange(), maxSize);
  }

  /**
   * Return the size of the list.
   */
  public int getLength()
  {
    return _size;
  }

  /**
   * Get an item from the list.
   */
  public DataObject getItem(int index)
  {
    // Make sure we're in range
    if ((index < 0) || (index >= _size))
      throw new IndexOutOfBoundsException();

    Row row = _iterator.getRowAtRangeIndex(index);
    if (row == null)
      return null;

    return new DO(row);
  }

  // An inner class that handles a single row
  static private final class DO implements DataObject
  {
    public DO(Row row)
    {
      _row = row;
    }

    public Object selectValue(RenderingContext context, Object key)
    {
      // Make sure that the key is non-null
      if (key != null)
      {
        try
        {
          // Treat the key as an attribute name
          return _row.getAttribute(key.toString());
        }
        catch (NoDefException nde)
        {
          // Do nothing.  It's legal to pass an invald key to DataObjects.
        }
      }

      return null;
    }

    private final Row _row;
  }

  private final RowIterator _iterator;
  private final int         _size;
}

This is fairly straightforward code, but how do you get the ViewObject to pass to the constructor? UIX provides two classes that are especially useful here:

A key point to remember is that these can only retrieve scoped BC4J objects. So, if you need to retrieve a root ApplicationModule, you have to be somewhere inside of a <bc4j:rootAppModuleScope<:


  <bc4j:rootAppModuleScope name="EmpAppModule"
                           xmlns="http://xmlns.oracle.com/uix/ui"
                           xmlns:data="http://xmlns.oracle.com/uix/ui">
   <contents>
    <dataScope>
     <provider>
      <!-- YourClass.getSomeData will be able to get at the application
           module -->
      <data name="fromJava">
       <method class="YourClass" method="getSomeData">
      </data>
     </provider>
     <contents>
      ...
     </contents>
    </dataScope>
   </contents>
  </bc4j:rootAppModuleScope>

So, let's write a data provider that gets at the current view object and turns it into a DataObjectList:


import java.util.HashMap;
import oracle.jbo.ViewObject;
import oracle.cabo.data.jbo.ui.bind.UIBindingUtils;
import oracle.cabo.ui.RenderingContext;

public class JavaHook
{
  static public Object getList(
    RenderingContext context,
    String           ns,
    String           name)
  {
    ViewObject vo = UIBindingUtils.getViewObject(context);
    if (vo == null)
      return null;

    HashMap values = new HashMap();
    values.put("list", new JBODataObjectList(vo));
    return values;
  }
}

UIBindingUtils.getViewObject() returns the currently scoped ViewObject. If we successfully find it, we turn the ViewObject into a DataObjectList, and stick it in a HashMap under the "list" key.

Finally, let's wrap this code up inside our uiXML page:


<?xml version="1.0" encoding="UTF-8" ?>
<page xmlns="http://xmlns.oracle.com/uix/controller"
      xmlns:ui="http://xmlns.oracle.com/uix/ui"
      xmlns:bc4j="http://xmlns.oracle.com/uix/bc4j" >

 <bc4j:registryDef>
  <bc4j:rootAppModuleDef name="EmpAppModule"
                         defFullName="oracle.cabo.data.jbo.demo.employee.EmployeeModule"
                         configName="EmployeeModuleLocal"
                         releaseMode="stateful" >
  <bc4j:viewObjectDef name="EmpView"
                      defFullName="oracle.cabo.data.jbo.demo.employee.EmpView"
                      rangeSize="10" />

  </bc4j:rootAppModuleDef>
 </bc4j:registryDef>

 <content>
  <bc4j:rootAppModuleScope name="EmpAppModule"
                           xmlns="http://xmlns.oracle.com/uix/ui"
                           xmlns:data="http://xmlns.oracle.com/uix/ui">
   <contents>
    <form name="emp">
     <contents>
      <!-- Move inside of the ViewObject scope -->
      <bc4j:viewObjectScope name="EmpView">
       <contents>
        <dataScope>
         <provider>
          <!-- Attach the getList DataProvider -->
          <data name="fromJava">
           <method class="JavaHook" method="getList"/>
          </data>
         </provider>
         <contents>
          <choice name="foo">
           <!-- Use the "list" to derive a repeating series of 
                   elements -->
           <contents data:childData="list@fromJava">
            <option data:text="Ename" data:value="Empno"/>
           </contents>
          </choice>
         </contents>
        </dataScope>
       </contents>
      </bc4j:viewObjectScope>
     </contents>
    </form>
   </contents>
  </bc4j:rootAppModuleScope>
 </content>
</page>

Most of this page is the same content you've used in other pages. The only differences are the addition of a <dataScope> with a <method> element, and the data:childData inside of the <choice>'s <contents>. If you're not familiar with the data:childData syntax, you can read about it in the Dynamic Structure for UIX Pages chapter.

You can use a similar technique inside event handlers, but instead of using UIBindingUtils to get at BC4J objects, you'll use ServletBindingUtils.

Using <bc4j:rowStamp>

The techniques just presented for Java-based access make it possible to repeat UI content once for each row in a ViewObject, but there's a much easier way. The <bc4j:viewObjectScope> element supports a <bc4j:rowStamp> child that automates this pattern. UIX will automatically repeat the content of <bc4j:rowStamp> once for every row in the current range of the view object. This is especially useful for binding the children of a <bc4j:choice> or <bc4j:list<. You can explicitly list the set of children for a choice:


  <bc4j:viewObjectScope name="EmpView">
   <contents>
     <bc4j:choice attrName="Job">
      <contents>
       <option text="Clerk" value="CLERK"/>
       <option text="Manager" value="MANAGER"/>
       <!-- etc. -->
      </contents>
     </bc4j:choice>
   </contents>
  </bc4j:viewObjectScope>

But it's frequently better to derive lists like this from database tables, and <bc4j:rowStamp> makes this much easier:


  <bc4j:viewObjectScope name="EmpView">
   <contents>
     <bc4j:choice attrName="Job">
      <contents>
       <bc4j:viewObjectScope name="JobListView">
         <bc4j:rowStamp>
           <option>
             <boundAttribute name="text">
               <bc4j:attrValue name="JobName"/>
             </boundAttribute>
             <boundAttribute name="value">
               <bc4j:attrValue name="JobId"/>
             </boundAttribute>
           </option>
         </bc4j:rowStamp>
       </bc4j:viewObjectScope>
      </contents>
     </bc4j:choice>
   </contents>
  </bc4j:viewObjectScope>

Instead of listing out each <option>, we use a new view object that contains a list of all possible jobs, and drive the "text" and "value" of the <option> off of its "JobName" and "JobId" attributes.

This example can be cleaned up even further with the <bc4j:option> element:


  <bc4j:viewObjectScope name="EmpView">
   <contents>
     <bc4j:choice attrName="Job">
      <contents>
       <bc4j:viewObjectScope name="JobListView">
         <bc4j:rowStamp>
           <bc4j:option attrName="JobId" textAttrName="JobName"/>
         </bc4j:rowStamp>
       </bc4j:viewObjectScope>
      </contents>
     </bc4j:choice>
   </contents>
  </bc4j:viewObjectScope>

Conclusion

The BC4J UIX technology integration allows developers to quickly and easily define UIX pages which interact with a real world data source, the Oracle9i Database, via Business Components for Java.