Chapter 6. Application Engines and Services

Table of Contents

Application Servlet
Required Pages
Server-Side State
Stateful vs. Stateless
Engine Services
Logging
Private Assets
Application Specification
<application> element
<page> element
<component-alias> element

The application engine is a central object whose responsibility is to run the request cycle for each request. To do this, it manages resources such as page loaders and page recorders and provides services to the pages and components utilized during the request cycle.

Application engines are instantiated by the application's servlet (described in the next section). They are stored into the HttpSession and are persistent between request cycles.

An important behavior of the engine is to provide named engine services, which are used to create and respond to URLs. The application engine creates and manages the request cycle and provides robust default behavior for catching and reporting exceptions.

The application engine provides the page recorder objects used by the request cycle. By doing so, it sets the persistence strategy for the application as a whole. For example, applications which use or subclass SimpleEngine will use the simple method of storing persistent state: in memory. Such applications may still be distributed, since the page recorders will be serialized with the application engine (which is stored within the HttpSession).

Application Servlet

Every Tapestry application has a single servlet, which acts as a bridge between the servlet container and the application engine. The application servlet is a subclass of ApplicationServlet.

The subclass provides the framework with the path to the application specification by implementing the method getApplicationSpecificationPath().

The servlet's main job is to find or create the IEngine instance. It then delegates all the behavior for processing the request to the application engine. Encoded in the URL will be a particular application service; the engine delegates to the service to perform the real work of handling the request.

Figure 6.1. ApplicationServlet Sequence

Is a subclass really necessary?

You would think that the resource path of the application specification could simply be a servlet initialization parameter, in which case no subclass of ApplicationServlet would be necessary.

This doesn't work for two reasons. First and foremost is how class loaders work inside an application server. Generally, the Tapestry framework will be loaded by the system class loader, and each web application will be loaded by a child class loader. The child class loader has visibility to all the classes in the WAR file, as well as all the classes on the class path, whereas the system class loader will only have visibility to the Tapestry framework classes.

The servlet instance acts as a "hook" exposing the child class loader; the framework gets the class loader from the servlet instance and uses that to instantiate Java classes for the Tapestry components.

A second, and less important reason, is that the subclass is responsible for overriding the setupLogging() method, which will be necessary for any production Tapestry application.

The servlet may also perform some static initialization for the application in its init() method. This includes tasks such as loading JDBC drivers.