You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2013/07/23 02:19:32 UTC
svn commit: r1505865 - in /myfaces/core/branches/2.0.x/impl/src:
main/java/org/apache/myfaces/application/
main/java/org/apache/myfaces/context/
main/java/org/apache/myfaces/view/facelets/
test/java/org/apache/myfaces/view/facelets/pss/acid/ test/java/...
Author: lu4242
Date: Tue Jul 23 00:19:31 2013
New Revision: 1505865
URL: http://svn.apache.org/r1505865
Log:
MYFACES-3739 @ResourceDependency annotation + JSF 1.2 state saving + c:if (dynamic section) creates components on each click (UIViewRoot grows)
Added:
myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/pss/acid/resourceDependency2.xhtml (with props)
Modified:
myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java
myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/RequestViewContext.java
myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java
myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/pss/acid/AcidMyFacesRequestTestCase.java
myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/pss/acid/managed/ResourceDependencyBean.java
Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java?rev=1505865&r1=1505864&r2=1505865&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java Tue Jul 23 00:19:31 2013
@@ -1785,7 +1785,7 @@ public class ApplicationImpl extends App
ResourceDependency dependency = dependencyList.get(i);
if (!rvc.isResourceDependencyAlreadyProcessed(dependency))
{
- _handleAttachedResourceDependency(context, dependency);
+ _handleAttachedResourceDependency(context, dependency, inspectedClass);
rvc.setResourceDependencyAsProcessed(dependency);
}
}
@@ -1830,7 +1830,8 @@ public class ApplicationImpl extends App
* @param facesContext
* @param component
*/
- private void setResourceIdOnFaceletsMode(FacesContext facesContext, UIComponent component)
+ private void setResourceIdOnFaceletsMode(FacesContext facesContext, UIComponent component,
+ Class<?> inspectedClass)
{
if (component.getId() == null)
{
@@ -1848,11 +1849,31 @@ public class ApplicationImpl extends App
{
root.getAttributes().put(RESOURCE_DEPENDENCY_UNIQUE_ID_KEY, Boolean.FALSE);
}
+ if (!mctx.isUsingPSSOnThisView())
+ {
+ // Now set the identifier that will help to know which classes has been already inspected.
+ component.getAttributes().put(
+ RequestViewContext.RESOURCE_DEPENDENCY_INSPECTED_CLASS, inspectedClass);
+ }
+ else if (mctx.isRefreshTransientBuildOnPSSPreserveState())
+ {
+ component.getAttributes().put(
+ RequestViewContext.RESOURCE_DEPENDENCY_INSPECTED_CLASS, inspectedClass);
+ }
+ }
+ else
+ {
+ // This happens when there is a programmatic addition, which means the user has added the
+ // components to the tree on render response phase or earlier but outside facelets control.
+ // In that case we need to save the dependency.
+ component.getAttributes().put(
+ RequestViewContext.RESOURCE_DEPENDENCY_INSPECTED_CLASS, inspectedClass);
}
}
}
- private void _handleAttachedResourceDependency(FacesContext context, ResourceDependency annotation)
+ private void _handleAttachedResourceDependency(FacesContext context, ResourceDependency annotation,
+ Class<?> inspectedClass)
{
// If this annotation is not present on the class in question, no action must be taken.
if (annotation != null)
@@ -1881,7 +1902,7 @@ public class ApplicationImpl extends App
// If the @ResourceDependency was done inside facelets processing,
// call setId() and set a proper id from facelets
- setResourceIdOnFaceletsMode(context, output);
+ setResourceIdOnFaceletsMode(context, output, inspectedClass);
// Obtain the Map of attributes from the UIOutput component by calling UIComponent.getAttributes().
Map<String, Object> attributes = output.getAttributes();
@@ -2311,7 +2332,7 @@ public class ApplicationImpl extends App
ResourceDependency dependency = dependencyList.get(i);
if (!rvc.isResourceDependencyAlreadyProcessed(dependency))
{
- _handleResourceDependency(context, component, dependency);
+ _handleResourceDependency(context, component, dependency, inspectedClass);
rvc.setResourceDependencyAsProcessed(dependency);
}
}
@@ -2333,7 +2354,8 @@ public class ApplicationImpl extends App
}
}
- private void _handleResourceDependency(FacesContext context, UIComponent component, ResourceDependency annotation)
+ private void _handleResourceDependency(FacesContext context, UIComponent component, ResourceDependency annotation,
+ Class<?> inspectedClass)
{
// If this annotation is not present on the class in question, no action must be taken.
if (annotation != null)
@@ -2361,7 +2383,7 @@ public class ApplicationImpl extends App
// If the @ResourceDependency was done inside facelets processing,
// call setId() and set a proper id from facelets
- setResourceIdOnFaceletsMode(context, output);
+ setResourceIdOnFaceletsMode(context, output, inspectedClass);
// Obtain the Map of attributes from the UIOutput component by calling UIComponent.getAttributes().
Map<String, Object> attributes = output.getAttributes();
Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java?rev=1505865&r1=1505864&r2=1505865&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java Tue Jul 23 00:19:31 2013
@@ -39,6 +39,7 @@ import javax.faces.view.StateManagementS
import javax.faces.view.ViewDeclarationLanguage;
import org.apache.myfaces.application.viewstate.StateCacheUtils;
+import org.apache.myfaces.context.RequestViewContext;
public class StateManagerImpl extends StateManager
{
@@ -149,6 +150,9 @@ public class StateManagerImpl extends St
{
facesContext.setViewRoot (uiViewRoot);
uiViewRoot.processRestoreState(facesContext, stateArray[1]);
+
+ RequestViewContext.getCurrentInstance(facesContext).refreshRequestViewContext(
+ facesContext, uiViewRoot);
}
}
}
Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/RequestViewContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/RequestViewContext.java?rev=1505865&r1=1505864&r2=1505865&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/RequestViewContext.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/RequestViewContext.java Tue Jul 23 00:19:31 2013
@@ -18,12 +18,20 @@
*/
package org.apache.myfaces.context;
+import java.util.Collections;
+import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
+import java.util.Set;
import javax.faces.application.ResourceDependency;
+import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.component.visit.VisitHint;
+import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
/**
@@ -37,6 +45,13 @@ public class RequestViewContext
public static final String VIEW_CONTEXT_KEY = "oam.VIEW_CONTEXT";
+ public static final String RESOURCE_DEPENDENCY_INSPECTED_CLASS = "oam.RDClass";
+
+ private static final String SKIP_ITERATION_HINT = "javax.faces.visit.SKIP_ITERATION";
+
+ //private static final Set<VisitHint> VISIT_HINTS = Collections.unmodifiableSet(
+ // EnumSet.of(VisitHint.SKIP_ITERATION));
+
private Map<ResourceDependency, Boolean> addedResources;
// No lazy init: every view has one (UIView.class) or more classes to process
@@ -125,4 +140,50 @@ public class RequestViewContext
}
renderTargetMap.put(target, value);
}
+
+ /**
+ * Scans UIViewRoot facets with added component resources by the effect of
+ * @ResourceDependency annotation, and register the associated inspected classes
+ * so new component resources will not be added to the component tree again and again.
+ *
+ * @param facesContext
+ * @param root
+ */
+ public void refreshRequestViewContext(FacesContext facesContext, UIViewRoot root)
+ {
+ for (Map.Entry<String, UIComponent> entry : root.getFacets().entrySet())
+ {
+ UIComponent facet = entry.getValue();
+ if (facet.getId() != null && facet.getId().startsWith("javax_faces_location_"))
+ {
+ try
+ {
+ facesContext.getAttributes().put(SKIP_ITERATION_HINT, Boolean.TRUE);
+
+ VisitContext visitContext = VisitContext.createVisitContext(facesContext, null, null);
+ facet.visitTree(visitContext, new RefreshViewContext());
+ }
+ finally
+ {
+ // We must remove hint in finally, because an exception can break this phase,
+ // but lifecycle can continue, if custom exception handler swallows the exception
+ facesContext.getAttributes().remove(SKIP_ITERATION_HINT);
+ }
+ }
+ }
+ }
+
+ private class RefreshViewContext implements VisitCallback
+ {
+
+ public VisitResult visit(VisitContext context, UIComponent target)
+ {
+ Class<?> inspectedClass = (Class<?>)target.getAttributes().get(RESOURCE_DEPENDENCY_INSPECTED_CLASS);
+ if (inspectedClass != null)
+ {
+ setClassProcessed(inspectedClass);
+ }
+ return VisitResult.ACCEPT;
+ }
+ }
}
Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java?rev=1505865&r1=1505864&r2=1505865&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java Tue Jul 23 00:19:31 2013
@@ -57,6 +57,7 @@ import javax.faces.view.ViewMetadata;
import org.apache.myfaces.application.StateManagerImpl;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+import org.apache.myfaces.context.RequestViewContext;
import org.apache.myfaces.shared.config.MyfacesConfig;
import org.apache.myfaces.shared.util.ClassUtils;
import org.apache.myfaces.shared.util.HashMapUtils;
@@ -219,6 +220,12 @@ public class DefaultFaceletsStateManagem
{
context.setViewRoot (view);
view.processRestoreState(context, fullState[1]);
+
+ // If the view is restored fully, it is necessary to refresh RequestViewContext, otherwise at
+ // each ajax request new components associated with @ResourceDependency annotation will be added
+ // to the tree, making the state bigger without real need.
+ RequestViewContext.getCurrentInstance(context).
+ refreshRequestViewContext(context, view);
}
}
else
@@ -444,6 +451,12 @@ public class DefaultFaceletsStateManagem
// Reset this list, because it will be calculated later when the view is being saved
// in the right order, preventing duplicates (see COMPONENT_ADDED_AFTER_BUILD_VIEW for details).
clientIdsAdded.clear();
+
+ // This call only has sense when components has been added programatically, because if facelets has control
+ // over all components in the component tree, build the initial state and apply the state will have the
+ // same effect.
+ RequestViewContext.getCurrentInstance(context).
+ refreshRequestViewContext(context, view);
}
}
@@ -739,7 +752,7 @@ public class DefaultFaceletsStateManagem
component.popComponentFromEL(context);
}
}
-
+
static List<String> getClientIdsAdded(UIViewRoot root)
{
return (List<String>) root.getAttributes().get(CLIENTIDS_ADDED);
Modified: myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/pss/acid/AcidMyFacesRequestTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/pss/acid/AcidMyFacesRequestTestCase.java?rev=1505865&r1=1505864&r2=1505865&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/pss/acid/AcidMyFacesRequestTestCase.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/pss/acid/AcidMyFacesRequestTestCase.java Tue Jul 23 00:19:31 2013
@@ -508,4 +508,102 @@ public class AcidMyFacesRequestTestCase
executeAfterRender(facesContext);
}
+ @Test
+ public void testResourceDependency2() throws Exception
+ {
+ setupRequest("/resourceDependency2.xhtml");
+ processLifecycleExecute();
+
+ executeBeforeRender(facesContext);
+ executeBuildViewCycle(facesContext);
+
+ UIPanel headPanel = (UIPanel) facesContext.getViewRoot().getFacet("head");
+ Assert.assertNull(headPanel);
+
+ String nextUniqueId = facesContext.getViewRoot().createUniqueId(facesContext, null);
+
+ executeViewHandlerRender(facesContext);
+ executeAfterRender(facesContext);
+
+ UICommand button = (UICommand) facesContext.getViewRoot().findComponent("mainForm:postback");
+ submit(button);
+
+ processLifecycleExecute();
+
+ ResourceDependencyBean bean = facesContext.getApplication().evaluateExpressionGet(
+ facesContext, "#{resourceDependencyBean}", ResourceDependencyBean.class);
+ bean.setIncludeContent(true);
+
+ executeBeforeRender(facesContext);
+ executeBuildViewCycle(facesContext);
+
+ headPanel = (UIPanel) facesContext.getViewRoot().getFacet("head");
+ Assert.assertNotNull(headPanel);
+ Assert.assertTrue(1 >= headPanel.getChildCount());
+ Assert.assertNotSame(nextUniqueId, headPanel.getChildren().get(0).getId());
+
+ executeViewHandlerRender(facesContext);
+ executeAfterRender(facesContext);
+
+ UICommand button2 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:postback");
+ submit(button2);
+
+ processLifecycleExecute();
+
+ bean = facesContext.getApplication().evaluateExpressionGet(
+ facesContext, "#{resourceDependencyBean}", ResourceDependencyBean.class);
+ bean.setIncludeContent(false);
+
+ executeBeforeRender(facesContext);
+ executeBuildViewCycle(facesContext);
+
+ headPanel = (UIPanel) facesContext.getViewRoot().getFacet("head");
+ Assert.assertNotNull(headPanel);
+ Assert.assertTrue(1 >= headPanel.getChildCount());
+ //Assert.assertNotSame(nextUniqueId, headPanel.getChildren().get(0).getId());
+
+ executeViewHandlerRender(facesContext);
+ executeAfterRender(facesContext);
+
+ UICommand button3 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:postback");
+ submit(button3);
+
+ processLifecycleExecute();
+
+ bean = facesContext.getApplication().evaluateExpressionGet(
+ facesContext, "#{resourceDependencyBean}", ResourceDependencyBean.class);
+ bean.setIncludeContent(true);
+
+ executeBeforeRender(facesContext);
+ executeBuildViewCycle(facesContext);
+
+ headPanel = (UIPanel) facesContext.getViewRoot().getFacet("head");
+ Assert.assertNotNull(headPanel);
+ Assert.assertTrue(1 >= headPanel.getChildCount());
+ //Assert.assertNotSame(nextUniqueId, headPanel.getChildren().get(0).getId());
+
+ executeViewHandlerRender(facesContext);
+ executeAfterRender(facesContext);
+
+ UICommand button4 = (UICommand) facesContext.getViewRoot().findComponent("mainForm:postback");
+ submit(button4);
+
+ processLifecycleExecute();
+
+ bean = facesContext.getApplication().evaluateExpressionGet(
+ facesContext, "#{resourceDependencyBean}", ResourceDependencyBean.class);
+ bean.setIncludeContent(false);
+
+ executeBeforeRender(facesContext);
+ executeBuildViewCycle(facesContext);
+
+ headPanel = (UIPanel) facesContext.getViewRoot().getFacet("head");
+ Assert.assertNotNull(headPanel);
+ Assert.assertTrue(1 >= headPanel.getChildCount());
+ //Assert.assertNotSame(nextUniqueId, headPanel.getChildren().get(0).getId());
+
+ executeViewHandlerRender(facesContext);
+ executeAfterRender(facesContext);
+ }
+
}
Modified: myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/pss/acid/managed/ResourceDependencyBean.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/pss/acid/managed/ResourceDependencyBean.java?rev=1505865&r1=1505864&r2=1505865&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/pss/acid/managed/ResourceDependencyBean.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/pss/acid/managed/ResourceDependencyBean.java Tue Jul 23 00:19:31 2013
@@ -46,4 +46,9 @@ public class ResourceDependencyBean
{
this.includeContent = includeContent;
}
+
+ public void toggleContent()
+ {
+ this.includeContent = !this.includeContent;
+ }
}
Added: myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/pss/acid/resourceDependency2.xhtml
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/pss/acid/resourceDependency2.xhtml?rev=1505865&view=auto
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/pss/acid/resourceDependency2.xhtml (added)
+++ myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/pss/acid/resourceDependency2.xhtml Tue Jul 23 00:19:31 2013
@@ -0,0 +1,33 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+ Licensed 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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jsp/jstl/core"
+ xmlns:test="http://testcomponent">
+<h:head>
+</h:head>
+<h:body>
+
+ <h:form id="mainForm">
+ <c:if test="#{resourceDependencyBean.includeContent}">
+ <test:rdcomponent id="rdcomp" value="test1"/>
+ </c:if>
+ <h:commandButton id="postback" value="POSTBACK"/>
+ </h:form>
+</h:body>
+</html>
+
Propchange: myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/pss/acid/resourceDependency2.xhtml
------------------------------------------------------------------------------
svn:eol-style = native