cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ovidiu Predescu <>
Subject Re: [RT] Flowmaps
Date Tue, 18 Jun 2002 04:35:23 GMT

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

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?)
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"/>

should be OK. 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.

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

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

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.

3. (Stefano) Template languages other than XSP to be used with the flow

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 ;)

4. Stefano's callPipeline() function. Is this equivalent to
sendPageAndContinue(), which is already implemented in the flow layer? 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? It
should be the task of the sitemap pipeline where the file is written. Am I
missing something?

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.

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.

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

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}" />

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?

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.

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;

  do {
  } while(!validator.isValid(instance));

  if(saveInstance(instance,id)) {
  else {

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

  // 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

- 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.

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.

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.

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

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?

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.

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.

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.

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,

Thanks for reading so far,

Ovidiu Predescu <> (Apache, GNU, Emacs...)

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

View raw message