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>