Monday, September 29, 2008

Second Session on UKOUG 2008 Conference

I already was accepted for UKOUG 2008 Conference with my paper - ADF Task Flow - Based On Practical JDeveloper 11g Experience.

However, during last week in San Francisco (Oracle OpenWorld), I got a phone call from UKOUG office and was invited to deliver second presentation on UKOUG 2008. They have asked to present similar session as I was doing on OpenWorld, Oracle Develop track - My Session at Oracle Open World 2008 (Oracle Develop). It is about Oracle Maps integration with ADF in JDeveloper 11g.

See you during UKOUG 2008, it will be really fun !

Wednesday, September 24, 2008

JDeveloper/ADF News from Oracle OpenWorld 2008

This week I'm in San Francisco, attending Oracle OpenWorld 2008 conference.

One of the main news for me, announced on Ted Farrell keynote - Breaking Enterprise Application Platform Barriers, was a date of JDeveloper 11g production release - October 1. I already can start to play with it, Oracle provided private ACE Directors build on September 21.

Ted Farrell announced Oracle Developer Tools Strategy:


As you see, JDeveloper/ADF is Oracle's strategic tool and framework. Enterprise Pack for Eclipse is second strategic tool, designed for core Java developers.

On the same keynote, vision for Rich Enterprise Applications powered by ADF and WebCenter was defined:


In 11g, ADF becomes really rich framework, with support for WebCenter Services, View layer with JSF Core, Data Visualization, GeoMap and Data Manipulation. ADF can render View layer on different devices, in the future there will be support for iPhone as well.

I already did my session on Monday - My Session at Oracle Open World 2008 (Oracle Develop). It was attended very well, almost full room (60 people), and what is most important no errors in demo development. You can download application - OraMaps11_Session.zip, I have developed during my session:

Saturday, September 13, 2008

JDeveloper 11g - CRUD in ADF Form Component

I'm again back to one of most popular topics on my blog - CRUD implementation in ADF. I was blogging previously about CRUD in 10g and also about CRUD in 11g af:table component - JDeveloper 11g - Create, Edit and Delete operations in ADF Faces af:table component. Today I want to describe CRUD in ADF Form implementation, it is different comparing to ADF Table implementation. Actually, its easy to implement CRUD operations in ADF Form, however it can be complex to implement user friendly CRUD behavior. Main focus of my blog post will be to describe how to achieve user friendly CRUD behavior with ADF Form component.


This post is based on sample application I have developed - UndoCreate.zip. Sample is based on standard HR schema, before running application make sure you have correct DB connection defined.

1) Find Functionality

By default, when you are using ADF Search Form functionality, entered query parameters are stored and are shown again when user will re-open form in Find mode. However, based on my experience, usually it is not a desired behavior. Users prefer not to see old query parameters when they re-open form in Find mode. For example, when some query parameter is entered:


Search is executed and result returned:


And now, when user will press Find button again, previous query criteria should be cleared. It is not cleared by default in ADF, however it is cleared in my sample application:


I'm clearing previous query parameters by executing combination of Rollback, Find, Delete and Create actions in backing bean findButton_action() method associated with Find button.

2) Find Functionality - No Results

When user enters query parameter, that will not give any result, and press Search button - empty form will be returned by default. Example of non-existing query criteria:


Empty form returned by default:


In my sample application, I have changed this default behavior in executeButton_action() method in backing bean. I'm doing a check - if iterator is empty, I'm returning to Find mode and displaying information message - 'No Results found!':


In this case I'm not clearing entered query criteria.

3) Undo Functionality in Create Mode

When form is in Create mode, user usually prefer to have 3 choices - to store entered data and to go to Edit mode, to clear entered data and to remain in Create mode, and to close Create mode by opening form in Find mode:


If with 2 cases - to store entered data or to open form in Find mode everything is less or more okej, there is a problem with a case when user wants to clear entered data and to remain in Create mode. With default Undo functionality, when using only Rollback action, user will be navigated back to Edit mode. In order to change this, I'm re-invoking Create mode initialization from backing bean in undoButton_action() method, it is invoked after default Rollback action. This allows to clear entered data and to stay in Create mode after Undo button is pressed:


4) Undo Functionality in Edit Mode

By default, when Undo button is pressed while in Edit mode and Rollback action is executed, changes will be discarded and at the same time form will be refreshed and will show first row from iterator. This means, user will be navigate from a row he is currently editing to a first row in iterator.

To make this behavior more user friendly, I have implemented custom Rollback functionality in undoButton_action() method in backing bean:


In this code, I'm acquiring form related iterator, getting current row user is editing and refreshing it. At the end, I'm applying Partial refresh to a form in order to display correct data. More information about Rollback functionality you can find in Chris Muir blog post - JDeveloper and the art of the rollback. The same functionality can be applied not only in 11g, but in 10g as well.

With implemented functionality, if user is editing data:


And decides to remove all changes by pressing Undo button, form will remain on the same row:


5) Delete Functionality

When user executes Delete functionality, I can recommend to commit transaction at the same time. In developed sample application, when Delete button is pressed - deleteButton_action() method is invoked, where confirmation popup is opened:


When user confirms Delete action, Commit action is executed at the same time, and row is removed from database.

6) Delete Functionality - Last Row

By default, after user will delete last row from iterator, empty form will be rendered:


Such behavior is not user friendly, much better to navigate to Find mode automatically:


This logic is implemented in deleteDialogListener(DialogEvent dialogEvent) method in backing bean:


7) Confirm or Undo Pending Changes

When user is editing data and there are pending changes (before commit or rollback), based on my experience its better not allow to navigate from current row. For example, when data is changed and there are pending changes:


Buttons related to form logic - Find, Create, Delete and buttons related to form navigation - First, Previous, Next and Delete are blocked. Information message is shown - 'Save or Undo Changes First!' asking user to confirm or dismiss current pending changes:



Information about pending changes is retrieved from bindings.Commit.enabled using Expression Language. Its enough to edit data available in the form and bindings.Commit.enabled will return true.

Wednesday, September 10, 2008

Oracle JDeveloper/ADF Developers Wanted

In my current Oracle JDeveloper/ADF project we are searching for additional developers. Project is based on Oracle Fusion 11g, so it can be excellent opportunity for you to get experience with a new Oracle JDeveloper/ADF release. However, if you already have knowledge in 11g, it will be only a benefit.

If you are interested, drop me an email with Resume. If it will be needed, I will be glad to provide more details.

Saturday, August 30, 2008

Custom LOV Type Functionality in JDeveloper 11g

JDeveloper 11g together with Oracle ADF provides fully functional LOV component, in 11g you can define LOV in Model, for specific attribute in View Object (ADF BC). However, at the moment there is problem with non-model LOV, main problem - Search region for non-model based LOV not available. For example, you can check my previous sample application, developed with JDeveloper 11g TP3 - List-Of-Values Component in Search and Edit Form. In this application, I was using non-model LOV, it was based on variable in Page Definition. However, same type LOV appears differently in JDeveloper 11g TP4 - without Search region, and its not clear if it will have Search region in next release.

So, what I want to say - usually its not recommended to reinvent the weel, but in practice every developer should know how to implement similar component functionality manually. With Oracle ADF you can implement your own LOV, but if you can wait for new release, or not facing problems with standard component, may be there is no need to implement own...

You can download my sample application - CustomLOV.zip. This application demonstrates how to implement own LOV functionality. Next step will be to implement custom ADF reusable component for LOV. Similar as Glasspane ADF reusable component - Glasspane in ADF Faces RC.

Now I will describe main steps, you can follow if there will be a need to have custom LOV type functionality.

First, we need somehow to open dialog window, it can be done relatively straightforward - to put af:clientListener operation on selected af:inputText field and specify dbClick type for this action. This will allow to raise popup with LOV when dbClick event will be catched.


Popup with our custom LOV is opened using Javascript function.

LOV is based on two sections - Search parameters and table with Results:


Main trick in this application is applied for row selection from LOV. Its not a problem to select row and return it by pressing OK button. But, its little bit more complex to return selected row just by double clicking on any row. Its a problem, because selection event is fired on single selection click, but not on on double click. However, you shouldn't forget - we are using ADF, almost all problems can be solved here ;) So, what i did - I have set af:clientListener with dbClick type for Results table and additionally have set af:serverListener for the same Results table.


Idea - when user performs double click event, Javascript client listener function is invoked and this Javascript function invokes Java method declared in af:serverListener. This Java method basically will retrieve current row from Results table iterator - thats all.

Here are two Javascript functions from developed sample application:


First function is responsible for popup with LOV invocation, second reacts to dbClick event in Results table.

Java code in Backing bean is concentrated into three main methods:


First method works as Dialog Listener, this means is invoked when LOV is closed using OK button. Second method is invoked from Javascript client listener function, when dbClick event is catched in LOV Results table. Third function just retrieving value selected in LOV and assigning it to parent field.

In sample application, LOV is defined for LocationId field, just double click on this field:


Our custom LOV is opened with Search region and Results table:


You see, LOV looks like standard Oracle one, however may be even better - possible to control Results table size :) And finally, when row in Results table is double clicked, selected data is returned to parent component:

Sunday, August 24, 2008

JBO-25058 and JBO-26001 exceptions

In a case if you will get JBO-25058 and JBO-26001 exceptions after running application developed with Oracle ADF in JDeveloper 11g, most probably my post will help you.

Those exceptions can be thrown, after refactoring Model part implemented with ADF BC. If Business Components Project file with extension *.jpx is moved to different package, jbo.project property available in bc4j.xcfg file must be changed accordingly. However, it is not changed always automatically. If its not changed, two exceptions will appear at runtime:

1) oracle.security.jazn.JAZNRuntimeException: JBO-25058: Definition JobTitle of type Attribute not found in JobTitle

2) oracle.jbo.NoXMLFileException: JBO-26001: XML File not found for the Container /Model.jpx

In order to solve this issue, double check bc4j.xcfg, ADF BC configuration file. For example, if Model.jpx file (this file can have different name in your project) is in lt.andrejusb.model package, jbo.project property in bc4j.xcfg file must be equal to jbo.project="lt.andrejusb.model.Model".

Sunday, August 17, 2008

Show Buttons based on Disclosed Tab

In 11g it becomes quite common use case to structure application page with tabbed panels. If you develop your pages based on templates, most probably there will be separate area for buttons implemented with af:toolbar tag. And this area will not be included into tabbed panel, since template usually will not contain panel elements. Here is example of such structure:


You will face a problem with this structure, when there will be requirement to display different sets of buttons based on different tab (in Oracle ADF, currently opened tab is called - disclosed). This means, area with buttons should be updated, each time user changes current tab.

You can download sample application, where described case is implemented - TabsButtonsDynamic.zip. This sample contains three tabs - Countries, Jobs and Departments. Based on tab currently selected, different buttons are rendered. However, all buttons are initially created on the page, just rendered conditionally.

There are three steps, in order to have buttons conditionally rendered based on currently disclosed tab:

1. Disclosure Listener

Since there is no AutoSubmit property for Tab component, we will use DisclosureListener in order to catch event, when current tab is disclosed:


In this case, we can use the same DisclosureListener for all Tabs.

2. Partial Target

Generated DisclosureListener method will contain only one line of code - it will refresh af:toolbar area with buttons.


As you have noticed, there is no need to refresh each button individually, its enough to apply partial target to toolbar.

3. Rendered property

Each button should have conditional Rendered property.


This property will return boolean value based on currently disclosed tab.

Thats all, really simple and straightforward solution.

If you will run developed sample application, you will notice 4 buttons displayed while in Countries tab - First, Previous, Next and Last:


There will be 2 buttons in Jobs tab - Create and Save:


Finally, 1 button in Departments tab - Save: