Recently I was hunting an interesting bug. The bug was pretty confusing for users because it seemed that some data can be transfered across user sessions. The reason of the bug was very common mistake. Sometimes ADF developers consider Entity definitions (EntityDef) and View definitions (ViewDef) as session scoped objects. They change properties of EntityDefImpl and ViewDefImpl instances, or, which is more likely, properties of AttributeDefImpl and forget that these changes effect all users sessions. There is only one instance of particular EntityDefImpl per application instance. The same is correct for ViewDefImpl as well.
Let's consider a simple task flow:
There is view activity BrowseView representing data in a table and allowing users to create new records. The default activity of the task flow is some method call setDefaultLastName. If we look at its code we'll see the following:
The correct way to implement this use case is to define some groovy expression as the default value of the "LastName" attribute. Something like this:
And, for sure, user's last name should be passed somehow to the business service layer. For example, by invoking the following method:
Let's consider a simple task flow:
There is view activity BrowseView representing data in a table and allowing users to create new records. The default activity of the task flow is some method call setDefaultLastName. If we look at its code we'll see the following:
//The method sets user's last name as //the default value of the "LastName" attribute public void setDefaultLastName(String lastName) { //Get Entity Definition EntityDefImpl ed = getDefinitionObject(); //Find an attribute definintion AttributeDefImpl ad = (AttributeDefImpl) ed.findAttributeDef("LastName"); //Set the default value ad.setDefaultValue(lastName); }So, when users start this task flow, the default value of the "LastName" attribute of the table becomes their last name. And, after that, when they create new records the value of the "LastName" is populated with their name. Cool! User, whose name is Stogova, entered the task flow, started to create new records and she is happy. So far. Another user, whose name is Smith, did the same. Stogova is still creating new records at BrowseView, and one moment she is realizing that she has become Smith. Cool!
The correct way to implement this use case is to define some groovy expression as the default value of the "LastName" attribute. Something like this:
adf.userSession.userData.lastName
And, for sure, user's last name should be passed somehow to the business service layer. For example, by invoking the following method:
public void setupUserLastName(String lastName) { ApplicationModule am = getApplicationModule(); am.getSession().getUserData().put("lastName", lastName); }That's it!
This article is very informative.
ReplyDeleteI am using Jdev 11.1.2.0.0
I have tried the scenario mentioned here with Declaratively created Entity object and the behavior is as you explained.
Then tried another scenario, create an EntityDefImpl at run time as below and adding AttributeDef depends on login user.
EntityDefImpl newEntity = new EntityDefImpl(DYNAMIC_EO);
newEntity.setFullName(DYNAMIC_PACKAGE + "." + DYNAMIC_EO);
eg: For user1, EntityDefImpl has 2 attributes.
For user2, EntityDefImpl has 4 attributes.
I have logged into the application with User1,User2 simultaneously and observation was, each user can see EntityDefImpl attributes on UI as expected.
Will EntityDefImpl scope changes to Session Scope, if EntityDefImpl creates at runtime?
Thanks
Nag
Hi Nag,
DeleteYes, if EntityDefImpl is created dynamically using EntityDefImpl(String name) it will have session scope.