Updated Branches: refs/heads/wicket-1.5.x 76cdc84ca -> cfe75499a
WICKET-4468 Stateful components which are invisible force page to be stateful Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/cfe75499 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/cfe75499 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/cfe75499 Branch: refs/heads/wicket-1.5.x Commit: cfe75499a7607c11e1aa4463cdf1779eb6da1bc5 Parents: 76cdc84 Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Mon Mar 26 12:00:03 2012 +0200 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Mon Mar 26 12:01:23 2012 +0200 ---------------------------------------------------------------------- .../src/main/java/org/apache/wicket/Component.java | 15 ++++- .../java/org/apache/wicket/behavior/Behavior.java | 4 +- .../org/apache/wicket/markup/html/image/Image.java | 2 +- .../test/java/org/apache/wicket/ComponentTest.java | 59 +++++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/cfe75499/wicket-core/src/main/java/org/apache/wicket/Component.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/Component.java b/wicket-core/src/main/java/org/apache/wicket/Component.java index ac48d28..60fce2b 100644 --- a/wicket-core/src/main/java/org/apache/wicket/Component.java +++ b/wicket-core/src/main/java/org/apache/wicket/Component.java @@ -2078,6 +2078,18 @@ public abstract class Component return false; } + if ( + // the component is either invisible or disabled + (isVisibleInHierarchy() && isEnabledInHierarchy()) == false && + + // and it can't call listener interfaces + canCallListenerInterface(null) == false + ) + { + // then pretend the component is stateless + return true; + } + for (Behavior behavior : getBehaviors()) { if (!behavior.getStatelessHint(this)) @@ -4431,7 +4443,8 @@ public abstract class Component * </p> * * @param method - * listener method about to be invoked on this component + * listener method about to be invoked on this component. Could be {@code null} - in this + * case it means <em>any</em> method. * * @return {@literal true} iff the listener method can be invoked on this component */ http://git-wip-us.apache.org/repos/asf/wicket/blob/cfe75499/wicket-core/src/main/java/org/apache/wicket/behavior/Behavior.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/behavior/Behavior.java b/wicket-core/src/main/java/org/apache/wicket/behavior/Behavior.java index 366c176..7f7b160 100644 --- a/wicket-core/src/main/java/org/apache/wicket/behavior/Behavior.java +++ b/wicket-core/src/main/java/org/apache/wicket/behavior/Behavior.java @@ -122,7 +122,9 @@ public abstract class Behavior } /** - * In case an unexpected exception happened anywhere between onComponentTag() and rendered(), + * In case an unexpected exception happened anywhere between + * {@linkplain #onComponentTag(org.apache.wicket.Component, org.apache.wicket.markup.ComponentTag)} and + * {@linkplain #afterRender(org.apache.wicket.Component)}, * onException() will be called for any behavior. Typically, if you clean up resources in * {@link #afterRender(Component)}, you should do the same in the implementation of this method. * http://git-wip-us.apache.org/repos/asf/wicket/blob/cfe75499/wicket-core/src/main/java/org/apache/wicket/markup/html/image/Image.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/image/Image.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/image/Image.java index b41bec9..b7f78a8 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/html/image/Image.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/image/Image.java @@ -296,7 +296,7 @@ public class Image extends WebComponent implements IResourceListener @Override public boolean canCallListenerInterface(Method method) { - boolean isResource = IResourceListener.class.isAssignableFrom(method.getDeclaringClass()); + boolean isResource = method != null && IResourceListener.class.isAssignableFrom(method.getDeclaringClass()); if (isResource && isVisibleInHierarchy()) { // when the image data is requested we do not care if this component is enabled in http://git-wip-us.apache.org/repos/asf/wicket/blob/cfe75499/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java b/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java index 04f5d06..f0961ef 100644 --- a/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/ComponentTest.java @@ -16,7 +16,12 @@ */ package org.apache.wicket; +import java.lang.reflect.Method; + import org.apache.wicket.ajax.AjaxEventBehavior; +import org.apache.wicket.behavior.Behavior; +import org.apache.wicket.markup.html.WebComponent; +import org.apache.wicket.markup.html.WebMarkupContainer; import org.junit.Test; /** @@ -89,4 +94,58 @@ public class ComponentTest extends WicketTestCase { executeTest(TestPage_1.class, "TestPageExpectedResult_1.html"); } + + /** + * https://issues.apache.org/jira/browse/WICKET-4468 + * + * Verifies that a stateful component can pretend to be stateless if both conditions are + * fulfilled: + * <ol> + * <li>it is either invisible or disabled (or both)</li> + * <li>it cannot call any listener interface method while invisible/disabled</li> + * </ol> + */ + @Test + public void isStateless() + { + Behavior statefulBehavior = new Behavior() + { + @Override + public boolean getStatelessHint(Component component) + { + return false; + } + }; + + WebComponent component = new WebComponent("someId"); + + // by default every component is stateless + assertTrue(component.isStateless()); + + // make the component stateful + component.add(statefulBehavior); + assertFalse(component.isStateless()); + + // invisible component cannot be requested by default so it + // can pretend being stateless + component.setVisible(false); + assertTrue(component.isStateless()); + + // same for disabled component + component.setVisible(true).setEnabled(false); + assertTrue(component.isStateless()); + + // make the component such that it can call listener interface + // methods no matter whether it is visible or enabled + component = new WebComponent("someId") { + @Override + public boolean canCallListenerInterface(Method method) + { + return true; + } + }; + component.add(statefulBehavior); + component.setVisible(false); + assertFalse(component.isStateless()); + } }
