You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by da...@apache.org on 2011/04/19 14:31:36 UTC
svn commit: r1095061 - in /wicket/trunk:
wicket-core/src/main/java/org/apache/wicket/request/cycle/
wicket-core/src/test/java/org/apache/wicket/request/cycle/
wicket-util/src/main/java/org/apache/wicket/util/listener/
Author: dashorst
Date: Tue Apr 19 12:31:35 2011
New Revision: 1095061
URL: http://svn.apache.org/viewvc?rev=1095061&view=rev
Log:
Fixes WICKET-3625 Order of IRequestCycleListener invocations
Added:
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderApplication.java
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderPage.html
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderPage.java
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderTest.java
Modified:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/AbstractRequestCycleListener.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/IRequestCycleListener.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/RequestCycleListenerCollection.java
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/listener/ListenerCollection.java
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/AbstractRequestCycleListener.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/AbstractRequestCycleListener.java?rev=1095061&r1=1095060&r2=1095061&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/AbstractRequestCycleListener.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/AbstractRequestCycleListener.java Tue Apr 19 12:31:35 2011
@@ -24,27 +24,23 @@ import org.apache.wicket.request.IReques
*/
public abstract class AbstractRequestCycleListener implements IRequestCycleListener
{
- public void onRequestHandlerScheduled(IRequestHandler handler)
- {
- }
-
public void onBeginRequest(RequestCycle cycle)
{
}
- public void onRequestHandlerResolved(IRequestHandler handler)
+ public void onEndRequest(RequestCycle cycle)
{
}
- public void onEndRequest(RequestCycle cycle)
+ public void onDetach(RequestCycle cycle)
{
}
- public void onDetach(RequestCycle cycle)
+ public void onRequestHandlerScheduled(IRequestHandler handler)
{
}
- public void onExceptionRequestHandlerResolved(IRequestHandler handler, Exception exception)
+ public void onRequestHandlerResolved(IRequestHandler handler)
{
}
@@ -52,4 +48,8 @@ public abstract class AbstractRequestCyc
{
return null;
}
+
+ public void onExceptionRequestHandlerResolved(IRequestHandler handler, Exception exception)
+ {
+ }
}
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/IRequestCycleListener.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/IRequestCycleListener.java?rev=1095061&r1=1095060&r2=1095061&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/IRequestCycleListener.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/IRequestCycleListener.java Tue Apr 19 12:31:35 2011
@@ -32,34 +32,72 @@ import org.apache.wicket.request.IReques
* of multi-threading issues.
* <p>
* <h3>Call order</h3>
+ * <p>
* The interface methods are ordered in the execution order as Wicket goes through the request
* cycle:
+ * </p>
* <ol>
- * <li>{@link #onRequestHandlerScheduled(IRequestHandler)}</li>
* <li>{@link #onBeginRequest(RequestCycle)}</li>
- * <li>{@link #onRequestHandlerResolved(IRequestHandler)}</li>
* <li>{@link #onEndRequest(RequestCycle)}</li>
* <li>{@link #onDetach(RequestCycle)}</li>
* </ol>
- * <h3>Exception handling</h3>
- * When an exception occurs during request processing, the following call sequence is maintained:
- * <ol>
- * <li>{@link #onExceptionRequestHandlerResolved(IRequestHandler, Exception)}</li>
- * <li>{@link #onException(RequestCycle, Exception)}</li>
- * </ol>
+ * <p>
+ * The previous call sequence is valid for any Wicket request passing through the Wicket filter.
+ * Additionally when a request handler was resolved, a new handler scheduled, or an unhandled
+ * exception occurred during the request processing, any of the following can be called:
+ * </p>
+ * <ul>
+ * <li>{@link #onRequestHandlerResolved(IRequestHandler)}</li>
+ * <li>{@link #onRequestHandlerScheduled(IRequestHandler)}</li>
+ * <li>{@link #onException(RequestCycle, Exception)}, followed by
+ * {@link #onExceptionRequestHandlerResolved(IRequestHandler, Exception)}</li>
+ * </ul>
+ *
+ * <h3>Implementing your own</h3>
+ * <p>
+ * Use {@link AbstractRequestCycleListener} for a default, empty implementation as a base class.
+ * </p>
+ *
+ * <h3>Example</h3>
+ * <p>
+ * A short example of a request counter.
+ * </p>
+ *
+ * <pre>
+ * public class RequestCounter extends AbstractRequestCycleListener
+ * {
+ * private AtomicLong counter = new AtomicLong(0);
+ *
+ * public void onBeginRequest(RequestCycle cycle)
+ * {
+ * counter.incrementAndGet();
+ * }
+ *
+ * public long getRequestCount()
+ * {
+ * return counter.longValue();
+ * }
+ * }
+ *
+ * public class MyApplication extends WebApplication
+ * {
+ * public void init()
+ * {
+ * super.init();
+ * getRequestCycleListeners().add(new RequestCounter());
+ * }
+ * }
+ * </pre>
*
* @author Jeremy Thomerson
+ * @author Martijn Dashorst
+ *
+ * @see AbstractRequestCycleListener
* @see Application#addRequestCycleListener(IRequestCycleListener)
- * @see RequestCycle#register(IRequestCycleListener)
*/
public interface IRequestCycleListener
{
/**
- * @param handler
- */
- void onRequestHandlerScheduled(IRequestHandler handler);
-
- /**
* Called when the request cycle object is beginning its response
*
* @param cycle
@@ -67,14 +105,6 @@ public interface IRequestCycleListener
void onBeginRequest(RequestCycle cycle);
/**
- * Called when an {@link IRequestHandler} is resolved and will be executed.
- *
- * @param handler
- */
- void onRequestHandlerResolved(IRequestHandler handler);
-
-
- /**
* Called when the request cycle object has finished its response
*
* @param cycle
@@ -89,12 +119,20 @@ public interface IRequestCycleListener
void onDetach(RequestCycle cycle);
/**
- * Called when an {@link IRequestHandler} is resolved for an exception and will be executed.
+ * Called when an {@link IRequestHandler} is resolved and will be executed.
*
* @param handler
- * @param exception
*/
- void onExceptionRequestHandlerResolved(IRequestHandler handler, Exception exception);
+ void onRequestHandlerResolved(IRequestHandler handler);
+
+ /**
+ * Called when a {@link IRequestHandler} has been scheduled. Can be called multiple times during
+ * a request when new handlers get scheduled for processing.
+ *
+ * @param handler
+ * @see RequestCycle#scheduleRequestHandlerAfterCurrent(IRequestHandler)
+ */
+ void onRequestHandlerScheduled(IRequestHandler handler);
/**
* Called when there is an exception in the request cycle that would normally be handled by
@@ -105,7 +143,7 @@ public interface IRequestCycleListener
*
* @param cycle
*
- * @return request handler that will be exectued or {@code null} if none. If a request handler
+ * @return request handler that will be executed or {@code null} if none. If a request handler
* is returned, it will override any configured exception mapper
*
* @param ex
@@ -114,4 +152,11 @@ public interface IRequestCycleListener
*/
IRequestHandler onException(RequestCycle cycle, Exception ex);
-}
\ No newline at end of file
+ /**
+ * Called when an {@link IRequestHandler} is resolved for an exception and will be executed.
+ *
+ * @param handler
+ * @param exception
+ */
+ void onExceptionRequestHandlerResolved(IRequestHandler handler, Exception exception);
+}
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/RequestCycleListenerCollection.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/RequestCycleListenerCollection.java?rev=1095061&r1=1095060&r2=1095061&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/RequestCycleListenerCollection.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/cycle/RequestCycleListenerCollection.java Tue Apr 19 12:31:35 2011
@@ -48,7 +48,7 @@ public class RequestCycleListenerCollect
public void onEndRequest(final RequestCycle cycle)
{
- notify(new INotifier<IRequestCycleListener>()
+ reversedNotify(new INotifier<IRequestCycleListener>()
{
public void notify(IRequestCycleListener listener)
{
@@ -90,7 +90,7 @@ public class RequestCycleListenerCollect
public void onDetach(final RequestCycle cycle)
{
- notify(new INotifier<IRequestCycleListener>()
+ reversedNotify(new INotifier<IRequestCycleListener>()
{
public void notify(IRequestCycleListener listener)
{
Added: wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderApplication.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderApplication.java?rev=1095061&view=auto
==============================================================================
--- wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderApplication.java (added)
+++ wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderApplication.java Tue Apr 19 12:31:35 2011
@@ -0,0 +1,92 @@
+/*
+ * 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.request.cycle;
+
+import java.util.ArrayList;
+
+import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.request.IRequestHandler;
+
+class MultiRequestCycleListenerCallOrderApplication extends WebApplication
+{
+ @Override
+ public Class<MultiRequestCycleListenerCallOrderPage> getHomePage()
+ {
+ return MultiRequestCycleListenerCallOrderPage.class;
+ }
+
+ @Override
+ public void init()
+ {
+ super.init();
+
+ getRequestCycleListeners().add(new CallRecordingListener("first"));
+ getRequestCycleListeners().add(new CallRecordingListener("second"));
+ }
+
+ public final ArrayList<String> callSequence = new ArrayList<String>();
+
+ /**
+ * Records calls to each method in the {@code callSequence}.
+ */
+ class CallRecordingListener implements IRequestCycleListener
+ {
+ private String name;
+
+ public CallRecordingListener(String name)
+ {
+ this.name = name;
+ }
+
+ public void onBeginRequest(RequestCycle cycle)
+ {
+ callSequence.add(name + ".onBeginRequest");
+ }
+
+ public void onRequestHandlerScheduled(IRequestHandler handler)
+ {
+ if (handler != null)
+ callSequence.add(name + ".onRequestHandlerScheduled");
+ }
+
+ public void onRequestHandlerResolved(IRequestHandler handler)
+ {
+ callSequence.add(name + ".onRequestHandlerResolved");
+ }
+
+ public void onEndRequest(RequestCycle cycle)
+ {
+ callSequence.add(name + ".onEndRequest");
+ }
+
+ public void onDetach(RequestCycle cycle)
+ {
+ callSequence.add(name + ".onDetach");
+ }
+
+ public void onExceptionRequestHandlerResolved(IRequestHandler handler, Exception exception)
+ {
+ callSequence.add(name + ".onExceptionRequestHandlerResolved");
+ }
+
+ public IRequestHandler onException(RequestCycle cycle, Exception ex)
+ {
+ callSequence.add(name + ".onException");
+ return null;
+ }
+ }
+}
Added: wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderPage.html
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderPage.html?rev=1095061&view=auto
==============================================================================
--- wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderPage.html (added)
+++ wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderPage.html Tue Apr 19 12:31:35 2011
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ </head>
+ <body>
+ </body>
+</html>
Added: wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderPage.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderPage.java?rev=1095061&view=auto
==============================================================================
--- wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderPage.java (added)
+++ wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderPage.java Tue Apr 19 12:31:35 2011
@@ -0,0 +1,28 @@
+/*
+ * 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.request.cycle;
+
+import org.apache.wicket.markup.html.WebPage;
+
+class MultiRequestCycleListenerCallOrderPage extends WebPage
+{
+ private static final long serialVersionUID = 1L;
+
+ public MultiRequestCycleListenerCallOrderPage()
+ {
+ }
+}
Added: wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderTest.java?rev=1095061&view=auto
==============================================================================
--- wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderTest.java (added)
+++ wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/cycle/MultiRequestCycleListenerCallOrderTest.java Tue Apr 19 12:31:35 2011
@@ -0,0 +1,59 @@
+/*
+ * 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.request.cycle;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import org.apache.wicket.util.tester.WicketTester;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Checks whether multiple registered requestcycle listeners are called in the right order:
+ * similarly to servlet filters.
+ */
+@SuppressWarnings("javadoc")
+public class MultiRequestCycleListenerCallOrderTest
+{
+ private WicketTester tester;
+ private MultiRequestCycleListenerCallOrderApplication application;
+
+ @Before
+ public void setUp()
+ {
+ application = new MultiRequestCycleListenerCallOrderApplication();
+ tester = new WicketTester(application);
+ }
+
+ @Test
+ public void callSequenceIsFirstInLastOut()
+ {
+ // start and render the test page
+ tester.startPage(new MultiRequestCycleListenerCallOrderPage());
+ // assert rendered page class
+ tester.assertRenderedPage(MultiRequestCycleListenerCallOrderPage.class);
+
+ assertThat(
+ application.callSequence,
+ is(equalTo(asList("first.onBeginRequest", "second.onBeginRequest",
+ "first.onRequestHandlerResolved", "second.onRequestHandlerResolved",
+ "second.onEndRequest", "first.onEndRequest", "second.onDetach", "first.onDetach"))));
+ }
+}
Modified: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/listener/ListenerCollection.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/listener/ListenerCollection.java?rev=1095061&r1=1095060&r2=1095061&view=diff
==============================================================================
--- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/listener/ListenerCollection.java (original)
+++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/listener/ListenerCollection.java Tue Apr 19 12:31:35 2011
@@ -102,6 +102,27 @@ public abstract class ListenerCollection
}
/**
+ * Notifies each listener in this in reversed order
+ *
+ * @param notifier
+ * notifier used to notify each listener
+ */
+ protected void reversedNotify(final INotifier<T> notifier)
+ {
+ reversedNotify(iterator(), notifier);
+ }
+
+ private void reversedNotify(Iterator<T> iterator, final INotifier<T> notifier)
+ {
+ if (iterator.hasNext())
+ {
+ T listener = iterator.next();
+ reversedNotify(iterator, notifier);
+ notifier.notify(listener);
+ }
+ }
+
+ /**
* Removes a listener from this set.
*
* @param listener