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 2009/09/30 06:49:26 UTC
svn commit: r820175 - in /myfaces/core/trunk:
api/src/main/java/javax/faces/component/
impl/src/main/java/org/apache/myfaces/view/facelets/
impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/
Author: lu4242
Date: Wed Sep 30 04:49:26 2009
New Revision: 820175
URL: http://svn.apache.org/viewvc?rev=820175&view=rev
Log:
MYFACES-2323 Implement <f:ajax> tag handler (if f:ajax is on a page, it should be created automatically a component that register and render jsf.js javascript with target head)
Modified:
myfaces/core/trunk/api/src/main/java/javax/faces/component/UIViewRoot.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/AjaxHandler.java
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=820175&r1=820174&r2=820175&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 Sep 30 04:49:26 2009
@@ -149,22 +149,40 @@
// Call getComponentResources to obtain the child list for the given target
List<UIComponent> componentResources = _getComponentResources(context, target);
- // If the component ID of componentResource matches the the ID of a resource that has already been added, remove the old resource.
+ // If the component ID of componentResource matches the ID of a resource that has already been added, remove the old resource.
String componentId = componentResource.getId();
+ // This var helps to handle the case when we try to add a component that already is
+ // on the resource list, because PostAddToViewEvent also is sent to components
+ // backing resources. The problem start when a component is already inside
+ // componentResources list and we try to relocate it again. This leads to a StackOverflowException
+ // so we need to check if a component is and prevent remove and add it again. Note
+ // that remove and then add a component trigger another PostAddToViewEvent. The right
+ // point to prevent this StackOverflowException is here, because this method is
+ // responsible to traverse the componentResources list and add when necessary.
+ boolean alreadyAdded = false;
+
if (componentId != null)
{
- for(UIComponent component : componentResources)
+ for(Iterator<UIComponent> it = componentResources.iterator(); it.hasNext();)
{
- if(componentId.equals(component.getId()))
+ UIComponent component = it.next();
+ if(componentId.equals(component.getId()) && componentResource != component)
+ {
+ it.remove();
+ }
+ else if (componentResource == component)
{
- componentResources.remove(component);
+ alreadyAdded = true;
}
}
}
// Add the component resource to the list
- componentResources.add(componentResource);
+ if (!alreadyAdded)
+ {
+ componentResources.add(componentResource);
+ }
}
/**
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java?rev=820175&r1=820174&r2=820175&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java Wed Sep 30 04:49:26 2009
@@ -95,7 +95,7 @@
import org.apache.myfaces.view.facelets.tag.composite.CompositeComponentResourceTagHandler;
import org.apache.myfaces.view.facelets.tag.composite.CompositeLibrary;
import org.apache.myfaces.view.facelets.tag.composite.CompositeResourceLibrary;
-import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
+import org.apache.myfaces.view.facelets.tag.jsf.core.AjaxHandler;
import org.apache.myfaces.view.facelets.tag.ui.UIDebug;
import org.apache.myfaces.view.facelets.util.DevTools;
import org.apache.myfaces.view.facelets.util.ReflectionUtil;
@@ -266,6 +266,10 @@
{
//context.getAttributes().put(view.toString(), Boolean.TRUE);
view.getAttributes().put(FILLED_VIEW, Boolean.TRUE);
+ // Remove this var from faces context because this one prevent AjaxHandler
+ // register the standard script library on Post-Redirect-Get pattern or
+ // in the next view
+ context.getAttributes().remove(AjaxHandler.STANDARD_JSF_AJAX_LIBRARY_LOADED);
}
/**
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/AjaxHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/AjaxHandler.java?rev=820175&r1=820174&r2=820175&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/AjaxHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/core/AjaxHandler.java Wed Sep 30 04:49:26 2009
@@ -19,6 +19,7 @@
package org.apache.myfaces.view.facelets.tag.jsf.core;
import java.io.IOException;
+import java.util.List;
import javax.el.MethodExpression;
import javax.faces.component.UIComponent;
@@ -28,6 +29,8 @@
import javax.faces.event.AbortProcessingException;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.AjaxBehaviorListener;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
import javax.faces.view.BehaviorHolderAttachedObjectHandler;
import javax.faces.view.facelets.ComponentHandler;
import javax.faces.view.facelets.FaceletContext;
@@ -71,6 +74,13 @@
{
public final static Class<?>[] AJAX_BEHAVIOR_LISTENER_SIG = new Class<?>[] { AjaxBehaviorEvent.class };
+
+ /**
+ * Constant used to check if in the current build view it has been rendered the standard jsf javascript
+ * library. It is necessary to remove this key from facesContext attribute map after build, to keep
+ * working this code for next views to be built.
+ */
+ public final static String STANDARD_JSF_AJAX_LIBRARY_LOADED = "org.apache.myfaces.STANDARD_JSF_AJAX_LIBRARY_LOADED";
/**
*
@@ -165,6 +175,27 @@
"Parent is not composite component or of type ClientBehaviorHolder, type is: "
+ parent);
}
+
+ // Register the standard ajax library on the current page in this way:
+ //
+ // <h:outputScript name="jsf.js" library="javax.faces" target="head"/>
+ //
+ // If no h:head component is in the page, we must anyway render the script inline,
+ // so the only way to make sure we are doing this is add a outputScript component.
+ // Note that call directly UIViewRoot.addComponentResource or use a listener
+ // does not work in this case, because check this condition will requires
+ // traverse the whole tree looking for h:head component.
+ FacesContext facesContext = ctx.getFacesContext();
+ if (facesContext.getAttributes().containsKey(STANDARD_JSF_AJAX_LIBRARY_LOADED))
+ {
+ UIComponent outputScript = facesContext.getApplication().
+ createComponent(facesContext, "javax.faces.Output", "javax.faces.resource.Script");
+ outputScript.getAttributes().put("name", "jsf.js");
+ outputScript.getAttributes().put("library", "javax.faces");
+ outputScript.getAttributes().put("target", "head");
+ parent.getChildren().add(outputScript);
+ facesContext.getAttributes().put(STANDARD_JSF_AJAX_LIBRARY_LOADED, Boolean.TRUE);
+ }
}
/**