An Introduction to Apache Cocoon 2.1
An Open Source Apache Software Foundation project based on open standards, Apache Cocoon is rapidly gaining momentum in the Web developer community. This is evidenced by ever increasing diverse developer and user communities, and the popularity of recent Cocoon meets that are attracting large numbers, and attendees from many parts of the world.
This article focuses on Apache Cocoon 2.1 and is intended to be an introduction to Cocoon and the concepts behind it.
What is Apache Cocoon?
Essentially, Cocoon is a Web development framework. It provides the developer with the infrastructure needed to quickly build flexible, maintainable, scalable, and robust XML Server Applications.
Cocoon is implemented as an abstract Java engine, and as such, can be run from both within an Application Server or from the command line. Cocoon introduces the concepts of "component pipelines" and "Cocoon flow" to Web Application building, to form the basis of a powerful Web architecture. It allows for easy:
- Content aggregation
- Pluggable multi-step XML transformations/augmentations (Typically via XSLT)
- Pluggable Multi-Channeling
- Form handling and validation (Cocoon Forms/Woody)
- Centralized application flow logic with Cocoon Flow while at the same encouraging maintainable, robust code and promoting Separation of Concerns (SoC)
The notion of separation of concerns among Logic, Content, and Style sits at the very heart of Cocoon. In fact, this notion was the original inspiration behind Cocoon's genesis. Cocoon methodology preaches that an "individual should do what they're good at;" the benefits of this are many fold and obvious. These range from clean uncluttered code, to more productive happy individuals.
As a component-based framework, Cocoon is highly modular. It is distributed with many "prefabricated" pluggable components. Because these components either consume or produce SAX events, they can be chained together to form SAX processing pipelines. Hence, the term "component pipelines" is often used.
The concept of "component pipelines" makes SoC easy. Each component within a pipeline is usually tasked with a particular concern. For example, rendering the same content to a Cell Phone or to a Web Browser becomes a simple matter of plugging in the appropriate "style" component into the pipeline, allowing the "styler" to work independently from the content provider.
Individual pipeline components are often compared to XML "Lego Blocks." This is because, like Lego blocks, pipeline components can be assembled into any number of configurations to quickly tailor the required XML solution. Web developers are not limited to the available component suite, but can write their own enterprise-specific "custom components" by extending existing components or by implementing the appropriate component interface.
A basic Cocoon pipeline would aggregate one or more data sources generating a single XML SAX stream that then is "piped" through the necessary transform components (including transforms that can augment content; for example, SOAP or SQL Transformers), transforming the XML as required before finally being serialized to the desired format.
There are numerous components available at the developers' disposal. An example of one such component would be the ServerPages generator component, which implements XSP. Extensible Server Pages, or XSP, is an extension of JSP that allows the developer to insert Java code into XML markup. There are too many types of generators, transformers, and serializers to list here.
Component pipelines are mapped to URI spaces via the Cocoon sitemap.
The Sitemap—Configuring Pipelines
The sitemap.xmap file is the core configuration file for Cocoon. This is where the Web Application developer defines enterprise-specific component pipelines.
A sitemap basically defines the set of available sitemap components, and provides a mapping between URIs and the corresponding pipeline assembly "blueprints." Typically, several pipeline definitions are contained within a single sitemap file.
Consider the following pipeline example:
<map:pipeline type="caching"> <map:match pattern="page/getUserinfo.html"> <map:generate type="serverpages" src="screens/userInfo.xsp"/> <map:transform src="context://samples/common/style/xsl/html/ simple-page2html.xsl"/> <map:transform type="i18n"/> <map:serialize type="html"/> </map:match> <map:match pattern="page/registrationSuccessful.html"> <map:generate type="serverpages" src="screens/registraionSuccessful.xsp"/> <map:transform src="context://samples/common/style/xsl/html/ simple-page2html.xsl"/> <map:transform type="i18n"/> <map:serialize type="html"/> </map:match> </map:pipeline>
The preceding pipeline maps the following URIs, "page/getUserInfo.html", and "page/registrationSuccesful.html", to the corresponding component pipeline definition. Note that these URIs are anchored under Cocoon's servlet context.
Both pipeline definitions build a pipeline by instantiating a "Caching" pipeline implementation, and using that to imbed a ServerPages generator component, a XSLT transformer component, an il8n transformer component (that transforms content into the appropriate language according to locale), and an HTL serializer component.
What if the developer wanted to serve one of the above pages to a WAP-enabled devices instead? To do this, the developer would simply slot in the WML stylesheet and change the serializer component as follows:
<map:pipeline> <map:match pattern="page/getUserinfo.vml"> <map:generate type="serverpages" src="screens/userInfo.xsp"/> <map:transform src="context://samples/common/style/xsl/ html/simple-page2wml.xsl"/> <map:transform type="i18n"/> <map:serialize type="wap"/> </map:match> </map:pipeline>
The above pipelines are simplified examples for the purpose of this article. There are many classes of component (let alone component types) that are not listed here; these include Action components, Selector components, and so forth. The sitemap allows for calling of sitemap resources, defining of views orthogonal to pipelines, pipeline redirection, defining custom protocols, and so on. The point is that the sitemap language is highly expressive and extensible, allowing the developer to describe pipelines in a powerful and concise fashion.
Of course, the developer need not define an entire Web application within a single sitemap. Cocoon allows for sitemaps to be split up into several mountable sub-sitemaps.