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

Monday, November 10, 2014

JBO - 29115 - App Module name mismatch and same path of the package


These exception comes on the below mentioned scenario and solution given below

JBO-29115 Unable to construct the error message due to error java.lang.ClassCastException: oracle.jbo.server.StringManagerImpl

JBO-33005: Configuration TestAppModuleLocal is not found.}
 at oracle.jbo.common.ampool.PoolMgr.findPool(PoolMgr.java:529)


 Scenario: This issue comes randomly in the deployed application in server.  It will be fine after server restart/bouncing.

JBO – 33005 – this will usually comes when there is mismatch in the AppModule Name in Databindings.cpx and bc4j.xcfg

JBO – 29115 – We don’t know when this issue is coming?

Solution:
 (Change the path of AM in two different Model project. Make sure package its not unique)
Two ADF view controller or ADF BC model projects with same package structure for one single application is not a supported source structuring. In your case, bc4j.xcfg is stored in <package>/common folder for both projects which will cause one to override the other. 

Change package for either of the model solved the problem.

Below is the stack trace for reference for the above exceptions,

Error 500--Internal Server Error

oracle.jbo.JboException: JBO-29115 Unable to construct the error message due to error java.lang.ClassCastException: oracle.jbo.server.StringManagerImpl. Use the exception stack trace and error code to investigate the root cause of this exception. Root cause error code is JBO-29000. Error message parameters are {0=oracle.jbo.ConfigException, 1=JBO-33005: Configuration TestAppModuleLocal is not found.}
 at oracle.jbo.common.ampool.PoolMgr.findPool(PoolMgr.java:529)
 at oracle.adf.model.bc4j.DCJboDataControl.findApplicationPool(DCJboDataControl.java:572)
 at oracle.adf.model.bc4j.DCJboDataControl.initializeSessionCookie(DCJboDataControl.java:396)
 at oracle.adf.model.bc4j.DCJboDataControl.initializeJboSession(DCJboDataControl.java:310)
 at oracle.adf.model.bc4j.DataControlFactoryImpl.createSessionInternal(DataControlFactoryImpl.java:220)
 at oracle.adf.model.bc4j.DataControlFactoryImpl.createSession(DataControlFactoryImpl.java:130)
 at oracle.adf.model.binding.DCDataControlReference.getDataControl(DCDataControlReference.java:167)
 at oracle.adf.model.BindingContext.instantiateDataControl(BindingContext.java:1056)
 at oracle.adf.model.dcframe.DataControlFrameImpl.doFindDataControl(DataControlFrameImpl.java:1566)
 at oracle.adf.model.dcframe.DataControlFrameImpl.internalFindDataControl(DataControlFrameImpl.java:143
8)
 at oracle.adf.model.dcframe.DataControlFrameImpl.findDataControl(DataControlFrameImpl.java:139
8)
 at oracle.adf.model.BindingContext.internalFindDataControl(BindingContext.java:1189)
 at oracle.adf.model.BindingContext.get(BindingContext.java:1139)
 at oracle.adf.model.binding.DCParameter.evaluateValue(DCParameter.java:82)
 at oracle.adf.model.binding.DCParameter.getValue(DCParameter.java:111)
 at oracle.adf.model.binding.DCBindingContainer.getChildByName(DCBindingContainer.java:2713)
 at oracle.adf.model.binding.DCBindingContainer.internalGet(DCBindingContainer.java:2761)
 at oracle.adf.model.binding.DCExecutableBinding.get(DCExecutableBinding.java:115)
 at oracle.adf.model.binding.DCUtil.findSpelObject(DCUtil.java:304)
 at oracle.adf.model.binding.DCBindingContainer.evaluateParameterWithElCheck(DCBindingContainer.java:145
8)
 at oracle.adf.model.binding.DCBindingContainer.findDataControl(DCBindingContainer.java:158
8)
 at oracle.adf.model.binding.DCIteratorBinding.initDataControl(DCIteratorBinding.java:2472)
 at oracle.adf.model.binding.DCIteratorBinding.getDataControl(DCIteratorBinding.java:2416)
 at oracle.adf.model.binding.DCBindingContainer.internalRefreshControl(DCBindingContainer.java:3069)
 at oracle.adf.model.binding.DCBindingContainer.refreshControl(DCBindingContainer.java:290
8)
 at oracle.adf.model.binding.DCBindingContainer.refresh(DCBindingContainer.java:2895)
 at oracle.adfinternal.controller.util.model.DataBindingActivityImpl.beforeExecute(DataBindingActivityImpl.java:109)
 at oracle.adfinternal.controller.engine.ControlFlowEngine.executeActivity(ControlFlowEngine.java:1016)
 at oracle.adfinternal.controller.engine.ControlFlowEngine.doRouting(ControlFlowEngine.java:921)
 at oracle.adfinternal.controller.engine.ControlFlowEngine.doRouting(ControlFlowEngine.java:820)
 at oracle.adfinternal.controller.engine.ControlFlowEngine.invokeTaskFlow(ControlFlowEngine.java:243)
 at oracle.adfinternal.controller.application.RemoteTaskFlowCallRequestHandler.invokeTaskFlowByUrl(RemoteTaskFlowCallRequestHandler.java:99)
 at oracle.adfinternal.controller.application.RemoteTaskFlowCallRequestHandler.doCreateView(RemoteTaskFlowCallRequestHandler.java:64)
 at oracle.adfinternal.controller.application.BaseRequestHandlerImpl.createView(BaseRequestHandlerImpl.java:57)
 at org.apache.myfaces.trinidadinternal.application.ViewHandlerImpl.createView(ViewHandlerImpl.java:95)
 at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._restoreView(LifecycleImpl.java:763)
 at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._executePhase(LifecycleImpl.java:375)
 at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:194)
 at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)