If you are using instance variables in your Application Module (AM) class, as part of some algorithm in your application and you expect these variables to persist from one user request to another so that the algorithm works as expected, passivation (and activation) support for these variables must be added. This FAQ will show you how to do this and at the same time build a "mini sub-framework" to avoid duplication of the basic passivation-activation code that you must write for all your AMs in your project.
Some Introductory Information
Application Module pooling is the process of acquiring an AM from and releasing it back to a pool. This pool of AMs contains a limited number of AMs defined in a configuration file. When all AMs have been associated with user sessions, an already-used AM must be re-used. For this to happen, the existing data associated with the AM must be saved. The passivation process saves information used by the AM into the passivation store - usually a database, while the activation process does exactly the opposite, restores the state of the AM from the passivation store. The information is saved as an XML document. Take a look at FAQ #14 - How to test an Application Module for activation-safe in ADF 11g for additional information regarding the passivation and activation processes.
You can add custom passivation and activation logic in your AM class by overriding the ApplicationModuleImpl methods passivateState() and activateState() respectively. The passivateState() method should create the necessary XML elements for each AM instance variable that you need to passivate. The activateState() method should detect the specific XML elements that identify the instance variables in the passivated XML document and restore them back into the instance variables.
A "mini sub-framework" for passivating/activating Application Module instance variables
If you are using multiple AMs, you can avoid code duplication of this basic implementation of the passivateState() and activateState() methods by putting it in a base AM class. Then derive all of your other AMs from this base AM. The base AM class can then provide activation/passivation "triggers" to which the derived AMs can respond. The implementation of passivateState() in the base AM should look like this:
As you can see, after calling super.passivateState() to allow the framework to do its own processing, we call onStartPassivation() to signal derived AMs that a passivation process is taking place. Derived AMs should override onStartPassivation() in order to provide a list of the identifiers - each identifier tied to a specific instance variable - to be passivated. Below is an example implementation of onStartPassivation() by a derived AM class.
In this case a single passivation identifier call EMPLOYEE_LIST_ID is returned to indicate a list of Employees class instance variable.
passivateState() then loops for all passivation identifiers, creates an XML node for each identifier in the XML passivation document and calls onPassivate() passing the passivation identifier as an argument to it. A derived AM will override this method in order to return the passivation data for the specific passivation identifier. An example implementation is shown below:
In this case the passivation identifier is checked and if it matches the expected identifier, the passivation data is supplied.
Finally, passivateState() calls onEndPassivation() to indicate the end of the passivation process.
The reverse process of activation is similar. activateState() calls onStartActivation() to get the activation identifiers. It then loops looking for each activation identifier in the activated XML document. If the identifier is found, calls onActivate() supplying the activation data along with its activation identifier as arguments. The derived AM can identify the instance variable being activated - based on the activation identifier, and restore it.
To test the framework, bring up the Edit Business Components Configuration dialog and disable Application Module Pooling as it shown below. You do this by right-clicking on the AM in the Application Navigator and selecting Configurations... Then you click on Edit... to edit the specific configuration.
This will in effect initiate a passivation-activation cycle for each request when the application is running. Finally save the configuration, enable debug logging on the console and run the application. You should see your AM class instance variables being activated.
To further explore this framework, the source code is supplied below.
If you are using class instance variables in the BC layer and you want their values to persit from one request to another, then passivating-activating these variables becomes necessary. The ADF BC framework allows you to do this by overriding the passivateState() and activateState() methods.
Until the next time, keep on JDeveloping!