Saturday, December 8, 2012

Good To Know - Conflicting View Objects and Shared Entity

While killing various issues and helping developers to get up to speed, during this week I encountered interesting ADF behavior - I would like to share it with you. Firstly it took some time to locate it and then I managed to reproduce it with sample application. Use case: 1 EO and 2 separate VO's, based on the same EO. You should admit, is quite common use case - often we share EO's across different forms and usually we implement dedicated VO's for each form (in most of the cases, hardly we can reuse the same VO with different View Criterias applied, because each form usually have different joins and different Master-Detail View Link relationships). Two separate VO's were conflicting during insert operation, more specifically - overridden create(AttributeList) method was invoked by the framework incorrectly. This method was overridden on VO (not on EO) level for a reason, because even VO's were based on the same EO - DB sequences for each of them were supposed to be different. I will describe it below - I hope it will be more clear at the end of this post, what I'm trying to explain (at this stage I believe is not) :)

Here you can download sample application, were described issue is reproduced (tested with the latest JDeveloper 11g - It is always easier to present complex issue through diagram drawing, here is the one:

Based on this drawing, sample application contains one EO and two different VO's, each based on the same EO. Both VO's are enabled with VO Implementation class, where standard create(AttributeList) method is overridden to get DB sequence (different for each VO). Representation for the same diagram drawing with ADF BC objects in JDeveloper 11g R2:

Open EmployeesOneViewRowImpl class for the first VO, you can see overridden method there and very important - EmployeeId key attribute is initialized with static test value 888:

Open EmployeesTwoViewRowImpl class for the second VO - EmployeeId key attribute is initialized with different static test value 999:

Run ADF BC tester utility and see how it works. What would you expect - two new rows (one row per VO), new row from the first VO with EmployeeId = 888 and new row from the second VO with EmployeeId = 999. Well - I also would expect the same, but is not how it works - good to know.

1. Insert new row into EmployeesOneView1 - correct value 888 is set for EmployeeId (see from the log, overridden create method was invoked):

2. Call Rollback for EmployeesOneView1 to forget inserted, but not yet commited row:

3. Insert new row into EmployeesTwoView1 - incorrect value 888 is set for EmployeeId. Instead of 888, value 999 must be set. Even more funny things - log reports that two overridden methods were invoked from different VO's:

It looks like ADF may misbehave in some situations, when we share common EO's across different VO's. However, I think this is special case related to new row creation and custom code invocation in overridden method for create(AttributeList). You should not worry, just double check carefully functionality you are implementing - sometimes unexpected bug may appear and spoil your work.

As a workaround for this problem, you can rely on ADF Groovy support and get DB sequence value through Groovy expression as default value for EmployeeId key attribute. Differently than initialization from overridden create(AttributeList) method, initialization through Groovy expression happens correctly - I have tested this. I would recommend to check how to use ADF Groovy for DB sequence value retrieval in Grant Ronald's white paper - Introduction to Groovy Support in JDeveloper and Oracle ADF 11g.


Anonymous said...

I think this is intended functionality, refer to 39.1.2 Maintaining New Row Consistency in View Objects Based on the Same Entity

Groeten, HJHorst

Andrej Baranovskij said...

Yes - bug by design? :)