cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Pier Fumagalli <p...@betaversion.org>
Subject Re: Java components in blocks
Date Wed, 13 Apr 2005 20:04:15 GMT
On 13 Apr 2005, at 18:08, Vadim Gritsenko wrote:
> Pier Fumagalli wrote:
>>
>> I'm just saying that the concerns are separate: a block provides 
>> generators, transformers, serializers, ... to other blocks, but those 
>> are de-coupled from the real java components (if any) doing the job.
>
> But *real* blocks, IIUC, *are* the only way to bring new (java) 
> components into the system, because Cocoon core lacks all the optional 
> components, and, at the minimum, consists only of environment, 
> treeprocessor, and block manager.
>
> So in extreme case xslt processor component itself is optional and 
> provided by the xslt real block.

I think that we're mixing again the idea behind a Cocoon block and an 
Avalon block.

As far as I've understood Cocoon blocks (and I might be _ENTIRELY_ 
wrong here) Cocoon blocks do not expose (for example) an XSLT Java 
transformer, but expose a transformer converting a specified format 
into another.

Again, an example using Forrest.

The forrest block (ForrestBlock) requires two different blocks 
implementing the following interfaces:
- ForrestRepository: a block exposing a generator that given a uri path 
(/2.1/whatsnew) generate an XML document in the <!DOCTYPE book PUBLIC 
"-//APACHE//DTD Cocoon Documentation Book V1.0//EN" 
"book-cocoon-v10.dtd"> format
- ForrestSkin: a block exposing a serializer converting a document in 
the above mentioned format into something usable by a browser and 
exposing a mountable pipeline containing the resources (images, css, 
javascripts, ...) that the client will see...

The ForrestBlock might have a sitemap which might look something like 
this:

<map:sitemap>
   <map:components>

     <map:generators>
       <map:generator name="repository"
                      src="block:repository:/generators/repository"/>
     </map:generators>

     <map:serializers>
       <map:serializer name="renderer"
                       src="block:skin:/serializers/renderer"/>
     </map:serializers>

   </map:components>

   <map:pipelines>
     <map:match pattern="resources/**">
       <map:mount src="block:skin:/pipelines/resources" 
uri-prefix="resources/"/>
     </map:match>

     <map:match pattern="**">
       <map:generate type="repository" src="{1}"/>
       <map:serialize type="html"/>
     </map:match>
   </map:pipelines>
</map:sitemap>

Now, the "repository" implementation block might expose a virtual 
generator like this:

<map:block>
   <map:generators>
     <map:generator name="repository">
       <map:generate type="file" src="{1}"/>
     </map:generator>
   </map:generators>
</map:block>

but another implementation might specify the following:

<map:block>
   <map:generators>
     <map:generator name="repository">
       <map:generate type="sql" src="select content from documents where 
id = '{1}'"/>
       <map:transform type="xslt" src="sql2document.xslt"/>
     </map:generator>
   </map:generators>
</map:block>

In the same way, the "skin" implementation block

<map:block>
   <map:serializers>
     <map:serializer name="renderer">
       <map:transform type="xslt" src="document2html.xslt"/>
       <map:serialize type="html"/>
     </map:serializer>
   </map:serializers>

   <map:pipelines>
     <map:pipeline name="resources">
       <map:match "**.jpg">
         <map:read type="resource" mime-type="images/jpeg" 
src="resources/images/{1}.jpeg"/>
       </map:match>
     </map:pipeline>
   </map:pipelines>
</map:block>

but again, another implementation might do different:

<map:block>
   <map:serializers>
     <map:serializer name="renderer">
       <map:transform type="stx" src="document2wap.stx"/>
       <map:serialize type="wap"/>
     </map:serializer>
   </map:serializers>

   <map:pipelines>
     <map:pipeline name="resources">
       <map:match "**.gif">
         <map:read type="image" mime-type="images/gif" 
src="resources/images/{1}.jpeg"
                   width="20" height="20" scale="yes"/>
       </map:match>
     </map:pipeline>
   </map:pipelines>
</map:block>

So far, easily enough, we can see how the "ForrestBlock" interacts with 
the block interfaces it requires, and how those can be composed 
differently. Easy enough, so in the sitemap we want to use from cocoon:

<map:sitemap>
...
   <map:match pattern="wap/**">
     <map:mount block="ForrestBlock">
       <map:parameter name="repository" value="SQLForrestRepository"/>
       <map:parameter name="renderer"   value="WAPForrestRenderer"/>
     </map:mount>
   </map:match>
   <map:match pattern="html/**">
     <map:mount block="ForrestBlock">
       <map:parameter name="repository" value="SQLForrestRepository"/>
       <map:parameter name="renderer"   value="HTMLForrestRenderer"/>
     </map:mount>
   </map:match>
...
</map:sitemap>

Now, without considering the real java component which are doing the 
job (XSLT transformer, IMAGE reader, STX transformer, ...) the block 
implementation can be entirely developed using the technology (Avalon's 
ECM/Carsten's ECM+++) without caring too much about Java components 
themselves.

You can simply deploy several versions of the same interface block in 
the same container, and given that we're taking the problem of loading 
classes out of the picture, blocks can work as they're supposed to be 
without thinking much about the crummy Java machinery behind them.

Also, think about one thing: is a transformer exposed by a cocoon block 
a specific XSL or STX or (you name it) transformer, or is it a 
pseudo-component which per se knows how to translate the input to its 
output?

The java component "XSLT transformer" doesn't do anything "by itself", 
it becomes a "Cocoon transformer" (it transforms a specified document 
into another) only when the java XSLT component is associated with the 
XSLT.

But the same "Cocoon transformer" can be created by associating the STX 
"java component" with an equivalent STX stylesheet.

Now, there is also another concern that falls into this ballpark.

In my view, I think that our "ForrestBlock" block will only be allowed 
declare its requirements through interface blocks. This means that for 
a block to work properly, its requirements must be abstracted entirely 
from the specific implementations.

But a block implementation MIGHT (in my view) require a 
_very_specific_java_component_ to fulfill the contract it implements. 
For example, in the case of the "ForrestRepository" interface 
implementation, the generator exposed is abstracted entirely, but to 
implement this component I can require a SQLGenerator (Java component), 
a FileGenerator (Java component), a JcrGenerator (Java component), and 
so on and so forth.

So, in my view, either we define an interface cocoon block for each 
possible component (95% of those will only have ONE implementation), or 
we allow blocks to require specific JAva components to do their jobs, 
without relying on interfaces.

So, at the end of the day, the java componentization of how a generic 
generator (for example) exposed by a block is a completely separate, 
different, concern from the one implied in the blocks: I want a 
generator that given a URI produces a document of "book" doctype.

My 0.02 £

	Pier




Mime
View raw message