How the Cocoon Engine Works
http://xml.apache.org/http://www.apache.org/http://www.w3.org/

Back

Download

Index
License

Install

Technologies
Infrastructure
User Guide
Dynamic XML
Caching
How it works
XML Links

XSP Processor
XSP WD
XMLFragments
ESQL Taglib
SQL Conn Pool
FP Taglib
LDAP Processor

SQL Processor
SQL Taglib

Contributing
3rd Party
Patch Queue

FAQ
Changes
Todo

Live Sites
Cocoon Hosting

Bug Database
Code Repository
Mail Lists
Mail Archives

Cocoon 2.0 Site
Cocoon 2.1 Site


How Cocoon 1.8 works

This document tries to follow the operations of Cocoon from a "document point of view" while the javadoc documentation describes it from a "procedural point of view". Therefore, here we try to be complementary to the javadoc and not to simply repeat what is stated there already. Furthermore, since the ultimate documentation is the source code itself, this document tries not to go too deep but eventually to integrate with the comments in the code. In fact, some people may find that reading the source code directly will shed more light than just reading this (significantly incomplete) overview.

Unless otherwise specified, for sake of brevity any class name is assumed to have the org.apache.cocoon prefix prepended to it.

Cocoon

This is the "main" class, either when Cocoon is being used as a servlet or for command-line use. Clearly, it contains the methods init for the latter case as well as main for the first case.

Hereafter are described the operations in the two common cases of command-line execution (typically used for offline site creation), and servlet usage.

From the Command-line

When Cocoon is invoked from the command-line, it requires as arguments the location of the cocoon.properties, the name of the file containing the XML to be processed, and the name of the output file. After reading the properties file, it creates a new EngineWrapper initialized with the above mentioned properties and then calls the handle method, and hands it an output Writer and an input File. There is no good reason for this asymmetry - the command-line operation mode of Cocoon was coded quickly as a temporary hack to meet a popular need, in lieu of the better, more integrated and well-designed command-line support planned for Cocoon 2.

EngineWrapper

This is a "hack" which provides a "fake" implementation of the Servlet API methods that are needed by Cocoon, in the inner classes HttpServletRequestImpl and HttpServletResponseImpl. When Cocoon gets integrated with Stylebook, this class will probably need to be cleaned up.

Basically, this class instantiates an Engine class and passes it the "fake" request and response objects mentioned above.

As a Servlet Startup Phase

As for any servlet, upon startup the init method is invoked. In Cocoon, this tries to load the cocoon.properties file, and, if that is successful, creates an Engine instance.

Production Phase

A service method is provided by Cocoon, which accepts all incoming requests, whatever their type. Servlet programmers may be accustomed to writing doGet or doPost methods to handle different types of requests, which is fine for simple servlets; however, a service method is the best way to implement a fully generic servlet like Cocoon.

Engine

This class implements the engine that does all the document processing.

What better definition of the function of this class than the words of its author (Stefano Mazzocchi)? From this otherwise lapidary definition, one should realize the importance of this Class in the context of the Cocoon operations and thus one should carefully read it through in order to understand the "big picture" of how Cocoon works.

Startup Phase

Either from command-line or from the servlet, upon startup of the cocoon servlet the Engine is instantiated by the private Engine constructor. For the sake of understanding Cocoon operations, it is important to know that at this point in time (and only this time in the whole lifespan of the Cocoon servlet) the objects performing the initialization of the various components are instantiated with the parameters contained by the Configuration object. This is the reason why, if changes are applied to the cocoon.properties file, these do not have any effect on Cocoon until the engine is stopped and then restarted.

These objects either directly represent the components (such as logger.ServletLogger) or are Factories to provide the correct components for a particular request (such as processor.ProcessorFactory). The long-winded setup code involved here reads class names from the cocoon.properties file and dynamically loads and configures the classes, thus allowing for easy "swapping in and out" of components without recompiling the whole of Cocoon.

Note In general, all components referenced here must be loadable at startup, otherwise Cocoon will refuse to initialize - even if the missing component(s) are not actually used in the web-application. Still, this is exactly the same situation as with a more convential Java application which does not store class names in configuration files.

production phase

The handle method has been already mentioned previously and is indeed the focal point for all the runtime operations of Cocoon. It is invoked with two objects, one being the input HttpServletRequest and one being the output HttpServletResponse (just as in a servlet).

Until the whole page is done, it repeats the following process for up to 10 times (the pipeline will only need to be repeated if an OutOfMemoryError occurs, in which case the cache will be cleared out somewhat and the pipeline restarted):

  1. Creates the Page wrapper for cacheing purposes
  2. Gets the initial document Producer from the ProducerFactory. The HTTP parameter "producer=myproducer" can be used to select the producer; if this parameter is not present, the default producer is used.
  3. Calls the producer to generate an org.w3c.dom.Document
  4. Setup the hash table environment to pass various parameters to the processor pipeline
  5. Process the document through the document Processors, (obtained from the ProcessorFactory) for each processor invoked in the Document
  6. Get the Formatter requested by the Document from the FormatterFactory
  7. Format the page
  8. Fill the Page bean with content
  9. Set the content type and the encoding

Finally,

  • Print the page to the response's PrintWriter object
  • Append timing information as an XML comment, if the content type allows
  • Flush the PrinterWriter to the client
  • Cache the page (if cacheing is enabled)

Now, I suggest you to take a deep breath and read the above steps again, since the simplicity of the algorithm exploited is so beautiful that it makes sense to appreciate it in depth and breath.

At this point the key elements are therefore the processors and the formatters, which directly operate upon the content of the Document. We are going to investigate them in detail. It should be already clear that indeed one can have more than one Processor per Document and that these are going to be applied sequentially one after the other. Namely, this is how is implemented the "chaining" of various Processors: in five lines of code (including debugging information). Again, simplicity and good coding style are assets of this implementation. Let us have a look then at what Processors and Formatters are, since these could be leveraged further and indeed these are going to be likely extended with new components for specific needs.

ProducerFactory

For each source there must be an appropriate Producer implemented. Currently (version 1.8), only ProducerFromFile is implemented. This is because XSP provides the best solution (both in terms of ease-of-use and forward-compatibility with Cocoon 2) for nearly all dynamic content solutions, so there is usually no need to write a Producer explicitly.

ProcessorFactory

For each processing instruction type there must be an appropriate Processor implemented. Currently (version 1.8), the following ones are implemented:

  • Light weight Directory Access Protocol (LDAP)
  • SQL (deprecated - SQL or EQSL taglibs are preferred)
  • eXtendible Server Pages (supercedes Dynamic Content Processor)
  • Dynamic Content Processor (deprecated, use XSP instead)
  • XInclude (attempts to implement a W3C draft standard, but may not always be up to date with the standard - as it is still evolving)
  • XSLT (implements the W3C Recommendation, XSLT)
FormatterFactory

For each format in which the output should be delivered (e.g. PDF, TEXT, HTML, XML, XHTML ), there must be an appropriate Formatter implemented. Currently (version 1.8), the following ones are distributed:

  • HTML
  • XHTML (while the HTML formatter writes some tags without closing tags for compatability with older user agents, the XHTML formatter is fully XML-compliant - indeed, it is just the XML formatter with a specific doctype.)
  • Text (i.e. plain text)
  • XML
  • FO2PDF (transforms XSL:FO to PDF which can be read by Acrobat Viewer/Reader)

Clearly, one might imagine many more formatters such as

  • FO2RTF Microsoft Rich Text Format
  • FO2MIF FrameMaker Interchange Format
  • BRAILLE

In Cocoon 1.8 all of the formatters provided are in fact implemented as simple "wrapper" classes (as can be easily seen by examining the source code in the formatters directory) which merely set the parameters to the Apache Serializers, or in the case of FO2PDF, Apache FOP, and then delegate the actual formatting to those classes. In a way, no "real work" actually goes on in the Formatter classes themselves. As you can see, Cocoon is a framework which tries not to reinvent the wheel too often!

If you're wondering why FO2PDF isn't a Processor instead of a Formatter, the answer is simple - it is conceptually more of a Processor (it transforms the entire document), but for one vital difference - it does not output XML. Yes, there is the workaround that XSP uses internally, which is to output one XML element with all the content inside that as a text node - but this method would be rather clunky for FO2PDF and would provide no real benefit.

Note that the CPU-intensive processing required for FO2PDF can be obviated by the use of newer XML-compliant graphics and document markup languages on the client side, such as SVG (Scalable Vector Graphics), or XSL:FO itself, which can just be written out as XML. This is definitely the future for dynamic web publishing, since the "rendering" of dozens of concurrent users' documents into PDF all on the server does not make any sense from a performance point of view - it is advantageous today of course because current popular browsers do not support XSL:FO or SVG natively, but in the future this will change.

In fact, XML markup languages like VoiceXML are supported by Cocoon by returning XML and indeed in that case the parameter to cocoon-format is text/xml! In the case of VRML, the cocoon format is model/vrml which in the cocoon.properties configuration file is mapped to TextFormatter.


Copyright © 1999-2001 The Apache Software Foundation. All Rights Reserved.