You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ja...@apache.org on 2010/04/07 16:40:22 UTC

svn commit: r931567 - in /myfaces/core/trunk: api/src/main/java/javax/faces/component/UIViewParameter.java api/src/main/java/javax/faces/component/UIViewRoot.java impl/src/main/java/org/apache/myfaces/context/servlet/PartialViewContextImpl.java

Author: jakobk
Date: Wed Apr  7 14:40:22 2010
New Revision: 931567

URL: http://svn.apache.org/viewvc?rev=931567&view=rev
Log:
MYFACES-2645 The view state is saved before encodeAll() is called on every UIViewParameter in an AJAX request (including some code cleanup)

Modified:
    myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewParameter.java   (contents, props changed)
    myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewRoot.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/context/servlet/PartialViewContextImpl.java

Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewParameter.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewParameter.java?rev=931567&r1=931566&r2=931567&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewParameter.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewParameter.java Wed Apr  7 14:40:22 2010
@@ -1,307 +1,307 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package javax.faces.component;
-
-import java.io.IOException;
-
-import javax.el.ValueExpression;
-import javax.faces.FactoryFinder;
-import javax.faces.application.FacesMessage;
-import javax.faces.context.FacesContext;
-import javax.faces.convert.Converter;
-import javax.faces.convert.ConverterException;
-import javax.faces.render.RenderKit;
-import javax.faces.render.RenderKitFactory;
-import javax.faces.render.Renderer;
-
-import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
-import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty;
-import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
-
-/**
- * 
- * TODO: documentation on jsp and pld are not the same. It appear two
- * params: maxlength and for, but no property getter and setter founded here. 
- * If maxlength is used, we can put something like this: 
- * JSFJspProperty(name = "maxlength", returnType = "java.lang.String")
- * 
- * @author Simon Lessard (latest modification by $Author: slessard $)
- * @version $Revision: 696523 $ $Date: 2009-03-14 14:43:57 -0400 (mer., 17 sept. 2008) $
- * 
- * @since 2.0
- */
-@JSFComponent(name = "f:viewParam", bodyContent = "JSP", 
-        tagClass = "org.apache.myfaces.taglib.core.ParamTag")
-@JSFJspProperty(name = "maxlength", returnType = "int", longDesc = "The max number or characters allowed for this param")
-public class UIViewParameter extends UIInput
-{
-    public static final String COMPONENT_FAMILY = "javax.faces.ViewParameter";
-    public static final String COMPONENT_TYPE = "javax.faces.ViewParameter";
-
-    private static final String DELEGATE_FAMILY = UIInput.COMPONENT_FAMILY;
-    private static final String DELEGATE_RENDERER_TYPE = "javax.faces.Text";
-    
-    private static Renderer _delegateRenderer;
-
-    public UIViewParameter()
-    {
-        setRendererType(null);
-    }
-
-    @Override
-    public String getFamily()
-    {
-        return COMPONENT_FAMILY;
-    }
-
-    @Override
-    public void decode(FacesContext context)
-    {
-        // Override behavior from superclass to pull a value from the incoming request parameter map under the 
-        // name given by getName() and store it with a call to UIInput.setSubmittedValue(java.lang.Object).
-        String value = context.getExternalContext().getRequestParameterMap().get(getName());
-        
-        // only apply the value if it is non-null (otherwise postbacks 
-        // to a view with view parameters would not work correctly)
-        if (value != null)
-        {
-            setSubmittedValue(value);
-        }
-    }
-
-    @Override
-    public void encodeAll(FacesContext context) throws IOException
-    {
-        if (context == null) 
-        {
-            throw new NullPointerException();
-        }
-        setSubmittedValue(getStringValue(context));
-    }
-
-    public String getName()
-    {
-        return (String) getStateHelper().get(PropertyKeys.name);
-    }
-
-    public String getStringValue(FacesContext context)
-    {
-        if (getValueExpression ("value") != null) 
-        {
-            // Value specified as an expression, so do the conversion.
-            
-            return getStringValueFromModel (context);
-        }
-        
-        // Otherwise, just return the local value.
-        
-        return ((String) this.getLocalValue());
-    }
-
-    public String getStringValueFromModel(FacesContext context) throws ConverterException
-    {
-        ValueExpression ve = getValueExpression ("value");
-        Converter converter;
-        Object value;
-        
-        if (ve == null) 
-        {
-            // No value expression, return null.
-            return null;
-        }
-        
-        value = ve.getValue (context.getELContext());
-        
-        if (value instanceof String) 
-        {
-            // No need to convert.
-            return ((String) value);
-        }
-        
-        converter = getConverter();
-        
-        if (converter == null) 
-        {
-            if (value == null) 
-            {
-                // No converter, no value, return null.
-                return null;
-            }
-            
-            // See if we can create the converter from the value type.
-            
-            converter = context.getApplication().createConverter (value.getClass());
-            
-            if (converter == null) 
-            {
-                // Only option is to call toString().
-                
-                return value.toString();
-            }
-        }
-        
-        return converter.getAsString (context, this, value);
-    }
-
-    @Override
-    public String getSubmittedValue()
-    {
-        return (String)super.getSubmittedValue();
-    }
-
-    @JSFProperty(tagExcluded=true)
-    @Override
-    public boolean isImmediate()
-    {
-        return false;
-    }
-    
-    @JSFProperty(tagExcluded=true)
-    @Override
-    public boolean isRendered()
-    {
-        return super.isRendered();
-    }
-    
-    @Override
-    public void processValidators(FacesContext context)
-    {
-        if (context == null) 
-        {
-            throw new NullPointerException ("context");
-        }
-        
-        // If value is null and required is set, validation fails.
-        
-        if ((getSubmittedValue() == null) && isRequired()) 
-        {
-            FacesMessage message;
-            String required = getRequiredMessage();
-            
-            if (required != null) 
-            {
-                message = new FacesMessage (FacesMessage.SEVERITY_ERROR, required, required);
-            }
-            else 
-            {
-                String label = _MessageUtils.getLabel (context, this);
-                
-                message = _MessageUtils.getMessage (context, context.getViewRoot().getLocale(),
-                     FacesMessage.SEVERITY_ERROR, REQUIRED_MESSAGE_ID, new Object[] { label });
-            }
-            
-            setValid (false);
-            
-            context.addMessage (getClientId (context), message);
-            context.validationFailed();
-            context.renderResponse();
-            
-            return;
-        }
-        
-        super.processValidators (context);
-    }
-    
-    enum PropertyKeys
-    {
-        name
-    }
-    
-    public void setName(String name)
-    {
-        getStateHelper().put(PropertyKeys.name, name );
-    }
-
-    @Override
-    public void updateModel(FacesContext context)
-    {
-        super.updateModel(context);
-        
-        // Put name in request map if value is not a value expression, is valid, and local
-        // value was set.
-        
-        if ((getValueExpression ("value") == null) && isValid() && isLocalValueSet()) 
-        {
-            context.getExternalContext().getRequestMap().put (getName(), getLocalValue());
-        }
-    }
-
-    @Override
-    protected Object getConvertedValue(FacesContext context, Object submittedValue)
-    {
-        return getDelegateRenderer(context).getConvertedValue(context, this, submittedValue);
-    }
-
-    private static Renderer getDelegateRenderer(FacesContext context)
-    {
-        if (_delegateRenderer == null)
-        {
-            RenderKitFactory factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
-            RenderKit kit = factory.getRenderKit(context, RenderKitFactory.HTML_BASIC_RENDER_KIT);
-
-            _delegateRenderer = kit.getRenderer(DELEGATE_FAMILY, DELEGATE_RENDERER_TYPE);
-        }
-
-        return _delegateRenderer;
-    }
-
-    /**
-     * @author Simon Lessard (latest modification by $Author: slessard $)
-     * @version $Revision: 696523 $ $Date: 2009-03-14 14:43:57 -0400 (mer., 17 sept. 2008) $
-     * 
-     * @since 2.0
-     */
-    public static class Reference
-    {
-        private int _index;
-        private UIViewParameter _param;
-        private Object _state;
-        private String _viewId;
-
-        public Reference(FacesContext context, UIViewParameter param, int indexInParent,
-                         String viewIdAtTimeOfConstruction)
-        {
-            // This constructor cause the StateHolder.saveState(javax.faces.context.FacesContext) method
-            // to be called on argument UIViewParameter.
-            _param = param;
-            _viewId = viewIdAtTimeOfConstruction;
-            _index = indexInParent;
-            _state = param.saveState(context);
-        }
-
-        public UIViewParameter getUIViewParameter(FacesContext context)
-        {
-            // If the current viewId is the same as the viewId passed to our constructor
-            if (context.getViewRoot().getViewId().equals(_viewId))
-            {
-                // use the index passed to the constructor to find the actual UIViewParameter instance and return it.
-                // FIXME: How safe is that when dealing with component trees altered by applications?
-                return (UIViewParameter) _param.getParent().getChildren().get(_index);
-            }
-            else
-            {
-                // Otherwise, call StateHolder.restoreState(javax.faces.context.FacesContext, java.lang.Object) on
-                // the saved state and return the result.
-                _param.restoreState(context, _state);
-
-                return _param;
-            }
-        }
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package javax.faces.component;
+
+import java.io.IOException;
+
+import javax.el.ValueExpression;
+import javax.faces.FactoryFinder;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import javax.faces.render.RenderKit;
+import javax.faces.render.RenderKitFactory;
+import javax.faces.render.Renderer;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
+
+/**
+ * 
+ * TODO: documentation on jsp and pld are not the same. It appear two
+ * params: maxlength and for, but no property getter and setter founded here. 
+ * If maxlength is used, we can put something like this: 
+ * JSFJspProperty(name = "maxlength", returnType = "java.lang.String")
+ * 
+ * @author Simon Lessard (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ * 
+ * @since 2.0
+ */
+@JSFComponent(name = "f:viewParam", bodyContent = "JSP", 
+        tagClass = "org.apache.myfaces.taglib.core.ParamTag")
+@JSFJspProperty(name = "maxlength", returnType = "int", longDesc = "The max number or characters allowed for this param")
+public class UIViewParameter extends UIInput
+{
+    public static final String COMPONENT_FAMILY = "javax.faces.ViewParameter";
+    public static final String COMPONENT_TYPE = "javax.faces.ViewParameter";
+
+    private static final String DELEGATE_FAMILY = UIInput.COMPONENT_FAMILY;
+    private static final String DELEGATE_RENDERER_TYPE = "javax.faces.Text";
+    
+    private static Renderer _delegateRenderer;
+
+    public UIViewParameter()
+    {
+        setRendererType(null);
+    }
+
+    @Override
+    public String getFamily()
+    {
+        return COMPONENT_FAMILY;
+    }
+
+    @Override
+    public void decode(FacesContext context)
+    {
+        // Override behavior from superclass to pull a value from the incoming request parameter map under the 
+        // name given by getName() and store it with a call to UIInput.setSubmittedValue(java.lang.Object).
+        String value = context.getExternalContext().getRequestParameterMap().get(getName());
+        
+        // only apply the value if it is non-null (otherwise postbacks 
+        // to a view with view parameters would not work correctly)
+        if (value != null)
+        {
+            setSubmittedValue(value);
+        }
+    }
+
+    @Override
+    public void encodeAll(FacesContext context) throws IOException
+    {
+        if (context == null) 
+        {
+            throw new NullPointerException();
+        }
+        setSubmittedValue(getStringValue(context));
+    }
+
+    public String getName()
+    {
+        return (String) getStateHelper().get(PropertyKeys.name);
+    }
+
+    public String getStringValue(FacesContext context)
+    {
+        if (getValueExpression ("value") != null) 
+        {
+            // Value specified as an expression, so do the conversion.
+            
+            return getStringValueFromModel (context);
+        }
+        
+        // Otherwise, just return the local value.
+        
+        return ((String) this.getLocalValue());
+    }
+
+    public String getStringValueFromModel(FacesContext context) throws ConverterException
+    {
+        ValueExpression ve = getValueExpression ("value");
+        Converter converter;
+        Object value;
+        
+        if (ve == null) 
+        {
+            // No value expression, return null.
+            return null;
+        }
+        
+        value = ve.getValue (context.getELContext());
+        
+        if (value instanceof String) 
+        {
+            // No need to convert.
+            return ((String) value);
+        }
+        
+        converter = getConverter();
+        
+        if (converter == null) 
+        {
+            if (value == null) 
+            {
+                // No converter, no value, return null.
+                return null;
+            }
+            
+            // See if we can create the converter from the value type.
+            
+            converter = context.getApplication().createConverter (value.getClass());
+            
+            if (converter == null) 
+            {
+                // Only option is to call toString().
+                
+                return value.toString();
+            }
+        }
+        
+        return converter.getAsString (context, this, value);
+    }
+
+    @Override
+    public String getSubmittedValue()
+    {
+        return (String)super.getSubmittedValue();
+    }
+
+    @JSFProperty(tagExcluded=true)
+    @Override
+    public boolean isImmediate()
+    {
+        return false;
+    }
+    
+    @JSFProperty(tagExcluded=true)
+    @Override
+    public boolean isRendered()
+    {
+        return super.isRendered();
+    }
+    
+    @Override
+    public void processValidators(FacesContext context)
+    {
+        if (context == null) 
+        {
+            throw new NullPointerException ("context");
+        }
+        
+        // If value is null and required is set, validation fails.
+        
+        if ((getSubmittedValue() == null) && isRequired()) 
+        {
+            FacesMessage message;
+            String required = getRequiredMessage();
+            
+            if (required != null) 
+            {
+                message = new FacesMessage (FacesMessage.SEVERITY_ERROR, required, required);
+            }
+            else 
+            {
+                String label = _MessageUtils.getLabel (context, this);
+                
+                message = _MessageUtils.getMessage (context, context.getViewRoot().getLocale(),
+                     FacesMessage.SEVERITY_ERROR, REQUIRED_MESSAGE_ID, new Object[] { label });
+            }
+            
+            setValid (false);
+            
+            context.addMessage (getClientId (context), message);
+            context.validationFailed();
+            context.renderResponse();
+            
+            return;
+        }
+        
+        super.processValidators (context);
+    }
+    
+    enum PropertyKeys
+    {
+        name
+    }
+    
+    public void setName(String name)
+    {
+        getStateHelper().put(PropertyKeys.name, name );
+    }
+
+    @Override
+    public void updateModel(FacesContext context)
+    {
+        super.updateModel(context);
+        
+        // Put name in request map if value is not a value expression, is valid, and local
+        // value was set.
+        
+        if ((getValueExpression ("value") == null) && isValid() && isLocalValueSet()) 
+        {
+            context.getExternalContext().getRequestMap().put (getName(), getLocalValue());
+        }
+    }
+
+    @Override
+    protected Object getConvertedValue(FacesContext context, Object submittedValue)
+    {
+        return getDelegateRenderer(context).getConvertedValue(context, this, submittedValue);
+    }
+
+    private static Renderer getDelegateRenderer(FacesContext context)
+    {
+        if (_delegateRenderer == null)
+        {
+            RenderKitFactory factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
+            RenderKit kit = factory.getRenderKit(context, RenderKitFactory.HTML_BASIC_RENDER_KIT);
+
+            _delegateRenderer = kit.getRenderer(DELEGATE_FAMILY, DELEGATE_RENDERER_TYPE);
+        }
+
+        return _delegateRenderer;
+    }
+
+    /**
+     * @author Simon Lessard (latest modification by $Author$)
+     * @version $Revision$ $Date$
+     * 
+     * @since 2.0
+     */
+    public static class Reference
+    {
+        private int _index;
+        private UIViewParameter _param;
+        private Object _state;
+        private String _viewId;
+
+        public Reference(FacesContext context, UIViewParameter param, int indexInParent,
+                         String viewIdAtTimeOfConstruction)
+        {
+            // This constructor cause the StateHolder.saveState(javax.faces.context.FacesContext) method
+            // to be called on argument UIViewParameter.
+            _param = param;
+            _viewId = viewIdAtTimeOfConstruction;
+            _index = indexInParent;
+            _state = param.saveState(context);
+        }
+
+        public UIViewParameter getUIViewParameter(FacesContext context)
+        {
+            // If the current viewId is the same as the viewId passed to our constructor
+            if (context.getViewRoot().getViewId().equals(_viewId))
+            {
+                // use the index passed to the constructor to find the actual UIViewParameter instance and return it.
+                // FIXME: How safe is that when dealing with component trees altered by applications?
+                return (UIViewParameter) _param.getParent().getChildren().get(_index);
+            }
+            else
+            {
+                // Otherwise, call StateHolder.restoreState(javax.faces.context.FacesContext, java.lang.Object) on
+                // the saved state and return the result.
+                _param.restoreState(context, _state);
+
+                return _param;
+            }
+        }
+    }
+}

Propchange: myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewParameter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewParameter.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewRoot.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewRoot.java?rev=931567&r1=931566&r2=931567&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewRoot.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewRoot.java Wed Apr  7 14:40:22 2010
@@ -337,41 +337,48 @@ public class UIViewRoot extends UICompon
         {
             super.encodeEnd(context);
             
-            ViewDeclarationLanguage vdl = context.getApplication().getViewHandler().getViewDeclarationLanguage(context, getViewId());
-            if (vdl != null)
+            // the call to encodeAll() on every UIViewParameter here is only necessary
+            // if the current request is _not_ an AJAX request, because if it was an
+            // AJAX request, the call would already have happened in PartialViewContextImpl and
+            // would anyway be too late here, because the state would already have been generated
+            PartialViewContext partialContext = context.getPartialViewContext();
+            if (!partialContext.isAjaxRequest())
             {
-                // If the current view has view parameters, as indicated by a non-empty and non-UnsupportedOperationException throwing 
-                // return from ViewDeclarationLanguage.getViewMetadata(javax.faces.context.FacesContext, String)
-                ViewMetadata metadata = null;
-                try
-                {
-                    metadata = vdl.getViewMetadata(context, getViewId());    
-                }
-                catch(UnsupportedOperationException e)
-                {
-                    logger.log(Level.SEVERE, "Exception while obtaining the view metadata: " + e.getMessage(), e);
-                }
-                
-                if (metadata != null)
+                ViewDeclarationLanguage vdl = context.getApplication().getViewHandler().getViewDeclarationLanguage(context, getViewId());
+                if (vdl != null)
                 {
+                    // If the current view has view parameters, as indicated by a non-empty and non-UnsupportedOperationException throwing 
+                    // return from ViewDeclarationLanguage.getViewMetadata(javax.faces.context.FacesContext, String)
+                    ViewMetadata metadata = null;
                     try
                     {
-                        Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(this);    
-                        if(!viewParams.isEmpty())
+                        metadata = vdl.getViewMetadata(context, getViewId());    
+                    }
+                    catch(UnsupportedOperationException e)
+                    {
+                        logger.log(Level.SEVERE, "Exception while obtaining the view metadata: " + e.getMessage(), e);
+                    }
+                    
+                    if (metadata != null)
+                    {
+                        try
                         {
-                            // call UIViewParameter.encodeAll(javax.faces.context.FacesContext) on each parameter.
-                            for(UIViewParameter param : viewParams)
+                            Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(this);    
+                            if(!viewParams.isEmpty())
                             {
-                                param.encodeAll(context);
+                                // call UIViewParameter.encodeAll(javax.faces.context.FacesContext) on each parameter.
+                                for(UIViewParameter param : viewParams)
+                                {
+                                    param.encodeAll(context);
+                                }
                             }
                         }
-                    }
-                    catch(UnsupportedOperationException e)
-                    {
-                        // If calling getViewParameters() causes UnsupportedOperationException to be thrown, the exception must be silently swallowed.
+                        catch(UnsupportedOperationException e)
+                        {
+                            // If calling getViewParameters() causes UnsupportedOperationException to be thrown, the exception must be silently swallowed.
+                        }
                     }
                 }
-    
             }
         }
         

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/context/servlet/PartialViewContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/context/servlet/PartialViewContextImpl.java?rev=931567&r1=931566&r2=931567&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/context/servlet/PartialViewContextImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/context/servlet/PartialViewContextImpl.java Wed Apr  7 14:40:22 2010
@@ -28,6 +28,8 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewParameter;
+import javax.faces.component.UIViewRoot;
 import javax.faces.component.visit.VisitCallback;
 import javax.faces.component.visit.VisitContext;
 import javax.faces.component.visit.VisitHint;
@@ -38,6 +40,7 @@ import javax.faces.context.PartialRespon
 import javax.faces.context.PartialViewContext;
 import javax.faces.context.ResponseWriter;
 import javax.faces.event.PhaseId;
+import javax.faces.view.ViewMetadata;
 
 import org.apache.myfaces.context.PartialResponseWriterImpl;
 import org.apache.myfaces.shared_impl.util.StringUtils;
@@ -291,23 +294,25 @@ public class PartialViewContextImpl exte
     public void processPartial(PhaseId phaseId) {
         assertNotReleased();
 
-        UIComponent viewRoot = _facesContext.getViewRoot();
+        UIViewRoot viewRoot = _facesContext.getViewRoot();
 
-
-
-        if (phaseId == PhaseId.APPLY_REQUEST_VALUES || phaseId == PhaseId.PROCESS_VALIDATIONS || phaseId == PhaseId.UPDATE_MODEL_VALUES) {
+        if (phaseId == PhaseId.APPLY_REQUEST_VALUES 
+                || phaseId == PhaseId.PROCESS_VALIDATIONS 
+                || phaseId == PhaseId.UPDATE_MODEL_VALUES) 
+        {
             processPartialExecute(viewRoot, phaseId);
-        } else if (phaseId == PhaseId.RENDER_RESPONSE) {
-
+        } 
+        else if (phaseId == PhaseId.RENDER_RESPONSE) 
+        {
             processPartialRendering(viewRoot, phaseId);
         }
-
-
     }
 
-    private void processPartialExecute(UIComponent viewRoot, PhaseId phaseId) {
+    private void processPartialExecute(UIViewRoot viewRoot, PhaseId phaseId) 
+    {
         Collection<String> executeIds = getExecuteIds();
-        if (executeIds == null || executeIds.isEmpty()) {
+        if (executeIds == null || executeIds.isEmpty()) 
+        {
             return;
         }
         Set<VisitHint> hints = new HashSet<VisitHint>();
@@ -317,7 +322,8 @@ public class PartialViewContextImpl exte
         viewRoot.visitTree(visitCtx, new PhaseAwareVisitCallback(_facesContext, phaseId));
     }
 
-    private void processPartialRendering(UIComponent viewRoot, PhaseId phaseId) {
+    private void processPartialRendering(UIViewRoot viewRoot, PhaseId phaseId) 
+    {
         // try to enable the ResponseSwitch again (disabled in RenderResponseExecutor)
         Object response = _facesContext.getExternalContext().getResponse();
         ResponseSwitch responseSwitch = ExternalContextUtils.getResponseSwitch(response);
@@ -338,8 +344,6 @@ public class PartialViewContextImpl exte
         //    return;
         //}
 
-
-
         PartialResponseWriter writer = getPartialResponseWriter();
         ResponseWriter oldWriter = _facesContext.getResponseWriter();
         boolean inDocument = false;
@@ -355,8 +359,8 @@ public class PartialViewContextImpl exte
         //http://support.microsoft.com/kb/234067
         externalContext.addResponseHeader("Expires", "-1");
 
-        try {
-
+        try 
+        {
             writer.startDocument();
             inDocument = true;
             _facesContext.setResponseWriter(writer);
@@ -365,18 +369,16 @@ public class PartialViewContextImpl exte
             if (renderIds != null && !renderIds.isEmpty())
             {
                 Set<VisitHint> hints = new HashSet<VisitHint>();
-                /*unrendered have to be skipped, transient definitely must be added to our list!*/
+                // unrendered have to be skipped, transient definitely must be added to our list!
                 hints.add(VisitHint.SKIP_UNRENDERED);
                 
                 // render=@all, so output the body.
-                
                 if (renderIds.contains ("javax.faces.ViewRoot"))
                 {
                     java.util.Iterator<UIComponent> iter = viewRoot.getFacetsAndChildren();
-                    
                     writer.startUpdate ("javax.faces.ViewRoot");
-                    
-                    while (iter.hasNext()) { 
+                    while (iter.hasNext()) 
+                    { 
                         UIComponent comp = iter.next();
                         
                         if (comp instanceof javax.faces.component.html.HtmlBody)
@@ -384,10 +386,8 @@ public class PartialViewContextImpl exte
                             comp.encodeAll (_facesContext);
                         }
                     }
-                    
                     writer.endUpdate();
                 }
-                
                 else
                 {
                     VisitContext visitCtx = VisitContext.createVisitContext(_facesContext, renderIds, hints);
@@ -395,6 +395,19 @@ public class PartialViewContextImpl exte
                 }
             }
             
+            // invoke encodeAll() on every UIViewParameter in the view to 
+            // enable every UIViewParameter to save its value in the state
+            // just like UIViewRoot.encodeEnd() does on a normal request
+            // (see MYFACES-2645 for details)
+            Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(viewRoot);    
+            if (!viewParams.isEmpty())
+            {
+                for (UIViewParameter param : viewParams)
+                {
+                    param.encodeAll(_facesContext);
+                }
+            }
+            
             //Retrieve the state and apply it if it is not null.
             String viewState = _facesContext.getApplication().getStateManager().getViewState(_facesContext);
             if (viewState != null)