Dynamic XML in Cocoon
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


Introduction

Web publishing is very limited without the ability to create dynamic content. By dynamic XML we mean the content that is created as a function of request parameters or state of the requested resource. For this reason, a lot of work and design has been put into Cocoon to allow dynamic XML content to be generated.

The Servlet/JSP model

People are used to writing small Java programs to create their dynamic web content. Servlets, and Java in general, are very powerful, easy to write and fast to debug, but they impose (like any other pure-logic solution) a significant management cost. This is due to the fact that programmable components like servlets must include both the logic to generate the dynamic code as well as all static elements (such as static content and style). The need for a more useful solution soon appeared.

To fill the gap between Java programmers and web engineers (groups that rarely overlap), Sun proposed the Java Server Pages (JSP) specification, a markup language (today with both SGML and XML syntax) that allows web engineers to include code in their pages, rather than include pages in their code. The impact of this strategy was significant: servlets were written directly in Java code if very little static content was to be used, otherwise JSP or other compiled server pages technologies were used.

This said, it would seem that using servlets/JSPs to create dynamic XML content would be the perfect choice. Unfortunately, design issues indicate that we should take a second look at the technology, and understand why this isn't so.

Servlet Chaining Vs. Servlet Nesting

Java Servlets were introduced by the Java Web Server team as a way to allow users to create their own web plug-ins. They were designed to handle the HTTP protocol and all possible dynamic web content (including HTML, XML, images, etc. - both text and binary streams). Unfortunately, the need for a componentized request handler was not taken into serious consideration in the design phase but only later, when at an implementation phase.

In fact, the Java Web Server provided the ability to chain multiple servlets, one becoming the filter of the other. Unfortunately, since the API doesn't include such a possibility in its design, such a servlet chain is very limited in its behavior and puts significant restrictions on the API use. Something that forced the Servlet API architects to come up with better solutions.

The solution was servlet nesting: the ability for a servlet to include another servlet's output inside its own transparently. This allowed programmers to separate different logic on different servlets.

Unfortunately servlet nesting does not allow you to easily "pass through" information about sessions and cookies, and it basically breaks the HTTP model because it invokes the second servlet from the wrong client (the server). So servlet nesting is just a temporary hack, useful for simple tasks, but not workable in general.

The next solution proposed was Request Dispatching. A servlet could alter the request object (but not the response!) and then forward the request to another servlet (a kind of internal redirect, invisible to the client).

The limitations of the Servlet Interface

However, the problem with all these approaches was very simple: the servlet interface was never designed to be a general-purpose object-oriented processing interface. Textual strings, returned from servlets, are the least time-efficient way of representing XML; DOM objects, used in Cocoon 1, are more time-efficient (and SAX events, used in Cocoon 2, are even more time-efficient).

Additionally, if you then want to start using your reusable XML-generating or XML-transforming servlet in a non servlet environment (for example a standalone desktop application) you have to somehow "emulate" the functionality of the servlet engine. This is silly - interfaces should not be unnecessarily complex. Cocoon follows the principle, If you don't need to write something as a servlet, don't!

The Cocoon Model

Rather than turning Cocoon into a servlet engine, thus limiting its portability, this document outlines some solutions that allow Cocoon users to get the servlet-equivalent functionality with internal Cocoon design ideas.

The Cocoon processing model is based on the separation of

  • Production -
  • where XML content is generated based on Request parameters (servlet equivalent)
  • Processing -
  • where the produced XML content is transformed/evaluated
  • Formatting -
  • where the XML content is finally formatted into the desired output format for client use.

    This separation of working contexts allows Cocoon users to implement their own internal modules to add the functionality they require to the whole publishing system. In fact, while a few of these components are already shipped with Cocoon, the highly modular structure allows you to build your own to fit your particular needs.

    Writing Producers

    Producers initiate the request handling phase. They are responsible for evaluating the HttpServletRequest parameters provided and create XML content that is fed into the processing reactor. Servlet logic should be translated into a producer if the request parameters can be used directly to generate the XML content (for example the FileProducer which loads the requested file from disk).

    Here follows the code for an example producer distributed with Cocoon:

    NoteOf course, this uses a string which is not as fast as building a DOM object directly, as mentioned above, but we wanted to keep the example really simple, and in a page this small the speed difference would not be noticeable anyway.

    public class DummyProducer
      extends AbstractProducer
      implements Status
    {
    
      String dummy = "<?xml version=\"1.0\"?>"
          + "<?cocoon-format type=\"text/html\"?>"
          + "<html><body>"
          + "<h1 align=\"center\">"
              + "Hello from a dummy page"
          + "</h1>"
          + "</body></html>";
    
      public Reader getStream(HttpServletRequest request)
        throws IOException
      {
        return new StringReader(dummy);
      }
    
      public String getPath(HttpServletRequest request) {
        return "";
      }
    
      public String getStatus() {
        return "Dummy Producer";
      }
    }
    

    The key method is getStream() which is responsible for processing the given servlet request and provide a Reader for reading the generated XML document.

    Note that AbstractProducer has also another method, getDocument(request), which is responsible for directly returning a DOM tree. In case you need to render your servlet code Cocoon-aware, the above example should tell you what to do.

    Please look at the shipped producers' source code for example code and look at the user guide for how to install and use your own producers.

    Writing Processors

    If your servlet needs many parameters to work, it is more reasonable that you write a Processor instead. A Processor transforms a given XML document (which, in this case should contain the needed static parameters) into something else, driven both by the input document and by the request object which is also available.

    Here is a simple processor example that should show you what the above means. Suppose you have the following document as input (note that it may have been produced from a file, from other sources or dynamically - see the above paragraph):

    <?xml version="1.0"?>
    <page>
     <p>Current time is <time/></p>
    </page>
    

    Our simple example processor will look for the <time/> tags and will expand them to the current local time, creating this result document:

    <?xml version="1.0"?>
    <page>
     <p>Current time is 6:48PM</p>
    </page>
    

    Please look at the shipped processors' source code for example code and look at the user guide for how to install and use your own processors.

    Using Cocoon processors

    The above example shows a very simple situation but needs non-trivial code to implement it. For this reason, the Cocoon distribution includes a number of processors that implement common needs and situations. These are:

  • The XSLT processor -
  • Applies XSLT transformations to the input document. XSLT allows you to solve your transformation needs as well as simple tag evaluation/processing due to its extensible and programmable nature. XSLT is a W3C Recommendation.
  • The XSP processor -
  • Evaluates XSP pages and compiles them into producers. This processor allows you include programmatic logic into your pages as well as to separate the logic from the content. See the XSP user guide for more information. Note that the XSP Processor assumes that it is getting its input from a static file, so it will not work well with pre-processing. Its design means that it should really have been a Producer in the first place, instead of a Processor. This change has been made in Cocoon 2.
  • The SQL processor (Deprecated) -
  • Evaluates simple tags describing SQL queries to JDBC drivers and formats their result-set in XML depending on given parameters. See the SQL processor user guide for more information. Note: This is deprecated - users are advised to use the XSP SQL taglib, or the more powerful Extended SQL taglib instead. The latter (ESQL taglib) allows easy post-processing of output within XSP, amongst other things, whilst the former taglib is mainly provided for backward compatability.
  • The LDAP processor -
  • the LDAP processor that evaluates simple tags describing LDAP queries to directory services and formats their result-set in XML depending on given parameters. See the LDAP processor user guide for more information.

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