cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Berin Loritsch <>
Subject Re: [RT] Componentizing Cocoon Applications
Date Wed, 06 Feb 2002 15:54:25 GMT
Stefano Mazzocchi wrote:

> Now, your question (and Berin's, he's been proposing schema-based
> contracts since a long time) becomes: is the 'webapp component' role a
> solid enough contract, or we need a schema for that?
> Ok, let's do some contract analysis on the above sample:
>   <match pattern="*.html>
>    <generate src="docs/{1}.docbook"/>
>    <transform src="[skin]://docbook/docbook2html.xslt"/>
>    <serialize/>
>   </match>
> [I will use this URI syntax as an example of its semantics, not as an
> example syntax]
> somewhere we have identified that 
>  skin ->
> then we have installed
>  mycoolskin.xcomp
> which contains a 'descriptor.xml' that indicates that this webapp
> component 
> "implements" ''
> So '' is the identifier of the
> *contract* between the two interoperating entities.

And this is what I was driving at.  It works similar to the way that
the XSP engine works, except better (XSP engine uses artificial bindings
to the combination of prefix and namespace).

KISS is the best way.  Start with something simple, and expand on the
idea until you need something better.

>                                        - o -
> But is this contract?
> Let's look at Java interfaces (which are the descriptions of the
> contracts between Avalon components): they have a unique identifier (the
> fully-qualified java classname) and they list a collection of methods
> and/or final static values (almost like XML entities).
> This contract indicates:
>  1) what data the methods accept (if any)
>  2) what data the methods return (if any)
>  3) what exceptions are supposed to trigger (if any)
> That's it.

I can't agree *completely*.  There are some things that the interface cannot
communicate, but are valid contracts nonetheless.  The ever-popular example:
"Is this Store persistent or transient?".  That is part of the contract,
although that bit of the contract cannot be expressed simply by the interface.

The Generator->Transform->Serialize pipeline approach also has certain
contracts that have crept in (although maybe not by design).  Such as, the
transformer must be able to accept the input schema, or a portion of it,
to provide a meaningful output schema.

> The contract doesn't include any other information (might do so in the
> future if Java generics are implemented properly, but I wouldn't count
> on it) and Avalon is built upon the concept that a component 'behavior'
> can be meaningfully described in a sufficiently solid way by a java
> interface.
> The success of Avalon seems to prove this fact true.

I agree with this.

However, XML and Java have different representations.  My assertion is that
the schema (whether XSchema or something else) is the interface for XML

>                                        - o -
> Ok, let's keep on the parallel here: the 
> '' contract (well, the URI is the
> indentifier, but it's a one2one relationship so I will call the
> identifier 'the contract' since it's its name) is composed of:
>  1) an internal addressing space
> that's it.
> Both you and Berin suggest that this might not be enough to indicate a
> contract: I disagree, the above is sure enough. But I agree with you
> guys that an addressing space might not be the best solution to describe
> the relationships because is somewhat too general.
> Let me explain: when we connect to 
>    <transform src="[skin]://docbook/docbook2html.xslt"/>
> this is nothing different from doing
>   ((ObjectStore) store).store(key, object);
> for Avalon components because 
>  skin -> ''
>  ObjectStore -> 'org.mystuff.components.ObjectStore'

Yes, but in this example you are mixing the contract of transform and skin.
I don't see that as clean.  If we are going to introduce the concept of
components, we must provide a distinct markup for them.

<match pattern="*.html">
   <generate src="docs/{1}.xml"/>
   <transform src="stylesheets/docbook2skin.xslt"/>
   <apply component=""/>

And in another place, the component is defined.  The definition of the
component in this case would be a simple sub-pipeline (i.e. transformer).

Perhaps the better approach would be something like this:

<match pattern="*.html">
   <component src="{1}" role="">
     <component role=""/>

The communicates that we are using components with components.  It communicates
that we want the "authenticate" component to wrap all requests to the
"product-approval" component only allowing the "Vendor" and "Retailer" roles.
Furthermore, the "product-approval" component uses the "skin" component for its

The contracts for a component is that it's pipeline must be complete.  For embeded
pipelines such as we have here, the outer pipeline acts as the generator for the
internal pipeline.  The Serializer of the inner pipeline is stripped.

The Component definitions for the pipeline management can be something like this:

<component role="">
     <!-- Map Components (i.e. generators/transformers/actions/etc.) are
          defined here

     <!-- Taking advantage of the fall through function of actions, we select the
          generator if the authentication is valid.  Notice the "embed:{uri}"
          protocol.  Embed means that the source from the embedded component is
          used.  The "component" protocol is a new protocol necessary to mark
          resources within the Component file.
     <act set="authorized">
        <map:select type="embeddedComponent">
          <map:case test="yes">
            <generate src="embed:component"/>
            <generate src="component://login-successful"/>

     <!-- At this point, the user is not authorized, so we want to authenticate
          them.  We have our own pipelines here.
     <act set="authenticate">
       <generator src="component://login-form.xml"/>

     <!-- Finally, we have either obtained the generator we want, or we have
          come to the place where there is an error.  The error can be that the
          login authenticated correctly, but was not able to be authorized for
          the resource.
     <generator src="component://login-error.xml"/>
     <map:select type="hasComponent">
       <map:case test="">
          <component role=""/>
         <transform src="component://stylesheets/form2html.xslt"/>

This markup explains how we can create components with the sitemap markup with the addition
of a couple of protocols, selectors, and tags.  Perhaps what is more important at this point
is that all components are described in terms of pipeline.  A component is a predefined pipeline,
that can have parts of it overridden by other embeded components.

Furthermore, it opens the door to have purely code components that do not have to be compiled.

It is preferred to have all components behave in a self-contained fashion, but use other components
if they exist.  Avalon Phoenix (the server kernel) addresses this with the concept of Blocks.
A Block is a Service that can be provided to any other service.  Each block has a "BlockInfo"
associated with it.  The BlockInfo publishes the service that is provided (i.e. the interface
that it implements), the version, and any dependencies it has on other Blocks.  A BlockInfo
implementation based, so different implementations can require different sets of external

Here is an example from a distributed print server I wrote recently:


   <!-- section to describe block -->

   <!-- services that are offered by this block -->
     <service name=""
              version="1.0" />

       <service name="" version="1.0"/>
       <service name=""
       <service name="" version="1.0"/>


We had at one time discussed optional dependencies, but I can't remember the solution for
that.  I *believe* that instead of placing the <dependency/> information in the <dependencies/>
element, they were places as children of the <requests/> element.  That way the Component
use the requested component if available--but won't fail if it does not exist.

Perhaps something like this would be a good starting place?


"They that give up essential liberty to obtain a little temporary safety
  deserve neither liberty nor safety."
                 - Benjamin Franklin

To unsubscribe, e-mail:
For additional commands, email:

View raw message