Sunday, October 23, 2011

Back to the basics. In most of the cases data is coming from Model layer, from ADF BC or EJB. When user is changing data on the screen, frameworks takes care and preserves temporary data. However, what about such screens where we have temporary fields, without any relation with the Model layer - transient data fields. What if there is no corresponding Model implementation, and still we need to store field data between requests - where should we store it? I believer, one of the best techniques is to use Page Definition variables, this is old approach back from ADF 10g times - but it still works very well. Main advantage - we are able to store transient temporary data between requests and there is no need to define session scope bean.

It happened to see scary things - developers are defining managed beans in Page Flow Scope, just because they want to make sure temporary UI values are preserved between requests :)

Download sample application - PageDefVariables.zip. This sample implements two input components - inputText and inputNumberSlider. Both components are enabled with autoSubmit, as well as value change listener is defined for both. Once value is changed for one of the components, we recalculate total sum of both fields and display as total:

Both input components exist only in UI, there is no Model layer representation - user types values, total is recalculated immediately. However, we still need to store entered values, otherwise once we select number slider - partial request will be invoked and value entered for income will be lost. ADF developer would try to store input value inside Backing Bean:

It would be wrong to store temporary value inside Backing Bean - this bean lifetime is as long as request, in other words - once we will enter second input value, first will be always lost. You may think to define Session or even Page Flow Scope bean - that would make it work, but why to waste server memory - only if you want to make your ADF applications slow.

We can use Page Definition variables to store temporary values, these values will be preserved between requests. Open Page Definition, associated with the page, expand executables and select to insert new variable:

Give a name and specify a type for new variable:

In my example, I will define all three variables in the same way - for each of the fields:

Once variables are defined, we are not done yet with Page Definition. For every defined variable we need to define corresponding attribute (will be accessed from the page). Insert new item under bindings - Attribute Value:

When creating new Attribute Value, make sure to select variables as Data Source and map related variable (defined one step above) name:

Once all done, we should have following picture - each variable is assigned with attribute value:

Go back to UI now, input component should have its value property mapped with attribute value (not with variable directly, because data will not be stored/retrieved) from Page Definition. For example: bindings.incomeVarAttr.inputValue:

Once again - UI component value you should map with attribute value, not with variable directly:

Finally, you may ask question - how to access attribute values defined in Page Definition programmatically? Easy - use ADFUtils wrapper class. There are two methods available for your convenience - getBoundAttributeValue("name") and setBoundAttributeValue("name", value):

Main reason is that pageFlowScope and viewScope stays clean and we can easier track what temporary values we are using. Plus we are leveraging ADF Model layer to store our data, without relying on memory scope.

Ideally, in pageFlowScope we should store only TF input parameters, by design.

viewScope remains active, only while on current page. But when storing temp values in ADF Model, values will remain - same as other values coming from ADF Model.

Please share your comments on another doubt of mine. I was just wondering if this implementation for saving temporary variables is HA compliant i.e. failover safe. When we put values into memory scopes and the scope is dirtied, it gets serialized and the changes are propagated to other nodes of the cluster. If a node goes down, the state is automatically recovered. Passivation takes care of temp. attributes in the BC layer. But, what about these page definition variables, are they also taken care off somewhere ?

I am trying to use PageDefinition variables, but getting some issues. Values are getting lost. I have also posted a question on OTN forum..https://forums.oracle.com/forums/thread.jspa?messageID=10846833#10846833