Monday, March 4, 2013

ADF Rollback Operation and Stay On Current Row

This post is extension for my previous posts about ADF CRUD and is based on - ADF Query Search and Results Form blog. As most likely you have noticed it already, Rollback operation in ADF removed all pending changes plus it resets current row to the first row in data collection. Resetting current row to the first is not always desirable, I will provide sample application which demonstrates how to prevent resetting to first row after Rollback operation was invoked.

Download completed sample application - ADFCRUDRollbackApp.zip. There are two ADF BC generic classes with overridden methods you should pay attention for in this sample - GenericVOImpl and GenericAMImpl.

GenericVOImpl contains beforeRollback(...) and afterRollback(...) overridden methods. beforeRollback(...) is responsible to retrieve and store current row key and range index (so we can reset it back):


afterRollback(...) method sets current row key back and scrolls to current row range (this allows to preserve current row on the UI with single generic and reusable implementation in ADF BC):


You must override prepareSession(...) method in Application Module generic class and disable clearing cache on rollback (otherwise nothing will help to keep current row, even setting it programmatically):


Let's do a test now - search with ADF Query and scroll few records, we can change hire date value:


Press Cancel button now:


Unsaved data will be cleaned and data row restored to its original state - current row remains the same:

18 comments:

ILya Cyclone said...

Hello Andrejus,
Many thanks for this post. Could you please explain if this method is passivation/activation safe as we're using BC variable?
Any side effects of overriding prepareSession in this way?

Andrej Baranovskij said...

Hi,

Yes - it is safe for passivation/activation, I was testing with AM pool disabled, no issues recorded.

I didn't encounter side effects specific to disabling clear cache on rollback at this moment. VO is re-executed from afterRollback method.

Andrejus

Vanessa said...

Hello Andrejus

First of all thanks for this post and many others, are very useful for me.
I have a problem that I think is related to this topic.

I have an af:table with CRUD buttons and popups to modify the data table. When I move the scroll to see the records in the middle of the table and click the edit button to open popup to edit record, when I rollback the operation the vertical scrollbar automatically resets to the top position and the currentRow remains in the correct row. When I do the same but commit the operation, the vertical scrollbar don't moves.

I override the beforeRollback/afterRollback methods as you suggest. I save the getRangeStart return value within the beforeRollback method and tried to set with scrollRange(range) or scrollToRangePage(range) methods within the afterRollback but nothing changes, the scrollbar resets to the top position. The getCurrentRow and getRangeStart methods return the original values before rollback, but the scrollbar continue moving at the top position of the table.

I execute the addPartialTarget method to refresh the af:table. When I comment this method then the scrollbar don't moves, but obviously the changes don't show.

Furthermore, the same application don't moves the scrollbar in JDeveloper 11.1.2.1, now I'm using JDeveloper 11.1.2.3

Is there any way to control the position of the scroll? Or is there any way to refresh the table without resetting the scroll?

Any ideas would be appreciated.

Thanks

Andrej Baranovskij said...

Hi,

Approach described here will work only for ADF form component. I know what you mean by keeping selected row in the table after scrolling, I faced this also - it looks to be a bug in latest JDev version, I didnt had time to look for workaround yet.

Andrejus

Emmerson Miranda said...

Hello,

This code take the state of the current row of viewObject, that works fine when -Djbo.ampool.doampooling=false.

But when is true, the better option is take the current state of the entities associates of current row, if the VO is based on entities.

You can prove this creating a row master, doing commit, create a row child in the last row create and make rollback while editing the detail row, then you can watch how current row is moved to another row master.

Andrej Baranovskij said...

Hi,

Yes indeed - this sample app is using row state from VO, mainly because of the issues related to Entity cache, when several VO instances using same EO - we had issues.

But generally I agree, is good to use state from EO - depends on the use case.

Andrejus

Anonymous said...

Hi Andrejus,
Can I use same code ,if I am loosing current row during activation and passivation

Andrej Baranovskij said...

This is very good question - I will test it and let you know.

Andrejus

Andrej Baranovskij said...

Hi,

You should not loose current row during activation/passivation by design, ADF ensures that current row will be preserved during activation/passivation.

Andrejus

Koen Verhulst said...

Hi Andrejus,

are there any disadvantages in setting the "ClearCacheOnRollback" to false?

Won't this lead to more stale data?

Thanks,

Koen

Koen Verhulst said...

Hi,

another small question: is there a reason why this does not work in the BC tester?

Does the current row change when browsing through data of a VO in the BC tester?

Regards,

Koen

Andrej Baranovskij said...

Hi,

You would need to use "ClearCacheOnRollback" to false, as we must access previous key after rollback.

I don't remember if it works in ADF BC tester, I don't see a reason why its not - I would need to test.

Andrejus

Habib said...

Thanks, it's really helpful.
According to this way if we navigate between many TFs and in each one we have some VOs and then back to the main page and click Rollback, all VOs execute again whereas we don't need
to execute all these VOs, doesn't have any negative effects?

Regards,
Habib

Eric F. Jones said...

Old Post, but I'll ask Habib's question anyway... In an app where there are many VO's that need to be re-executed during rollback process, wouldn't that make for a slow operation? Is there a way a to only re-execute VO's that had pending transactions in them for rollback?

Thanks!
- Eric

Andrej Baranovskij said...

Hi,

Rollback is done per AM, this means all VO instances will be re-initialized from this AM. Thats why you should plan to have multiple AMs in the app, most likely one AM per use case, or use isolated TF's, with smaller number of AMs

You have an option to refresh row from current VO to clear changes, with row.refresh method. But this depends on your use case.

Regards,
Andrejus

Koen said...

Hi Andrejus,

we currently use this method to restore current rows in our application(s). Is there a way to store the current row and clear the cache on rollback?

Also, as stated by Erik Jones above: ".. would't make this a slow operation". Are there any alternatives better for performance?

Regards,

Koen

Habib said...

Thanks, We have a root AM so others AMs nested to this root AM, and commit and rollback done into root AM.
We've defined a custom property for any VO that we need to stay on current row after rollback and in beforeRollback() method, first check if this property has value or not

Regards,
Habib

Sarron said...

We have a situation where import is going into infinite while loop based on the vo iterator as it's reset during a rollback. We tried this approach and it's working fine.Though it works fine with am pooling disabled,But using instance variables would give code violations for passivation safety. Can you pls suggest something on the same?