cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marc Portier <>
Subject [apples] research-report on alternative flow implementations
Date Fri, 25 Jul 2003 11:54:51 GMT
Hi all,

I've set myself to hacking up some of my alternative flow ideas 
so it could feed the 'generalized flow' discussion (and guide us 
through understanding possibly required refactoring)

I dubbed the thing 'apples' for now:
It basically sprung off from the short 'app' for application and 
'applet' was already taken :-p (I also like the implied wit that 
we shouldn't compare any of his to pears)

For those that find emails longer then 20 words ;-) difficult to 
grasp, here is the TOC:
[1] explanation of current apples
[2] proposed refactoring to the current flow-codebase
[3] reflections on code sharing
[4] future directions

I think section [2] holds the most info related to the rest of 
the community (at least on short notice)

I hope (expect) for some discussion to come round those section 
[2] topics for sure... all comments on the rest is highly 
appreciated of course


[1][explanation of current apples]
The goal
(appart from 'doing research' which is  a goal an sich ;-))
- explore the creation of a Java API to disclose the flow concepts
- such that people could reuse their OO thinking and their 
Java-class and Avalon-component coding skills to write 'Apples'
- which would be Avalon components hosting your business logic 
and making flow and publication decissions (i.e. selecting the 
uri and preparing the bizdata)

Here is what goes on to date:

The core is called the ApplesProcessor which is currently hooked 
up as a subclass of the existing Interpreter class

- it gets declared inside cocoon.xconf with some
<component-instance  name="apples" logger="apples"
among the <flow-interpreters>

- and gets selected as the flow-impl to use in any sitemap by 
adding the:
<map:flow language="apples"/>

calling the logic inside your java-'apple' is based on the 
existing flow-directives in the sitemap:

  <map:match pattern="**/*.kont">
    <map:call continuation="{2}"/>

  <map:match pattern="start/use-case_X/*">
    <map:call function="package.names.MyXApple">
      <map:parameter name="param_A" value="val_A"/>

These sitemap directives directly map onto the following methods 
of the Interpreter interface:

void callFunction(String fqcn, List args, Environment env)
void handleContinuation(String id, List args, Environment env)

the AppleProcessor will do the following:
in the event of callFunction(fqcn, args, env)
- make an instance of the class specified in fqcn
- cast it to its interface of interest: AppleController
- pull it through the avalon lifecycles (lifecycehelper)
- wrap it up in a WebContinuation object (full reuse of the 
existing ContinuationsManagerImpl)
- let this fresh Apple process the 'request'
- get uri and bizdata from the 'response'
- use those in the forwardTo(uri, bizdata, wk, env) of the 
Intrepreter interface

and in the event of handleContinuation(id, args, env)
- find the nested continuation in the WebContinuation pointed to 
by id
- cast that to its interface of interest: AppleController
- let this re-found (stateful) Apple process the 'request'
- get uri and bizdata from the 'response'
- use those in the forwardTo(uri, bizdata, wk, env) of the 
Intrepreter interface

Your arbitrary business logic can be a sample Java class that
- can exploit the following avalon lifecycle-interfaces 
(Serviceable, (not yet Composable) and LogEnabled) -- (not yet 
- needs to implement void processRequest(AppleRequest, AppleResponse)

these new Request-Response objects are just convenient ways to 
control the access these Apples have to anything that is 
available to the AppleProcessor at the time of the call.

- AppleRequest gives access to the CocoonRequest and the map of 
parameters (args) passed over...
- AppleResponse allows to set uri and bizdata


[2] proposed refactoring to the current flow-codebase

If above seemed like not that big a thing then you are absolutely 
correct: the layers to hook up any FlowImplementation you like 
are already present inside Cocoon, and it's a real pleasure to 
work with them.

There is only a slight tendency in naming and argument-passing 
that directs implementations towards using a 
scripting-language-interpreter to do the job.

Also, getting in some closer to the flow from a slightly 
different angle then the current js makes me suggest a number of 
additional modifications...

Here goes my set of proposed refactorings
(There is a fair chance that continued investigation will bring 
up some more of these...)

1/ modified forwardTo() in the AbstractInterpreter

All flow implementations just need to implement Interpreter but 
are likely to subclass AbstractInterpreter to do so.  In that 
event they inherit already the implementation of the forwardTo() 

Changing that implementation to this:

public void forwardTo(String uri, Object bizData,
                       WebContinuation continuation,
                       Environment environment) throws Exception
     if (SourceUtil.indexOfSchemeColon(uri) == -1) {
         uri = "cocoon:/" + uri;

     Map objectModel = environment.getObjectModel();
     FlowHelper.setContextObject(objectModel, bizData);
     FlowHelper.setWebContinuation(objectModel, continuation);
                      .redirect(false, uri);

will proclaime the same forwarding behaviour accross all 

forward-uri      --> results in actual forward to
no-leading-slash/whatever  --> cocoon:/no-leading-slash/whatever
   which maps onto a pipe in the current sitemap

/with-leading-slash/more   --> cocoon://with-leading-slash/more
   which maps to a pipe in the top-sitemap

scheme://full-uri          --> unchanged
   which assumes that the flowscript writer knows what he is 
doing himself.  this could even be a http:// uri which results in 
a client-side redirect.

(see also 

2/ renaming interfaces, classes and methods (and sitemap nodes)

Interpreter --> FlowProcessor
AbstractIntrepreter --> AbstractFlowProcessor

this probably ties up to the <flow-interpreters> becoming 
<flow-processors> in the xconf

Interpreter.callFunction() --> FlowProcessor.initiateFlow()
Interpreter.handleContinuation() --> FlowProcessor.continueFlow()

which brings us back to the non-closed vote on changing sitemap 
semantics that could be mirrored by one of the proposals:

map:call/@function -->   map:initiate/@flow
map:call/@continuation --> map:continue/@flow

3/ signature change of callFunction and handleContinuation

In both methods the 2nd argument is a java.util.List of 
Interpreter.Argument objects.
I understand that the scripting implementations require the thus 
implied order on the <parameters>/arguments, however it would 
make sense to maybe redesign this passed 2nd argument to allow 
for both named or indexed lookup of the arguments...

(Currently just filling an additional hashmap from the List, 
actuall it's no big hastle, just 'additional', and giving some 
cosmetical unease)

4/ dispose() the wrapped continuation object upon invalidation

I'ld like the ContinuationsManager to check if the wrapped 
continuation is implementing Disposable upon invalidation of it's 
wrapper WebContinuation.

While at it it might preform the same service on the wrapped 
'userObject' (although I have no direct need for this, it seems a 
logical extension of the reasoning)

5/ multiple flow declarations inside one sitemap

Well, to be fair I haven't seen the need here and now, but the 
discussion was also still open.

It still makes sense IMHO but I haven't got into proposing here 
something myself.


[3][reflections on code-sharing]
For those that need to read the code to think about all of this I 
am in the process of bundling up a first cut (rough stuff) as a 
src-zip/jar file that could (eventually) be added as some sort of 
a premature block....

I'm wide open to any suggestions about getting it to each or all 
of you (bugzilla being my natural choice unless someone makes me 
see differently)


[4][future directions]

First of all I'ld like to welcome any thought and code 
participation on this, so this can really go into any direction...

here is some directions/aspects where I'ld like to get some 
future investigation into:
(all of these should probably start off with checking up on the 
current js implementation -- if someone knows by heart please 
speak up)

- access control on live continuations (what if someone else uses 
your kont-id?)

- synchronization/locking on live continuations (what if two 
requests hit the same kont-id simultaneously)

- allow to programmically control the 'end-of-use-case' from the 
Apple itself

- make time-to-live somewhat more configurable and maybe even 
use-case controlled?

- get into the class-loader horror for dynamic reloading of these 
Apples (possibly through some -hopefully existing- Avalon component)

thx for reading up to here...

Marc Portier                  
Outerthought - Open Source, Java & XML Competence Support Center
Read my weblog at                        

View raw message