dev@javaserverfaces.java.net

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

From: Jayashri Visvanathan <Jayashri.Visvanathan_at_Sun.COM>
Date: Tue, 17 May 2005 10:52:10 -0700

Hi Jacob, Adam,
   The purpose this change is mainly to allow the pre JSF 1.2
applications that added components programatically to continue to run. I
thought this might be a common case in JSF 1.1 applications. But if we
all feel that disallowing adding components at render time shouldn't
pose a major problem to existing applications, I am fine with not
checking this in.

  Adam, thanks a lot for the feedback. Regarding your suggestion (2),
Iam not clear as to why it should be coupled to StateManager. Can't we
just register a phase listener in jsf-ri-config.xml ? That way it will
be guaranteed to be there.

Thanks
-Jayashri


jacob_at_hookom.net wrote:

>I consider myself a little more draconian than most, but I would simply
>disallow adding components at render time. I thought TCCI was supposed
>to correct issues correlated to render time state saving?
>
>Do we have a specific use case or request to tie this change to? Does
>this re-enforce some of the discussion pertaining to a phase event
>before rendering in the client side scripting issues Ed/Roger brought
>up?
>
>-- Jacob
>
>Adam Winer <adam.winer_at_oracle.com> wrote on 05/17/2005, 06:22:45 PM:
>
>
>>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;
>>>
>>> /**
>>> * ViewHandlerImpl 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
>>
>>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: dev-unsubscribe_at_javaserverfaces.dev.java.net
>For additional commands, e-mail: dev-help_at_javaserverfaces.dev.java.net
>
>
>