Skip navigation.

JOracle

Oracle's Java technologies: JDeveloper, OC4J, ADF

May 2009

( Monthly archive )

List of Values Popup in 10g / Trinidad

, ,

In ADF Faces Rich Client (RC) there is a nifty little component that will show a list of values for an input field. This takes the form of a popup with a table of values with a search form. It is very useful for filling in foreign key fields that often don’t have a value that means anything to users.

Before 11g came out, I had already started on something in 10g with the exact same functionality and since we're not going to move to 11g any time soon (all of our customers still use Internet Explorer 6), I thought that maybe there were some others out there who were in the same position and needed the same functionality.



NOTE
I have included sample applications for JDeveloper 10g (10.1.3.4.0, ADF Faces) and 11g (11.1.1.0.2, Trinidad) using the HR database schema. The HR (human resources) schema is a sample schema from Oracle and is usually found in Oracle databases. If not, it is fairly easy to install (Google it). There is, however, one bug in the schema. It contains a trigger that is fired whenever an employee's job or department is changed. It will insert a new record into the job_history table, with the previous job and department and the duration the employee was there (start_date and end_date). The problem is that the primary key on the table is employee_id and start_date and the trigger (actually a procedure that the trigger calls) inserts the same start_date every time an employee is modified, therefore violating the primary key constraint. If you can work out how to fix this, feel free to try. I however, have simply dropped the trigger as I don’t need the functionality any way.

Okay, so you've seen what the ADF Faces RC version looks like above, here is my version (10g):


There are some minor differences – some which are better in the 11g version and some, which in my opinion, are better in my version :smile:

These are the differences and why I think it makes my version better or worse:-
My version: Popup doesn't have a search form.
11g version: Popup has a search form.
Comment: Can easily be added to my version (I have done it).

My version: Popup is quite large.
11g version: Popup is compact.
Comment: 11g is better.

My version: A moderate amount of setup is required.
11g version: A minimal amount of setup is required.
Comment: 11g is better.

My version: Form field is uneditable.
11g version: Form field is editable.
Comment: It depends what you want. I quite like the fact that you can't type in any old rubbish into mine.

My version: Form field can show any value you want.
11g version: Form field can only show field value.
Comment: I'm not actually sure this is true as I've not really played around with LOV's in 11g, but I think that being able to show any value you want is an advantage.

My version: Popup can contain any ADF component.
11g version: Popup is restricted to a search form and a table of values.
Comment: Mine is better.

My version: Previous value can be pre-selected when popup appears.
11g version: Don't know.
Comment: This one is a matter of opinion, but at least mine has the option of either doing it or not.

I think that the main advantage of my solution is that it effectively hides the original field value, which as I said before, could be meaningless to the user.

To get a generic solution that will work in pretty much any situation, I have constructed a class which does most of the work for you, and just requires a few inputs. Other than that, there are a small number of methods and values that you need to set up and that's it!

The class is called SelectionDialogModel (even though I'm British and we spell it 'dialogue'), and for each field that requires a selection popup, you need to set up a managed bean of this class with these attributes:
displayAttrMap - This is a key-value map of view object attribute names and an expression language (EL) string to get/set the value. The EL must be WITHOUT #{} as the class calculates the value on-the-fly and with #{} it would calculate the value too early. This can be used to populate backing bean attributes that will be shown instead of the field value. (Not required, but this means that the original field value can’t be replaced with meaningful values).
viewObjectName - This is the absolute view object name to retrieve from the application module. (Required).
keyAttrName - This is the name of the key attribute in the view object. This is used as the value to populate the background (hidden) field. (Required).
keyAttrValueEL - This is the EL to get or set the background field. (Required).
preSelect - This is a boolean value that determines whether the current value is already selected when the popup appears. (Not required. Default value is false).

Okay, now let's run through an example (included in the sample workspace).
I have a page that shows a table of departments with a selection column and an edit button. The edit button navigates to another page with the selected department's data. In the edit page there are two fields: Department Name and Manager. I want the manager field to show the full name of the manager and not the id, and I also want to have a list of values popup, showing all the possible managers I can choose.

I'm assuming that the model has already been created and I will be focusing on the view layer.

This is the process to follow:
1. Create a backing bean for the edit page.
2. Create a managed bean for the selection dialogue.
3. Create a popup page.
4. Replace form fields with uneditable fields and choose buttons.

Create a backing bean for the edit page.
I've called my class DepartmentEdit.java and the managed bean backing_DepartmentEdit. This class will hold the value(s) that will be shown instead of the hidden value. For the department page there needs to be two values stored (first name and last name of the manager). It also holds a method to clear the values when entering the edit page from the list page.

Create a managed bean for the edit page.
I've called it selection_DepartmentManager and pointed it to the SelectionDialogModel class. Then set the attribute values - I have given it these values:
displayAttrMap = [FirstName=backing_DepartmentEdit.managerFirstName, LastName=backing_DepartmentEdit.managerLastName]
viewObjectName = ManagersView1
keyAttrName = EmployeeId
keyAttrValueEL = bindings.ManagerId.inputValue
preSelect = true

The displayAttrMap attribute is pointing the FirstName and LastName view attributes to their equivalent in the backing bean.
The viewObjectName attribute is set to the view of managers in the model. This is simply another instance of the employees view – kept separate so that each can be iterated through independently.
The keyAttrName attribute is set to the EmployeeId value in the managers view.
The keyAttrValueEL attribute is set to the page definition value binding of the ManagerId attribute in the departments view.
The preSelect attribute is set to true so that the current manager will be selected when the popup appears.

Create a popup page.
This has a table of the managers available with a selection column and two buttons: choose and cancel. Choose will call the chooseActionListener in the SelectionDialogModel class. So, how does it know which managed bean to use, since an edit page could have more than one selection dialogue and a selection dialogue might be called from more than one edit page? Well the SelectionDialogModel instance that is called by the edit page puts a copy of itself in the process scope (this is specifically used within popup pages), meaning that all popup pages call the two methods (chooseActionListener and cancelActionListener) in the same way: processScope.selectionDialog.chooseActionListener and processScope.selectionDialog.cancelActionListener. The choose method will return the currently selected row to the return listener, which is also in this class.
There will also need to be a navigation rule from the edit page to the popup page with a dialog: prefix. I have named mine dialog:SelectManager.

Replace form fields with uneditable fields and choose buttons.
The editable field (inputText component) containing the real value needs to be removed from the form on the edit page and replaced with a label (outputText component) to output a string that the user will understand. There also needs to be a choose button (or image) that will launch the popup.

In this case, the outputText component points to two backing bean attributes (managerFirstName and managerLastName in the backing_DepartmentEdit backing bean). The choose button (commandButton component) should navigate using the dialog:SelectManager navigation rule set up previously. Other attributes that should be set are these:
LaunchListener = #{selection_DepartmentManager.launchListener} - This is called when the popup is launched and sets up the values needed in the popup.
ReturnListener = #{selection_DepartmentManager.returnListener} - This is called when the popup is closed.
UseWindow = true - Tells the application to launch a popup.
WindowHeight/WindowWidth - Change these to whatever size you want the popup to be.

The only other thing to do is make sure that the backing bean attributes are repopulated with the current values each time the user enters the edit page. Do this by putting an action listener on the button that takes the user to the edit page.

And that's it. I would recommend that you have a look at the sample workspace provided as it has this example plus a more complex example using employees. It has three selection popups (job, department and manager).


Sample Workspaces
ADF Faces 10g version: SelectionDialog-10_1_3_4_0.zip

Trinidad 11g version: SelectionDialog-11_1_1_0_2.zip

Batch Script to Alter CVS Location [PC Only]

, , ,

It's been a while since I made a post on here. This is not because I haven't wanted to, but because the company I work for has been blocking every blog site. Thankfully, they seem to have relaxed a bit and I can post some of the things I've been waiting to.

Firstly, before I go into this, I want to apologise to any non-PC users. This blog is specifically for the PC. I only use a PC at work and home and don't have an amazing knowledge of Linux or Mac OS.

So, what's this post about?
Basically, at work we have very few resources (servers) and it takes a long time to get new machines. So when we first set up a CVS repository for our code (using CVSNT), we didn't have a dedicated development box. So we set it up on one of our developer workstations.

This was fine for a while, but then we got a server for deploying and testing our development work. Even though this was not perfect for the CVS repository, it was better than a workstation. So we moved the repository.

Then we came across a problem. There were a number of developers working on code in this repository, who had local copies (with changes). In this project there are hundreds of folders, each with a CVS subfolder and a Root file inside detailing the location of the repository. It would take far too much time for everyone to manually edit all these files, so wrote a batch script to do the job for us. I then improved it in case we needed to change other aspects of the root string at a later date.

The script works in one of two ways:
1. User specifies one or more "sections" of the root string to replace.
2. User specifies the entire root string.

The root string is made up of a number of sections:
:protocol:user.name@host:/folder

protocol - pserver, ext, ssh,...
user.name - The CVS username
host - The host machine (server)
folder - The CVS module

In the first way of using the script, the user can replace one or more of these sections:
CVSUTIL /P protocol /U user.name /H host /F folder


In the second way, the user can replace the entire root string:
CVSUTIL /S :protocol:user.name@host:/folder


In both these methods, the current path with be treated as the top folder in a local copy, or the user can specify a path:
CVSUTIL C:\LocalCopy /S :protocol:user.name@host:/folder


The script will use the user-supplied values and iterate through all the Root files in all the CVS subfolders and change the contents. Once it has finished, the local copy should be pointing to the new location of the CVS repository and life can go on as normal!

I've attached the script to this post and it is freely available for anyone to look at the guts and modify or improve it. I would appreciate it if you help me and others and post your improvements to this blog :smile: Also some of the stuff in there is quite complex and hard to follow, so if there is demand, I may write a blog explaining some of the techniques I have used.

So here it is...
cvsutil.bat
May 2009
S M T W T F S
April 2009June 2009
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30