Wednesday, November 25, 2009

CRUD Operations in Oracle ADF 11g Table Using PopUp Component

I was blogging on previous week about how to implement CRUD operations in table component using external dialog framework (new feature in JDeveloper 11g R1 PS1) - CRUD Operations in JDeveloper/ADF 11g R1 PS1 Table Component. I got several questions from my readers about how to catch dialog Cancel event when using inline windows through external dialog framework. However, there is no Cancel Listener available for external dialog framework in this release, so its not possible to catch Cancel event. In some specific use cases it can create problems, because we want to execute Rollback when user is closing dialog by pressing Cancel button. On other hand, af:popup component have Cancel Listener, today I will show how you can use af:popup for CRUD operations in Oracle ADF 11g table.

Download updated sample application - TableDialogEdit2.zip, this sample based on my previous post mentioned above. The key difference is that now I'm using af:popup to show currently edited or newly inserted record. Editing case:



Data is edited and changes are commited to database using OK button:



If user would press Cancel, (X) or Escape keyboard button - Rollback action would be triggered. Same applies when inserting new record:



If we will take a look into source code, we will see that I have created af:popup and this component is opened through af:showPopupBehavior operations declared for Insert and Edit buttons:



Popup component itself is defined with lazyUncached content delivery and two listeners - PopupFetchListener and PopupCanceledListener:



First one is invoked during popup opening and is used to trigger Insert mode when it is needed. And second is triggered when user wants to dismiss editing dialog. Editing dialog is based on DialogListener, where Commit or Rollback operations are called:



The main trick with af:popup component usage is on Insert. The problem is, when you define af:showPopupBehavior, framework will not execute Action or ActionListener defined for the same button. So, I'm calling CreateInsert operation from PopupFetchListener, during that moment when popup is rendering. This allows to make it work for Inserts through af:popup component. Additionally, I'm doing a check there and invoking CreateInsert operation only when Insert button was pressed and not when Edit:



DialogListener invokes Commit or Rollback operations based on user action:



PopupCanceledListener is extremelly helpful and is triggered when user is closing dialog with (X) or Escape keyboard button:


50 comments:

Unknown said...

Very nice, clean and clever solution sir!!!

Andrej Baranovskij said...

Thanks Sir ;)))

rafher said...

Good job. Thanks for the simplicity.

Michael Koniotakis said...

Nice post
Yet, the solution for invocking actionListener is to just set the triggerType of ShowPopupBehavior to click

We will miss you in Greece :)

Andrej Baranovskij said...

Hello :)

I was testing with click triggerType, then af:popup wasn't opening for me, at least in Safari browser.

I will miss Greece too, but I will return ;)

Anonymous said...

Found several problems using Jdeveloper (11.1.1.2.0)
1. Selection listener reloads table on each row click
2. Undo button ain't working (save too) since commit/rollbacks executed on close popup dialog
3. If we engage there some business rules, error messages act very weird.. sometimes they showup, sometime they just blink the screen and return field to the previous value. Sometimes it shows double error (business rule error message and mandatory message).
4. If I try to insert record and business rule exception occurs, sometimes it shows exception, sometimes it just erases field and I can see row with empty mandatory field being added to the table on background, however if I press cancel this field dissapears.

Any comments about it ?

Andrej Baranovskij said...

Hi,

All these described are typical wrong usage of ADF functionality. You should read dev guide about these features.

For example, table refresh is done, because auto ppr is enabled on iterator, you can disabled it, if dont want to refresh related operators automatically.

And etc.

Regards,
Andrejus

Unknown said...

this create adn edit method are owrking for adf table. do we have a similar method for adf tree table crate / edit both child and parent nodes..

Andrej Baranovskij said...

Yes, you can check in ADF Faces Components demo application. Also you can download source code and see example.

Regards,
Andrejus

Andrey said...

Sorry for dumb question, but: how to make refresh of table/tree (when iterator ChangeEventPolicy is set to "none") after closing popup (and exec of "Commit" or "Rollback"? Exec of "Execute" not help at all...

Andrej Baranovskij said...

Hi Andrey,

You should try to PPR programatically from dialog listener. AdfFacesContext.getCurrentInstance.addPartialTarget(this.getTable)

Andrey said...

Thank you very much! Just what i need!

Andrey said...

And second question:
i have opened popup with data editors, input some data with errors, press "OK" button on popup dialog, errors and red borders appears. Then press "Cancel" button and dialog closed (on Cancel Listener have exec "Rollback" operations). But: error balloon still on screen and reappears each time when i click on any table row. How to rid of this balloon? Or I doing something wrong?

Thanks in advance.

Andrej Baranovskij said...

Hi,

Are you getting this with my sample app, or inside your app?

Regards,
Andrejus

Andrey said...

This happens in my test app - one table in database, one entity, one view. Only difference - table and popup placed in page fragment, which rendered in region on "dictionary" page.

Anonymous said...

Hi Andrejus,

Thank you very much for this information, its exactly what I need.

I'm struggling with one thing though, the close icon of the popup itself. The returnlistener isn't notified when the popup is closed with that button, and I can't find where to disable it.

When you now click the insert button, and then immediately close the popup with its close button, you're left with an empty (and possibly invalid) row which isn't rolled back.

Do you know how to workaround this?

Thanks alot and kind regards,
Gerben

Anonymous said...

hi,

This is the same thing I am looking for..

Please do let me know if you got this issue under control..

Thanks & Regards,
Viraj Save

Manasa said...

Hi How to use 'in' operator with multiple values for a view criteria pls explain

Manasa said...

Hi sir,
Please tel me how to use 'in' operator with a view criteria

Thanks in Advance

Andrej Baranovskij said...

Hi,

I believe, you can find it in Oracle ADF Developer Guide, check View Criteria section.

Regards,
Andrejus

Manasa said...

Hi
I have a small doubt in panel splitter is there any way the following scenario can be achieved using ADf panel splitter
we have a panel splitter with two facets
and first facet has links and when user clicks links on first facet the corresponding jsp pages in second facet should change.
How can we achieve this in ADF 11g

Manasa said...

Hi How can i acheive following scenario in ADF
i have a panel splitter with two facets and have links on first facet when the user clicks on links present in first facet the corresponding jsp pages shud be changed in second facet.

Andrej Baranovskij said...

Hi Manasa,

I guess you can achieve this with PartialTrigger functionality.

Regards,
Andrejus

Manasa said...

Can u pls provide me some sample example as iam unable to get this .

Abhishek Kumar said...

Hi Andrejus,
In 11.1.1.3.0 I am noticing that popupCanceledListener is called even if you press any other custom button on the dialog. Is this a bug or epected behavior
Thanks
Abhishek

Andrej Baranovskij said...

Hi,

Didn't reproduced. For me popupCanceledListener is called only when pressing keyboard Cancel button or built-in Cancel button. It is called when closing popup with X. In all other cases, not called.

Regards,
Andrejus

Anonymous said...

I want the user to give flexibility where he can choose the column and criteria and udpate multiple rows based on that criteria. Say i have a table with columns employee name,age,dept and want to allow user
to choose at runtime the column say age and some condition like name age>26 and update all the rows for it.similarly he can use other column and criteria dynamically

Andrej Baranovskij said...

Hi,

You can implement this functionality in Backing Bean method.

Regards,
Andrejus

Anonymous said...

Can you provide any sample for doing that in backing bean

IM'pRoPeR said...

Hi,

I am trying to add rows to a child table using createinsert operation of the child table within a popup. The trouble im having is that on clicking the createinsert (ADF button) the popup closes. But the button performs its task.

Is there any way i can make the popup refresh on the press of the button?

Thanks
Rohin

IM'pRoPeR said...

Hi,

Is there any way of making the popup refresh on the press of a button??

Thanks

Anonymous said...

I was able to implement your approach in my application, however I have the following problem. I require some fields to be set by default, and not have every field of the table as an input text field. What is the best way to set these properties?

Andrej Baranovskij said...

You may try to use CreateWithParams: http://andrejusb.blogspot.com/2011/02/createwithparams-operation-for-oracle.html

Andrejus

Andrejs Dasko said...

You may try to use CreateWithParams:

Is there a way to do that programmatically from a backing bean? I have been using popupFetchEvent to call CreateInsert and it worked just fine:

BindingContainer bindings = getBindings();
OperationBinding operationBinding = bindings.getOperationBinding("CreateInsert");
operationBinding.execute();

If I could only call CreateWithParameters and set the parameters in this same method prior to calling execute, that would be exactly what I need.

Perhaps, if you know a better way to call this function programmatically, please share.

Andrej Baranovskij said...

Yes of course, you can call CreateWithParams programmatically as you are describing. In order to set parameter values programmatically as well, make sure to use correct EL for NDValus field for NamedData (for example reference value from Request Scope, set before invoking action).

Andrejus

Andrejs Dasko said...

I have the following scenario. I have two custom buttons on my pop-up, that when 'OK' button is pressed, it submits the form as a new row to the database. I am using 'CreateInsert' operation. When 'Cancel' is pressed, I use the following lines to revert the changes made by 'CreateInsert':

OperationBinding operationBinding = getBindings().getOperationBinding("Rollback"); operationBinding.execute();

My pop-up is triggered when a value is changed in a dropdown of a table. This makes my popup to appear. Now, when I cancel the popup and revert, I want the value of my dropdown to change back to it's old value, since no change was made. Before, when I was using bindings to update, and not 'CreateInsert', I used this code snippet:

DCBindingContainer bindings =(DCBindingContainer)ADFUtils.resolveExpression("#{bindings}");
DCIteratorBinding iter = bindings.findIteratorBinding("ItemVO1Iterator");
Row row = iter.getViewObject().getCurrentRow();
row.refresh(Row.REFRESH_WITH_DB_FORGET_CHANGES);

however, after rollback is done, the row I get is always null. I suspect this is because the current row is dropped to the position before the first row. How can I solve this problem, so I can revert the 'CreateInsert' AND also change the dropdown status back to it's original value?

Andrej Baranovskij said...

You may try to use Row.REFRESH_UNDO_CHANGES. Check this post: http://andrejusb.blogspot.com/2008/09/jdeveloper-11g-crud-in-adf-form.html

Also Chris post: http://one-size-doesnt-fit-all.blogspot.com/2007/02/jdeveloper-and-art-of-rollback.html

Andrejus

Cgprada said...

Hi,

I'm new in ADF, sorry if this question is Dummy. I'm trying to implement this example, the difference is that mi View Object has a where condition with a parameter (because i need to show some data of the table, not all of them). Also, in the bindings section, I have an ExecuteWithParams action and an InvoqueAction with always refresh to show the data when the page load.

When I try to add a new record with the popup, it always edit the first record of the table. What should i do to show the filtered data and insert new rows with the popup?.


Thanks in advance and sorry for my english.

Andrej Baranovskij said...

Make sure these 3 properties are set in your table:

selectedRowKeys="#{bindings.DepartmentsView1.collectionModel.selectedRow}"
selectionListener="#{bindings.DepartmentsView1.collectionModel.makeCurrent}"
rowSelection="single"

Looks like row selection is not executing correctly.

Andrejus

MarioK said...

Hi Andrejus
i'm trying to reproduce this example in HR shema using ADF 11.1.2.1 and keep geting a strange mistake: every time Insert button is pressed, popup is showing with a blank row following a message "Error: A value is required" for each required attribute. Like some kind of submit is invoked, but I'm not able to resolve this. Can you help me?

infantafdo said...

Hi sir,
I am trying to implement this
example. When I try to add a new record with the popup, the popup fields are non-editable. What can be the mistake?

Infanta.

Andrej Baranovskij said...

I guess you forgot to call CreateInsert operation as Task Flow initializer method, before loading fragment in the popup.

Andrejus

Anonymous said...

Actually, it looks like the step to add CreateInsert to the page's binding's is missing. Once I did that I was able to replicate the page just fine.

Just go to your pages bindings table and add the CreateInsert operation.

Andrej Baranovskij said...

Sure, you need to add CreateInsert in page definition. Keep in mind - I never have a goal to describe every little step, thats why I post sample code - for the reader to look and research by himself as well, otherwise it would be too easy :-)

Andrejus

Anonymous said...

Hello Andrejus,

Thank You for great post!

We plan to use many CreateEdit popop windows for CRUD operations (like in Your example).
I also found example where Edit Page and Bounded TaskFlow as Popup are used.
http://jneelmani.blogspot.com/2012/12/adf-how-to-implement-create-edit.html
Just I wonder, which method is recommended to use. What are advantages and disadvantages?

Andrej Baranovskij said...

Hi,

PopUp is better as described in this post, is more lightweight. But anyway, I have in 2009 posted CRUD with dialog as well: http://andrejusb.blogspot.com/2009/11/crud-operations-in-jdeveloperadf-11g-r1.html

Andrejus

Anonymous said...

Nice Post.

Is it possible to invoke the popup on mouse over over a table row?

Thanks,
Nachi

Andrej Baranovskij said...

Yes, should be possible.

Andrejus

huaymas said...

Hi. i'm new on adf world and im trying to call CreateWithParams from backing bean, to catch exception and execute rollback method.
Or you can help me to call rollback method on entity validator and call rollback without losing current row?

fayza said...

very helpful, thanks you Andrejus Baranovskis