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:


59 comments:

Prueba said...

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

Andrejus Baranovskis said...

Hi,

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

Regards,
Andrejus

Prueba said...
This comment has been removed by the author.
directorscott said...

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.

Andrejus Baranovskis said...

Hello,

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

Regards,
Andrejus

directorscott said...

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

Andrejus Baranovskis said...

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

Andrejus

amer sohail said...

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.

Andrejus Baranovskis said...

Its available only from JDeveloper 11g R1 SP1.

Prueba said...

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

முத்துவேல் said...

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 !

Anonymous said...

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

Andrejus Baranovskis said...

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

Anonymous said...

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

can u help me ??

Andrejus Baranovskis said...

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

Nagh said...

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.

Anonymous said...

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

أحمد عبدالرحمن said...

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,

Andrejus Baranovskis said...

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

أحمد عبدالرحمن said...

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

Andrejus Baranovskis said...

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

Anonymous said...

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?

Anonymous said...

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?

Andrejus Baranovskis said...

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

Andrejus

Hiroshy Rojas Salcedo said...

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

Andrejus Baranovskis said...

Hi,

I will test this in my environment.

Andrejus

Andrejus Baranovskis said...

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

Hiroshy Rojas Salcedo said...

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.

Andrejus Baranovskis said...

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

Hiroshy Rojas Salcedo said...

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

Andrejus Baranovskis said...

Hi,

This URL is not accessible.

Andrejus

Hiroshy Rojas Salcedo said...

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

Hiroshy Rojas Salcedo said...

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

Andrejus Baranovskis said...

To answer, what exactly? :)

Andrejus

Hiroshy Rojas Salcedo said...

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.

Andrejus Baranovskis said...

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

André said...

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é

abhijeet pratap singh said...

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

Andrejus Baranovskis said...

Please explain your question. I dont understand.

Thanks,
Andrejus

Anonymous said...

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.

Andrejus Baranovskis said...

Its working well for me in WebCenter app as well.

Andrejus

Anonymous said...

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

Anonymous said...

kindly guide me.
I am waiting for your answer

Sadia

Andrejus Baranovskis said...

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

Sadia said...

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

Andrejus Baranovskis said...

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

Sadia said...

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

Andrejus Baranovskis said...

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

Andrejus

Sadia said...

Hey Andrejus

Thanks alot

Groovy expression are really powerful. I got my solution.

Thanks again.

Sadia said...

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

abhijeet said...

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

sydbrat said...

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.

Anonymous said...

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

Andrejus Baranovskis said...

Hi Dan,

What version of JDev you are using?

Andrejus

Anonymous said...

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.

Anonymous said...

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.

Anonymous said...

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.

Siu Fai Ng said...

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

Asuman AKYILDIZ said...

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!