You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ta...@apache.org on 2022/12/19 13:45:39 UTC

[myfaces] branch main updated: MYFACES-4514

This is an automated email from the ASF dual-hosted git repository.

tandraschko pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/myfaces.git


The following commit(s) were added to refs/heads/main by this push:
     new e1fcfbeea MYFACES-4514
e1fcfbeea is described below

commit e1fcfbeeafbb630f481c7d1321a16557c335ffbb
Author: Thomas Andraschko <ta...@apache.org>
AuthorDate: Mon Dec 19 14:45:30 2022 +0100

    MYFACES-4514
---
 .../tag/faces/core/AjaxBehaviorListenerImpl.java   | 101 +++++++++
 .../view/facelets/tag/faces/core/AjaxHandler.java  | 229 ++++-----------------
 .../html/behavior/AjaxBehaviorRenderTestCase.java  | 114 ++++++++++
 .../myfaces/renderkit/html/behavior/ajax_1.xhtml   |  35 ++++
 .../myfaces/renderkit/html/behavior/ajax_2.xhtml   |  34 +++
 .../myfaces/renderkit/html/behavior/ajax_3.xhtml   |  34 +++
 .../myfaces/renderkit/html/behavior/ajax_4.xhtml   |  35 ++++
 7 files changed, 394 insertions(+), 188 deletions(-)

diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/tag/faces/core/AjaxBehaviorListenerImpl.java b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/faces/core/AjaxBehaviorListenerImpl.java
new file mode 100644
index 000000000..766ab7e66
--- /dev/null
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/faces/core/AjaxBehaviorListenerImpl.java
@@ -0,0 +1,101 @@
+/*
+ * 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 org.apache.myfaces.view.facelets.tag.faces.core;
+
+import jakarta.el.MethodExpression;
+import jakarta.faces.component.PartialStateHolder;
+import jakarta.faces.context.FacesContext;
+import jakarta.faces.event.AbortProcessingException;
+import jakarta.faces.event.AjaxBehaviorEvent;
+import jakarta.faces.event.AjaxBehaviorListener;
+
+/**
+ * Wraps a method expression in a AjaxBehaviorListener
+ */
+public final class AjaxBehaviorListenerImpl implements AjaxBehaviorListener, PartialStateHolder
+{
+    private MethodExpression _expr;
+    private boolean _transient;
+    private boolean _initialStateMarked;
+
+    public AjaxBehaviorListenerImpl ()
+    {
+    }
+
+    public AjaxBehaviorListenerImpl(MethodExpression expr)
+    {
+        _expr = expr;
+    }
+
+    @Override
+    public void processAjaxBehavior(AjaxBehaviorEvent event) throws AbortProcessingException
+    {
+        _expr.invoke(FacesContext.getCurrentInstance().getELContext(), new Object[] { event });
+    }
+
+    @Override
+    public boolean isTransient()
+    {
+        return _transient;
+    }
+
+    @Override
+    public void restoreState(FacesContext context, Object state)
+    {
+        if (state == null)
+        {
+            return;
+        }
+        _expr = (MethodExpression) state;
+    }
+
+    @Override
+    public Object saveState(FacesContext context)
+    {
+        if (initialStateMarked())
+        {
+            return null;
+        }
+        return _expr;
+    }
+
+    @Override
+    public void setTransient(boolean newTransientValue)
+    {
+        _transient = newTransientValue;
+    }
+
+    @Override
+    public void clearInitialState()
+    {
+        _initialStateMarked = false;
+    }
+
+    @Override
+    public boolean initialStateMarked()
+    {
+        return _initialStateMarked;
+    }
+
+    @Override
+    public void markInitialState()
+    {
+        _initialStateMarked = true;
+    }
+}
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/tag/faces/core/AjaxHandler.java b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/faces/core/AjaxHandler.java
index 1898eb139..a5ae7e69c 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/tag/faces/core/AjaxHandler.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/faces/core/AjaxHandler.java
@@ -20,19 +20,14 @@ package org.apache.myfaces.view.facelets.tag.faces.core;
 
 import java.io.IOException;
 import java.util.Collection;
-import java.util.List;
-import java.util.Map;
 
 import jakarta.el.MethodExpression;
 import jakarta.faces.application.ResourceHandler;
-import jakarta.faces.component.PartialStateHolder;
 import jakarta.faces.component.UIComponent;
 import jakarta.faces.component.UniqueIdVendor;
 import jakarta.faces.component.behavior.AjaxBehavior;
-import jakarta.faces.component.behavior.ClientBehavior;
 import jakarta.faces.component.behavior.ClientBehaviorHolder;
 import jakarta.faces.context.FacesContext;
-import jakarta.faces.event.AbortProcessingException;
 import jakarta.faces.event.AjaxBehaviorEvent;
 import jakarta.faces.event.AjaxBehaviorListener;
 import jakarta.faces.view.BehaviorHolderAttachedObjectHandler;
@@ -45,6 +40,7 @@ import jakarta.faces.view.facelets.TagConfig;
 import jakarta.faces.view.facelets.TagException;
 import jakarta.faces.view.facelets.TagHandler;
 import java.util.ArrayList;
+import java.util.function.Consumer;
 
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
@@ -318,14 +314,10 @@ public class AjaxHandler extends TagHandler implements
     @Override
     public void applyAttachedObject(FacesContext context, UIComponent parent)
     {
-        // Retrieve the current FaceletContext from FacesContext object
-        FaceletContext faceletContext = (FaceletContext) context.getAttributes()
-                .get(FaceletContext.FACELET_CONTEXT_KEY);
-
-        // cast to a ClientBehaviorHolder
+        FaceletContext faceletContext =
+                (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
         ClientBehaviorHolder cvh = (ClientBehaviorHolder) parent;
-        
-        
+
         String eventName = null;
         if (_event != null)
         {
@@ -374,56 +366,16 @@ public class AjaxHandler extends TagHandler implements
                         "event it is not a valid eventName defined for this component");
             }
         }
-        
-        Map<String, List<ClientBehavior>> clientBehaviors = cvh.getClientBehaviors();
-
-        List<ClientBehavior> clientBehaviorList = clientBehaviors.get(eventName);
-        if (clientBehaviorList != null && !clientBehaviorList.isEmpty())
-        {
-            for (ClientBehavior cb : clientBehaviorList)
-            {
-                if (cb instanceof AjaxBehavior)
-                {
-                    // The most inner one has been applied, so according to 
-                    // jsf 2.0 spec section 10.4.1.1 it is not necessary to apply
-                    // this one, because the inner one has precendece over
-                    // the outer one.
-                    return;
-                }
-            }
-        }
 
         AjaxBehavior ajaxBehavior = createBehavior(context);
-
-        if (_disabled != null)
-        {
-            if (_disabled.isLiteral())
-            {
-                ajaxBehavior.setDisabled(_disabled.getBoolean(faceletContext));
-            }
-            else
-            {
-                ajaxBehavior.setValueExpression("disabled",
-                        _disabled.getValueExpression(faceletContext, Boolean.class));
-            }
-        }
-        if (_execute != null)
-        {
-            ajaxBehavior.setValueExpression("execute", 
-                    _execute.getValueExpression(faceletContext, Object.class));
-        }
-        if (_immediate != null)
-        {
-            if (_immediate.isLiteral())
-            {
-                ajaxBehavior.setImmediate(_immediate.getBoolean(faceletContext));
-            }
-            else
-            {
-                ajaxBehavior.setValueExpression("immediate",
-                        _immediate.getValueExpression(faceletContext, Boolean.class));
-            }
-        }
+        setAttribute(faceletContext, ajaxBehavior, _disabled, Boolean.class, (v) -> ajaxBehavior.setDisabled(v));
+        setAttribute(faceletContext, ajaxBehavior, _execute, Object.class);
+        setAttribute(faceletContext, ajaxBehavior, _immediate, Boolean.class, (v) -> ajaxBehavior.setImmediate(v));
+        setAttribute(faceletContext, ajaxBehavior, _onerror, String.class, (v) -> ajaxBehavior.setOnerror(v));
+        setAttribute(faceletContext, ajaxBehavior, _onevent, String.class, (v) -> ajaxBehavior.setOnevent(v));
+        setAttribute(faceletContext, ajaxBehavior, _render, Object.class);
+        setAttribute(faceletContext, ajaxBehavior, _delay, String.class, (v) -> ajaxBehavior.setDelay(v));
+        setAttribute(faceletContext, ajaxBehavior, _resetValues, Boolean.class, (v) -> ajaxBehavior.setResetValues(v));
         if (_listener != null)
         {
             MethodExpression expr = _listener.getMethodExpression(
@@ -431,59 +383,6 @@ public class AjaxHandler extends TagHandler implements
             AjaxBehaviorListener abl = new AjaxBehaviorListenerImpl(expr);
             ajaxBehavior.addAjaxBehaviorListener(abl);
         }
-        if (_onerror != null)
-        {
-            if (_onerror.isLiteral())
-            {
-                ajaxBehavior.setOnerror(_onerror.getValue(faceletContext));
-            }
-            else
-            {
-                ajaxBehavior.setValueExpression("onerror",
-                        _onerror.getValueExpression(faceletContext, String.class));
-            }
-        }
-        if (_onevent != null)
-        {
-            if (_onevent.isLiteral())
-            {
-                ajaxBehavior.setOnevent(_onevent.getValue(faceletContext));
-            }
-            else
-            {
-                ajaxBehavior.setValueExpression("onevent",
-                        _onevent.getValueExpression(faceletContext, String.class));
-            }
-        }
-        if (_render != null)
-        {
-            ajaxBehavior.setValueExpression("render",
-                    _render.getValueExpression(faceletContext, Object.class));
-        }
-        if (_delay != null)
-        {
-            if (_delay.isLiteral())
-            {
-                ajaxBehavior.setDelay(_delay.getValue(faceletContext));
-            }
-            else
-            {
-                ajaxBehavior.setValueExpression("delay",
-                        _delay.getValueExpression(faceletContext, String.class));
-            }
-        }
-        if (_resetValues != null)
-        {
-            if (_resetValues.isLiteral())
-            {
-                ajaxBehavior.setResetValues(_resetValues.getBoolean(faceletContext));
-            }
-            else
-            {
-                ajaxBehavior.setValueExpression("resetValues",
-                        _resetValues.getValueExpression(faceletContext, Boolean.class));
-            }
-        }
 
         // map @this in a composite to @composite
         if (parent instanceof ClientBehaviorRedirectEventComponentWrapper)
@@ -514,6 +413,35 @@ public class AjaxHandler extends TagHandler implements
         cvh.addClientBehavior(eventName, ajaxBehavior);
     }
 
+    protected <T> void setAttribute(FaceletContext faceletContext, AjaxBehavior behavior, TagAttribute attr,
+            Class<T> type)
+    {
+        setAttribute(faceletContext, behavior, attr, type, null);
+    }
+    
+    protected <T> void setAttribute(FaceletContext faceletContext, AjaxBehavior behavior, TagAttribute attr,
+            Class<T> type, Consumer<T> setter)
+    {
+        if (attr != null)
+        {
+            if (!attr.isLiteral() || setter == null)
+            {
+                behavior.setValueExpression(attr.getLocalName(), attr.getValueExpression(faceletContext, type));
+            }
+            else
+            {
+                if (type == Boolean.class)
+                {
+                    ((Consumer<Boolean>) setter).accept(attr.getBoolean(faceletContext));
+                }
+                else
+                {
+                    setter.accept((T) attr.getValue(faceletContext));
+                }
+            }
+        }
+    }
+    
     protected AjaxBehavior createBehavior(FacesContext context)
     {
         return (AjaxBehavior) context.getApplication().createBehavior(AjaxBehavior.BEHAVIOR_ID);
@@ -529,79 +457,4 @@ public class AjaxHandler extends TagHandler implements
     {
         return null;
     }
-
-    /**
-     * Wraps a method expression in a AjaxBehaviorListener
-     */
-    public final static class AjaxBehaviorListenerImpl implements AjaxBehaviorListener, PartialStateHolder
-    {
-        private MethodExpression _expr;
-        private boolean _transient;
-        private boolean _initialStateMarked;
-        
-        public AjaxBehaviorListenerImpl ()
-        {
-        }
-        
-        public AjaxBehaviorListenerImpl(MethodExpression expr)
-        {
-            _expr = expr;
-        }
-
-        @Override
-        public void processAjaxBehavior(AjaxBehaviorEvent event) throws AbortProcessingException
-        {
-            _expr.invoke(FacesContext.getCurrentInstance().getELContext(), new Object[] { event });
-        }
-
-        @Override
-        public boolean isTransient()
-        {
-            return _transient;
-        }
-
-        @Override
-        public void restoreState(FacesContext context, Object state)
-        {
-            if (state == null)
-            {
-                return;
-            }
-            _expr = (MethodExpression) state;
-        }
-
-        @Override
-        public Object saveState(FacesContext context)
-        {
-            if (initialStateMarked())
-            {
-                return null;
-            }
-            return _expr;
-        }
-
-        @Override
-        public void setTransient(boolean newTransientValue)
-        {
-            _transient = newTransientValue;
-        }
-        
-        @Override
-        public void clearInitialState()
-        {
-            _initialStateMarked = false;
-        }
-
-        @Override
-        public boolean initialStateMarked()
-        {
-            return _initialStateMarked;
-        }
-
-        @Override
-        public void markInitialState()
-        {
-            _initialStateMarked = true;
-        }
-    }
 }
diff --git a/impl/src/test/java/org/apache/myfaces/renderkit/html/behavior/AjaxBehaviorRenderTestCase.java b/impl/src/test/java/org/apache/myfaces/renderkit/html/behavior/AjaxBehaviorRenderTestCase.java
new file mode 100644
index 000000000..a6fcfc170
--- /dev/null
+++ b/impl/src/test/java/org/apache/myfaces/renderkit/html/behavior/AjaxBehaviorRenderTestCase.java
@@ -0,0 +1,114 @@
+/*
+ * 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 org.apache.myfaces.renderkit.html.behavior;
+
+import java.io.StringWriter;
+import jakarta.faces.application.ViewHandler;
+
+import jakarta.faces.component.UIViewRoot;
+
+import org.apache.myfaces.test.mock.MockResponseWriter;
+import org.apache.myfaces.util.lang.StringUtils;
+import org.apache.myfaces.view.facelets.FaceletTestCase;
+import org.junit.Test;
+
+public class AjaxBehaviorRenderTestCase extends FaceletTestCase {
+
+    @Override
+    protected void setUpServletObjects() throws Exception
+    {
+        super.setUpServletObjects();
+        servletContext.addInitParameter(ViewHandler.FACELETS_SKIP_COMMENTS_PARAM_NAME, "true");
+    }
+
+    @Test
+    public void testAjax1() throws Exception {
+        UIViewRoot root = facesContext.getViewRoot();
+        vdl.buildView(facesContext, root, "ajax_1.xhtml");
+        
+        StringWriter sw = new StringWriter();
+        MockResponseWriter mrw = new MockResponseWriter(sw);
+        facesContext.setResponseWriter(mrw);
+        root.encodeAll(facesContext);
+        sw.flush();
+
+        String response = sw.toString();
+        assertFalse(response.contains("faces.util.chain"));
+        assertFalse(response.contains("myfaces.ab"));
+    }
+ 
+    @Test
+    public void testAjax2() throws Exception {
+        UIViewRoot root = facesContext.getViewRoot();
+        vdl.buildView(facesContext, root, "ajax_2.xhtml");
+        
+        StringWriter sw = new StringWriter();
+        MockResponseWriter mrw = new MockResponseWriter(sw);
+        facesContext.setResponseWriter(mrw);
+        root.encodeAll(facesContext);
+        sw.flush();
+
+        String response = sw.toString();
+        assertTrue(response.contains("faces.util.chain"));
+        assertTrue(response.contains("myfaces.ab"));
+        assertEquals(countMatches(response, "faces.util.chain"), 1);
+        assertEquals(countMatches(response, "myfaces.ab"), 1);
+    }
+    
+    @Test
+    public void testAjax3() throws Exception {
+        UIViewRoot root = facesContext.getViewRoot();
+        vdl.buildView(facesContext, root, "ajax_3.xhtml");
+        
+        StringWriter sw = new StringWriter();
+        MockResponseWriter mrw = new MockResponseWriter(sw);
+        facesContext.setResponseWriter(mrw);
+        root.encodeAll(facesContext);
+        sw.flush();
+
+        String response = sw.toString();
+        assertTrue(response.contains("faces.util.chain"));
+        assertTrue(response.contains("myfaces.ab"));
+        assertEquals(countMatches(response, "faces.util.chain"), 1);
+        assertEquals(countMatches(response, "myfaces.ab"), 1);
+    }
+    
+    @Test
+    public void testAjax4() throws Exception {
+        UIViewRoot root = facesContext.getViewRoot();
+        vdl.buildView(facesContext, root, "ajax_4.xhtml");
+        
+        StringWriter sw = new StringWriter();
+        MockResponseWriter mrw = new MockResponseWriter(sw);
+        facesContext.setResponseWriter(mrw);
+        root.encodeAll(facesContext);
+        sw.flush();
+
+        String response = sw.toString();
+        assertTrue(response.contains("faces.util.chain"));
+        assertTrue(response.contains("myfaces.ab"));
+        assertEquals(countMatches(response, "faces.util.chain"), 1);
+        assertEquals(countMatches(response, "myfaces.ab"), 2);
+    }
+    
+    public int countMatches(String all, String search)
+    {
+        return all.split(search, -1).length - 1;
+    }
+}
diff --git a/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_1.xhtml b/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_1.xhtml
new file mode 100644
index 000000000..7b3903206
--- /dev/null
+++ b/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_1.xhtml
@@ -0,0 +1,35 @@
+<!--
+ * 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.
+ *
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:ui="http://java.sun.com/jsf/facelets"
+      xmlns:f="http://java.sun.com/jsf/core"
+      xmlns:h="http://java.sun.com/jsf/html">
+    <body>
+        <h:form id="form" >
+            <!-- Test one: No behaviors rendered -->
+            <h:inputText id="input">
+                <f:ajax execute="@all" render="@all" disabled="true"/>
+                <f:ajax execute="@this" render="@all" disabled="true"/>
+            </h:inputText>
+            <br/>
+        </h:form>
+    </body>
+</html>
diff --git a/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_2.xhtml b/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_2.xhtml
new file mode 100644
index 000000000..950e7f114
--- /dev/null
+++ b/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_2.xhtml
@@ -0,0 +1,34 @@
+<!--
+ * 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.
+ *
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:ui="http://java.sun.com/jsf/facelets"
+      xmlns:f="http://java.sun.com/jsf/core"
+      xmlns:h="http://java.sun.com/jsf/html">
+    <body>
+        <h:form id="form" >
+            <!-- Test two: Second behavior rendered -->
+            <h:inputText id="input">
+                <f:ajax execute="@all" render="@all" disabled="true"/>
+                <f:ajax execute="@this" render="@all"/>
+            </h:inputText>
+        </h:form>
+    </body>
+</html>
diff --git a/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_3.xhtml b/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_3.xhtml
new file mode 100644
index 000000000..c62c04d2f
--- /dev/null
+++ b/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_3.xhtml
@@ -0,0 +1,34 @@
+<!--
+ * 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.
+ *
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:ui="http://java.sun.com/jsf/facelets"
+      xmlns:f="http://java.sun.com/jsf/core"
+      xmlns:h="http://java.sun.com/jsf/html">
+    <body>
+        <h:form id="form" >
+            <!-- Test three: First behavior rendered -->
+            <h:inputText id="input">
+                <f:ajax execute="@this" render="@all"/>
+                <f:ajax execute="@all" render="@all" disabled="true"/>
+            </h:inputText>
+        </h:form>
+    </body>
+</html>
diff --git a/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_4.xhtml b/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_4.xhtml
new file mode 100644
index 000000000..fddb36cd9
--- /dev/null
+++ b/impl/src/test/resources/org/apache/myfaces/renderkit/html/behavior/ajax_4.xhtml
@@ -0,0 +1,35 @@
+<!--
+ * 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.
+ *
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:ui="http://java.sun.com/jsf/facelets"
+      xmlns:f="http://java.sun.com/jsf/core"
+      xmlns:h="http://java.sun.com/jsf/html">
+    <body>
+        <h:form id="form" >
+            <!-- Test one: No behaviors rendered -->
+            <h:inputText id="input">
+                <f:ajax execute="@all" render="@all" disabled="false"/>
+                <f:ajax execute="@this" render="@all" disabled="false"/>
+            </h:inputText>
+            <br/>
+        </h:form>
+    </body>
+</html>