Thursday, 7 January 2016

extend passivation snapshot with some extra data

Few things about passivation itself. I won't be much creative, quot from the docs 40.2.2:

An application module supports passivating (storing) its pending transaction state to an XML document, which is stored in the database in a single, generic table, keyed by a unique passivation snapshot ID. It also supports the reverse operation of activating pending transaction state from one of these saved XML snapshots. This passivation and activation is performed automatically by the application module pool when needed.
AM is passivating also such data like view criteria values, rows marked as current within iterators and much more. Data are passivated to the passivation store, by default to the PS_TXN database table. They can be stored also in a file and, depends on the documentation, in memory (but i haven't tried memory passivation store yet). Passivation store is the first place where you can find what data are exactly dumped.

Second option, more comfortable for developers is to dump BC4J debug data to the console. In 11g you'll use

-Djbo.debugoutput=console

parameter added to Java options. To achieve the same in 12c is to change proper log handler in logging.xml file (check solution provided here: https://community.oracle.com/message/11145783).

OK, but how to force AM to passivate its data more often or in easily reproduceable scenarios? Set recommended settings for developers - disable AM pooling and enable failover option:

-Djbo.ampool.doampooling=false -Djbo.dofailover=true

or in AM configuration wizard:


Now after each request each entity marked as modified will be passivated in order to hold the state. Please create entity object implementation class (I've checked only Accessors) and override two methods there: readAttrsFromXML and appendXMLElementNodes.


Drag and drop your collection on the test page as a form with navigation buttons and run the page. Change value of one of the attributes and check JDev console for the data.




In this demo I've used HR schema and REGIONS table.

Tuesday, 17 November 2015

region refresh after a button is clicked

Lets begin with an use case - I have got reusable taskflow which is drag&dropped on a page as a region. It should be refreshed each time the button is clicked. Easy? Easy!

To explicitly check if task flow is refreshed, I've used System.out stream to log messages. Whole initial implementation (bean, view activity, task flow diagram, bean definitions and the test page itself).






I'd like to have test message logged each time a button is pressed. It can be done with a lot of java code, but I won't write any java code more than test method. I'll print screen actions performed to implement the requirement.





What has happend? Step by step. First of all I need to have something which gives me more or less a random value. A value which will change on each request. Defining java.util.Date as a bean in the request scope in adfc-config.xml file I have got ability to get current date in EL expression. Inspiration can be found on one Duncan Mills post.

My reusable task flow must be extended with additional input parameter. I've named it refreshIndicator and marked it as mandatory. But it can stay optional too.

Changing task flow interface, each page definition must be updated with the new parameter. But do not set it with #{now} expression. I've used pageFlowScope memory to store the "random" value. Request scope is too low - the page or the region can invoke multiple requests during its lifetime. And the requirement was to refresh it only after a button is clicked.

The second change in the page definition file is value of task flow Refresh attribute - IfNeeded means that a task flow must be refreshed if any binding parameter value is changed. In this case if refreshIndicator parameter is changed.

So the last step is to update #{pageFlowScope.param} with #{now} value after a button is clicked. The easiest declarative way is af:setPropertyListener. And that's it. Below is the result:


Tuesday, 6 October 2015

High Available (HA) checklist for ADF applications

Making ADF application HA enabled, there are two groups of actions that should be performed. One is the configuration and the second is the development part of work. Below you'll find my checklist:
  1. in adf-config.xml descriptor put code <adf-scope-ha-support>true</adf-scope-ha-support>
  2. in weblogic.xml descriptor set session persistent store type as REPLICATED_IF_CLUSTERED
  3. each application module must have jbo.dofailover attribute set to true
  4. if you're using POJO DataControls, you need to implement three methods there: createSnapshot(), restoreSnapshot(Serializable handle) and removeSnapshot(Serializable handle); more about that here: Creating and Configuring Bean Data Controls
  5. each bean defined in the memory scope higher than request level must implement java.io.Serializable interface
    • avoid using java transient keyword regarding to the bean attributes
    • each attribute that extends UIComponent aren't serializable! if UI component must be binded with the code, use org.apache.myfaces.trinidad.util.ComponentReference wrapper there
    • make the framework aware of changes that needs to be replicated against the cluster, mark the scope as dirty, ie. using ControllerContext.getInstance().markScopeDirty(AdfFacesContext.getCurrentInstance().getViewScope());
  6. each page flow and session attributes must implement java.io.Serializable interface
 As short as possible. Hope it'll be helpful :)