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:

  1. Very nice, clean and clever solution sir!!!

    ReplyDelete
  2. Good job. Thanks for the simplicity.

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

    We will miss you in Greece :)

    ReplyDelete
  4. 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 ;)

    ReplyDelete
  5. 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 ?

    ReplyDelete
  6. 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

    ReplyDelete
  7. 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..

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

    Regards,
    Andrejus

    ReplyDelete
  9. 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...

    ReplyDelete
  10. Hi Andrey,

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

    ReplyDelete
  11. Thank you very much! Just what i need!

    ReplyDelete
  12. 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.

    ReplyDelete
  13. Hi,

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

    Regards,
    Andrejus

    ReplyDelete
  14. 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.

    ReplyDelete
  15. 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

    ReplyDelete
  16. 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

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

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

    Thanks in Advance

    ReplyDelete
  19. Hi,

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

    Regards,
    Andrejus

    ReplyDelete
  20. 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

    ReplyDelete
  21. 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.

    ReplyDelete
  22. Hi Manasa,

    I guess you can achieve this with PartialTrigger functionality.

    Regards,
    Andrejus

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

    ReplyDelete
  24. 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

    ReplyDelete
  25. 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

    ReplyDelete
  26. 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

    ReplyDelete
  27. Hi,

    You can implement this functionality in Backing Bean method.

    Regards,
    Andrejus

    ReplyDelete
  28. Can you provide any sample for doing that in backing bean

    ReplyDelete
  29. 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

    ReplyDelete
  30. Hi,

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

    Thanks

    ReplyDelete
  31. 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?

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

    Andrejus

    ReplyDelete
  33. 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.

    ReplyDelete
  34. 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

    ReplyDelete
  35. 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?

    ReplyDelete
  36. 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

    ReplyDelete
  37. 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.

    ReplyDelete
  38. 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

    ReplyDelete
  39. 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?

    ReplyDelete
  40. 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.

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

    Andrejus

    ReplyDelete
  42. 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.

    ReplyDelete
  43. 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

    ReplyDelete
  44. 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?

    ReplyDelete
  45. 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

    ReplyDelete
  46. Nice Post.

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

    Thanks,
    Nachi

    ReplyDelete
  47. 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?

    ReplyDelete
  48. very helpful, thanks you Andrejus Baranovskis

    ReplyDelete