This post will describe solution how to share custom user data in ADF BC. There is a way to access HTTP session scope directly from ADF BC -
Bad Practice for Session Scope Access in ADF BC, while you can follow this approach in exceptional cases, this is not recommended from enterprise architecture point of view. Mainly because you may face snow ball effect - there will be more and more ADF BC and ADF UI dependency introduced over time and at the end will make system not maintainable. Solution is generic and will cover following requirements:
1. Custom user data will be initialized for every AM instance automatically
2. Custom user data will be preserved between passivation/activation requests
Download sample application -
UserDataADFBCSample.zip. Implemented solution is based on such architecture:
Where on the higher level we have user preferences variables stored in HTTP session. For each Data Control, where we want associated Application Module to be initialized with custom variables for User Data, is defined custom Data Control factory class. Data Control factory class is calling generic Application Module implementation class, where it invokes generic method to populate User Data. Every AM extends from generic Application Module implementation class - this means it gets User Data set. There are standard methods for passivation and activation overriden inside generic Application Module implementation class - this allows to preserve custom User Data between passivation/activation requests.
From developer perspective, in order to use this solution for specific AM - only one configuration thing is required - set custom Data Control factory class, the rest will be handled by implemented generic classes. Select Data Control usage from DataBindings.cpx:
Set Data Control factory class to our custom class:
I will describe now, what happens behind the scenes - how this solution works based on proposed architecture.
1. Make sure Model project is configured with Base Classes, specifically in this case with generic Application Module class (responsible for extended activation/passivation process and User Data initialization):
Generic Application Module class overrides ADF BC framework
passivateState(...) method - its the place, where we store custom variables from User Data along with standard ADF BC data into PS_TXN table:
activateState(...) method is overriden as well - to initialize activated custom variables back into User Data:
Generic User Data initialization method is pretty simple in this example, it stores only one variable:
Every AM should extend from generic class. For test purpose, I have implemented custom method to print User Data entry - you will see that it will be preserved across passivation/activation requests thanks to the Application Module implementation generic class - CustomAMImpl:
2. There is custom Data Control factory class defined. This class substitutes Data Control class with our own custom class:
Custom Data Control class overrides only one method -
setSessionCookie(...). This method is called by the framework only once, when Data Control gets initialized (Data Control may get initialized multiple times during the same session, if you are using isolated Task Flows (not recommended)). From setSessionCookie(...) method, we are getting instance of generic Application Module implementation class (by casting Data Provider) and initializing User Data with user preferences variable value stored in HTTP session scope. This is completely generic, because action is done through generic class without touching underlying AM for selected Data Control:
3. Time to test. You should test with AM pooling OFF - means will simulate stress test environment and force AM instance to passivate/activate on each request:
With jbo detail logging enabled, we can see that passivation request stores into PS_TXN table along with standard ADF BC data, our own custom User Data also (because overriden method in CustomAMImpl):
Tags for custom entry and other data is declared inside CustomAMImpl. There is limitation of max 10 entries for custom User Data passivation is set, you can increase it (its safer to control this, in case someone will start to enter hundreds of entries into User Data):
When fragment is loaded, based on our test - passivation/activation happens (AM pooling is OFF). With default implementation of User Data - values will be lost, but now CustomAMImpl takes care for this. Press
Print Uset Data Entry to test if variable from User Data is retrieved correctly:
Variable data is printed:
4. Task Flow isolated mode. This solution works for Task Flow isolated mode:
When task flow is opened in isolated mode -
setSessionCookie(...) method from Data Control class gets invoked again:
This mean, there is new fresh AM instance created of the same Application Module. But, because
setSessionCookie(...) method is called - user data gets initialized for that new instance. User data can be initialized not only during login process, but during session lifetime as well.
We can test this by opening isolated task flow:
Print user data variable:
Data is printed successfully:
5. Test without passivation/activation for custom User Data. Comment out custom code for User Data passivation inside CustomAMImpl class:
There will be no custom data added into passivation package:
User data will be NULL, after passivation/activation request: