cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stefano Mazzocchi <>
Subject [RT] Flowscript [was Re: [RT] Flowmaps]
Date Tue, 18 Jun 2002 15:35:57 GMT
Ovidiu Predescu wrote:
> Guys,
> I'm really overwhelmed by your reaction to the flow idea! Thanks all for
> sharing your thoughts!
> First of all, I think the thanks should go to Christian Queinnec, who came
> up with the idea, and to Christopher Oliver, who implemented continuations
> in Rhino. I just put all the things together and implement the support in
> Cocoon.

Once flow docos are in place, we'll make sure to give all credits to
those who deserve it. For sure, you deserve lots of it.

> Now, there are few points that have been raised here. I'll try to answer to
> all of them in this email, both as a way to synthesize this great
> discussion, and to minimize the time I take to respond to individual
> messages (otherwise I can easily spend my entire evening replying). Please
> raise your issue again if you don't see an answer for it here.
> 1. Stefano points out that flowmaps (I don't really like this term, a "map"
> is more appropriate for state machines, how about flowscript instead?)

You are right. The concept of 'flowmap' came because of a mental
parallel I had between a declarative approach and a procedural one...
but after understanding that we don't need that, being the HTTP
client/server model intrinsically declarative.

So +1 for 'flowscript'.

> should not be considered as ordinary resources, but a separate concept. I
> have no issue declaring them in a different way, just to emphasize this
> point. So something like
>   <map:flowscripts default="calculator">
>    <map:flowscript name="calculator" language="javascript">
>      <map:script src="calc.js"/>
>    </map:flowscript>
>   </map:flowscripts>
> should be OK. 

Hmmm, call me picky, but what's wrong with

   <map:flowscripts default="calculator">
    <map:flowscript name="calculator" src="calc.js"

> Beside a different name for elements, the fundamental
> difference between this syntax and Stefano's is that it allows multiple
> files to contain the implementation of a flow script.

yes, this is also a parallel with any other sitemap concept, such as
components, resources and views.
> Each named flow script declared in <map:flowscripts> could and should be
> independent on the others. Each script should have different set of global
> variables, which is different from another script, and of course, is
> different each user gets his/her own set of values for these variables.
> This is an issue today, as it does not really happen. I'm working on solving
> it.

Great to hear that.
> 2. (Stefano) How to encode the continuation ids.
> Stefano would like to have ContinuationURLEncodingTransformer, which takes
> care of encoding the continuation id. Sylvain points out that continuation
> ids can be passed not only as part of the URL, but also as request
> parameter.
> I think it makes sense to have a transformer which encodes the continuation
> URL. This would make it very easy to change the way the continuation id is
> generated, without having to go to each XSP, JSP, whatever and change it.


> The transformer would probably work best when the continuation id is encoded
> in the URL. When the id is encoded as a request parameter, there will be
> some awareness required from the page designer to have this id enclosed
> inside a form.

Many ask to make continuations ID as transparent as session IDs. Do you
think this is possible/desirable?
> 3. (Stefano) Template languages other than XSP to be used with the flow
> layer.
> This should certainly be possible, I've started with XSP because it was very
> easy to get implement. JSP and Velocity should be equally easy to implement
> though. We just need somebody to do it ;)

Great. Please explain how then, because I think lack of knowledge and
docos was the real issue (see how things changed with a single email)!
> 4. Stefano's callPipeline() function. Is this equivalent to
> sendPageAndContinue(), which is already implemented in the flow layer?

No, I don't think so (see below).

> It
> essentially allows you to have a page processed through a pipeline, and
> continue the execution of the script. BTW, I think your sitemap snippet has
> a bug in it, shouldn't it have the <map:match> names swapped?
> Also in your callPipeline(), how does the output parameter get used?

That's the key issue: many people, in the past, pointed out that they
would like to reuse the concept of cocoon pipelines to create stuff but
send it somewhere else, not back to the client.

Currently, there is no way for a pipeline stage to call another pipeline
*detaching* it from the client output stream and attaching it a
different output stream. I would like the flowscript to be able to do

> It
> should be the task of the sitemap pipeline where the file is written. Am I
> missing something?

It's *not* the sitemap concern to know where the output stream is. If
you look at how the sitemap is implemented, it's the sitemap caller's
concern to provide the output stream. Servlets call the sitemap engine
passing the ResponseOutputStream and the CLI calls the sitemap engine
passing FileOutputStreams.

But the granularity is all or nothing. I would like to be able to call a
pipeline 'detaching it' from the output stream that the container

Why? simply because it allows very creative uses of cocoon pipelines and
would instantly stop all those requests for 'forking pipelines' that
keep bugging me in the back of my mind.
> 5. Ivelin points out the potential of stale continuations.
> I think this is indeed a real issue. One way to avoid it is to have
> continuations automatically expire after a time of inactivity, or do
> deactivate them manually in the flow script. The first approach is something
> I considered, and there are some hooks in the current code, but more support
> code needs to be written. The second approach can be implemented today: you
> can invalidate not only a single continuation, but the whole subtree of
> continuations which start from it. You just need to keep a hold on the
> continuation at the top of the tree, and invoke invalidate() on it.

Speaking of which, would it good to have a 'continuation' object in the

> 6. Multi-page forms are not dominating, and continuation based compared to
> even driven (GUI-like) programming approaches.
> I used to program GUIs a lot, I think for certain things, event-driven is
> better than using continuations. I do think however that continuations have
> a place, especially for multi-page forms. Now I think it depends a lot on
> the application, whether these forms are prevalent or not.

I agree and this is the reason why I think deprecating Actions is a bad
thing (at least, today). We'll provide options and guidelines, users
will decide what to do with the tools we provide.

> 7. Bruno's question regarding the advantage of flow scripts versus actions.
> The advantage would be that with flow scripts you can describe all the
> actions in a single flow script, where each action becomes a separate
> function. Since these functions share the same global variables, it's very
> easy to share data between them. You can share data using the session
> object, but with explicit variables is much easier to follow what's going
> on.
> If you don't care about sharing data between actions, then there's probably
> little value describing your action logic in a flow script. Other than the
> fact that you don't have to write Java code, which means compile, build war
> file, restart tomcat. With flow scripts, you just modify the script file and
> resend the request: the script is automatically reloaded and parsed by
> Cocoon, there's no need to restart anything.
> 8. Vadim's idea about making the syntax easier.
> I think the idea of having something as simple as:
> <map:match pattern="calc/*">
>   <map:flow method="calculator" continuation="{1}" />
> </map:match>
> makes a lot of sense. Using different matchers, the continuation id can be
> extracted from the request parameters, cookies, you name it. The only
> problem with it is that is a bit inflexible in terms of the URI design. If
> I'd like to have calc/kont/*, there's no easy way to specify it.
> So I'd say we can have two alternative ways of writing this: using the above
> proposal and what is already implemented, for power users that want more
> control. How about this?

Sorry, but I lost you here.

> 9. Reinhard asks what happens if two different flow scripts have a function
> with a similar name name.
> Since the flow scripts have their own variable space (not now due to some
> problems in the current implementation), there shouldn't be any problem.
> Each flow script can use its own variable and function names, without
> worrying about possible conflicts with other scripts.

Yes, and also I was thinking about having something like

 <map:call flow="calculator" method="calculator"/>

that provides sort of namespacing and avoids collisions.

> 10. Torsten asks how xmlform/precept could be implemented with flow scripts.
> I think the more generic question is how to implement multi-page forms using
> flow scripts. It would also be nice if the validation could happen not only
> on the server side, but also in the client browser, using JavaScript if
> that's available.
> Your example would become a lot simpler if you factor out the repetitive
> code in a function:
> var validator;
> var instance;
> var prefix;
> function wizard(uriPrefix) {
>   var id = cocoon.request.getParameter("someid");
>   var factory = SchemaFactory.getInstance("ns");
>   //maybe we can get the schema from a pipeline??
>   var schema = factory.compile("someschema.xsd.dtd.rng.sch");
>   validator = schema.createValidator();
>   instance = new Instance();
>   prefix = uriPrefix;
>   loadInstance(instance,id);
>   do {
>     showAndValidatePage(1);
>     showAndValidatePage(2);
>     showAndValidatePage(3);
>   } while(!validator.isValid(instance));
>   if(saveInstance(instance,id)) {
>    sendPage("success.html");
>   }
>   else {
>    sendPage("failed.html");
>   }
> }
> function showAndValidatePage(number)
> {
>    do {
>     sendPage(prefix + "page" + number + ".html");
>     Instance.populate(instance, cocoon.request);
>    } while(!validator.isValid(instance, "page" + number));
> }
> Torsten's example uses a heavily xmlform type of approach, where the data to
> be validated is kept in a Java object or a DOM tree. This is one way of
> doing things; another one would be to use explicit variables which, at the
> end of the validation, could be written in the database directly, or used to
> construct a object hierarchy which is then saved in the database using JDO,
> EJBs or whatever other means. The validation could be done directly in
> JavaScript, instead of a Schema approach. The code that does the validation
> could then be used on the client side as well.
> As Stefano mentioned, the flow layer is an infrastructure which can be used
> to create higher level abstractions. Here are some things I am currently
> looking at, which can improve the usability of the flow script engine:
> - automatic binding of JavaScript variables to form values. This would allow
> you to declare something like:
>   var username, password;
>   // Send a page to collect the user name and the password
>   sendPage("login.html");
>   // When the user fills in the form and presses the submit button, the
>   // script restarts here. The flow engine automatically binds the username
>   // and password to the values submitted in the form.
>   // make use of username and passwd here

I didn't know PHP had problems with this approach, but it smells a lot
anyway. I'm always afraid of implicity behavior, expecially when it's

This is not automatically a security hole, but it could become one since
you are letting potential attackers one step closer to your door. And
you are making things hidden so harder to spot.

I would be against anything so implicit.

> - automatic validation of form values on both server and client side. This
> should allow the same piece of JavaScript validation code to be executed
> both on the server and client side. More on this later.
> 11. With respect to how to put a back button on a page, I think I replied to
> this some time ago. The idea is to use the <jpath:continuation select="1"/>
> which selects the previous continuation.

I agree with Torsten: I'd like to keep the flow layer detached from the
jpath logicsheet. (I would also use -1 as well to indicate backwards)

> As I mentioned in some other message, the continuations created during the
> execution will form a tree, or a list if the user never presses the back
> button and starts on a different path. At any given point you can access the
> continuations above you in the tree, which identify the past pages, by using
> the "select" attribute in <jpath:continuation>.
> 12. Torsten: sub-flows, flow-2-flow, what are these? Is assembly of
> functions that represent independent flows enough?
> 13. Piroumian asks how to cancel a continuation.
> As I mentioned in several ocasions, sendPage() returns the saved
> continuation. If you want to cancel the continuation just invoke on it the
> invalidate() method. It will cancel all the receiver and all the
> continuations that inherit from it.

Cool. Ovidiu, we *definately* need more docs on what you wrote. It's
simply too undocumented right now... don't need to be XML-ized edited or
anything, just bare raw but with juicy info inside, we'll make them
better ourselves.

> 14. Another question Piroumian has is how to validate against business
> logic. Since JavaScript is tightly integrated with Java, you can call Java
> logic from the flow script to do the business logic validation. This way you
> can invoke whatever logic you want. If this is too generic, then provide
> some use case and I'll try to sketch a solution.

I think you should provide a real-life example of use of a java data
model to show how java can be called from the flowscript.

> 15. Flow management: obtaining a list of all active flows.
> All the flows are kept in an array, which is managed by a Cocoon component.
> Each flow is a tree of continuations, where each continuation is a
> JavaScript object which can be dynamically inspected for properties and so
> on.
> 16. Sylvain: should flow scripts be inherited by sub-sitemaps?
> I'm not sure of the security implications of allowing them to be inherited:
> what should be the behavior if a developer alters definitions from an
> inherited flow script?

My perception is that flowscripts are not components and should not be

> 17. The proposal to use map:call with "function(arg, arg, ...)".
> I think this is more like a syntactic sugar than real value. I don't think
> passing arguments via map:param would confuse people, the semantic is still
> the same as function invocation.

All right, let's remove this.

> 18. Access to continuations.
> I think there is a bit of confusion of terms in this discussion. The
> continuation id is passed in the HTTP request in some way or another: as
> part of the URL, as a request parameter etc. This encoding should be visible
> to the sitemap only. I'd very much like to have it hidden from the view
> layer as well, so if we can avoid putting explicit URLs in page templates,
> that would be great! This reduces the dependency between the URL design in
> the sitemap and the view generation.
> A continuation is a real object that lives on the server side, which is
> represented by its id in the request. A continuation object is returned by
> sendPage(). A continuation id is fairly much useless in a flow script, what
> you really need is the continuation object itself, which contains this
> information and more.

Yes, there is confusing between the 'continuation object' and the
'continuation id'.

Many don't like the fact that you have to explicitly pass along the
'continuation id', unlike sessions where the 'session id' is (generally)
transparently passed back and forth (which was one of the biggest values
of the Servlet API)

> 19. There are some other things that need to be fixed, but the following
> item is the biggest one.
> Currently the global variable space is shared between _all_ the flow scripts
> and _all_ the users. This is clearly wrong, and it will change soon. What we
> should have is the global variable space common only to a flow script, and
> only to a single user. This has been a challenge so far with the Rhino, but
> I think I have a solution for it.
> Variables in this global variable space will act as session variables. To
> facilitate communication between applications or share constant values
> between users of the same application, an application and a global space
> will be introduced.
> In this new approach, it should be possible to have multiple top level
> functions be invoked from the same sitemap, and have them share the same
> global variable scope, for a given user. This makes things a lot easier when
> programming with the flow layer, as you are not forced to always use
> continuations. You can store your application variables as global variables
> in a JavaScript script, and have multiple functions operated on them, where
> each function is called from the sitemap.

Great to hear.

> 20. My job - thanks Stefano for bringing it up. Here's my shameless plug :)
> If you think of using Cocoon for building Web apps or Web services, and you
> need support in doing so, I am providing consultancy for doing it, anytime,
> anywhere.

Good luck for all this!

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

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

View raw message