Saturday, November 29, 2014

Cluster configuration for High availability ADF applications

Need of clustered environment

If your system is underperforming and not available enough then that signs that you need clustering. It will improve Scalability and high availability (If one member of the cluster is unavailable, any other available member of the cluster is able to handle the request.)
When the Fusion web application runs in a clustered environment, a portion of the application’s state is serialized and copied to another server or a data store at the end of each request so that the state is available to other servers in the cluster .If it not serialized then user will lose data upon fail-over.
WebLogic duplicates those sessions by serializing the objects in the session and then transfers it to the secondary machine. Only the objects that are stored in the session will be replicated. From an ADF perspective this means that managed bean with pageFlowScope and above will be replicated.

Configuring Oracle ADF development for High Availability

JSF Component Binding
  1. Always use ComponentReference binding code in your managed beans, regardless of the scope  the bean is in.
  2. Never use UIComponent binding in session-scoped managed beans.
  3. Please make sure that managed beans used in ADF application with a scope greater than one request should be serializable (implement the java.io.Serializable interface).

Specifically, beans stored in session scope, page flow scope, and view scope need to be serializable.
UIComponent is not a serializable class, and you are going to get a serialization exception in case of binding components to the long-living managed beans.
Also the UI component tree might not be released correctly, significantly increasing the memory load of your application.

Solution: (for Binding UI Component)
The standard UIComponent binding code looks like this:

RichInputText nameField;
 public void setNameField(RichInputText nameField)
{
  this.nameField = nameField;
}
 public RichInputText getNameField()
{
  return nameField;
}

Should be replaced with code like this:

private ComponentReference nameField;
public RichInputText getNameField()
{
  if (nameField!=null)
  {
    return (RichInputText) nameField.getComponent();
  }
  return null;
}

public void setNameField(RichInputText nameField)
{
  this.nameField = ComponentReference.newUIComponentReference(nameField);
}

Configuring Application Modules

Right-click the application module and select Configurations. Click Edit. Click the Pooling and Scalability tab. Select the Failover Transaction State Upon Managed Release checkbox.

<AppModuleConfig ...
 <AM-Pooling jbo.dofailover="true"/>
</AppModuleConfig>

Configuring weblogic.xml

In weblogic.xml file, add entry as below persistent-store-type definition to the session-descriptor element like below


<weblogic-web-app>
    <session-descriptor>
    <persistent-store-type>REPLICATED_IF_CLUSTERED</persistent-store-type>
    </session-descriptor>
</weblogic-web-app>

Configuring adf-config.xml

In adf-config.xml file, add entry as like below
<adf-controller-config xmlns="http://xmlns.oracle.com/adf/controller/config">
 <adf-scope-ha-support>true</adf-scope-ha-support>
</adf-controller-config>

Notify ADF for Bean new value

When a value within a managed bean in either view scope or page flow scope is modified, the application needs to notify Oracle ADF so that it can ensure the bean's new value is replicate.

Map<String, Object> viewScope =
    AdfFacesContext.getCurrentInstance().getViewScope();
MyObject obj = (MyObject)viewScope.get("myObjectName");
Obj.setName("newValue");
Use the markScopeDirty() method,
controllerContext ctx = ControllerContext.getInstance();
ctx.markScopeDirty(viewScope);

There is one more option which needs to be tested:
You can also enable automatic tracking of scope modifications. To do this you should modify adf-config.xml as shown below,


Check default logger messages

Run each use case in UI application. Verify that you don’t see below highlighted errors in Domain console log.

[manageserver1] [ERROR] [] [oracle.adfinternal.controller.state.SessionBasedScopeMap] 
java.io.NotSerializableException: com.ram.mytest.manage.TestMB

Changes in Application server

While doing development Jdeveloper integrated server will not throw any errors by default. Add this parameter in server (setDomainEnv.cmd) has to be run with the following JVM parameter:

-Dorg.apache.myfaces.trinidad.CHECK_STATE_SERIALIZATION=all

For more detail about sample application deployment in cluster and configurations, check out my post here

4 comments:

  1. This blog helped me a lot for testing I'm doing an application in a cluster environment, but give it 2 Questions
    1-If you could be more explicit about how to set this parameter -Dorg.apache.myfaces.trinidad.CHECK_STATE_SERIALIZATION = all
    2- I want to centrally manage all users who are connected and disconnect to demand, that the function of an administrator for example, but does not apply to disconnect the session, but only seems to do it on the primary server, secondary server not be where this replica of the sessions, I wonder if this was possible and if you could help.
    regards

    ReplyDelete
    Replies
    1. -Dorg.apache.myfaces.trinidad.CHECK_STATE_SERIALIZATION = all goes in setDomainEnv.cmd

      Delete
  2. Hi,
    Its really a great information on Cluster configuration .This information is very much needful to every person, because everyone is suffering from hacking now a days.Thanks for sharing the valuable information. Oracle Financials training
    Thank you.

    ReplyDelete