Monday, January 18, 2010

Storing/Accessing Objects in ADF BC UserData Map

While implementing one of the requirements for View Criteria, I faced an issue when there was a request to filter View Criteria Item based on user language. Well, its trivial when you want to filter choice list defined for attribute - just specify bind variable value in View Accessor. Its a bit more tricky for View Criteria Item choice list, mainly because View Criteria can't access value from VO row. This means, if we want to filter View Criteria Item choice list, we need to use Groovy language script in order to retrieve value for View Accessor bind variable. In my case it was user language. What I did - I have read Example #154 from Steve Muench blog - Not Yet Documented ADF Sample Applications, and decided to store user language in UserData map, in order to access it from View Accessor Groovy.

If you will read Steve post, you will understand there are two approaches to access from your Model data available in ViewController layer. I prefer approach when UserData is set from custom Application Module method and then it can be accessed through Groovy.

Download sample application - UserDataGroovy.zip, where LocationId choice list is filtered based on user language. When browser works with English locale, LocationId brings locations from US:



When its set with French locale, LocationId is filtered again and shows French speaking countries:



As I already mentioned, there should be always clear separation between Model and ViewController. I'm storing user language value in UserData by calling ADF Task Flow Method Call:



This Method Call is invoking Application Module custom method, where current language is stored in UserData map:



You should see, language is stored in UserData map with currentUserLanguage ID. Same ID is used to access current language from View Accessor - adf.userSession.userData.currentUserLanguage:


10 comments:

Juan Pablo said...

Andrejus,
Excellent your blog...
I need to use ADF BC with Stored Procedures and want to know which is the best recommendation to do that.
Thank You.
JP

Andrej Baranovskij said...

Hi Juan,

Thanks. If your Stored Procedures dont have Table types, probably you can use just standard ADF BC functionality to call them.

If Table types are used, will need to adopt JPublisher to generate Java objects for those complex types and then again to use with ADF BC API.

Regards,
Andrejus

Juan Pablo said...

Andrejus,

Thanks for your response.
Do you have any examples? or links that I can use? because is difficult to find something usable...

Thank you again.

JP

Andrej Baranovskij said...

There was project started by Avrom Federman, you can get source code from here: https://database-api-based-adf-bc.samplecode.oracle.com

About JPublisher you can read here: http://www.oraclenerd.com/2009/07/sql-objects-jdeveloper-jpublisher-and.html

Regards,
Andrejus

Karim Hasan Abdellatif said...

Hello Andrejus,
your blog is very useful and interesting
may you post something showing the best practice of using Effective Dated Entity Objects

Thank you,
Karim

Samson Fu said...

Andrejus,
I found an exception when I try to apply the adf.userSession.userData.variable to my VO's Bind variable.
>> Name __userBCSession__ not found in the given object: oracle.jbo.server.ViewDefImpl

Since I have 6 Application Modules in my application. I've called
this.getSession().getUserData().put("variable", data);
in a common AM during user login.
Then I will use it in other AMs as your example. Can I do that, or I have to assign the userData in each AMs individually?

Thank you.
Samson Fu

Andrej Baranovskij said...

Hi,

I didnt tested myself with different app modules. But I guess, you will need to store it in each module individually.

Regards,
Andrejus

secretPlace18 said...

Hi, Andrejus, please, I need to make debugging of the expresion adf.userSession.userData.currentUserLanguage, but I need know how get user session without groovy, i.e. programatically from initdefaults() in a EO class.
Thanks.

Unknown said...

Hi Andrejus,

It's really excellent blog. I tried to follow the same approach. Some how,getting null value with this.getSession in AMImpl. Please suggest if you have any clue on the issue.
Thanks,
Samba.

Andrej Baranovskij said...

Hi,

Yes, you need to implement passivation/activation support for the custom values in user map: http://andrejusb.blogspot.com/2012/05/solution-for-sharing-global-user-data.html

Otherwise value will be lost during passvation/activation for the AM.

Andrejus