dev@javaserverfaces.java.net

[REVIEW] ViewHandler optimization

From: Ryan Lubke <Ryan.Lubke_at_Sun.COM>
Date: Wed, 30 Aug 2006 18:35:45 -0700

Optimziation.
If an application uses client side state saving and
a particular view contains multiple forms, the current
implementation will perform the serialization and
base64 encoding of the view for each form in the view.

This change will cache the result from the ResponeStateManager
implementation and will write the contents of said cache
as appropriate.

SECTION: Modified Files
----------------------------
M src/com/sun/faces/application/ViewHandlerImpl.java
 -see above


SECTION: Diffs
----------------------------
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.78
diff -u -r1.78 ViewHandlerImpl.java
--- src/com/sun/faces/application/ViewHandlerImpl.java 15 Aug 2006
16:50:36 -0000 1.78
+++ src/com/sun/faces/application/ViewHandlerImpl.java 31 Aug 2006
01:34:49 -0000
@@ -958,15 +958,28 @@
         }
 
         /**
- * <p> Write directly from our StringBuilder to the provided
+ * <p> Write directly from our FastStringWriter to the provided
          * writer.</p>
          * @param writer where to write
          * @throws IOException if an error occurs
          */
         public void flushToWriter(Writer writer) throws IOException {
- StateManager stateManager = Util.getStateManager(context);
- Object stateToWrite = stateManager.saveView(context);
+ // Save the state to a new instance of StringWriter to
+ // avoid multiple serialization steps if the view contains
+ // multiple forms.
+ StateManager stateManager =
Util.getStateManager(context);
+ ResponseWriter origWriter = context.getResponseWriter();
+ FastStringWriter state =
+ new FastStringWriter((stateManager.isSavingStateInClient(
+ context)) ? bufSize : 32);
+ context.setResponseWriter(origWriter.cloneWithWriter(state));
+ stateManager.writeState(context,
stateManager.saveView(context));
+ context.setResponseWriter(origWriter);
+
+ // begin writing...
             int totalLen = builder.length();
+ StringBuilder stateBuilder = state.getBuffer();
+ int stateLen = stateBuilder.length();
             int pos = 0;
             int tildeIdx = getNextDelimiterIndex(pos);
             while (pos < totalLen) {
@@ -988,7 +1001,29 @@
                         if (builder.indexOf(
                               RIConstants.SAVESTATE_FIELD_MARKER,
                               pos) == tildeIdx) {
- stateManager.writeState(context, stateToWrite);
+ // buf is effectively zero'd out at this point
+ int statePos = 0;
+ while (statePos < stateLen) {
+ if ((stateLen - statePos) > bufSize) {
+ // enough state to fill the buffer
+ stateBuilder.getChars(statePos,
+ (statePos +
bufSize),
+ buf,
+ 0);
+ writer.write(buf);
+ statePos += bufSize;
+ } else {
+ int slen = (stateLen - statePos);
+ stateBuilder.getChars(statePos,
+ stateLen,
+ buf,
+ 0);
+ writer.write(buf, 0, slen);
+ statePos += slen;
+ }
+
+ }
+ //stateManager.writeState(context,
stateToWrite);
                         }
                         
                         // push us past the last '~' at the end of the
marker