Request processing overview has been edited by syl (Jan 09, 2008).

(View changes)

Content:

To make it clear "request processing" here means all actions which take place within HttpServlet#doGet/doPost() or Filter#doFilter() method call. These is no single class in Wicket that does all the job. Classes delegate request processing to each other. In a simplified way it goes like this:
Unable to render embedded object: File (request_processing(simple).jpg) not found.

1.browser requests a URL
2.WicketFilter/Servlet receives request from servlet container and creates RequestCycle object (it's created for every request)
3.RequestCycle processes request in several steps, using for this IRequestCycleProcessor
4.Depending on request parameters IRequestCycleProcessor creates IRequestTarget (in Wicket this process is referred to as "resolving")
5.IRequestTarget use existing Page or creates new one, optionally run callbacks (user code which handles link clicks, form submits, etc.), asks Page and Components to render
6.Page/Components render themselves what means to produce markup and write it to HttpResponse
7.servlet container writes output to browser

TDB: use it somewhere else? – In general the aim of request processing is to:
(optionally) execute code which somehow changes data (stored in http session, database or elsewhere)
output HTML page to HttpServletResponse (output may reflect data change)

There are more classes involved in request processing. Below is short description of each of these classes. Descriptions say what is the purpose of the class, when it is created, how to get its instance(s). It's also a good idea to look at these classes' javadocs.

Relation between classes involved in request processing

WebApplication

WebApplication contains some classes (such as IRequestCycleProcessor) which are essential for request processing. It is also used for storing application scope data such as Settings and SharedResources.
WebApplication is created when WicketFilter/Servlet is initialized. It is created by IWebApplicationFactory which can be specified in the web.xml using applicationFactoryClassName parameter:

<init-param>
	<param-name>applicationFactoryClassName</param-name>
	<param-value>org.apache.wicket.MyApplicationFactory</param-value>
</init-param>

You can implement IWebApplicationFactory and create the application instance you want. But usually it is not necessary since if there is no applicationFactoryClassName parameter in the web.xml Wicket uses default factory implementation. Default factory reads applicationClassName parameter and creates application instance of specified class using reflection.
There is only one instance of Application per WicketFilter/Servlet. You can get this instance by calling Application#get() method.


RequestCycle

RequestCycle delegates most of request processing to IRequestCycleProcessor (see RequestCycle#step()). Besides that RequestCycle contains instances of WebRequest, WebResponse which basically wraps HttpServletRequest and HttpServletResponse adding Wicket related functionality. Instances of all these classes are created on every request.
This is a pseudo code of how RequestCycle is created:

public final void doGet(final HttpServletRequest servletRequest,
                        final HttpServletResponse servletResponse)
{
  ...
  // WebApplication instance is already created while initializing servlet/filter
  final WebRequest request = webApplication.newWebRequest(servletRequest);
  final WebResponse response = webApplication.newWebResponse(servletResponse);
  RequestCycle cycle = webApplication.newRequestCycle(request, response);
  cycle.request();
  ...
}

You can customize creation of WebRequest, WebResponse and RequestCycle by overriding WebApplication#newWebRequest(), newWebResponse() or newRequestCycle().
To obtain RequestCycle instance you can call RequestCycle#get() which gets instance from ThreadLocal variable. You can get obtain WebRequest, WebResponse instances from WebRequestCycle calling getWebRequest(), getWebResponse() methods. To get HttpServletRequest/Response you can do something like this (this is not straightforward but you should not need to do it in Wicket):

final WebRequestCycle webRequestCycle = (WebRequestCycle) RequestCycle.get();
        webRequestCycle.getWebRequest().getHttpServletRequest();
        webRequestCycle.getWebResponse().getHttpServletResponse();

IRequestCycleProcessor

IRequestCycleProcessor is responsible for handling the steps of a request cycle. Its methods are called in a pre-defined order:

  • IRequestTarget resolve(RequestCycle, RequestParameters) is called to get the request target. A request might refer to e.g. a bookmarkable page, a component on a previously rendered page. This is one of the main responsibilities of IRequestCycleProcessor. RequestParameters here consists of possible optional parameters that can be translated from servlet request parameters and serves as a strongly typed variant of these (see IRequestCodingStrategy).
  • void processEvents(RequestCycle) is called after the target is resolved. It is meant to handle events like calls on components e.g. onClick(), onSubmit() event handlers.
  • void respond(RequestCycle) is called to create a response to the requesting client i.e. generate web page or do redirect.
    Typically IRequestCycleProcessor creates target and then delegates event processing and response generation to this target.

There is one instance of IRequestCycleProcessor per Application. It is lazily created during the first request. Its creation can be customized by overriding WebApplication#newRequestCycleProcessor(). You can get its instance by WebApplication#getRequestCycleProcessor().

WebSession

WebSession holds information about a user session including some fixed number of most recent pages. WebSession roughly corresponds to HttpSession. It is lazily created during request handling. Then WebSession is stored in HttpSession and restored from there on next request. If HttpSession expires and WebSession in which is stored it can't be reached anymore new WebSession instance is created.
To customize Session creation you can override Application#newSession().
You can get instance of Session using Session#get() method.

IRequestCodingStrategy

IRequestCodingStrategy implementation is responsible for digesting the incoming request and creating a suitable RequestParameters object for it, as well as creating URL representations for request targets. These are methods that do it:

RequestParameters decode(Request request);
CharSequence encode(RequestCycle requestCycle, IRequestTarget requestTarget);

There is one instance of IRequestCodingStrategy per IRequestCycleProcessor. It is usually WebRequestCodingStrategy which is lazily created during the first request. Its creation can be customized by overriding AbstractRequestCycleProcessor#newRequestCodingStrategy().
See also Request coding strategy page.

IRequestTarget

IRequestTarget is responsible for calling event handling code (for example onSubmit() method) and asking pages and components to render. IRequestTarget is created by IRequestCycleProcessor on every request. Which subclass of IRequestTarget will be created depends on RequestParameters instance which is decoded from requested URL. For example if a bookmarkable page is requested BookmarkablePageRequestTarget will be created, if a link is pressed ListenerInterfaceRequestTarget will be created.
You can get current request target by calling RequestCycle#getRequestTarget().
See also Request targets page.

Reply via email to