001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.request.cycle;
018
019import org.apache.wicket.Application;
020import org.apache.wicket.request.IRequestHandler;
021import org.apache.wicket.request.Url;
022
023/**
024 * A callback interface for various methods in the request cycle. If you are creating a framework
025 * that needs to do something in this methods, rather than extending RequestCycle or one of its
026 * subclasses, you should implement this callback and allow users to add your listener to their
027 * custom request cycle.
028 * <p>
029 * These listeners can be added directly to the request cycle when it is created or to the
030 * {@link Application}.
031 * <p>
032 * <b>NOTE</b>: a listener implementation is a singleton and hence needs to ensure proper handling
033 * of multi-threading issues.
034 * <p>
035 * Call order
036 * <p>
037 * The interface methods are ordered in the execution order as Wicket goes through the request
038 * cycle:
039 * </p>
040 * <ol>
041 * <li>{@link #onBeginRequest(RequestCycle)}</li>
042 * <li>{@link #onEndRequest(RequestCycle)}</li>
043 * <li>{@link #onDetach(RequestCycle)}</li>
044 * </ol>
045 * <p>
046 * The previous call sequence is valid for any Wicket request passing through the Wicket filter.
047 * Additionally when a request handler was resolved, a new handler scheduled, or an unhandled
048 * exception occurred during the request processing, any of the following can be called:
049 * </p>
050 * <ul>
051 * <li>{@link #onRequestHandlerResolved(RequestCycle, org.apache.wicket.request.IRequestHandler)}</li>
052 * <li>{@link #onRequestHandlerScheduled(RequestCycle, org.apache.wicket.request.IRequestHandler)}</li>
053 * <li>{@link #onException(RequestCycle, Exception)}, followed by
054 * {@link #onExceptionRequestHandlerResolved(RequestCycle, org.apache.wicket.request.IRequestHandler, Exception)} </li>
055 * </ul>
056 *
057 * <p>
058 * A short example of a request counter.
059 * </p>
060 * 
061 * <pre>
062 * public class RequestCounter implements IRequestCycleListener
063 * {
064 *      private AtomicLong counter = new AtomicLong(0);
065 * 
066 *      public void onBeginRequest(RequestCycle cycle)
067 *      {
068 *              counter.incrementAndGet();
069 *      }
070 * 
071 *      public long getRequestCount()
072 *      {
073 *              return counter.longValue();
074 *      }
075 * }
076 * 
077 * public class MyApplication extends WebApplication
078 * {
079 *      public void init()
080 *      {
081 *              super.init();
082 *              getRequestCycleListeners().add(new RequestCounter());
083 *      }
084 * }
085 * </pre>
086 * 
087 * @author Jeremy Thomerson
088 * @author Martijn Dashorst
089 * 
090 * @see org.apache.wicket.Application#getRequestCycleListeners()
091 */
092public interface IRequestCycleListener
093{
094        /**
095         * Called when the request cycle object is beginning its response
096         * 
097         * @param cycle
098         */
099        default void onBeginRequest(RequestCycle cycle)
100        {}
101
102        /**
103         * Called when the request cycle object has finished its response
104         * 
105         * @param cycle
106         */
107        default void onEndRequest(RequestCycle cycle)
108        {}
109
110        /**
111         * Called after the request cycle has been detached
112         * 
113         * @param cycle
114         */
115        default void onDetach(RequestCycle cycle)
116        {}
117
118        /**
119         * Called when an {@link IRequestHandler} is resolved and will be executed.
120         * 
121         * @param cycle
122         * 
123         * @param handler
124         */
125        default void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler)
126        {}
127
128        /**
129         * Called when a {@link IRequestHandler} has been scheduled. Can be called multiple times during
130         * a request when new handlers get scheduled for processing.
131         * 
132         * @param cycle
133         * @param handler
134         * @see RequestCycle#scheduleRequestHandlerAfterCurrent(IRequestHandler)
135         */
136        default void onRequestHandlerScheduled(RequestCycle cycle, IRequestHandler handler)
137        {}
138
139        /**
140         * Called when there is an exception in the request cycle that would normally be handled by
141         * {@link RequestCycle#handleException(Exception)}
142         * 
143         * Note that in the event of an exception, {@link #onEndRequest(RequestCycle)} will still be called after
144         * these listeners have {@link #onException(RequestCycle, Exception)} called
145         * <p>
146         * <strong>Important</strong>: Custom implementations are recommended to <strong>not</strong> try to
147         * handle exceptions implementing {@link org.apache.wicket.IWicketInternalException} interface.
148         * Usually such kind of exceptions should be handled by the framework.
149         * </p>
150         *
151         * @param cycle The current {@link RequestCycle request cycle}
152         * @param ex
153         *            the exception that was passed in to
154         *            {@link RequestCycle#handleException(Exception)}
155         * @return request handler that will be executed or {@code null} if none. If a request handler
156         *         is returned, it will override any configured
157         *         {@link Application#getExceptionMapperProvider() exception mapper}.
158         */
159        default IRequestHandler onException(RequestCycle cycle, Exception ex)
160        {
161                return null;
162        }
163
164        /**
165         * Called when an {@link IRequestHandler} is resolved for an exception and will be executed.
166         * 
167         * @param cycle
168         * @param handler
169         * @param exception
170         */
171        default void onExceptionRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler,
172                Exception exception)
173        {}
174
175        /**
176         * Called after an {@link IRequestHandler} has been executed. If the execution resulted in an
177         * exception this method will not be called for that particular {@link IRequestHandler}.
178         * 
179         * @param cycle
180         * @param handler
181         */
182        default void onRequestHandlerExecuted(RequestCycle cycle, IRequestHandler handler)
183        {}
184
185        /**
186         * Called after a Url is generated for a {@link IRequestHandler}. This method can be used to
187         * modify generated urls, for example query parameters can be added.
188         * 
189         * @param cycle
190         * @param handler
191         * @param url
192         */
193        default void onUrlMapped(RequestCycle cycle, IRequestHandler handler, Url url)
194        {}
195}