cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stefano Mazzocchi <stef...@apache.org>
Subject [RT] Cocoon Blocks and internal web services
Date Thu, 28 Mar 2002 15:35:48 GMT
Now that Cocoon 2.0.2 is out of the door, I think it's time that we
continue the discussion on Cocoon Blocks, which, IMO, represent the
major step forward that we should aim for Cocoon 2.1.

Thanks to all of those who helped me shaping up the cocoon block idea.

                                    -- o --

A Cocoon block is a zip archive, with extension .cob and MIME-type to be
defined.

Each Cocoon Block *MUST* implement a behavioral cocoon block "contract"
that describes its behavior. This allows blocks to behave
polymorphically.

This contract is fully identified by a URI.

For validation purposes, the idenfitying URI can also be seen as an
address that locates the 'contract descriptor' that can be used by block
handlers to validate the blocks.

This contract explicitly indicates:

 1) web resources exposed by the block (for example files accessible
from other blocks)
 2) service components exposed by the block (for example avalon
components or sitemap components)

Each block contains a descriptor file (located in
/BLOCK-INF/block.xinfo) which indicates:

 1) information about the block (author, version, original location,
license and all that other block metadata)

 2) behavioral contract that the block implements (along with
information on mappings between the contract and this block's
implementation)

 3) dependencies: this is a list of zero or more 'block contracts' upon
which the block depends.

                                    -- o --

The resources exposed by blocks are accessed using a URI-compatible
protocol description of the form:

 block:[role]://path/resource

where

 block: -> identifies the protocol
 [role] -> identifies the block in the current context and it's a short
identifier that maps to the fully-qualifying URI that identifies the
block contract.

For example, suppose we have something like this:

 <map:transform src="block:skin://xslt/document2html.xslt">

the block role 'skin' must be translated to a fully qualifying URI (much
similar to the prefix -> URI translation that happens for XML
namespaces).

This is done by adding the following semantics to the sitemap:

 <map:blocks>
  <map:block role="skin"
uri="http://apache.org/cocoon/blocks/skin/2.1"/>
 </map:blocks>

After this translation is performed, the 'block:' protocol handler will
have to identifiy the resource and retrieve it from the block archive
(which can be extracted or left compressed, this should not change
behavior since the blocks are not allowed to write in their own
addressing space directly).

This mapping is performed by the block deployer, which has the
information on how to map this URI to the block that was installed to
operate that contract for the requesting block.

This futher decoupling is the key to the polymorphic behavior of blocks:
in fact, the block "role" identifies a contract, not an actual
implementation and it's therefore entirely possible to:

 a) have different implementations of the same block associated to
different blocks, so, for example, two different blocks might require a
'skin' role, but each of them might have associated different
implementations of that role.

 b) share the same implementation between different blocks.

 c) hot-deploy/hot-update a block implementation simply by changing the
last mapping translation.

                                    -- o --

The logic components exposed by the blocks are located exactly as
before, using fully qualified dot-notation for java classes. All
translation and mapping will be automatically performed by the
classloaders.

So, for example, if Block A does

 <map:generator type="mygen" class="com.mystuff.whatever.Generator"/>

the classloader responsible for Block A will look for that class in the
/BLOCK-INF/lib or /BLOCK-INF/classes directories and included jar
archives of the blocks on which this Block A depends on.

                                    -- o --

Here I describe a potential use of a block-based cocoon system:

 1) let us suppose that Cocoon is already installed in a servlet
container and up and running.

 2) let us suppose that we have a tool that implements block
management/deployment on top of Cocoon [how this is implemented is not
important for our current needs]

 3) the user has three ways to install new blocks: 

    - provide the block manager with a URI where the block archive is
located on the web

    - have the block manager discover and locate a block repository,
which will be a web service that will interact with the block manager
and list information on new blocks and all that (sort of apt-get)
 
    - provide the block manager with a 'block deployment descriptor'
which contains an 'installable' and complete dependency set of blocks
that implement a given web application. (this is to ease installation)

 4) once the user has choosen what block/s to install, the block manager
downloads it/them from the internet and reads its metadata to find out
eventual dependencies.

 5) for each dependency, the block manager scans the registry of
currently installed blocks in the system. If a block that implements the
dependent contract is already installed, the user is ask to confirm its
use, otherwise, the block manager will look in the block repositories to
download the appropriate block and will ask the user to choose between a
list of compatible implementations of that role.

In case of deployment descriptors, the block manager can be asked to
install the system without performing checkings (but these are
implementation details)

 6) after all blocks are downloaded and all dependencies are satisfied,
each block that exposes direct URI mounts to the Cocoon public URI space
will have to be *mounted* on that URI space. The user will be asked to
provide these mount points (the blocks will provide default values).
After the mount points are given, the system will check for consistency
of the URI space (one block cannot mount inside the URI space of another
block, for safety reasons) and ask for alternatives if errors are found.

 7) when everything is satisfied, the blocks are deployed and initiated
and they can start providing their own services to both the public URI
space and both internally for the other blocks.

                                    -- o --

So far so good.

There is still one big design issues to address: how detailed is the
block contract and its description.

There can be two different types of component models: strong-typed and
weak-typed. (actually, there are full range between these opposite
points, but anyway)

Java is a language that forces strong-typing and we all came to love
that, but it is also evident that sometimes Java isn't that strong-typed
anymore: it could be possile to have an Avalon component that exposes
the following interface

 interface WeakTyped {
    Object doSomething(Object o) throws Exception;
 }

which is strongly typed from a compiler point of view, but is totally
weak from a behavioral validation point of view.

So, what level of description we need for our block contracts?

I see several levels:

1) no description: blocks identify their contract with an URI that
that's it, there is no way to validate the fact that a block implements
a specified contract, this is the weakest form of contract. It's easier
to implement and places the burden of validation at runtime.

2) little description: the contract identifier indicates the 'skeleton'
of the contract but doesn't declare more detailed behavior. There is a
way to perform structure validation on the blocks and also a way to
auto-document the block contract itself, but the behavioral validation
cannot be automated and it's left to the user checking at runtime.

3) detailed description: the contract identifier indicates both the
skeleton and the behavior of the contract. This allows high granular
automatic validation.

Following these descriptions, the third option seems the best, but let
me warn you: describing the behavior of a block will be an extremely
complex task and could end up being even more complex than describing
web services.

For example, suppose that a block exposes the resource

 block:news://newsfeed

how do we describe it's behavior?

We could start saying that it implements the GET and POST actions, that
the GET action will return a specific schema (that must be included in
the description) and that the POST action requires an XML as payload
that is validated againt another schema.

But this is not enough: behavioral description *depends* on the type of
the exposed resource.

For example, a resource such as 

 block:skin://xslt/document2html

will have to expose the returning MIME-type (XSLT in this case) as well
as it's schema, as well as the schema of the conten that it's capable of
transforming and the schema of the content that is capable of generating
after the transformation.

This can go on forever.

I personally don't think that this level of description is required, but
keeping the contract weak might inhibit the ability for this system to
scale beyond the control of a single development community, since all
block instances will have to be manually validated against a particular
behavior.

Also it is true that it's not up to the block implementors to describe
the block contract, just like it's not up to the API implementor to
describe the API and we all know that writing a contract is a very
expensive and complex task, but luckily it doesn't have to be performed
once per block implementation but only once per block 'contract'.

At the same time, this description format is very well going to be so
complex that WSDL will look like piece of cake and I'm scared about
this.... on the other hand, it might enable things like form validation
and so on automatic and rather painless.

So, anyway, these were the last RT on the topic, now it's your turn to
throw the stones in the lake.

Ciao.


-- 
Stefano Mazzocchi      One must still have chaos in oneself to be
                          able to give birth to a dancing star.
<stefano@apache.org>                             Friedrich Nietzsche
--------------------------------------------------------------------


---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Mime
View raw message