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