dev@javaserverfaces.java.net

Re: Review: support fail over with server side state saving.

From: Roger Kitain <Roger.Kitain_at_Sun.COM>
Date: Thu, 05 Aug 2004 15:49:00 -0400

Jayashri Visvanathan wrote:

> Fix the server side state saving to support failover. Since the
> UIComponent instances are not serializable, instead of saving
> the view in session, this change bundles saves the SerializedView
> (result of
> calling getTreeStructureToSave() and getTreeStateToSave()) in session.
> This can enabled using the ServletContextInitParameter
> "com.sun.faces.enableHighAvailability"
>
> M src/com/sun/faces/application/StateManagerImpl.java
> modify state saving in server mode logic in saveSerializedView() and
> restoreView() to support failover case.
>
> M src/com/sun/faces/application/ViewHandlerImpl.java
> Move debug statements inside the "if" block so that they are output only
> for state saving in client case.
>
> M src/com/sun/faces/taglib/jsf_core/ViewTag.java
> stateSaving in server mode if "HA" enabled returns SerializedView and
> not
> null. So check for that. Otherwise, client side state saving logic will
> be executed.
>
>
> A test/com/sun/faces/application/TestHAStateManagerImpl.java
> unit test to verify failover state saving mode.
>
>------------------------------------------------------------------------
>
>Index: src/com/sun/faces/application/StateManagerImpl.java
>===================================================================
>RCS file: /cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/application/StateManagerImpl.java,v
>retrieving revision 1.23
>diff -u -r1.23 StateManagerImpl.java
>--- src/com/sun/faces/application/StateManagerImpl.java 22 Jul 2004 17:40:44 -0000 1.23
>+++ src/com/sun/faces/application/StateManagerImpl.java 5 Aug 2004 19:09:21 -0000
>@@ -47,12 +47,27 @@
>
> private static final String FACES_VIEW_LIST =
> RIConstants.FACES_PREFIX + "VIEW_LIST";
>+
>+ private static final String ENABLE_HA_PARAM = "enableHighAvailability";
>+
>+ private static final String JSF_ENABLE_HA_PARAM =
>+ RIConstants.FACES_PREFIX + ENABLE_HA_PARAM;
>+
>+ private static final String APPSERVER_ENABLE_HA_PARAM =
>+ "com.sun.appserver." + ENABLE_HA_PARAM;
>+
>
> /**
> * Number of views to be saved in session.
> */
> int noOfViews = 0;
>-
>+
>+ /**
>+ * value of <code>com.sun.faces.enableHighAvailability</code>
>+ * <code>com.sun.appserver.enableHighAvailability</code>
>+ * parameter
>+ */
>+ private Boolean haStateSavingSet = null;
>
> public SerializedView saveSerializedView(FacesContext context)
> throws IllegalStateException{
>@@ -70,12 +85,13 @@
> removeTransientChildrenAndFacets(context, viewRoot, new HashSet());
>
> if (!isSavingStateInClient(context)) {
>+ // save state in server
> if (log.isDebugEnabled()) {
>- log.debug("Saving view in session for viewId " +
>+ log.debug("Begin saving view in session for viewId " +
> viewRoot.getViewId());
> }
>+ Map sessionMap = Util.getSessionMap(context);
> synchronized (this) {
>- Map sessionMap = Util.getSessionMap(context);
> // viewList maintains a list of viewIds corresponding to
> // all the views stored in session.
> ArrayList viewList = (ArrayList) sessionMap.get(
>@@ -99,10 +115,35 @@
> if (!foundMatch) {
> viewList.add(viewRoot.getViewId());
> }
>- sessionMap.put(viewRoot.getViewId(), viewRoot);
> sessionMap.put(FACES_VIEW_LIST, viewList);
>+
>+ // if highly available state saving option is chosen, save
>+ // the SerializedView in session instead of UIViewRoot since
>+ // the UIComponent instances are not serializable.
>+ if (isHAStateSavingSet(context)) {
>+ if (log.isDebugEnabled()) {
>+ log.debug("Highly Available state saving option enabled ");
>+ log.debug("Begin creating serialized view for " +
>+ viewRoot.getViewId());
>+ }
>+ result = new SerializedView(getTreeStructureToSave(context),
>+ getComponentStateToSave(context));
>+ if (log.isDebugEnabled()) {
>+ log.debug("End creating serialized view " +
>+ viewRoot.getViewId());
>+ }
>+ sessionMap.put(viewRoot.getViewId(), result);
>+
>+ } else {
>+ sessionMap.put(viewRoot.getViewId(), viewRoot);
>+ }
>+ }
>+ if (log.isDebugEnabled()) {
>+ log.debug("End saving view in session for viewId " +
>+ viewRoot.getViewId());
> }
> } else {
>+ // save state in client
> if (log.isDebugEnabled()) {
> log.debug("Begin creating serialized view for " +
> viewRoot.getViewId());
>@@ -190,6 +231,7 @@
>
> UIViewRoot viewRoot = null;
> if (isSavingStateInClient(context)) {
>+ // restore view from response.
> if (log.isDebugEnabled()) {
> log.debug("Begin restoring view from response " + viewId);
> }
>@@ -198,8 +240,8 @@
> restoreComponentState(context, viewRoot, renderKitId);
> } else {
> if (log.isDebugEnabled()) {
>- log.debug("Possibly a new request. Tree structure could not be restored for "
>- + viewId);
>+ log.debug("Possibly a new request. Tree structure could not "
>+ + " be restored for " + viewId);
> }
> }
> if (log.isDebugEnabled()) {
>@@ -207,15 +249,38 @@
> }
> } else {
> // restore tree from session.
>+ // if high available state saving option is chosen, restore
>+ // the SerializedView from session instead of UIViewRoot.
>+ if (log.isDebugEnabled()) {
>+ log.debug("Begin restoring view in session for viewId " + viewId);
>+ }
> Map sessionMap = Util.getSessionMap(context);
> synchronized (this) {
>- viewRoot = (UIViewRoot) sessionMap.get(viewId);
>- if (log.isDebugEnabled()) {
>- log.debug(
>- "Restoring view from session for viewId " + viewId);
>+ if (isHAStateSavingSet(context)) {
>+ if (log.isDebugEnabled()) {
>+ log.debug("High available state saving option enabled");
>+ log.debug("Begin restoring serialized view for "+viewId);
>+ }
>+ SerializedView serializedView = (SerializedView)
>+ sessionMap.get(viewId);
>+ viewRoot = restoreSerializedView(context, serializedView,
>+ viewId);
>+ if (log.isDebugEnabled()) {
>+ log.debug("End restoring serialized view " + viewId);
>+ }
>+
>+ } else {
>+ viewRoot = (UIViewRoot) sessionMap.get(viewId);
>+ if (log.isDebugEnabled()) {
>+ log.debug(
>+ "Restoring view from session for viewId " + viewId);
>+ }
> }
> removeViewFromSession(context, viewRoot);
> }
>+ if (log.isDebugEnabled()) {
>+ log.debug("End restoring view in session for viewId " + viewId);
>+ }
> }
> return viewRoot;
> }
>@@ -420,5 +485,55 @@
> restoreComponentTreeStructure(facetTreeStructure, facetComponent);
> }
> }
>-
>+
>+ /**
>+ * Returns true one of <code>com.sun.faces.enableHighAvailability</code>
>+ * or <code>com.sun.appserver.enableHighAvailability</code>
>+ * servlet context parameter is set.
>+ */
>+ protected boolean isHAStateSavingSet(FacesContext context) {
>+ if (null != haStateSavingSet) {
>+ return haStateSavingSet.booleanValue();
>+ }
>+ haStateSavingSet = Boolean.FALSE;
>+
>+ String haStateSavingParam = context.getExternalContext().
>+ getInitParameter(JSF_ENABLE_HA_PARAM);
>+ if (haStateSavingParam != null){
>+ haStateSavingSet = Boolean.valueOf(haStateSavingParam);
>+ } else {
>+ haStateSavingParam = context.getExternalContext().
>+ getInitParameter(APPSERVER_ENABLE_HA_PARAM);
>+ if (haStateSavingParam != null){
>+ haStateSavingSet = Boolean.valueOf(haStateSavingParam);
>+ }
>+ }
>+ return haStateSavingSet.booleanValue();
>+ }
>+
>+ /**
>+ * Returns the <code> UIViewRoot</code> corresponding the
>+ * <code> viewId </code> by restoring the view structure and state.
>+ */
>+ protected UIViewRoot restoreSerializedView(FacesContext context,
>+ SerializedView sv, String viewId) {
>+ if ( sv == null) {
>+ if (log.isDebugEnabled()) {
>+ log.debug("Possibly a new request. Tree structure could not "
>+ + " be restored for " + viewId);
>+ }
>+ return null;
>+ }
>+ TreeStructure structRoot = (TreeStructure) sv.getStructure();
>+ if (structRoot == null) {
>+ return null;
>+ }
>+ UIComponent viewRoot = structRoot.createComponent();
>+ if (viewRoot != null) {
>+ restoreComponentTreeStructure(structRoot, viewRoot);
>+ Object state = sv.getState();
>+ viewRoot.processRestoreState(context, state);
>+ }
>+ return ((UIViewRoot)viewRoot);
>+ }
> }
>Index: src/com/sun/faces/application/ViewHandlerImpl.java
>===================================================================
>RCS file: /cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/application/ViewHandlerImpl.java,v
>retrieving revision 1.44
>diff -u -r1.44 ViewHandlerImpl.java
>--- src/com/sun/faces/application/ViewHandlerImpl.java 20 Jul 2004 21:54:48 -0000 1.44
>+++ src/com/sun/faces/application/ViewHandlerImpl.java 5 Aug 2004 19:09:21 -0000
>@@ -408,18 +408,20 @@
> message = message +"context " + context;
> throw new NullPointerException(message);
> }
>- if (log.isTraceEnabled()) {
>- log.trace("Begin writing state to response for viewId" +
>- context.getViewRoot().getViewId());
>- }
>+
> if (Util.getStateManager(context).isSavingStateInClient(context)) {
>+ if (log.isTraceEnabled()) {
>+ log.trace("Begin writing state to response for viewId" +
>+ context.getViewRoot().getViewId());
>+ }
> context.getResponseWriter().writeText(
> RIConstants.SAVESTATE_FIELD_MARKER, null);
>- }
>- if (log.isTraceEnabled()) {
>- log.trace("End writing state to response for viewId" +
>+ if (log.isTraceEnabled()) {
>+ log.trace("End writing state to response for viewId" +
> context.getViewRoot().getViewId());
>+ }
> }
>+
> }
>
>
>Index: src/com/sun/faces/taglib/jsf_core/ViewTag.java
>===================================================================
>RCS file: /cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/taglib/jsf_core/ViewTag.java,v
>retrieving revision 1.25
>diff -u -r1.25 ViewTag.java
>--- src/com/sun/faces/taglib/jsf_core/ViewTag.java 10 May 2004 19:56:08 -0000 1.25
>+++ src/com/sun/faces/taglib/jsf_core/ViewTag.java 5 Aug 2004 19:09:22 -0000
>@@ -176,7 +176,11 @@
> Util.SAVING_STATE_ERROR_MESSAGE_ID, params), ie);
> }
> try {
>- if (view == null) {
>+ // if high availability is enabled, view will not null even in the
>+ // state saving in server mode. Thats why it is required to check
>+ // state saving method here.
>+ if (view == null ||
>+ (!(stateManager.isSavingStateInClient(context)))) {
> getPreviousOut().write(content);
> } else {
> contentLen = content.length();
>
>
>
>------------------------------------------------------------------------
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: dev-unsubscribe_at_javaserverfaces.dev.java.net
>For additional commands, e-mail: dev-help_at_javaserverfaces.dev.java.net
>
>
r=rogerk.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe_at_javaserverfaces.dev.java.net
For additional commands, e-mail: dev-help_at_javaserverfaces.dev.java.net