Tuesday, November 27, 2007

JDeveloper 11g - Create, Edit and Delete operations in ADF Faces af:table component

In this post, I have decided to implement JDeveloper 11g Technical Preview 2 sample application, based on one of my most popular blog post - Create, Edit and Delete operations in ADF Faces af:table component. I already received several requests to provide sample application for similar functionality in JDeveloper 11g, so here it comes.

Developed sample application EditableTable11.zip, provides read-only table with those actions - Delete, Create, Edit, Save, Cancel. Row selected for editing is shown in editable mode and can be updated. Application is based on HR schema that comes with Oracle XE database. Application logic is based on Jobs entity from HR schema.

This sample is developed using the same principle as described in my previous post. I will describe what are the differences in implementation:

1. In JDeveloper 11g CreateInsert operation is not hidden anymore, you can use it directly from Data Control. This operation is used to create new row in table:


2. In From field of af:setActionListener, defined for Edit button, is used access to row - #{bindings.JobsView1Iterator.currentRow}, instead of access to individual column - {row.JobId}.

3. isEnableEditing() method in ValueHolder.java is changed, new code:


What's the difference here? First thing - since ValueBinding is deprecated, I'm using ValueExpression to access column value in a table. And second - I'm using oracle.jbo.server.ViewRowImpl to hold selected row.

How it works? JDeveloper 11g comes with ADF Faces Rich Client, it gives new level of usability in Web applications - you will notice this immediately. Create functionality is invoked by pressing Create button:


When data is entered, Save button allows to store information into database:


There is no more ugly radio button components for row selection, you can use just your mouse to select any row for editing:


And finally, several words about some of new features available in af:table component that comes with JDeveloper 11g ADF Faces Rich Client. First feature - standard functionality allows to rearrange columns in a table on runtime:

Filter can be used, to execute search directly in the table:


And, when let's say wrong input is provided, nice error message is shown at the same time when new value is typed:


I'm sure, you will like af:table component that comes with JDeveloper 11g ADF Faces Rich Client ;-)

35 comments:

rwb said...

This is extremely impressive. Thanks for sharing the information with us, this will drop web-app dev time enormously.

Oracle continues to impress.

Anonymous said...

It's very interesting. When I click create the program successfully creates a new row, as long as the first row in the table is selected. However, if I select any row other than the first row before clicking the "Create" button, the values I enter are used to update the first row rather than to create a new row. I am using TP3 for my test. Do you know why this is happening?

Larry

Andrejus Baranovskis said...

Hi Larry,

I tested it as you described and I'm getting the same behavior. It seems a bug in TP3.

I have developed workaround - create Method Action for Create button and replace generated code with:

public String createButton_action() {
BindingContainer bindings = getBindings();

DCIteratorBinding dcib = (DCIteratorBinding) bindings.get("JobsView1Iterator");
RowSetIterator iter = dcib.getRowSetIterator();
Row newRow = iter.createRow();
iter.insertRowAtRangeIndex(0, newRow);

return null;
}

This code will put new row always as first row in table, even if selected row is not first.

If you want, drop me an email, I will send you updated application.

Regards,
Andrejus

Anonymous said...

Yes, that works. Thank you very much for your help. At least I now have code that works.

It's very annoying that I can't force the table component to insert anywhere except at the top.

I AM able to change the table's "rowIndex" property to point to the selected row using code like this:

RowKeySet rks = this.getTheTable().getSelectedRowKeys();
System.out.println("Number of selected rows is >" + rks.getSize() + "<");
Iterator selection = rks.iterator();
while (selection.hasNext()) {
Object rowKey = selection.next();
this.getTheTable().setRowKey(rowKey);
}
System.out.println("Now the current row index is >" + this.getTheTable().getRowIndex() + "<");

Note that I have the table configured to only allow single-row selections, so there is always only 1 row in the RowKeySet.

However if I try to insert the new row at the selection position like this:

rowNumForInsert = this.getTheApplicationTable().getRowIndex();
iter.insertRowAtRangeIndex(rowNumForInsert,newRow);

it makes no difference and the table still applies the data to whatever row is at the top.

I agree with you that it is most likely a bug in the RichTable component in TP3.

Larry

Anonymous said...

Hi Andrejus,
What if i add rows to the underlying View Objects rather than the af:table itself ?

I want to add rows after the selected row in the af:table. Could you please tell me if its possible in TP4 ? Please share the code if so..

Thanks in Advance
Raj

Andrejus Baranovskis said...

Hi,

You can check my older post, same principle applies to TP4 also: Create multiple rows in Oracle ADF.

Regards,
Andrejus

Anonymous said...

Hi Andrejus,

I had expected the multiple selection of rows to be multiple delete enabled by default but that does not seem to be working. I enabled 'multiple' option for row selection but am not able to delete multiple rows.

Can you throw some light on how to delete multiple rows from a adf Rich Table component?

Thanks and regards,

Arun

Andrejus Baranovskis said...

Arun,

It deletes only first from selected rows?

Andrejus

Anonymous said...

Hi Andrejus,
I have PL/SQL package converted to java with jdeveloper 11g. On that package i have a createModify function, wich is the function that i must use to create or modify a row in the table.

I´ve tried to make a new data control with the .java file, and from that data control take createModify function and throw as a commandButton in the page. But ¿how can i say to the function to take the selected row´s atributes as parametres of the function?

Is that the correct way to do this?

Or is it best to create a managed bean?

Rowan

Andrejus Baranovskis said...

Rowan,

I think, in your case it will be better to use Managed Bean.

Regards,
Andrejus

Anonymous said...

OK,
i will use managed beans.
So, i use a command button binding to the function of the managed bean that i need. But that function is to create a new row, so firts i need to insert a blank row in the table.
Where must i put de code of the blank row.
¿In my new create funcition? or ¿can i use the createinsert function and bind it to my newcreate function?

Thanks,

Rowan

Anonymous said...

Hi Andrejus,

I actually got a method that calls a for loop over the RowKeySet to delete the rows that are selected with ctrl+mouse click. The rows get deleted from the UI and the table refreshes to reflect the remaining rows. But I am facing an issue with commit...

The error is that that "JBO 25019: Entity Row of Key oracle.jbo.key[*KeyValueHere*] not found in DetailEO.

The method that I added to the manage bean to perform the delete is:

public void onDeleteLevel1(ActionEvent actionEvent) {

FacesContext fctx = FacesContext.getCurrentInstance();
Application application;
application = fctx.getApplication();

ELContext elctx = fctx.getELContext();
ExpressionFactory exprfactory = application.getExpressionFactory();

ValueExpression valueExpression = exprfactory.createValueExpression
(elctx,"#{bindings}",Object.class);
DCBindingContainer dcbinding =
(DCBindingContainer) valueExpression.getValue(elctx);

FacesCtrlHierBinding treeRootNode =
(FacesCtrlHierBinding) dcbinding.get("RatingLevel");

RowKeySet rowKeySet = (RowKeySet)getRatingsTable1().getSelectedRowKeys();
for (Object facesTreeRowKey : rowKeySet) {
getRatingsTable1().setRowKey(facesTreeRowKey);
JUCtrlHierNodeBinding rowData =
(JUCtrlHierNodeBinding) getRatingsTable1().getRowData();
((JUCtrlHierNodeBinding)treeRootNode.getCollectionModel().
getRowData()).getRow().remove();
}
}

I read that the error is caused because the remove() operation will cause the entity row to be removed from cache.

Can you please suggest how do I update the cache to retain the lock and then perform the commit.

Thanks,

Arun

Anonymous said...

following this example(yours), i created a new one. after execution on browser, when i performs the second action (for any action like sorting: first action is desc then the second action asc) it returns the error like this:
Messages for this page are listed below.
Empno Error
java.lang.NullPointerException
Empname Error
java.lang.NullPointerException
Empdob Error
java.lang.NullPointerException
Salary Error
java.lang.NullPointerException

plz.. help me

Mark Williamson said...

I get the same error. I just tried to implement my own version and on the two mandatory fields in my table, I get a nullPointerException in the ADF popup error box. Any thoughts ?

Andrejus Baranovskis said...

Hi,

I know how to solve your problem. Its a bug in TP4 JSF library.

Temporary and quick solution is to remove f:validator tags for all columns in the table. It will solve this problem.

Regards,
Andrejus

Mark Williamson said...

Hi Andrejus,

I am having difficulties making this work from scratch in the new JDEV 11G release.

When I add a row, enter nothing and hit cancel the rollback does not clear away the row.

Can you test this example out in 11g and see if it works for you?

Mark

Andrejus Baranovskis said...

I will test it, will post update.

Regards,
Andrejus

Mark Williamson said...

Thanks so much.

Anonymous said...

Thanks for your wonderful blog. I'm also new to Jdev11g & so may I ask how I could achieve this functionality? What I would like to do is to show a popup dialog and prompt users for input instead of inline row editing. So, how do I detect whether a row is being selected to disable/enable the Edit button accordingly? Using your example, I tried this EL expression but it does not seem to work. Am I missing sth?

disabled='#{bindings.JobsView1Iterator.currentRow== null}'

Thanks in advance,
Phil

Mark Williamson said...

Hi Andrejus,

I found that my specific problem with JDEV 11G and this create edit delete table is something to do with the cancel button and Rollback.

When I add a new row and decide I want to cancel, it won't get rid of the new row.

Any thoughts ?

Mark

Thivahar said...

Hi Andrejus,

May i know how can i remove the selected row in ADF table using the code. I need to remove the selected row when another action occurs. So i have the actionListener and the blinded RichTable reference in my backing bean.

Thiva

Thivahar said...

Just found that we can remove the selected row by using the tichTable::getSelectedRowKeys().clear();

Thiva

Dennis said...

Hi, wonderfull post I have the problem java.lang.NullPointerException with the create method, and I already remove the af:validator but still the same, any clue?

Srinivasa said...

Hi,

I am following the same example for one of my requirement but i found that On create operation if any DB validation failed i found that table row has became read-only. But same thing is not happening on the Edit.

Please guide me how to resolve this issue.

Nilesh said...

To- Andrejus Baranovskis

How to insert new record in database using ADF form in jdeveloper 11g? How do I use createInsert operation to insert new record?

Anonymous said...

Hi, Andrejus Baranovskis,

Your solution is really nice. But when deploy it in JDev 11.1.1.4, after click "Edit" button, then click "Cancel" button, all the rows become editable. Did you ever see this phenomenon?

Really appreciate if you can have a look!

Best Regards,

Alfred

Andrejus Baranovskis said...

Hi,

I have updated sample application, it works now on 11g PS3. Please download again ;)

Andrejus

Anonymous said...

Hi, Andrejus Baranovskis,

You are so efficient. Cool!

Best Regards,

Alfred

Les said...

Hi Andrejus
I am a newbie and have read most of your works/posts in the internet. Do you have anyother consolidated source where I can get all the information you post?

I have some questions regarding this post btw:
1. when you set disabled property in the cancel button for eg., you also set which other button has to be disabled at the time this cancel button is enabled. For instance we have !valueHolder.editAction for the disabled property for cancel btn. The questio I have is how this is set or unset using the bean as I see no direct method being called and only the property. how the set/unset take place as you dont explicitly set a listener. The last question is I dont understand the af:setactionlister that well as I dont find any doco on this on the net. please find some time to help
Thank you
Les

Sumit Yadav said...

Hi Andejus,
After selecting the row in my adf table I am clicking delete and it deletes the row but when i press save and tries to commit the transaction, it throws
"Attempt to access dead entity in xyzEO, key=oracle.jbo.Key[10 ]

Any pointers ??

Thanks
Sumit Yadav

Sumit Yadav said...

Hi ,
I got the issue, actually after deleting the row, in my EOImpl of that vo,in the DoDml() method i was trying to set the lastUpdatedBy column value and since the row is already deleted it was not able to find a reference which was throwing the error .
Foe resolution, i am now checking the state of the row by
if (this.getEntityState() != STATUS_DELETED)
and executing accordingly .

Thanks
Sumit

subu said...

can

you help me.

http://forums.oracle.com/forums/thread.jspa?threadID=2267085&tstart=0

Anonymous said...

Hello,
How could I add the row in a Form instead of a table? Same logic? for 11g.

Thanks

Andrejus Baranovskis said...

Hi,

Yes - may be this post will help you: http://andrejusb.blogspot.com/2008/09/jdeveloper-11g-crud-in-adf-form.html

Andrejus

caromeva said...

Hello I am new to ADF, I would like to know if you have an example of an ADF table with basic CRUD functionality, but you can choose which rows will save, by selecting a row for selectBooleanCheckbox. It is possible?
Please I need help.
Thank you very much.