Tuesday, November 17, 2009

CRUD Operations in JDeveloper/ADF 11g R1 PS1 Table Component

While working on the customer side during last week, we have discussed a use case where user works with read-only tables and performs data editing through inline popup. In ADF 11g you can use clickToEdit editing mode for a table component in order to improve rendering performance. With this mode table will be rendered as read-only, but user will be able to edit rows by double clicking on current row. However this case was not suitable for the client, they wanted to edit and insert new rows in inline popup, mainly because there will be additional editable columns. We have tried to implement this requirement in JDeveloper/ADF 11g R1, using af:popup component, but it was not working for insert mode. Same week we got new Oracle JDeveloper release - JDeveloper 11g R1 PS1, and new functionality that allows to open ADF Task Flows as inline popups (read Frank Nimphius blog post - JDeveloper 11g R1 PS1 New Feature: Launching DHTML popup dialogs using the external dialog framework). In this blog post I will describe how you can enable CRUD operations in table component using ADF Faces external dialog framework.

Download sample application with implemented CRUD functionality - TableDialogEdit.zip. This sample provides a table component, with implemented Insert, Edit, Save, Delete and Undo functionality:


Table is read-only, Insert and Edit operations will be performed through inline dialog. User can select a row and by pressing Edit, will open a dialog to edit data:


When user will press Close button inside inline dialog, Dialog Return Listener method will be invoked to refresh parent table, see code in managed bean. Data in parent table is refreshed, user can commit his changes by pressing Save button or revert by pressing Undo:


In similar way, user can create new row by pressing Insert, blank row will be opened in inline dialog:


User can insert data, and close inline dialog with Close button:


Previously inserted blank row will be refreshed with entered data, same as in editing case user can commit or revert it:


I have implemented this functionality based on information from Frank Nimphius blog mentioned above. From main page located in ADF Unbounded Task Flow, I'm calling ADF Bounded Task Flow where editing JSPX page is implemented. If Insert button was pressed, before calling ADF Bounded Task Flow, CreateInsert operation Method Call is invoked:


Call for ADF Bounded Task Flow is defined to run as dialog and to be displayed as inline popup:


This allows us to open standard ADF Bounded Task Flow as inline dialog:


On the main page, table panel collection contains five buttons, two of them - Insert and Edit are opening inline dialog for data editing:


Those two buttons should be configured to open inline dialog, by setting UseWindow, WindowEmbedStyle and WindowModalityType properties accordingly:


60 comments:

  1. Hi Adrejus!

    Thank you for all Tips.

    I need to use this new version using the DBSequences.

    Have you try to set automatically the departmentId when you insert a new department row?

    oracle.jbo.AttrValException: JBO-27014

    Regards,

    Efrain

    ReplyDelete
  2. Hi,

    It should work nicely, just drag and drop DepartmentId component on UI side again.

    Regards,
    Andrejus

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Hello,

    This article was very useful for me, thank you.

    But i am facing a problem:

    If (X) button is used for closing the dialog, no rollback operations is applied. In other words, ReturnListener is not invoked. Do you know if there is a way to invoke the ReturnListener method to be invoked in case of closing the dialog via (X) button on the top right?

    Thanks.

    ReplyDelete
  5. Hello,

    No, there is no listener in current release for (X), its why I have create Undo button on main page.

    Regards,
    Andrejus

    ReplyDelete
  6. Is it possible to remove or disable the X button completely? (I am using inline-popup)

    ReplyDelete
  7. Only if you will use af:popup component, it have this feauture.

    Andrejus

    ReplyDelete
  8. In JDeveloper 11.1.1.1.0, there is no "Display Type" property for task-flow. Moreover, for command button, there is no "WindowEmbedStyle" and WindowModalityType". And my popup is shown in secondary window. What should i do because i want to show dialog as inline.

    ReplyDelete
  9. Its available only from JDeveloper 11g R1 SP1.

    ReplyDelete
  10. Hi Andrejus,

    Can you explain us how we have to use ReturnEvent parameters (returnEvent.getReturnValue())? It doesn't work with

    AdfFacesContext.getCurrentInstance().returnFromDialog("value", null);

    because it isn't a Dialog. am I right?

    Thanks!

    Efraín

    ReplyDelete
  11. Hi Adrejus!

    I have a use case:-
    1. First the read only table of department list will show in the page
    and the page has two buttons for new and edit.
    2.If i press new, new entry form will occur and we can enter the department details and if we press save, it has to be committed in the DB.
    3. And has to return the list of departments with the newly added department.

    This 3 steps in a task flow. Session Bean methods are used

    I have done with this.
    But, in the 3rd step, i'm not getting the list with the new department.
    i tried with all refresh, refreshcondition, and changeeventpolicy parameters, but no luck. Only time it works is when i put the refresh always and chache true. In this case it works for new department creation, but after edit department creation, the department list is not comming.

    Please help me learning this !

    ReplyDelete
  12. Hi Andrejus,

    Very nice and clean.
    I need to provide the same functionality for Insert only. Your Insert button is refreshing the department table:
    adfFacesContext.addPartialTarget(this.getTable());

    My Department table is in a region2 which is in a region1. So I have nested regions. My Insert button has to refresh Department table from region2 (easy to do since you did that), but also has to refresh the table which is in a parent region - region1.
    Can this be achieved?
    Can the child region (from bean code) refresh object from the parent page?

    Your response is very appreciated.
    Thanks, Vesna

    ReplyDelete
  13. Hi Vesna,

    You can use ADF Contextual Events for this purpose. Check Edwin blog for more info: http://biemond.blogspot.com/2009/11/adf-contextual-events-in-11g-r1-ps1.html

    Regards to Serbia ;-)

    Andrejus

    ReplyDelete
  14. it is very efficient but, in case of using fragments it did not work correctly

    can u help me ??

    ReplyDelete
  15. You might be interested to take a look into another sample app for the same case - http://andrejusb.blogspot.com/2009/11/crud-operations-in-oracle-adf-11g-table.html

    Regards,
    Andrejus

    ReplyDelete
  16. Returning to the "x" button problem.

    Seems like only some embedded javascript solution will work.
    However I doesn't have enough ADF knowledge to implement it.

    But, found out - that if you run this taskflow as transactional one (always begin new transaction), then "x" button won't commit transaction and no changes will be applied.
    However it may lead to some unexpected outcomes, for example partial trigger events won't launch after popup closed.

    And another problem with this type of popups - they won't let anything to go out of their boundaries.
    For example if u'll put inputDate control inside and limit window size to fit just input field, calendar will be hidden behind scrollbars (as it'd be real new small browser window)

    I'm doubt there are any solutions for this problems and only hope that next release will fix it.

    However i'd be highly appreciated if by any chance you have suggestion to workaround this problems.

    ReplyDelete
  17. There is the possibility of creating a project from scratch? including ejb jpa, and how to generate the db from the ejb, please complete crud with a two or three pages

    Greetings from Ecuador

    Existe la posibilidad de crear un proyecto desde cero? que incluya ejb jpa, y como generar la db desde los ejb, por favor un crud completo con dos o tres paginas

    un saludo desde ecuador

    ReplyDelete
  18. Hi Andrejust,
    Thanks alot for your tips,

    I've a case, of which I have an editable table, that needs to be rendered in read-only mode dependant on some condition.
    I didn't find any property that makes all the table fields in read-only mode.
    I've come to a partial solution, by making the edit mode "clickToEdit" and made the row selection "none", by doing so, I've all the field in read-only form, and the user can't select a row in-order to edit.
    It's working fine, but the problem I'm facing now, is that the clickToEdit mode defaults the first row to be editable!!

    Do you have some better solution to make the table read-only, or some way to alter the default behavior of clickToEdit?

    Thanks,

    ReplyDelete
  19. Hi,

    In this case, you should put expression language on ReadOnly property of each inputText (column). That will give better runtime performance in your case.

    Regards,
    Andrejus

    ReplyDelete
  20. Thanks Andrejus,

    But I've got lots of tables, and hence lots & lots of columns.
    So, I was trying to find some generic solution on the table level not on the field (column) level to make the whole table read-only.

    Any idea?
    Your reply is highly appreciated,
    Thanks,
    Ahmed

    ReplyDelete
  21. Hi,

    Ok, then there is a good way to control rendering directly from Model, through IsAttributeUpdateable method.

    Check my blog post: http://andrejusb.blogspot.com/2009/12/overriding-isattributeupdateable-method.html

    Regards,
    Andrejus

    ReplyDelete
  22. Hi Adrejus,

    I've tried your example but with a checkbox on the popup. The problem is that the first time I press edit button the checkbox has the right value from the table, but if I try to edit any other row the checkbox is always empty.
    From the popup I can update the table, the only problem is when the popup opens it "loses" reference to the current checkbox state.
    Can you please help?

    ReplyDelete
  23. Hi Adrejus!

    I have a problem, when i use this with weblogic and firefox browser, adf popup doesn't close and adffacescontext don't execute? Can you help me?

    ReplyDelete
  24. You mean my sample app is not working, or you are creating your own?

    Andrejus

    ReplyDelete
  25. I also I have the same problem.
    to run on Weblogic and Firefox browser (the most current version) the "popup"for both your example as developed by me, not close. This is a great poblem for me, I hope you can help me

    ReplyDelete
  26. Hi,

    I will test this in my environment.

    Andrejus

    ReplyDelete
  27. Hi,

    I have tested with Firefox 3.6.16, its all works fine with sample app. Dialog is closed with Close button or by pressing X.

    Andrejus

    ReplyDelete
  28. hmmm ... I might not explain it right ... local mode everything works fine, but when loading the application to the application server - which is Weblogic 10.3.3 - popups work fine the first time that loaded, then to refresh the page, the popups do not close, it stays empty page Only with the X.

    ReplyDelete
  29. Ok, you mean on standalone server. It should be the same. No difference to run on standalone or embedded. I was testing on PS3.

    Andrejus

    ReplyDelete
  30. Hello ... sorry to insist with the subject of the popup. here is the link you an example. This has a tree-menu, go to option "Tipos de Ensayos y Analisis", there you can see the problem I have with the popups.

    http://app.corporacionlife.com.pe:7001/ERPDanielaDiamond/faces/Principal

    user : andrejus
    pass : andrejus

    Thank you to assist

    ReplyDelete
  31. Hi,

    This URL is not accessible.

    Andrejus

    ReplyDelete
  32. I'm sorry, try again please....that day there was power outage

    ReplyDelete
  33. Hi Andrejus!! What happened? Could you solve my problem? Answer me, please.

    ReplyDelete
  34. The popups do not close, it stays empty page Only with the X.

    I attached a link to a sample of it. the application is loaded on Weblogic...

    please check I gave you access so you can better see the problem I have.

    ReplyDelete
  35. Hi,

    I checked your link - it worked in Chrome, didnt tested on other browsers. I open Nuevo/Editar button - it loads popup. I can click on Grueba or Cancelar buttons - popup is closing.

    Andrejus

    ReplyDelete
  36. Hi,

    I've done a inline popup like the example and works great, but I want to know if is possible to set the "Close" action in the task-flow to the closing button of the dialog (the cross button in the dialog generated by the adf) instead of creating a closing button.

    Regards,
    André

    ReplyDelete
  37. hi
    Andrejus
    can we saved multiple record at one instance with code generation code.
    plz help me.
    thanks.

    ReplyDelete
  38. Please explain your question. I dont understand.

    Thanks,
    Andrejus

    ReplyDelete
  39. Hi Andrejus,

    I tried to implement same thing in a webcenter portal application but its not working properly.
    When i click on edit or insert button it does not open any popup.
    It also give me following error when i refresh my page.

    java.lang.IllegalStateException: The expression "#{bindings.navigationrenderer1.regionModel}" (that was specified for the RegionModel "value" attribute of the region component with id "pt_r1") evaluated to null.
    This is typically due to an error in the configuration of the objects referenced by this expression.
    If it helps, the expression "#{bindings.navigationrenderer1}" evaluates to "null".
    If it helps, the expression "#{bindings}" evaluates to "null". Now using an empty RegionModel instead.

    Kindly guide me to solve this problem.

    ReplyDelete
  40. Its working well for me in WebCenter app as well.

    Andrejus

    ReplyDelete
  41. Hi andrejus

    Have you tried to handle department Id automatically in spite of manually inserting one during new insert

    You have given its ans already in your cortical like :

    "It should work nicely, just drag and drop DepartmentId component on UI side again."

    But i cant understand this

    Best Regards
    sadia

    ReplyDelete
  42. kindly guide me.
    I am waiting for your answer

    Sadia

    ReplyDelete
  43. Yes, you should use DB sequence for that.

    There are two possible implementations from ADF side:

    1. When you have DB trigger to increment sequence, use DBSequence type for DepartmentID

    2. When there is no DB trigger, use Groovy script for DepartmentID to fetch new value from DB sequence. Or override EO create method

    Andrejus

    ReplyDelete
  44. Yes I have created a sequence for that. Do i need to add that sequence in adf model project ? Like we add adf BC from tables ??

    Also guid me how to override EO create method?? i have no trigger and have no idea about groovy script

    I have created my CRUD following your artical "CRUD Operations in Oracle ADF 11g Table Without Auto PPR"

    Need your help urgent. Thanks

    Sadia

    ReplyDelete
  45. May be this will help: http://one-size-doesnt-fit-all.blogspot.com/2009/03/adf-bc-using-groovy-to-fetch-sequence_20.html

    Andrejus

    ReplyDelete
  46. Hey Andrejus

    Got this error.

    ADF: Adding the following JSF error message: No signature of method: oracle.jbo.server.EntityImpl.seqNextVal() is applicable for argument types: (java.lang.String) values: [EVENT_SQN]
    groovy.lang.MissingMethodException: No signature of method: oracle.jbo.server.EntityImpl.seqNextVal() is applicable for argument types: (java.lang.String) values: [EVENT_SQN]


    Kindly tell what to do

    ReplyDelete
  47. check this blog: http://hasamali.blogspot.com/2011/04/adf-bc-various-way-of-setting-sequence.html

    Andrejus

    ReplyDelete
  48. Hey Andrejus

    Thanks alot

    Groovy expression are really powerful. I got my solution.

    Thanks again.

    ReplyDelete
  49. Hi Andrejus,

    Need your help for CRUD functionality between parent and child tables. I mean i need to generate CRUD for two tables in tree table or any other form.

    Best Regards
    Sadia

    ReplyDelete
  50. Hi Adrejus,

    I followed your steps to create Popup form but I am not getting the desired result as shown by your tutorial.

    First editPopupCancelListener() is getting called even if I am clicking cancel button or Esc on keyboard.

    Also once the rollback is executed the empty row is not getting deleted from the main table.

    Did you set any thing to fresh the table once the rollback is done?

    Regards,
    Abhijeet

    ReplyDelete
  51. Hi Adrejus and others-
    Did you guys get the popup to work? The example works fine but when I follow the exact same approach, my insert page doesn't render in a popup. Instead, the main page leaves rendering the insert page. What am I missing? UseWindow is set to "true" and WindowEmbedStyle is set to "inlineDocument". Yes, I am new to this. And yes, I googled the heck out.

    ReplyDelete
  52. Hi Andrejus,

    I have tried your method but i got errors : dialogListener="#{backing.editDialogListener}": java.lang.NullPointerException after editing a record.

    Would you have any idea with this problem?

    Thanks
    Dan

    ReplyDelete
  53. Hi Dan,

    What version of JDev you are using?

    Andrejus

    ReplyDelete
  54. Hi Sir,

    I am using Jdev 11.1.1.4.0. I did this but I observed that popup fetch listener is not working. It is not getting invoked at runtime. Please help me in solving out.

    Thanks in Advance.

    ReplyDelete
  55. Hi sir,

    I did this in Jdeveloper 11.1.1.4.0 I observed that the popup fetch listener class is not getting invoked at the runtime. I followed the blog post and did the exact replica of what have been posted. Kindly help me in finding where it is going wrong.

    thanks.

    ReplyDelete
  56. Hi Sir, This is same anonyomouns who posted that the Listener is not working. Now It is working but I am getting "java.lang.NullPointerException

    ADF_FACES-60097:For more information, please see the server's error log for an entry beginning with: ADF_FACES-60096:Server Exception during PPR, #1"

    this exception at runtime. what could be the problem please help me.

    Thanks.

    ReplyDelete
  57. Hi,
    I encounter a problem related to returnListener, but it may not related to the current item.

    I have a page with a popup button which will redirect to another page after the popup window is closed. The popup window is just a dummy window with OK and Cancel button only.
    For example,



    public void returnListener(ReturnEvent returnEvent) {
    redirect();
    }

    public void redirect() {
    String redirectURL = "http://127.0.0.1:7101/TestApp-ViewController-context-root/faces/test2.jspx";
    FacesContext context = FacesContext.getCurrentInstance();
    try {
    context.getExternalContext().redirect(redirectURL);
    } catch (IOException e) {
    e.printStackTrace();
    }
    context.renderResponse();
    }

    I can jump to test2.jspx page but encounter the following error.
    javax.faces.FacesException: Software caused connection abort: socket write error
    at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._renderResponse(LifecycleImpl.java:804)
    at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._executePhase(LifecycleImpl.java:294)
    at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:214)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)


    If I use another button to call the "redirect" function directly without popup a window. Everything is OK.
    It seems that the reason is the redirection is called from the returnListener.
    Any suggestion?

    Regards,
    Tony

    ReplyDelete
  58. Hi Adrejus;

    Thank you for the article. I have a very strange problem.

    I have a read only table. By clicking to the button on the row, a popoup dialog is opened. Here is a form for another table which takes initial values from the row clicked. I enter form values and commit, no problem. But when I do the same operation again for another row, it stucks in createInsert operationBinding.execute(). A heap space exception is given. I tried different solitions, but got the same problem. There is sometihing wrong withe the entity? Could you help m?

    Thank you!

    ReplyDelete
  59. Hi Team,

    I am unable to download the Zip file, please check and provide me with the updated link.

    ReplyDelete