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: */
017: package org.apache.wicket.settings;
018:
019: import java.util.List;
020:
021: import org.apache.wicket.IResponseFilter;
022: import org.apache.wicket.RequestCycle;
023: import org.apache.wicket.Session;
024: import org.apache.wicket.markup.html.pages.BrowserInfoPage;
025: import org.apache.wicket.protocol.http.WebRequestCycle;
026: import org.apache.wicket.settings.IExceptionSettings.UnexpectedExceptionDisplay;
027: import org.apache.wicket.util.lang.EnumeratedType;
028: import org.apache.wicket.util.time.Duration;
029:
030: /**
031: * Interface for request related settings
032: * <p>
033: * <i>bufferResponse </i> (defaults to true) - True if the application should
034: * buffer responses. This does require some additional memory, but helps keep
035: * exception displays accurate because the whole rendering process completes
036: * before the page is sent to the user, thus avoiding the possibility of a
037: * partially rendered page.
038: * <p>
039: * <i>renderStrategy </i>- Sets in what way the render part of a request is
040: * handled. Basically, there are two different options:
041: * <ul>
042: * <li>Direct, ApplicationSettings.ONE_PASS_RENDER. Everything is handled in
043: * one physical request. This is efficient, and is the best option if you want
044: * to do sophisticated clustering. It does not however, shield you from what is
045: * commonly known as the <i>Double submit problem </i></li>
046: * <li>Using a redirect. This follows the pattern <a
047: * href="http://www.theserverside.com/articles/article.tss?l=RedirectAfterPost"
048: * >as described at the serverside </a> and that is commonly known as Redirect
049: * after post. Wicket takes it one step further to do any rendering after a
050: * redirect, so that not only form submits are shielded from the double submit
051: * problem, but also the IRequestListener handlers (that could be e.g. a link
052: * that deletes a row). With this pattern, you have two options to choose from:
053: * <ul>
054: * <li>ApplicationSettings.REDIRECT_TO_RENDER. This option first handles the
055: * 'action' part of the request, which is either page construction (bookmarkable
056: * pages or the home page) or calling a IRequestListener handler, such as
057: * Link.onClick. When that part is done, a redirect is issued to the render
058: * part, which does all the rendering of the page and its components. <strong>Be
059: * aware </strong> that this may mean, depending on whether you access any
060: * models in the action part of the request, that attachement and detachement of
061: * some models is done twice for a request.</li>
062: * <li>ApplicationSettings.REDIRECT_TO_BUFFER. This option handles both the
063: * action- and the render part of the request in one physical request, but
064: * instead of streaming the result to the browser directly, it is kept in
065: * memory, and a redirect is issue to get this buffered result (after which it
066: * is immediately removed). This option currently is the default render
067: * strategy, as it shields you from the double submit problem, while being more
068: * efficient and less error prone regarding to detachable models.</li>
069: * </ul>
070: * </li>
071: * </ul>
072: * Note that this parameter sets the default behavior, but that you can manually
073: * set whether any redirecting is done by calling method
074: * RequestCycle.setRedirect. Setting the redirect flag when the application is
075: * configured to use ONE_PASS_RENDER, will result in a redirect of type
076: * REDIRECT_TO_RENDER. When the application is configured to use
077: * REDIRECT_TO_RENDER or REDIRECT_TO_BUFFER, setting the redirect flag to false,
078: * will result in that request begin rendered and streamed in one pass.
079: * <p>
080: * More documentation is available about each setting in the setter method for
081: * the property.
082: *
083: * @author Igor Vaynberg (ivaynberg)
084: */
085: public interface IRequestCycleSettings {
086: /**
087: * Enumerated type for different ways of handling the render part of
088: * requests.
089: */
090: public static class RenderStrategy extends EnumeratedType {
091: private static final long serialVersionUID = 1L;
092:
093: RenderStrategy(final String name) {
094: super (name);
095: }
096: }
097:
098: /**
099: * All logical parts of a request (the action and render part) are handled
100: * within the same request. To enable a the client side redirect for a
101: * request, users can set the 'redirect' property of {@link RequestCycle}to
102: * true (getRequestCycle.setRedirect(true)), after which the behavior will
103: * be like RenderStragegy 'REDIRECT_TO_RENDER'.
104: * <p>
105: * This strategy is more efficient than the 'REDIRECT_TO_RENDER' strategy,
106: * and doesn't have some of the potential problems of it, it also does not
107: * solve the double submit problem. It is however the best option to use
108: * when you want to do sophisticated (non-sticky session) clustering.
109: * </p>
110: */
111: public static final IRequestCycleSettings.RenderStrategy ONE_PASS_RENDER = new IRequestCycleSettings.RenderStrategy(
112: "ONE_PASS_RENDER");
113:
114: /**
115: * All logical parts of a request (the action and render part) are handled
116: * within the same request, but instead of streaming the render result to
117: * the browser directly, the result is cached on the server. A client side
118: * redirect command is issued to the browser specifically to render this
119: * request.
120: */
121: public static final IRequestCycleSettings.RenderStrategy REDIRECT_TO_BUFFER = new IRequestCycleSettings.RenderStrategy(
122: "REDIRECT_BUFFER");
123:
124: /**
125: * The render part of a request (opposed to the 'action part' which is
126: * either the construction of a bookmarkable page or the execution of a
127: * IRequestListener handler) is handled by a seperate request by issueing a
128: * redirect request to the browser. This is commonly known as the 'redirect
129: * after submit' pattern, though in our case, we use it for GET and POST
130: * requests instead of just the POST requests. To cancel the client side
131: * redirect for a request, users can set the 'redirect' property of
132: * {@link RequestCycle}to false (getRequestCycle.setRedirect(false)).
133: * <p>
134: * This pattern solves the 'refresh' problem. While it is a common feature
135: * of browsers to refresh/ reload a web page, this results in problems in
136: * many dynamic web applications. For example, when you have a link with an
137: * event handler that e.g. deletes a row from a list, you usually want to
138: * ignore refresh requests after that link is clicked on. By using this
139: * strategy, the refresh request only results in the re-rendering of the
140: * page without executing the event handler again.
141: * </p>
142: * <p>
143: * Though it solves the refresh problem, it introduces potential problems,
144: * as the request that is logically one, are actually two seperate request.
145: * Not only is this less efficient, but this also can mean that within the
146: * same request attachement/ detachement of models is done twice (in case
147: * you use models in the bookmarkable page constructors and IRequestListener
148: * handlers). If you use this strategy, you should be aware of this
149: * possibily, and should also be aware that for one logical request,
150: * actually two instances of RequestCycle are created and processed.
151: * </p>
152: */
153: public static final IRequestCycleSettings.RenderStrategy REDIRECT_TO_RENDER = new IRequestCycleSettings.RenderStrategy(
154: "CLIENT_SIDE_REDIRECT");
155:
156: /**
157: * Adds a response filter to the list. Filters are evaluated in the order
158: * they have been added.
159: *
160: * @param responseFilter
161: * The {@link IResponseFilter} that is added
162: */
163: void addResponseFilter(IResponseFilter responseFilter);
164:
165: /**
166: * @return True if this application buffers its responses
167: */
168: boolean getBufferResponse();
169:
170: /**
171: * Gets whether Wicket should try to get extensive client info by
172: * redirecting to
173: * {@link BrowserInfoPage a page that polls for client capabilities}. This
174: * method is used by the default implementation of
175: * {@link WebRequestCycle#newClientInfo()}, so if that method is overriden,
176: * there is no guarantee this method will be taken into account.
177: *
178: * @return Whether to gather extensive client info
179: */
180: boolean getGatherExtendedBrowserInfo();
181:
182: /**
183: * Gets in what way the render part of a request is handled.
184: *
185: * @return the render strategy
186: */
187: IRequestCycleSettings.RenderStrategy getRenderStrategy();
188:
189: /**
190: * @return an unmodifiable list of added response filters, null if none
191: */
192: List getResponseFilters();
193:
194: /**
195: * In order to do proper form parameter decoding it is important that the
196: * response and the following request have the same encoding. see
197: * http://www.crazysquirrel.com/computing/general/form-encoding.jspx for
198: * additional information.
199: *
200: * @return The request and response encoding
201: */
202: String getResponseRequestEncoding();
203:
204: /**
205: * Gets the time that a request will by default be waiting for the previous
206: * request to be handled before giving up.
207: *
208: * @return The time out
209: */
210: Duration getTimeout();
211:
212: /**
213: * @see org.apache.wicket.settings.IExceptionSettings#getUnexpectedExceptionDisplay()
214: *
215: * @return UnexpectedExceptionDisplay
216: */
217: UnexpectedExceptionDisplay getUnexpectedExceptionDisplay();
218:
219: /**
220: * @param bufferResponse
221: * True if this application should buffer responses.
222: */
223: void setBufferResponse(boolean bufferResponse);
224:
225: /**
226: * Sets whether Wicket should try to get extensive client info by
227: * redirecting to
228: * {@link BrowserInfoPage a page that polls for client capabilities}. This
229: * method is used by the default implementation of
230: * {@link WebRequestCycle#newClientInfo()}, so if that method is overriden,
231: * there is no guarantee this method will be taken into account.
232: *
233: * <p>
234: * <strong>WARNING: </strong> though this facility should work transparently
235: * in most cases, it is recommended that you trigger the roundtrip to get
236: * the browser info somewhere where it hurts the least. The roundtrip will
237: * be triggered the first time you call {@link Session#getClientInfo()} for
238: * a session, and after the roundtrip a new request with the same info (url,
239: * post parameters) is handled. So rather than calling this in the middle of
240: * an implementation of a form submit method, which would result in the code
241: * of that method before the call to {@link Session#getClientInfo()} to be
242: * executed twice, you best call {@link Session#getClientInfo()} e.g. in a
243: * page constructor or somewhere else where you didn't do a lot of
244: * processing first.
245: * </p>
246: *
247: * @param gatherExtendedBrowserInfo
248: * Whether to gather extensive client info
249: */
250: void setGatherExtendedBrowserInfo(boolean gatherExtendedBrowserInfo);
251:
252: /**
253: * Sets in what way the render part of a request is handled. Basically,
254: * there are two different options:
255: * <ul>
256: * <li>Direct, ApplicationSettings.ONE_PASS_RENDER. Everything is handled
257: * in one physical request. This is efficient, and is the best option if you
258: * want to do sophisticated clustering. It does not however, shield you from
259: * what is commonly known as the <i>Double submit problem </i></li>
260: * <li>Using a redirect. This follows the pattern <a
261: * href="http://www.theserverside.com/articles/article.tss?l=RedirectAfterPost"
262: * >as described at the serverside </a> and that is commonly known as
263: * Redirect after post. Wicket takes it one step further to do any rendering
264: * after a redirect, so that not only form submits are shielded from the
265: * double submit problem, but also the IRequestListener handlers (that could
266: * be e.g. a link that deletes a row). With this pattern, you have two
267: * options to choose from:
268: * <ul>
269: * <li>ApplicationSettings.REDIRECT_TO_RENDER. This option first handles
270: * the 'action' part of the request, which is either page construction
271: * (bookmarkable pages or the home page) or calling a IRequestListener
272: * handler, such as Link.onClick. When that part is done, a redirect is
273: * issued to the render part, which does all the rendering of the page and
274: * its components. <strong>Be aware </strong> that this may mean, depending
275: * on whether you access any models in the action part of the request, that
276: * attachement and detachement of some models is done twice for a request.
277: * </li>
278: * <li>ApplicationSettings.REDIRECT_TO_BUFFER. This option handles both the
279: * action- and the render part of the request in one physical request, but
280: * instead of streaming the result to the browser directly, it is kept in
281: * memory, and a redirect is issue to get this buffered result (after which
282: * it is immediately removed). This option currently is the default render
283: * strategy, as it shields you from the double submit problem, while being
284: * more efficient and less error prone regarding to detachable models.</li>
285: * </ul>
286: * Note that this parameter sets the default behavior, but that you can
287: * manually set whether any redirecting is done by calling method
288: * RequestCycle.setRedirect. Setting the redirect flag when the application
289: * is configured to use ONE_PASS_RENDER, will result in a redirect of type
290: * REDIRECT_TO_RENDER. When the application is configured to use
291: * REDIRECT_TO_RENDER or REDIRECT_TO_BUFFER, setting the redirect flag to
292: * false, will result in that request begin rendered and streamed in one
293: * pass.
294: *
295: * @param renderStrategy
296: * the render strategy that should be used by default.
297: */
298: void setRenderStrategy(
299: IRequestCycleSettings.RenderStrategy renderStrategy);
300:
301: /**
302: * In order to do proper form parameter decoding it is important that the
303: * response and the following request have the same encoding. see
304: * http://www.crazysquirrel.com/computing/general/form-encoding.jspx for
305: * additional information.
306: *
307: * Default encoding: UTF-8
308: *
309: * @param responseRequestEncoding
310: * The request and response encoding to be used.
311: */
312: void setResponseRequestEncoding(final String responseRequestEncoding);
313:
314: /**
315: * Sets the time that a request will by default be waiting for the previous
316: * request to be handled before giving up.
317: *
318: * @param timeout
319: */
320: void setTimeout(Duration timeout);
321:
322: /**
323: * @see org.apache.wicket.settings.IExceptionSettings#setUnexpectedExceptionDisplay(org.apache.wicket.settings.Settings.UnexpectedExceptionDisplay)
324: *
325: * @param unexpectedExceptionDisplay
326: */
327: void setUnexpectedExceptionDisplay(
328: final UnexpectedExceptionDisplay unexpectedExceptionDisplay);
329: }
|