Summary

Definitions

Overview

Illustration 1

Illustration 2

Illustration 3

-The Framework - a flyby-

Conclusion

Biography

Resources

The framework - a flyby
In the above illustrations, we saw how we can utilize the services provided by the framework to build our applications elegantly and effortlessly. Here, we will skim the framework and unveil some of the key objects and their mechanics, that provide these services.
In the servlet world, every user request goes through a cycle of being sent to the server, mapped to a servlet, processed in the servlet using the query string, Request and Session objects, responded by the servlet by manually building the markup and finally rendered in the browser. This cycle entails a lot of convoluted, shoddy coding that frustrates developers and maintainers. Tapestry framework is a rich API that deconvolutes this coding and shields the developer from the shoddiness. The API, built on top of the servlet API, provides the developer with all the servlet functionality, and a lot more, in a much friendly way, in the form of objects that forms the framework.
We saw in our illustrations that Pages are made of three parts - the template, the specification and the component class, and that a Page may be composed of other components recursively that are in turn each made of the three parts. This means, when a request is made for a particular page, the framework has to build a single HTML page from the three parts of the Page component and recursively from the parts of its contained components. This build task entails resolving, parsing and loading the XML specification, instantiating the component class and resolving, parsing and loading the template. The "loading" step is where the bulk of the work happens that involves building all contained components recursively. This build step for each contained component entails the same steps as the build task of the Page. At the end of the build task, we have an object, Page object, of type org.apache.tapestry.IPage that represents the entire Page. BasePage that we saw earlier is an object of this type. The analagous object that you will have at the end of building a JWC will be of type org.apache.tapestry.IComponent. The making of these objects, as we have just learned, is quite an involved, time-consuming process, and it would be a huge performance impact to discard it after one use. This gives rise to the concept of caching.
When a request is made for a particular page, the framework goes to a Source object, org.apache.tapestry.engine.IPageSource, to get an instance of the requested Page. The Page Source object maintains a pool of Page objects previously built and pops one out for each request. If the pool is empty, it is responsibility of the Page Source object to build the Page object and provide it to the framework. Once the request is processed, the Page is returned back to the Source and put in the pool for future use. In addition to IPageSource, the framework has a few other Source objects that is used in obtaining other resources - org.apache.tapestry.engine.ISpecificationSource and org.apache.tapestry.engine.ITemplateSource are a couple of them. Each of these Source objects caches the objects they provide in a pool just like the Page Source. Ok, we now know that the framework goes to the Source object to retrieve the Page, but how does the framework know which Page was requested in the first place? Well, to answer that, we need a bit of understanding of the wiring in a Page.
When the framework renders a Page, contained components encode framework specific information including the Page name into the Page. Later when the Page is submitted, this information, in the form of request parameters, is read by the framework and parsed to retrieve the Page name and other information used by the framework for request processing. This responsibility of encoding and parsing of request parameters is entrusted with the framework Service object - org.apache.tapestry.engine.IEngineService. All components go to the Service object to encode or parse request parameters. The framework comes with a predefined set of Services for different types of user requests - enter a Tapestry application (org.apache.tapestry.engine.HomeService), navigate to a Page (org.apache.tapestry.engine.PageService), submit a form (org.apache.tapestry.engine.DirectService or org.apache.tapestry.engine.ActionService) just to name a few. When components encode the component-specific request parameters, they also encode the type of Service object they used to encode their request parameters. This enables the framework to go to the right Service object to parse the various components' request parameters. The other responsibility of the Service object is to manage the request processing (includes loading the Page and executing the listeners of the component class) and response rendering (includes setting the correct content type and rendering the Page) tasks. In addition to the framework provided Services, the developer is empowered with the framework API to implement any number of custom Services that one may need. These custom Services are specified in the application specification via the <service> element.
The framework provides support for many other aspects of a Tapestry application viz. localization, application state management, bytecode enhancement and script support to name a few. All these, and other, different aspects of the web application is managed by an aptly named pivotal framework object, the engine - org.apache.tapestry.IEngine. The Engine object is responsible for instantiating and initializing most of the objects needed for processing the request including the Service objects, Source objects, object pools and others. These objects that the Engine initializes are common to all instances of the application and so are held in the ServletContext. Application data common to all instances of the application is stored in a developer provided Plain-Old-Java-Object called the Global. The Global object, like other request-processing objects, is also managed by the Engine and stored in the ServletContext. The developer specifies the Global object via the application specification property org.apache.tapestry.global-class. Data specific to a single instance (user session data) will be stored in a special object called the "Visit". The Visit is also a developer provided Plain-Old-Java-Object that is managed by the Engine. The Engine creates the Visit when necessary and stores it in HTTPSession. The developer specifies the Visit object via the application specification property org.apache.tapestry.visit-class.
A user request mapped to a Tapestry servlet is delegated to the Engine for processing. The Engine handles the controller aspect and delegates it further to the Engine Service. This chain-of-responsibility requires that the objects needed for request processing be passed around to every single object that has any processing responsibility. Passing around a bunch of objects can and will be unmaintainable. To solve this problem, the framework wraps all objects required for request processing in a single object of type org.apache.tapestry.IRequestCycle. Request Cycle wraps the HTTPServletRequest, HTTPServletResponse, Engine, Engine Service and the current Page among other objects. With all this wrapped information, the Request Cycle acts as a facade to the request processing event.
<< Previous Next >>