You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by jr...@apache.org on 2010/10/21 04:37:12 UTC
svn commit: r1025813 - in /wicket/trunk/wicket/src:
main/java/org/apache/wicket/ main/java/org/apache/wicket/request/cycle/
test/java/org/apache/wicket/request/cycle/
Author: jrthomerson
Date: Thu Oct 21 02:37:11 2010
New Revision: 1025813
URL: http://svn.apache.org/viewvc?rev=1025813&view=rev
Log:
fixes WICKET-3125
Added:
wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/BaseRequestHandlerStackTest.java
wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/RequestCycleListenerTest.java
Modified:
wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java
wicket/trunk/wicket/src/main/java/org/apache/wicket/request/cycle/RequestCycle.java
wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/RequestHandlerStackTest.java
Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java?rev=1025813&r1=1025812&r2=1025813&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java Thu Oct 21 02:37:11 2010
@@ -66,6 +66,7 @@ import org.apache.wicket.request.Request
import org.apache.wicket.request.Response;
import org.apache.wicket.request.component.IRequestablePage;
import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.cycle.RequestCycle.IRequestCycleListener;
import org.apache.wicket.request.cycle.RequestCycleContext;
import org.apache.wicket.request.mapper.CompoundRequestMapper;
import org.apache.wicket.request.mapper.ICompoundRequestMapper;
@@ -169,6 +170,8 @@ public abstract class Application implem
/** */
private List<IComponentOnAfterRenderListener> componentOnAfterRenderListeners;
+ private final List<IRequestCycleListener> requestCycleListeners = new ArrayList<IRequestCycleListener>();
+
/** root mapper */
private IRequestMapper rootRequestMapper;
@@ -1150,6 +1153,25 @@ public abstract class Application implem
}
/**
+ * Registers a listener to extend functionality in the {@link RequestCycle}.
+ *
+ * @param listener
+ */
+ public void addRequestCycleListener(IRequestCycleListener listener)
+ {
+ requestCycleListeners.add(listener);
+ }
+
+ /**
+ * @return the unmodifiable request list of {@link IRequestCycleListener}s in this application
+ */
+ public List<IRequestCycleListener> getRequestCycleListeners()
+ {
+ return Collections.unmodifiableList(requestCycleListeners);
+ }
+
+
+ /**
* Removes an {@link IComponentOnAfterRenderListener}.
*
* @param listener
Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/request/cycle/RequestCycle.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/request/cycle/RequestCycle.java?rev=1025813&r1=1025812&r2=1025813&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/request/cycle/RequestCycle.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/request/cycle/RequestCycle.java Thu Oct 21 02:37:11 2010
@@ -19,6 +19,7 @@ package org.apache.wicket.request.cycle;
import java.util.ArrayList;
import java.util.List;
+import org.apache.wicket.Application;
import org.apache.wicket.MetaDataEntry;
import org.apache.wicket.MetaDataKey;
import org.apache.wicket.Page;
@@ -87,6 +88,51 @@ public class RequestCycle extends Reques
}
/**
+ * A callback interface for various methods in the request cycle. If you are creating a
+ * framework that needs to do something in this methods, rather than extending RequestCycle or
+ * one of its subclasses, you should implement this callback and allow users to add your
+ * listener to their custom request cycle.
+ *
+ * These listeners can be added directly to the request cycle when it is created or to the
+ * {@link Application}
+ *
+ * @author Jeremy Thomerson
+ * @see Application#addRequestCycleListener(IRequestCycleListener)
+ * @see RequestCycle#register(IRequestCycleListener)
+ */
+ public interface IRequestCycleListener
+ {
+ /**
+ * Called when the request cycle object is beginning its response
+ */
+ void onBeginRequest();
+
+ /**
+ * Called when the request cycle object has finished its response
+ */
+ void onEndRequest();
+
+ /**
+ * Called when there is an exception in the request cycle that would normally be handled by
+ * {@link RequestCycle#handleException(Exception)}
+ *
+ * Note that in the event of an exception, {@link #onEndRequest()} will still be called
+ * after these listeners have {@link #onException(Exception)} called
+ *
+ * @param ex
+ * the exception that was passed in to
+ * {@link RequestCycle#handleException(Exception)}
+ */
+ void onException(Exception ex);
+ }
+
+ private interface IExecutor<T>
+ {
+
+ void execute(T object);
+ }
+
+ /**
* Returns request cycle associated with current thread.
*
* @return request cycle instance or <code>null</code> if no request cycle is associated with
@@ -116,6 +162,8 @@ public class RequestCycle extends Reques
private final List<DetachCallback> detachCallbacks = new ArrayList<DetachCallback>();
+ private final List<IRequestCycleListener> requestCycleListeners = new ArrayList<IRequestCycleListener>();
+
private UrlRenderer urlRenderer;
/** MetaDataEntry array. */
@@ -256,6 +304,13 @@ public class RequestCycle extends Reques
boolean result;
try
{
+ callRequestCycleListeners(new IExecutor<IRequestCycleListener>()
+ {
+ public void execute(IRequestCycleListener rcl)
+ {
+ rcl.onBeginRequest();
+ }
+ }, "onBeginRequest");
onBeginRequest();
result = processRequest();
}
@@ -266,6 +321,26 @@ public class RequestCycle extends Reques
return result;
}
+ private void callRequestCycleListeners(IExecutor<IRequestCycleListener> executor, String method)
+ {
+ List<IRequestCycleListener> app = Application.get().getRequestCycleListeners();
+ int size = requestCycleListeners.size() + app.size();
+ List<IRequestCycleListener> listeners = new ArrayList<IRequestCycleListener>(size);
+ listeners.addAll(app);
+ listeners.addAll(requestCycleListeners);
+ for (IRequestCycleListener rcl : listeners)
+ {
+ try
+ {
+ executor.execute(rcl);
+ }
+ catch (Exception ex)
+ {
+ log.error("Error executing " + method + " on IRequestCycleListener", ex);
+ }
+ }
+ }
+
/**
*
* @param handler
@@ -302,6 +377,13 @@ public class RequestCycle extends Reques
*/
protected IRequestHandler handleException(final Exception e)
{
+ callRequestCycleListeners(new IExecutor<RequestCycle.IRequestCycleListener>()
+ {
+ public void execute(IRequestCycleListener object)
+ {
+ object.onException(e);
+ }
+ }, "onException");
return exceptionMapper.map(e);
}
@@ -496,6 +578,13 @@ public class RequestCycle extends Reques
try
{
+ callRequestCycleListeners(new IExecutor<IRequestCycleListener>()
+ {
+ public void execute(IRequestCycleListener rcl)
+ {
+ rcl.onEndRequest();
+ }
+ }, "onEndRequest");
onEndRequest();
}
catch (RuntimeException e)
@@ -536,6 +625,16 @@ public class RequestCycle extends Reques
}
/**
+ * Registers a listener to extend functionality in the {@link RequestCycle}.
+ *
+ * @param listener
+ */
+ public void register(IRequestCycleListener listener)
+ {
+ requestCycleListeners.add(listener);
+ }
+
+ /**
* Convenience method for setting next page to be rendered.
*
* @param page
@@ -574,11 +673,22 @@ public class RequestCycle extends Reques
RenderPageRequestHandler.RedirectPolicy.AUTO_REDIRECT));
}
+ /**
+ * Gets whether or not feedback messages are to be cleaned up on detach.
+ *
+ * @return true if they are
+ */
public boolean isCleanupFeedbackMessagesOnDetach()
{
return cleanupFeedbackMessagesOnDetach;
}
+ /**
+ * Sets whether or not feedback messages should be cleaned up on detach.
+ *
+ * @param cleanupFeedbackMessagesOnDetach
+ * true if you want them to be cleaned up
+ */
public void setCleanupFeedbackMessagesOnDetach(boolean cleanupFeedbackMessagesOnDetach)
{
this.cleanupFeedbackMessagesOnDetach = cleanupFeedbackMessagesOnDetach;
Added: wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/BaseRequestHandlerStackTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/BaseRequestHandlerStackTest.java?rev=1025813&view=auto
==============================================================================
--- wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/BaseRequestHandlerStackTest.java (added)
+++ wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/BaseRequestHandlerStackTest.java Thu Oct 21 02:37:11 2010
@@ -0,0 +1,64 @@
+/*
+ * 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 junit.framework.TestCase;
+
+import org.apache.wicket.request.RequestHandlerStack;
+import org.apache.wicket.request.Response;
+
+/**
+ * @author Jeremy Thomerson
+ */
+public class BaseRequestHandlerStackTest extends TestCase
+{
+
+ protected Response newResponse()
+ {
+ return new Response()
+ {
+ @Override
+ public void write(byte[] array)
+ {
+ }
+
+ @Override
+ public void write(CharSequence sequence)
+ {
+ }
+
+ @Override
+ public String encodeURL(CharSequence url)
+ {
+ return null;
+ }
+ };
+ }
+
+ protected RequestHandlerStack newStack(Response response)
+ {
+ return new RequestHandlerStack(response)
+ {
+ @Override
+ protected RequestCycle getRequestCycle()
+ {
+ return null;
+ }
+ };
+ }
+
+}
Added: wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/RequestCycleListenerTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/RequestCycleListenerTest.java?rev=1025813&view=auto
==============================================================================
--- wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/RequestCycleListenerTest.java (added)
+++ wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/RequestCycleListenerTest.java Thu Oct 21 02:37:11 2010
@@ -0,0 +1,179 @@
+/*
+ * 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.Application;
+import org.apache.wicket.ThreadContext;
+import org.apache.wicket.mock.MockWebRequest;
+import org.apache.wicket.request.IExceptionMapper;
+import org.apache.wicket.request.IRequestCycle;
+import org.apache.wicket.request.IRequestHandler;
+import org.apache.wicket.request.IRequestMapper;
+import org.apache.wicket.request.Request;
+import org.apache.wicket.request.Response;
+import org.apache.wicket.request.Url;
+import org.apache.wicket.request.cycle.RequestCycle.IRequestCycleListener;
+import org.apache.wicket.resource.DummyApplication;
+
+/**
+ * @author Jeremy Thomerson
+ */
+public class RequestCycleListenerTest extends BaseRequestHandlerStackTest
+{
+ private int begins, ends, exceptions, exceptionsMapped, responses, detaches = 0;
+
+ private RequestCycle cycle;
+ private IRequestHandler handler;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ setupNewRequestCycle(false);
+ ThreadContext.setApplication(new DummyApplication());
+ }
+
+ private void setupNewRequestCycle(final boolean throwExceptionInRespond)
+ {
+ final Response originalResponse = newResponse();
+ Request request = new MockWebRequest(Url.parse("http://wicket.apache.org"));
+ handler = new IRequestHandler()
+ {
+ public void respond(IRequestCycle requestCycle)
+ {
+ if (throwExceptionInRespond)
+ {
+ throw new RuntimeException("testing purposes only");
+ }
+ responses++;
+ }
+
+ public void detach(IRequestCycle requestCycle)
+ {
+ detaches++;
+ }
+ };
+ IRequestMapper requestMapper = new IRequestMapper()
+ {
+ public IRequestHandler mapRequest(Request request)
+ {
+ return handler;
+ }
+
+ public Url mapHandler(IRequestHandler requestHandler)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getCompatibilityScore(Request request)
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ IExceptionMapper exceptionMapper = new IExceptionMapper()
+ {
+ public IRequestHandler map(Exception e)
+ {
+ exceptionsMapped++;
+ return null;
+ }
+ };
+ RequestCycleContext context = new RequestCycleContext(request, originalResponse,
+ requestMapper, exceptionMapper);
+ cycle = new RequestCycle(context);
+ }
+
+ /**
+ * @throws Exception
+ */
+ public void testBasicOperations() throws Exception
+ {
+ Application.get().addRequestCycleListener(newIncrementingListener());
+ assertValues(0, 0, 0, 0, 0, 0);
+ /*
+ * begins, ends, responses and detaches should increment by one because we have one listener
+ *
+ * exceptions should not increment because none are thrown
+ */
+ cycle.processRequestAndDetach();
+ assertValues(1, 1, 0, 0, 1, 1);
+
+ // TEST WITH TWO LISTENERS
+ setupNewRequestCycle(false);
+ cycle.register(newIncrementingListener());
+ /*
+ * we now have two listeners (app and cycle)
+ *
+ * begins and ends should increment by two (once for each listener)
+ *
+ * exceptions should not increment because none are thrown
+ *
+ * responses and detaches should increment by one
+ */
+ cycle.processRequestAndDetach();
+ assertValues(3, 3, 0, 0, 2, 2);
+
+ // TEST WITH TWO LISTENERS AND AN EXCEPTION DURING RESPONSE
+ setupNewRequestCycle(true);
+ cycle.register(newIncrementingListener());
+ /*
+ * begins and ends should increment by two (once for each listener)
+ *
+ * exceptions should increment by two (once for each listener)
+ *
+ * exceptionsMapped should increment by one
+ *
+ * responses should not increment because of the error
+ *
+ * detaches should increment by one
+ */
+ cycle.processRequestAndDetach();
+ assertValues(5, 5, 2, 1, 2, 3);
+ }
+
+ private void assertValues(int begins, int ends, int exceptions, int exceptionsMapped,
+ int responses, int detaches)
+ {
+ assertEquals(begins, this.begins);
+ assertEquals(ends, this.ends);
+ assertEquals(exceptions, this.exceptions);
+ assertEquals(exceptionsMapped, this.exceptionsMapped);
+ assertEquals(responses, this.responses);
+ assertEquals(detaches, this.detaches);
+ }
+
+ private IRequestCycleListener newIncrementingListener()
+ {
+ return new IRequestCycleListener()
+ {
+ public void onException(Exception ex)
+ {
+ exceptions++;
+ }
+
+ public void onEndRequest()
+ {
+ ends++;
+ }
+
+ public void onBeginRequest()
+ {
+ begins++;
+ }
+ };
+ }
+}
Modified: wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/RequestHandlerStackTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/RequestHandlerStackTest.java?rev=1025813&r1=1025812&r2=1025813&view=diff
==============================================================================
--- wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/RequestHandlerStackTest.java (original)
+++ wicket/trunk/wicket/src/test/java/org/apache/wicket/request/cycle/RequestHandlerStackTest.java Thu Oct 21 02:37:11 2010
@@ -16,8 +16,6 @@
*/
package org.apache.wicket.request.cycle;
-import junit.framework.TestCase;
-
import org.apache.wicket.request.IRequestCycle;
import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.RequestHandlerStack;
@@ -27,7 +25,7 @@ import org.apache.wicket.request.Respons
*
* @author Matej Knopp
*/
-public class RequestHandlerStackTest extends TestCase
+public class RequestHandlerStackTest extends BaseRequestHandlerStackTest
{
/**
@@ -37,40 +35,6 @@ public class RequestHandlerStackTest ext
{
}
- private Response newResponse()
- {
- return new Response()
- {
- @Override
- public void write(byte[] array)
- {
- }
-
- @Override
- public void write(CharSequence sequence)
- {
- }
-
- @Override
- public String encodeURL(CharSequence url)
- {
- return null;
- }
- };
- }
-
- private RequestHandlerStack newStack(Response response)
- {
- return new RequestHandlerStack(response)
- {
- @Override
- protected RequestCycle getRequestCycle()
- {
- return null;
- }
- };
- }
-
private boolean testFlag1;
private boolean testFlag2;
private boolean testFlag3;
@@ -268,7 +232,6 @@ public class RequestHandlerStackTest ext
assertTrue(detachedFlag4);
}
-
/**
*
*/
@@ -301,10 +264,10 @@ public class RequestHandlerStackTest ext
testFlag3 = false;
stack.scheduleRequestHandlerAfterCurrent(handler4);
- // make sure that handler4's respond method is fired after this one ends
+ // make sure that handler4's respond method is fired after this
+ // one ends
testFlag4 = false;
-
// code must be be reached
testFlag3 = true;
}