dev@javaserverfaces.java.net

Re: Review: Put back marker logic (First iteration)

From: Adam Winer <adam.winer_at_oracle.com>
Date: Fri, 20 May 2005 16:01:55 -0700

Jayashri,

Oops - I was thinking of the tokenized, server-side state
saving mode. In that case, we don't need to buffer at all,
but can instead have ViewHandler.writeState() call
directly through to the StateManager/ResponseStateManager,
as long as you use a PhaseListener to actually perform
the processSaveState() when the tree is finished.

With full client-side state saving, you're right that
we either need to buffer or put limitations on the mutability
of the tree during rendering.

-- Adam



Jayashri Visvanathan wrote:
> Hi Adam,
> I thought more about (2) but I dont see how it avoids buffering
> because once we write out a marker, we need to buffer, isn't it ? can
> you please elaborate on that ?
> Thanks in advance
> -Jayashri
>
> Adam Winer wrote:
>
>> Jayashri,
>>
>> A couple of options;
>>
>> (1) Simplify this code, and eliminate the
>> buffering, by stating that components added after the
>> first call to UIForm.encodeEnd() are not guaranteed to be
>> saved? I'm uncomfortable with requiring all ViewHandlers
>> to support dynamically adding components during Render
>> Response - in general, this is bad coding style.
>>
>> Or,
>>
>> (2) Write the state marker immediately - since it certainly
>> won't change - but delay actually saving the state and structure
>> of the UIViewRoot by using an RI-specific PhaseListener
>> that is coupled to the RI StateManager that runs in afterPhase()
>> of Render Response.
>>
>> I prefer #2.
>>
>> -- Adam
>>
>>
>> Jayashri Visvanathan wrote:
>>
>>> Hi Ed,
>>> If you have ideas on how to simplify this, please let me know. Based
>>> on that I can send another iteration of the change bundle.
>>> Thanks
>>> -Jayashri
>>>
>>> M com/sun/faces/application/ViewHandlerImpl.java
>>> Put back the state marker replace logic we used have before
>>> TCCI changes to enable components to be added programatically
>>> during encode.
>>>
>>>
>>> ------------------------------------------------------------------------
>>>
>>> Index: com/sun/faces/application/ViewHandlerImpl.java
>>> ===================================================================
>>> RCS file:
>>> /cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/application/ViewHandlerImpl.java,v
>>>
>>> retrieving revision 1.52
>>> diff -u -r1.52 ViewHandlerImpl.java
>>> --- com/sun/faces/application/ViewHandlerImpl.java 2 May 2005
>>> 14:58:44 -0000 1.52
>>> +++ com/sun/faces/application/ViewHandlerImpl.java 17 May 2005
>>> 00:06:59 -0000
>>> @@ -45,6 +45,7 @@
>>> import com.sun.faces.RIConstants;
>>> import com.sun.faces.util.Util;
>>>
>>> +import java.io.StringWriter;
>>>
>>> /**
>>> * <B>ViewHandlerImpl</B> is the default implementation class for
>>> ViewHandler.
>>> @@ -123,34 +124,65 @@
>>> ServletResponse response = (ServletResponse)
>>> extContext.getResponse();
>>> ResponseWriter oldWriter =
>>> context.getResponseWriter();
>>> + StringWriter strWriter = new StringWriter();
>>> ResponseWriter newWriter = null;
>>> if (null != oldWriter) {
>>> - newWriter = oldWriter.cloneWithWriter(response.getWriter());
>>> + newWriter = oldWriter.cloneWithWriter(strWriter);
>>> }
>>> else {
>>> - newWriter =
>>> renderKit.createResponseWriter(response.getWriter(),
>>> - null, -
>>> request.getCharacterEncoding());
>>> + newWriter = renderKit.createResponseWriter(strWriter, null,
>>> + request.getCharacterEncoding());
>>> }
>>> context.setResponseWriter(newWriter);
>>> -
>>> + newWriter.startDocument();
>>>
>>> doRenderView(context, viewToRender);
>>>
>>> newWriter.endDocument();
>>> -
>>> + + // replace markers in the body content and write it
>>> to response.
>>> + ResponseWriter responseWriter = null;
>>> + if (null != oldWriter) {
>>> + responseWriter =
>>> oldWriter.cloneWithWriter(response.getWriter());
>>> + } else {
>>> + responseWriter =
>>> renderKit.createResponseWriter(response.getWriter(), +
>>> null, request.getCharacterEncoding());
>>> + }
>>> + context.setResponseWriter(responseWriter);
>>> + + String bodyContent = strWriter.getBuffer().toString();
>>> + replaceMarkers(bodyContent, context);
>>> + if (null != oldWriter) {
>>> context.setResponseWriter(oldWriter);
>>> }
>>> - if
>>> (!context.getExternalContext().getRequestMap().containsKey(RIConstants.SAVED_STATE))
>>> {
>>> + // write any AFTER_VIEW_CONTENT to the response
>>> + Object content =
>>> extContext.getRequestMap().get(AFTER_VIEW_CONTENT);
>>> + assert(null != content);
>>> + if (content instanceof byte []) {
>>> + response.getWriter().write(new String((byte[]) content));
>>> + } else if (content instanceof char []) {
>>> + response.getWriter().write((char []) content);
>>> + } else {
>>> + assert(false);
>>> + } + + response.flushBuffer(); //
>>> PENDING(edburns): necessary?
>>> + + // remove the AFTER_VIEW_CONTENT from the view root
>>> + extContext.getRequestMap().remove(AFTER_VIEW_CONTENT);
>>> + + // PENDING (visvan) do we need this any more since
>>> we save the tree
>>> + // after encode ??
>>> + /* if
>>> (!context.getExternalContext().getRequestMap().containsKey(RIConstants.SAVED_STATE))
>>> {
>>> // if we didn't serialize the state, or we didn't save
>>> it in
>>> // the client, we need to manually remove the transient
>>> // children and facets.
>>> removeTransientChildrenAndFacets(context, viewToRender,
>>> new HashSet());
>>> - }
>>> + } */
>>> }
>>> /**
>>> @@ -175,19 +207,6 @@
>>> UIViewRoot viewToRender) throws IOException,
>>> FacesException {
>>> ExternalContext extContext = context.getExternalContext();
>>> - ServletResponse response = (ServletResponse)
>>> extContext.getResponse();
>>> -
>>> - // NOTE: With tree pre-creation, components can be
>>> dynamically added - // to the tree by registering a
>>> beforeRender phaseListener. So, any - // component added
>>> during encodeAll, will not be persisted as a result.
>>> - // With this change, we can avoid buffering and the marker
>>> replacement
>>> - // complexity since the actual state is written out during
>>> - // ViewHandler.writeState(). saveSerializedView() must be
>>> called before
>>> - // encodeAll because writeState() needs the actual state
>>> which gets
>>> - // created during saveSerializedView
>>> - Object view = -
>>> Util.getStateManager(context).saveSerializedView(context);
>>> - extContext.getRequestMap().put(RIConstants.SAVED_STATE, view);
>>>
>>> ApplicationAssociate associate =
>>> ApplicationAssociate.getInstance(extContext);
>>> @@ -200,25 +219,7 @@
>>> logger.log(Level.FINE, "About to render view " +
>>> viewToRender.getViewId());
>>> }
>>> - viewToRender.encodeAll(context);
>>> - - // write any AFTER_VIEW_CONTENT to the response
>>> - Object content =
>>> extContext.getRequestMap().get(AFTER_VIEW_CONTENT);
>>> - assert(null != content);
>>> - if (content instanceof byte []) {
>>> - response.getWriter().write(new String((byte[]) content));
>>> - } else if (content instanceof char []) {
>>> - response.getWriter().write((char []) content);
>>> - } else {
>>> - assert(false);
>>> - }
>>> - - response.flushBuffer(); // PENDING(edburns):
>>> necessary?
>>> - - // remove the AFTER_VIEW_CONTENT from the view root
>>> - extContext.getRequestMap().remove(AFTER_VIEW_CONTENT);
>>> - - +
>>> viewToRender.encodeAll(context); }
>>> private void removeTransientChildrenAndFacets(FacesContext
>>> context,
>>> @@ -505,6 +506,7 @@
>>> // replace the original response
>>> extContext.setResponse(originalResponse);
>>> + // new
>>> com.sun.faces.util.DebugUtil().printTree(viewToExecute,System.out);
>>> }
>>> @@ -625,22 +627,16 @@
>>> message = message +"context " + context;
>>> throw new NullPointerException(message);
>>> }
>>> - StateManager stateManager = Util.getStateManager(context);
>>> - - SerializedView viewState = (SerializedView)
>>> -
>>> context.getExternalContext().getRequestMap().get(RIConstants.SAVED_STATE);
>>>
>>> - assert(null != viewState);
>>> -
>>> + if (logger.isLoggable(Level.FINE)) {
>>> - logger.fine("Begin writing state to response for viewId " +
>>> + logger.fine("Begin writing market for viewId " +
>>> context.getViewRoot().getViewId());
>>> }
>>>
>>> - // write out the state
>>> - stateManager.writeState(context, viewState);
>>> -
>>> + context.getResponseWriter().writeText(
>>> + RIConstants.SAVESTATE_FIELD_MARKER, null);
>>> if (logger.isLoggable(Level.FINE)) {
>>> - logger.fine("End writing state to response for viewId " +
>>> + logger.fine("End writing marker for viewId " +
>>> context.getViewRoot().getViewId());
>>> }
>>> @@ -876,6 +872,47 @@
>>>
>>> }
>>> return convertedViewId;
>>> + }
>>> + + public void replaceMarkers(String content, FacesContext
>>> context) {
>>> + SerializedView view = null;
>>> + try {
>>> + view =
>>> Util.getStateManager(context).saveSerializedView(context);
>>> + } catch (IllegalStateException ise) {
>>> + throw new FacesException(ise);
>>> + } catch (Exception ie) {
>>> + // catch any exception thrown while saving the
>>> view + throw new
>>> FacesException(Util.getExceptionMessageString(
>>> + Util.SAVING_STATE_ERROR_MESSAGE_ID), ie); + }
>>> + int
>>> + beginIndex = 0,
>>> + markerIndex = 0,
>>> + markerLen = RIConstants.SAVESTATE_FIELD_MARKER.length(),
>>> + contentLen = 0;
>>> + + try {
>>> + contentLen = content.length();
>>> + do {
>>> + // if we have no more markers
>>> + if (-1 == (markerIndex =
>>> + content.indexOf(RIConstants.SAVESTATE_FIELD_MARKER,
>>> + beginIndex))) {
>>> + // write out the rest of the content
>>> +
>>> context.getResponseWriter().write(content.substring(beginIndex));
>>> + } else {
>>> + // we have more markers, write out the current chunk
>>> + +
>>> context.getResponseWriter().write(content.substring(
>>> + beginIndex,
>>> markerIndex)); +
>>> Util.getStateManager(context).writeState(context,
>>> view); + beginIndex = markerIndex +
>>> markerLen;
>>> + }
>>> + } while (-1 != markerIndex && beginIndex < contentLen);
>>> + } catch (Exception ex) {
>>> + // catch any thrown while write state.
>>> + throw new FacesException(ex);
>>> + }
>>> }
>>>
>>>
>>> ------------------------------------------------------------------------
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe_at_javaserverfaces.dev.java.net
>>> For additional commands, e-mail: dev-help_at_javaserverfaces.dev.java.net
>>
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe_at_javaserverfaces.dev.java.net
>> For additional commands, e-mail: dev-help_at_javaserverfaces.dev.java.net
>>