Sunday, September 30, 2007

Sofia - Beautiful City

On this week I was visiting Sofia, Bulgarian capital. City is a mix of western and eastern culture, this makes it unique and beautiful. Definitely you should find time to visit it, you will have a chance to meet very warm and friendly people ;).

St. Alexander Nevsky Cathedral, it was built in honour to the Russian soldiers who died during the Russo-Turkish War of 1877-1878. It looks really impressive.

Friday, September 14, 2007

Automatic Java class invocation after deployment of Oracle ADF application

Recently I was implementing requirement of automatic Java class invocation right after application is deployed on Oracle Application Server. Automatic class loading possibly is required when for example job scheduling system like Quartz is used by application. This means that job scheduling should be started right after application is deployed, so main question is how to to invoke Java class automatically.

In developed sample application - DeploymentRegistration.zip, I have decided not to use any job scheduling invocation, but to implement deployment registration functionality. Implemented logic - when application is deployed, record with history data is stored in the database table. Application itself is based on standard HR schema, however some additional elements are used. You can find SQL script with statements for database table, sequence and trigger in sample application package.

Data is inserted into database table using application module that is looked up and created using a Command-Line Java Test Client for ADF BC. So, this means that ADF BC functionality is accessed from external Java class. Java class code, which is invoked automatically after deployment:

DeploymentHistory class acquires application module, creates new row and commits it into database. You are probably interested, how this code is invoked automatically, after deployment. Automatic invocation is implemented using simple servlet - AutoLoader, this servlet is loaded automatically after deployment and invokes main method in DeploymentHistory class. Servlet code:


AutoLoader servlet is declared in web.xml with load-on-startup setting equal to 1, this means that servlet will be loaded after deployment automatically and init method code will be executed. Declaration in web.xml:


Now we can test developed application. To test it we can use OC4J that comes with JDeveloper, just right-click on main.jspx and choose Run - application will be deployed on embedded OC4J and started. Developed application shows a table with information about countries and provides a button - Deployments History, which opens pop-up window with information about deployments history stored in the database.


Let's say there were several deployments, it is reflected in deployments history:


When running sample application, don't forget to add adf-faces-impl.jar and jsf-impl.jar to application's WEB-INF\lib directory.

Wednesday, September 5, 2007

Oracle Fusion User Group and JDev/ADF Labs

We (Frans Thamura and me) have decided to open Oracle Fusion User Group (OFUG). User Group homepage - ofug-global.

OFUG is created in order to bring together technical people who are working with Oracle Fusion. This group will be focused on educational aspect, everyone could share knowledge and get benefit from acquiring available knowledge.

OFUG was created by Frans and is based on labs material that I have prepared recently. Everyone who will join OFUG, can use this material for his/her education. In October I will deliver 1 day workshop based on those labs in Vilnius for local technical community.

Currently in OFUG are available those labs:
  1. Labs environment description
  2. Data model layer development using ADF Business Components
  3. Page flow definition
  4. Search functionality development. Search page contains a form for search parameters and a table for search results
  5. Create functionality development. This page contains several select-one-choice components and allows to insert new data into Departments entity
  6. Edit functionality development
  7. Complex table component development. This component will allow to perform create, update, and delete operations
OFUG mailing list: ofug-global@yahoogroups.com

Multi-selection and Row Data Editing in ADF Faces

In this post I have decided to dive into multi-selection feature offered by ADF Faces little bit more deeper and to show how it could be used in practice. Developed application use case is based on two pages, in first page user can select multiple rows in search results table and press edit button. Second page will be opened only with selected rows. So, this post is focused on how to open in second page only rows selected in first page.

Sample application - TableSelection.zip is based on standard HR schema. Two pages are implemented - search.jspx and edit.jspx. In search.jspx you can find two components - a search form and and a table for search results. In search form is implemented af:selectOneChoice component and table contains read-only af:selectOneChoice for region names. In edit.jspx there is editable table with af:selectOneChoice component for region name.

So, what happens when in search.jspx Edit button is pressed? Edit button is binded with editButton_action() method, available in backing_search backing bean. This means, when Edit button is pressed - editButton_action() is invoked:


This method finds needed iterator and acquires keys for selected rows. And main functionality - method sets where clause for View object that is used in edit.jspx page. Where clause is generated according to primary keys data of selected rows, this allows to open in edit.jspx only needed rows.

Just imagine, that we want to move several countries to other continent - no problem, select those countries and press Edit button:


Edit form is opened, here you can change region name for selected countries, save your changes and return to search form:


And..., you can continue a process... :-)

When running sample application, don't forget to add adf-faces-impl.jar and jsf-impl.jar to application's WEB-INF\lib directory.

Wednesday, August 29, 2007

ADF Task Flow in JDeveloper 11g

In JDeveloper 10g there is only one possibility to design application page flow structure - using JSF navigation flows. But sometimes, use cases require to implement complex page flow, that is not supported by JSF navigation flows. JDeveloper 11g brings ADF task flows in addition to JSF navigation flows. From Oracle JDeveloper 11g Technology Preview, Fusion Developer's Guide for ADF:

Task flows provide a more modular and transactional approach to navigation and application control. Like standard JSF navigation flows, task flows mostly contain pages that will be viewed. However, instead of describing navigation between pages, task flows facilitate transitions between activities. Aside from navigation, task flow activities can also call methods on managed beans, evaluate an EL expression, or call another task flow, all without invoking a particular page. This facilitates reuse, as business logic can be invoked independently of the page being displayed.

In developed sample application - ADFTaskFlow.zip, task flow is implemented for Department data editing. Sample is based on standard HR schema, available in Oracle XE Database. Application contains one JSPX page and this page is divided into two parts - in first part Locations are shown, in second part Departments are managed. Departments management requires to have two views - one for viewing and selecting, second for editing and saving. Additional requirement - to have Locations table displayed always. In JDeveloper 10g, we probably would implement such application with two pages, but in JDeveloper 11g we can use task flow functionality and implement it with one page.

In application Model layer, two entity objects are implemented - Departments and Locations. Based on those entities, View objects are generated and exposed as HrModule Data Model components.

Central role in developed application plays task flow implementation:

Task flow is available in task-flow-definition.xml file - two views and navigation cases are defined. You can define task flow components by dragging and dropping required elements to task flow diagram from Component Palette:


viewDepartments implements a table component with selection feature. When row is selected and opened for editing - editDepartments view is opened. In editDepartments you can change available data and commit it to database - viewDepartments will be opened automatically.

In order to use developed task flow, you can drag and drop it into your JSPX page. Select task flow in Application Navigator window:


When you will put it into your JSPX page, pop-up menu will be opened, where you can choose how task flow should be created:


In developed sample application, I have created task flow as Region.

And last step - JSPX page that contains a task flow, should be registered in adfc-config.xml file. In developed sample, I have just dragged and dropped main.jspx page into adfc-config.xml file:

Now we can check, how application screen look. Page contains two parts - Locations and Departments. Locations part is implemented as simple table with filtering feature, just to browse through data. In Departments part, task flow is implemented, first part of task flow - viewDepartments is shown here:


We can select any row in Departments table and open second part of task flow - editDepartment:


Edit form for Department data is opened in the same page and table with Locations is still shown - required behavior. Main advantage of task flow in this application - data for locations is always available and action can be performed in the same time. If user wants to change department location and wants to know more about new location - he/she can browse for required location in Locations table.


We set Munich city as a new location and press Save button - data is commited to database and first view of task flow - viewDepartments is opened.

Saturday, August 18, 2007

Create multiple rows in Oracle ADF

Recently I have noticed a question on OTN JDeveloper forum about how to create multiple rows in ADF Faces af:table component and insert those rows into database. Actually almost at the same time my friend asked me for help, her goal was to develop exactly the same functionality. So, it seems multiple inserts could be quite often requirement.

Developed sample application - CreateMultipleLocations.zip is based on LOCATIONS table from standard HR schema. Developed business logic allows to create several locations in specified city at once.

To make this sample more interesting, number of rows to create is specified in property file - Resources.properties. Property value available in this file is retrieved in backing bean method and specified number of rows is created respectively.

Sample application JSPX page is divided into two main areas - Panel Box and Table:


First part contains a form, this form allows to provide a city, where locations will be created. It is mandatory to provide a city name, before creating locations. What is most important - Create button for LocationsView1 is developed in the same way as it is described in my previous post - Creating new row using CreateInsert operation. In second part, editable table is created, this table allows to add and edit locations data.

I guess, you may wonder - where is a specific of multi insert. In fact, it is only in one place - in action method for Create button. Developed createButton_action() method:


In first line of this method, value from property file is retrieved. Based on retrieved value, one or multiple rows are created and inserted into View object.

Let's say we want to create several new locations in Vilnius city, so just provide city name and press Create:


Provide required data and press Save:


When running sample application, don't forget to add adf-faces-impl.jar and jsf-impl.jar to application's WEB-INF\lib directory.

Thursday, August 9, 2007

Three Dependent List Boxes in af:table Component

You may already have read Frank Nimphius blog post - ADF Faces: How-to create dependent list boxes in a table. Frank describes in his blog how two dependent list boxes can be implemented in af:table component. He implements dependency between Departments and Employees from standard HR schema.

One day I have decided to implement three dependent list boxes in af:table. I thought it will be simple - have applied the same steps as Frank describes and enabled partial triggering on third list based on first and second. However, things aren't always simple - it was not working in such way. But, I have found a solution and implemented it as sample application - DependentListBoxesThree.zip.

Implemented sample application is based on standard HR schema, also the same additional table as in Frank sample is used - VACATIONREQUESTS. However, table is updated with LOCATION_ID column and foreign key is created that references LOCATIONS table. SQL script for table update you will find in application archive.

Sample is based on solution available in Frank blog, so I will describe only those things I have added to make three dependent list boxes work. I have implemented dependency between LOCATIONS, DEPARTMENTS and EMPLOYEES tables from HR schema.

Steps I have applied:

1. In Model layer implement read-only View Object - DepartmentsCheckView. This View Object will be used to check specified department availability in particular location.


2. Open Vacationrequests Entity Object edit window and select Refresh After Insert for Approved attribute.


3. In View layer, for all iterators related to list boxes dependency set StateValidation="false". This will help to avoid JBO-35007 error, this error was generated sometimes for me during sample testing. More information about this error you can find in Chris Muir blog post - Bah! What is JBO-35007.

4. The main problem was to refresh third list box, when second or first list boxes are changed. When second list box is changed, the same solution as for first and second is applied. However, when first is changed, second list changes and third list should appear empty as value in second list is not selected. For this purpose in getEmployeesSelectItems() method checkDepartmentByLocation is invoked. It accepts two parameters - depId and locId and returns 0 or 1. Returned value helps to determine how third list should be generated.


checkDepartmentByLocation method is implemented in Application Module class:


5. List box for employees is created based on EmployeesView2 from DepartmentsView1.


And now will show how it works. Three dependent list boxes:


It is possible to create new row, you can select location, department and employee from list available for selected department. Also notice, that in fourth row I have changed location from Munich to South San Francisco and you can choose department, but can't select employee as no department is currently selected:

When running sample application, don't forget to add adf-faces-impl.jar and jsf-impl.jar to application's WEB-INF\lib directory.