http://xml.apache.org/http://www.apache.org/http://www.w3.org/

Index
License
Install

Technologies
Infrastructure
User Guide
Dynamic Content

XSP Processor
SQL XSP Taglib
SQL Processor
LDAP Processor
DCP Processor

XSP WD

Javadocs

Cocoon 2
Javadoc XML

FAQ
Changes
Todo

Live Sites

Code Repository
Dev Snapshots
Mail Archive
Bug Database


Introduction

Web publishing is very limited without the ability to create dynamic content. For dynamic XML we refer to 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 write 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/JPS to create dynamic XML content would be the perfect choice, unfortunately design issues impose that we take a second look to 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 don't include such possibility in their design, such servlet chain is very limited in its behavior and poses significant restriction on the API use. Something that forced the Servlet API architects to come up with better solutions.

The solution was servlet nesting: the ability to include a servlet output inside its own transparently. This allowed programmers to separate different logic on different servlets, thus removing the need for servlet chaining


The limitations of Servlet Nesting

While servlet nesting was a major advantage over servlet chaining because it allowed servlets to be somewhat modular without loosing the full API power, a common design pattern applies to the Servlet model in general: no servlet is allowed to modify the output of another servlet. This holds true for all servlet API versions up to today (version 2.2).

This limitation is the key: if no further XML processing is needed on the server side, using servlets/JSP for creating XML is a perfect choice, but if this output requires some server side processing (for example XSLT transformations), the Servlet API does not allow another servlet to post process it's output. This other servlet is, in our case, Cocoon.

In a few words, the Servlet API doesn't support Servlet Piping.


The Cocoon model

Rather than turning Cocoon into a servlet engine, thus limiting its portability, this documents 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 wanted 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 to evaluate the HttpServletRequest parameters provided and create XML content that is fed into the processing reactor. A 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:

    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 to create process the given servlet request and provide an output stream for reading the generated XML document.

    Note that Produce has also another method, getDocument(request), which is responsible to return directly a DOM tree. In case you need to render you 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 on 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 on 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 - the XSLT processor that 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.
  • The XSP processor - the XSP processor that 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.
  • The DCP processor - the DCP processor that evaluates XML processing instructions with multi-language (Java and EcmaScript) logic. This processor allows you to do programmatic substitution and inclusion eliminating the need for complex processing logic. See the DCP user guide for more information.
  • The SQL processor - the SQL processor that 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.
  • 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-2000 The Apache Software Foundation. All Rights Reserved.