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);
+        }
     }
 
     /**