Friday, May 31, 2013

There is new free ADF eLearning material available from Oracle - ADF Academy delivered online and available to anyone. You can access and learn from the first published course - Developing Applications with ADF Mobile.

One of the great things about this material - different technical resources are collected into one single place. Plus interactive way of viewing these video/audio resources makes ADF learning real fun !

Thursday, May 30, 2013

If you are looking for simple but effective solution to refresh data in ADF, you might be interested to check ADF Poll component. This component integrates well with ADF fragments - reload event is isolated in the scope of fragment and not distributed to entire page, means whole page will not be refreshed, but only fragment. I will demo this below with example.

Poll is set to initiate reload event every 5 seconds by default. It will stop sending reload events after 600000 seconds. PollListener is defined to implement reload logic:

PollListener re-executes VO SQL for the table and at the end sends Partial Trigger event to perform visual refresh for the Panel Collection UI component containing table with Employees data:

VO is re-executed by accessing iterator bindings from Page Definition:

Main page includes ADF region where Poll component is configured and additionally it contains another table component. There is one more table included to prove that data reload event is not distributed outside of the fragment:

We can see how it works. Open Departments tab from the main page, where no Poll component is configured and select any row from the table - remember your selection, we are going to check it later:

Go to the Employees tab and there check current salary value for Lex De Haan employee. Salary value is 17007:

Open database table and change salary value for the same employee to be 1500, commit your changes:

Switch back to page and you will see that during next data reload Poll event - change will be fetched to the UI:

Similar if you create new record and commit it in the database:

This record will appear in the UI automatically for you:

If you go to Departments, previously selected row still remains correct - this means Poll component was distributing reload event only in the scope of the fragment:

Monday, May 20, 2013

We were facing issues overriding Custom Transaction Factory in ADF 11g R1, it was initialized only for the first loaded AM, this seems is not the case anymore in ADF 11g R2 (11.1.2.x). I would like to present today a use case of implementing global after commit call. Read more about use cases with Custom Transaction Factory in ADF Developer Guide - 12.8 Customizing Business Components Error Messages.

You can see that message is printed after calling super in both cases:

If you want to execute code after commit operation was completed, you should call it after super in commit() method. This will be called one single time after commit, for all EO's at once.

In addition I have overriden doDML and afterCommit methods available in EO implementation to compare invocation time. Obviously these methods will be invoked separately for each EO:

We can test it now. Edit data from the first AM and commit transaction with Save button:

Check the log - first it starts executing SQL update statement. It calls doDML() method from EO implementation, next it calls doCommit() method from Transaction Factory, right before DB commit it calls afterCommit() method from EO implementation and finally after DB commit - commit() method from Transaction factory (after calling super) is called. This means afterCommit() method from EO is really invoked after data was posted to DB, but not after actual DB commit. In contrast, after super in Transaction Factory commit(), we can call custom logic and it will be executed after DB commit:

Test the same for the second AM:

It does same logic as for the first AM, you can check it applies correct AM instance:

Here you can download sample application - NewRowRemoveApp_v2.zip. So, the main trick is additionally to setting Immediate=true for Delete button, add ADF resetActionListener operation to the same Delete button:

Make sure Immediate=true is set for Delete button, along with ADF resetActionListener:

Add new row, force validation errors by trying to navigate to the next row:

Press Delete button to remove new row, validation errors will be ignored and row will be removed:

For ADF Form component is not enough to set Immediate=true property only, ADF resetActionListener must be added to force form refresh.

Wednesday, May 15, 2013

ADF Mobile is one of the hot topics in ADF area currently. If you want to see it in practice and learn about ADF Mobile architecture, I'm sure you should join UKOUG SIG in London on May 21st. Check here for more info and registration link - UKOUG Run Full Day SIG on ADF Mobile.

Grant Ronald and Susan Duncan are well known Oracle speakers, they will host this event. I know there are few seats left, you should hurry to register.

Thursday, May 9, 2013

Probably you already noticed that by default data is shared between VO instances (or even separate VO's) based on the same EO. Newly inserted row into one instance becomes instantly visible from another VO instance. There is a way to control this behavior in ADF, this post is based on excellent Steve Muench source of information - Using the RowQualifies() Method to Fine Tune View Link Consistency Behavior. As Steve says, by default data is shared and you can turn it off either by calling setAssociationConsistent(false) or globally per AM with jbo.viewlink.consistent=false configuration property:

Idea of this post is to go a bit deeper and to show how you control data sharing between VO instances programmatically. For example how to delay new row sharing between VO instances until this row is commited.

Two fragments are implemented in ADF Controller. First displays data from EmployeesEditView and allows to insert new row. While second displays a table with data from EmployeesListView:

We create now new row in the first fragment:

Navigate to the second fragment with the table. Keep in mind - new row is not commited yet, it is just inserted into EmployeesEditView VO instance. However, as per default behavior data is shared between VO's and this new row is appearing in the list from EmployeesListView VO instance:

In order to control when newly inserted row is shared between VO instances, we can override rowQualifies method from VO Implementation as per Steve Muench suggestion above. We have access to the row and can check row status. In this example row is qualified to be added into rowset if its status is unmodified:

Test now again the same scenario - try to insert new row, but don't commit yet:

Navigate to the second fragment with list data - new row is not added yet as expected:

Go back and save new row:

You can check it will be added to the rowset now and displayed in the list from second VO instance:

Saturday, May 4, 2013

New JDeveloper 11g (11.1.2.4.0) on Windows fails to start with embarrassing error after fresh installation, this is known issue and Oracle is fixing it. Seems like Oracle engineers missed it and released JDeveloper 11g (11.1.2.4) with wrong JDK. Once you install JDeveloper 11g (11.1.2.4.0) and try to start it, JDK error is reported - Java version 1.6.0_24 not supported. The minimum version required is 1.6.0_35 and JDEV startup stops, basically unusable:

If you go and check installation contents for JDeveloper 11g (11.1.2.4.0), you will see only JDK 1.6.0_24 packaged. This looks like a mistake to me:

Workaround (until Oracle will fix it in JDeveloper 11g (11.1.2.4.0)) is to install required JDK 1.6.0_35 manually by yourself and point it during JDEV startup:

With manually installed JDK 1.6.0_35 JDEV works:

Still this is quite funny - why JDK 1.6.0_24 would be included if JDEV requires JDK version 1.6.0_35.

Thursday, May 2, 2013

One of the bug requests I was fixing during this week was related to duplicate validation error message display on ADF UI. This was quite annoying to the users - the same validation error message displayed twice:

There was nothing special about this validation rule, as any other validation rule defined on ADF BC Entity Object:

I noticed something strange in Page Definition file. As per screenshot above, ADF UI renders only table component. However, in Page Definition file table binding was defined along with attribute binding for the Salary attribute:

Salary in the table is rendered from table binding, and as additionally we have attribute binding for the same element, this is causing the same validation error message reported twice (one for Salary in the table binding and another for Salary attribute binding):

Make sure not to leave duplicate bindings for the same attributes:

It reports only one validation error message, as expected:

Here you can download sample application with duplicate validation error message, try to fix it as described in this post - ADFValidationErrorApp.zip.