Author: jrthomerson
Date: Tue Mar 24 04:44:20 2009
New Revision: 757661
URL: http://svn.apache.org/viewvc?rev=757661&view=rev
Log:
Added a contribution by Marat Radchenko to help with stateless page development
Issue: WICKET-2170
Added:
wicket/trunk/wicket/src/main/java/org/apache/wicket/annotations/
wicket/trunk/wicket/src/main/java/org/apache/wicket/annotations/StatelessChecker.java
wicket/trunk/wicket/src/main/java/org/apache/wicket/annotations/StatelessComponent.java
wicket/trunk/wicket/src/test/java/org/apache/wicket/annotations/
wicket/trunk/wicket/src/test/java/org/apache/wicket/annotations/StatelessCheckerTest.java
Added:
wicket/trunk/wicket/src/main/java/org/apache/wicket/annotations/StatelessChecker.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/annotations/StatelessChecker.java?rev=757661&view=auto
==============================================================================
---
wicket/trunk/wicket/src/main/java/org/apache/wicket/annotations/StatelessChecker.java
(added)
+++
wicket/trunk/wicket/src/main/java/org/apache/wicket/annotations/StatelessChecker.java
Tue Mar 24 04:44:20 2009
@@ -0,0 +1,117 @@
+/*
+ * 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.wicket.annotations;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.Page;
+import org.apache.wicket.Component.IVisitor;
+import org.apache.wicket.application.IComponentOnBeforeRenderListener;
+
+/**
+ * Stateless checker. Checks if components with {...@link StatelessComponent}
annotation are really
+ * stateless. This is a utility that is intended for use primarily during
development. If you add an
+ * instance of this class to your application, it will check all components or
pages marked with the
+ * <tt>StatelessComponent</tt> annotation to make sure that they are stateless
as you intended.
+ *
+ * This is useful when trying to maintain stateless pages since it is very
easy to inadvertantly add
+ * a component to a page that internally uses stateful links, etc.
+ *
+ * @author Marat Radchenko
+ * @see StatelessComponent
+ */
+public class StatelessChecker implements IComponentOnBeforeRenderListener
+{
+ /**
+ * Returns <code>true</code> if checker must check given component,
<code>false</code>
+ * otherwise.
+ *
+ * @param component
+ * component to check.
+ * @return <code>true</code> if checker must check given component.
+ */
+ private static boolean mustCheck(final Component component)
+ {
+ final StatelessComponent ann =
component.getClass().getAnnotation(StatelessComponent.class);
+ return ann != null && ann.enabled();
+ }
+
+ /**
+ * @see
org.apache.wicket.application.IComponentOnBeforeRenderListener#onBeforeRender(org.apache.wicket.Component)
+ */
+ public void onBeforeRender(final Component component)
+ {
+ if (StatelessChecker.mustCheck(component))
+ {
+ final IVisitor<Component> visitor = new
Component.IVisitor<Component>()
+ {
+ public Object component(final Component comp)
+ {
+ if (component instanceof Page &&
StatelessChecker.mustCheck(comp))
+ {
+ // Do not go deeper, because
this component will be checked by checker
+ // itself.
+ // Actually we could go deeper
but that would mean we traverse it twice
+ // (for current component and
for inspected one).
+ // We go deeper for Page
because full tree will be inspected during
+ // isPageStateless call.
+ return
IVisitor.CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER;
+ }
+ else if (!comp.isStateless())
+ {
+ return comp;
+ }
+ else
+ {
+ return
IVisitor.CONTINUE_TRAVERSAL;
+ }
+ }
+ };
+
+ final String msg = "'" + component + "' claims to be
stateless but isn't.";
+ if (!component.isStateless())
+ {
+ throw new IllegalArgumentException(msg +
+ " Possible reasons: no stateless hint,
statefull behaviors");
+ }
+
+ if (component instanceof MarkupContainer)
+ {
+ // Traverse children
+ final Object o =
((MarkupContainer)component).visitChildren(visitor);
+ if (o == null)
+ {
+ throw new IllegalArgumentException(msg
+ " Offending component: " + o);
+ }
+ }
+
+ if (component instanceof Page)
+ {
+ final Page p = (Page)component;
+ if (!p.isBookmarkable())
+ {
+ throw new IllegalArgumentException(msg +
+ " Only bookmarkable pages can
be stateless");
+ }
+ if (!p.isPageStateless())
+ {
+ throw new IllegalArgumentException(msg
+ " for unknown reason");
+ }
+ }
+ }
+ }
+}
Added:
wicket/trunk/wicket/src/main/java/org/apache/wicket/annotations/StatelessComponent.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/annotations/StatelessComponent.java?rev=757661&view=auto
==============================================================================
---
wicket/trunk/wicket/src/main/java/org/apache/wicket/annotations/StatelessComponent.java
(added)
+++
wicket/trunk/wicket/src/main/java/org/apache/wicket/annotations/StatelessComponent.java
Tue Mar 24 04:44:20 2009
@@ -0,0 +1,49 @@
+/*
+ * 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.wicket.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for wicket components that you want to be sure remain stateless
during the development
+ * cycle. Can be attached to pages and components.
+ *
+ * <b>Note:</b> this annotation <u><i>does not</i></u> make the component
stateless or affect it's
+ * statelessness in any way. This annotation should be used in combination with
+ * <tt>StatelessChecker</tt> to give you runtime warning if you inadvertantly
made a page or
+ * component stateful.
+ *
+ * @author Marat Radchenko
+ * @see StatelessChecker
+ */
+...@documented
+...@retention(RetentionPolicy.RUNTIME)
+...@target(ElementType.TYPE)
+...@inherited
+public @interface StatelessComponent {
+
+ /**
+ * Can be set to <code>false</code> to disable stateless (this is
useful if stateful component
+ * inherits from stateless one).
+ */
+ boolean enabled() default true;
+}
Added:
wicket/trunk/wicket/src/test/java/org/apache/wicket/annotations/StatelessCheckerTest.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/annotations/StatelessCheckerTest.java?rev=757661&view=auto
==============================================================================
---
wicket/trunk/wicket/src/test/java/org/apache/wicket/annotations/StatelessCheckerTest.java
(added)
+++
wicket/trunk/wicket/src/test/java/org/apache/wicket/annotations/StatelessCheckerTest.java
Tue Mar 24 04:44:20 2009
@@ -0,0 +1,99 @@
+/*
+ * 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.wicket.annotations;
+
+import junit.framework.TestCase;
+
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.util.tester.DummyHomePage;
+import org.apache.wicket.util.tester.WicketTester;
+
+/**
+ * @author Marat Radchenko
+ */
+public class StatelessCheckerTest extends TestCase
+{
+ /**
+ *
+ */
+ @StatelessComponent
+ public static class StatelessPage extends DummyHomePage
+ {
+ }
+
+ /**
+ *
+ */
+ @StatelessComponent
+ private static class StatelessLabel extends Label
+ {
+ private static final long serialVersionUID = 1L;
+
+ public StatelessLabel(final String id)
+ {
+ super(id);
+ }
+ }
+
+ private final StatelessChecker checker = new StatelessChecker();
+ private WicketTester tester;
+
+ /**
+ * @see junit.framework.TestCase#setUp()
+ */
+ @Override
+ public void setUp()
+ {
+ tester = new WicketTester();
+ }
+
+ /**
+ * @see junit.framework.TestCase#tearDown()
+ */
+ @Override
+ public void tearDown()
+ {
+ tester.destroy();
+ }
+
+ /**
+ *
+ */
+ public void testNonBookmarkablePage()
+ {
+ boolean hit = false;
+ try
+ {
+
tester.getApplication().addPostComponentOnBeforeRenderListener(checker);
+ tester.startPage(StatelessPage.class);
+ }
+ catch (IllegalArgumentException ex)
+ {
+ hit = true;
+ }
+ assertTrue("Expected exception", hit);
+ }
+
+ /**
+ *
+ */
+ public void testPositive()
+ {
+
tester.getApplication().addPostComponentOnBeforeRenderListener(checker);
+ tester.startComponent(new StatelessLabel("foo"));
+ }
+}