Thursday, June 2, 2011

Understanding ADF BC View Object Instances

Its quite easy topic, but sometimes is confusing, especially for ADF newbies. I will try to explain today, how View Object instance works and what you should know when using the same View Object instance across different ADF task flows.

Sample application contains two bounded ADF task flows, both of them are referencing the same View Object instance - EmployeesView:


Same View Object instance is accessed programmatically as well, from custom Application Module method:


As described above, Application Module is exposing single View Object instance:


This is most typical mistake, when developers want to access the same View Object from different forms, they are assuming they can access the same View Object instance. However, this may be conflicting behavior.

First ADF task flow is loaded, first record is shown:


Open second tab, to load second ADF task flow and filter data for First Name:


Go back to first tab - open first ADF task flow, data will be filtered as well:


This means, even we are using two different ADF task flows - same View Object instance is sharing same data.

Custom method from Application Module is returning same results, View Instance is filtered and first row is not pointing anymore to original first row:


Let's fix this data conflict behavior and add one more same View Object instance into Data Control:


Application Module custom method is changed to consume newly added View Object instance as well:


Page Definition from one of the ADF task flows is refactored, now Iterator points to new View Object instance from Data Control:


Second ADF task flow is filtered:


Differently than before, now first ADF task flow is not affected anymore by changes from another ADF task flow - it still brings all records, as we would expect when using different View Object instance:


Programmatic method returns expected results as well - data is not filtered from another View Object instance:


As you can see, if different ADF task flows are using same View Object, you should avoid using same View Object instance - unless its expected behavior to maintain same set of rows in both task flows (which is not often practical use case).

Download sample application - ADFBCVOUsage.zip.

13 comments:

morph said...

Why can't we just clear VOCaches when we parse a different taskflow by calling clearVOCaches. I think if a person needs to reuse the same view object in 10 different taskflows one would be better off clearing the cache then creating 10 different instances.

Andrejus Baranovskis said...

And what if two task flows will be used at same time? Then we will end up into conflict. Its most typical mistake.

Andrejus

morph said...

Hmm maybe you are correct in saying that but in that case wouldn't one want to use default behavior. Also in case one has independent taskflows wouldn't they be better off if they just clear vo caches.

Andrejus Baranovskis said...

To clear VO caches is not typical ADF BC behavior, is more like a hack. Also, even independent ADF Task Flows by default are sharing Data Control - means cache is preserved for VO's. You can run ADF Task Flows in isolated mode, then it will clean cache for you - but it will consume more DB connections, will not keep state, etc.

Exactly, to use different VO instances is default ADF BC behavior.

Andrejus

mbonga said...

thanks very helpful, but how can i access view object in managed bean to invoke CreateInsert method for example

Andrejus Baranovskis said...

Hi,

There is even no need to acces VO directly for this scenario - calling CreateInsert. You can call CreateInsert operation from bindings, inside bean.

Its interesting topic, i will post sample app.

Andrejus

Anonymous said...

Well this makes you wonder why there is no means of defining a view object instance at the task flow level in addition to defining one at the application module level

Dinesh said...

Hi Andrejus,

In java, I want to get the rows from the view object based on one particular attribute's value (may be if attr == true) and get the rowset for further processing.

What I'm doing now is just getting the view object in java and iterating it in a loop based on the condition. But I don't think this would be the right way if there are large number of rows.

Could you please tell me the best solution.

Thanks,
Dinesh

Andrejus Baranovskis said...

Create another VO instance, define View Criteria and execute it to filter directly from DB.

Andrejus

Dinesh said...

Hi Andrejus,

In my application, I call a procedure which inserts rows in a table say X. But the view object corresponding to this table is not getting updated and this is not occurring every time.(may be once in 3 times).
I tried using VO.executeQuery() and still the new rows are not visible in VO.
But when I get the same viewobject from the viewLink, I can see the inserted rows. But how I couldn't understand.
In both cases the VO instance is the same.

Could you please tell me what exactly goes wrong in my implementation.

Thanks,
Dinesh

Anonymous said...

Hi Andre,

How can we create an viewObject instance programmatically. Consider I want to creat a detail object instance programmatically how can i do that. Please help me in this.

Thanks,
Ravi.

Praveer Das said...

Hi Andrejus,

If I create a new View Instance, is it possible to change the number of columns in the new instance ? My requirement is to reduce the number of columns in the new VO Instance, as compared to the original VO.

Komputer said...

hi andre,

can i ask ? this is my ApplicationModule, but always display error "too many object...."

public void BeforePostingCR(String UserName, String JournalNo, String JournalNoBank, String PaymentId, Number HLL){
voPaymentMasterTODetailImpl voPaymentMasterTODetail = (voPaymentMasterTODetailImpl)getvoPaymentMasterTODetail1();
voPaymentMasterTODetail.executeQuery();

TrJournalImpl TrJournal = (TrJournalImpl)getTrJournal1();

Row CurrentPaymentMasterTODetail = null;
Row CurrentTrJurnal = null;


if(voPaymentMasterTODetail.getEstimatedRowCount()>0){
System.out.println("voPaymentMasterTODetail : "+voPaymentMasterTODetail.getEstimatedRowCount());
while(voPaymentMasterTODetail.hasNext()){
voPaymentMasterTODetail.next();

CurrentPaymentMasterTODetail = voPaymentMasterTODetail.getCurrentRow();

System.out.println("InvoiceNo : "+CurrentPaymentMasterTODetail.getAttribute("InvoiceNo"));
System.out.println("Installment : "+CurrentPaymentMasterTODetail.getAttribute("Installment"));

ViewCriteria vcTrJurnal = (TrJournal).getViewCriteria("FindInvoiceNoFromPaymentDetail");
vcTrJurnal.reset();
TrJournal.setP_INVOICE_NO(CurrentPaymentMasterTODetail.getAttribute("InvoiceNo").toString().substring(0, 15));
TrJournal.setP_INSTALLMENT(CurrentPaymentMasterTODetail.getAttribute("Installment").toString());
TrJournal.applyViewCriteria(vcTrJurnal);
TrJournal.executeQuery();

if(TrJournal.getEstimatedRowCount()>0){
System.out.println("Total TrJournal : "+TrJournal.getEstimatedRowCount());

while(TrJournal.hasNext()){
TrJournal.next();
CurrentTrJurnal = TrJournal.getCurrentRow();

System.out.println("CurrentTrJurnal InvoiceNo : "+CurrentTrJurnal.getAttribute("InvoiceNo"));
System.out.println("CurrentTrJurnal Installment : "+CurrentTrJurnal.getAttribute("Installment"));
}
}
}
}else{
System.out.println("voPaymentMasterTODetail Empty");
}}


can u help me please...