Saturday, February 24, 2007

Oracle Object Types in Oracle ADF

While browsing through OTN JDeveloper forum, I have found a question about how to use Oracle Spatial MDSYS.SDO_GEOMETRY object type with ADF BC. MDSYS.SDO_GEOMETRY object type is described in Oracle Spatial documentation - SDO_GEOMETRY Object Type. So, I have tried to implement support for it in ADF BC using ADF BC Domains - Creating Domains for Oracle Object Types When Useful. It seems, there is enough to generate Entity object from database table - ADF BC domains for spatial column are generated automatically.

I have developed sample application, that shows how to use MDSYS.SDO_GEOMETRY object type in ADF BC applications - However, all principles described in this sample, can be applied when using other Oracle Object Types in your applications. Developed sample use standard MVDEMO schema CITIES table, this schema can be downloaded from - Oracle MapViewer Demo Data Set. Model layer is developed using ADF Business Components, in View layer ADF Faces components are used.

When Entity object for CITIES table is created, type for spatial column is generated - SdoGeometry domain. Additionally, SdoPointType domain is generated. SdoPointType is a subdomain for SdoGeometry.

If we will look deeper, and review Java classes generated by Oracle ADF Business Components Design Time, we could find initStructureDef() method in both - and Code in this method represent object type structure. initStructureDef() method code for SdoGeometry domain:

initStructureDef() method code for SdoPointType domain:

There is no any modifications in ADF BC View object and Application Module, everything is created using default properties.

Ok, now we can switch to the View layer and review how users can edit and update data represented by ADF BC domains. Let's start from Data Control Palette - MDSYS.SDO_GEOMETRY object type is included into Data Control, we can explore and use it. Data Control with domain for object type looks like:

Developed sample application contains two pages - cities.jspx and sdoPointEdit.jspx. First page displays attribute cities data, in sdoPointEdit.jspx spatial data for selected city can be updated. Cities table content:

Let's select San Diego city and press 'Edit Geometry' button. Edit form for spatial information (X, Y) is displayed:

For example, we can change Y value to 33.815 and update SanDiego city geographical location ;-).

Ok, how to be sure, and check that spatial data is really updated. I think, we can use good old SQL*Plus and execute a query - 'SELECT C.LOCATION.SDO_POINT.Y FROM CITIES C WHERE C.RANK90 = 6', on CITIES table. Returned result is as we have expected: 33.815. So, operations on Oracle Object Types in ADF BC application can be implemented really easy. SQL*Plus shell window:

Saturday, February 17, 2007

Multi-selection feature and ADF Faces af:table component

In this post I will describe how to use multi-selection feature in ADF Faces. First of all I should say - multi-selection feature is fully supported by ADF Faces af:table component. However, those who are trying to use this feature for the first time, may have different opinion. You may ask - why? Simply, because multi-selection table by default may have one unneeded property, and this property is a source of a problem for those who are trying to use multi-selection. Which property is unneeded? Ok, let's look deeper and imagine that it is our first time when we are enabling multi-selection table and we have not used it before. One of the possible ways to create multi-selection table is:
  1. Drag and drop method return from Data Control Pallete in JDeveloper, and from pop-up window choose to create ADF Read-only Table. In my sample I'm using method return for Departments;

  2. In Edit Table Columns dialog select 'Enable selection' check-box. Press OK;
  3. Single-selection table in JSPX page is created;
  4. Using right mouse button, click on af:table element in Structure window and choose Properties;
  5. In Table Properties dialog select Formatting tab and instead 'Single Selection' choose 'Multiple Selection' for 'Include Selection Column' option. Press OK.
For af:table component, in JSPX should be generated by JDeveloper something like this:

Ok, there is enough only five steps, to create multi-selection table, let's test it. When table is opened, first row is selected by default. Hm..., it is like in single-selection table.

If you do not care about first row selected by default, let's randomly select any three rows and press Select button:

After Select button is pressed, only row for 'Human Resources' becomes selected:

So, it seems something is not ok. I have decided to research more deeper and have created 'Action Method Binding' for Select button in Backing bean. This method retrieves keys for the selected rows and prints information contained in those rows.

When selectButton_action() method was implemented, I have tested created multi-selection table for the second time. I have selected three rows and pressed Select button, in JDeveloper Log window was displayed only one row (should be three):

07/02/17 12:01:32 Selected Department: Human Resources

So, finally we have found a problem - multi-selection is enabled, but it works like a single-selection. How to solve this? Thanks God, it is simple - there is one property we should remove for af:table component:


Yes, selectionState set to 'selectedRow' is not needed in multi-selection table - remove it. When this property is removed, multi-selection feature works fine. Output in JDeveloper Log window, when three rows are selected:

07/02/17 12:09:39 Selected Department: Human Resources
07/02/17 12:09:39 Selected Department: IT
07/02/17 12:09:39 Selected Department: Executive

Download developed sample - Model layer for this sample is developed using Oracle TopLink, standard HR schema DEPARTMENTS table is used. View layer is implemented using Oracle ADF Faces. Sample contains one JSPX page - multiSelection.jspx, where described multi-selection table functionality is implemented.

Saturday, February 10, 2007

TopLink as a Content Repository for WebCenter Portlet

Almost two weeks ago was released Oracle JDeveloper, and Oracle WebCenter Suite was included into this release. Main new feature - possibility of using portlets in JSF, all new features are described in this document - New in Oracle JDeveloper ( I have decided to research more deeply functionality of WebCenter Suite and to build sample application based on acquired knowledge. There are very useful tutorials on OTN for this topic - Oracle WebCenter Suite Demos and Samples, and - Oracle WebCenter Framework Tutorial. However, I have not found an answer in those documents about how to use data from Model layer as a content repository for standard portlet. So, I have developed a sample -

It was interesting for me to create a content repository for portlet, based on Oracle TopLink object-relational mapping. Developed sample, demonstrates how to use standard portlets with TopLink and how to integrate portlets into ADF application. Sample contains two workspaces, this means that it is based on two independent samples - PortletProvider and PortletConsumer.

PortletProvider implements a portlet along with content repository. PortletConsumer consumes implemented portlet and provides additional logic. Both parts are based on standard HR schema and use TopLink in Model layer.

It is time to describe a business logic of developed application. There are two pages - viewJobs.jspx and editJob.jspx, first page is developed using ADF Faces components and displays a list of jobs, in the second page developed portlet is used. When a job is selected for editing, ADF Faces form is displayed, where job data can be updated. Additionally, a portlet is included into editJob.jspx, this portlet provides a list of employees assigned to the selected job.

In PortletProvider, I'm retrieving employees list by provided jobId, using TopLink Session query.

This method is called from portlet's view.jsp page. So, in such way it is possible to use as a content repository for portlet not only Web page, CSV file or RSS but also data stored in the database, through object-relational mapping.

PortletConsumer consumes deployed portlet and shows it in editJob.jspx. With WebCenter it becomes possible to use portlets in the same page where ADF Faces components are used and even enable communication between a portlet and ADF Faces component. Below I'm demonstrating how it looks in practice.

Let's say we want to edit job entry data for Programmer position:

When Edit button is clicked, selected row jobId attribute value is passed to edit page, where data for edit form and portlet is retrieved using supplied jobId. In editJob.jspx ADF Faces form component and portlet are used:

If we will select another job, for example - Finance Manager:

Then only one employee will be returned by portlet:

Saturday, February 3, 2007

Using #{row.rowKeyStr} property with Composite View Object

Synchronizing view and edit pages in ADF is pretty easy. Let's say, in view page we have a read-only table and in edit page - editable form. The task is to edit selected row. To implement this task, we need to pass a selected row key value to the edit form, in this way selected row data will be opened for editing. If you do not know how to do this, you will find detailed instructions in JDeveloper tutorial, available on OTN - Build an End-to-End Web Application with ADF Business Components and JavaServer Faces.

However, it is possible that in the view page you will be using a table, which will be based on a composite view object (based on several entities). And, editable form in the edit page will be based on another, simple non-composite view object. So, you may have a question - what about #{row.rowKeyStr} passed from view to edit page, it will be correct or no? In fact, it depends, how you have created a composite view object.

Developed sample -, demonstrates how to synchronize a table which is based on composite view object with an edit form which is based on another non-composite view object. This sample is developed using ADF BC and is based on standard HR schema COUNTRIES and LOCATIONS tables. When I was developing this sample, my steps were:
  1. Create entity objects for COUNTRIES and LOCATIONS tables
  2. Create two view objects. One for Locations entity, and another (composite) for Locations and Countries entities. In the composite view object's entities list, first element is for Locations entity and second is for Countries entity
  3. Generate application module
  4. Create faces-config.xml and two pages - viewComposite.jspx and editLocations.jspx along with the relationship between them
  5. Create a table in viewComposite.jspx, based on composite view object
  6. Create an edit form in editLocations.jspx, based on simple view object
  7. Synchronize both pages
The most important step is to correctly create composite view object, if it will be wrong - JBO-25006 error will be generated, when trying to pass #{row.rowKeyStr} and open an edit form. Let's say we want to edit location data for the second row:

When Edit button is clicked and in the case if composite view object is wrong, JBO-25006 will be generated, this means - passed #{row.rowKeyStr} is incorrect:

What's the problem? Why this error is generated? When reviewing created composite view object, I have found that for the second element (Countries) in the composite view object's entities list, 'Key Attribute' is checked:

This means, that #{row.rowKeyStr} for the selected row will be generated not only based on Locations entity 'Key Attribute', but also on Countries 'Key Attribute'. I have deselected 'Key Attribute' for CountryId1, that belongs to Countries entity and there is no more JBO-25006 error:

Oracle and snow in Vilnius

Yesterday evening I was walking near Oracle building in Vilnius and have decided to capture it using my mobile phone. You may notice, that from architectural point of view, this building is little bit similar to Oracle HQ in Redwood.

Unfortunately, there are only Oracle's sales people and there is no Oracle development. By the way, we have a lot of snow in Vilnius, this week...