Thank you eversomuch! Thats very helpful. I'm going to take some time and digest it all and then I'll provide any thoughts.
Stefano Mazzocchi wrote: >Last time I wrote an RT about these things, the flowmap wasn't >implemented. Today it's working, but there are things that I would like >to change. > >This RT is to start a discussion that will hopefully lead to a coherent >and community-driven design on what the flowmap engine will look like. > >First of all, since there is no clear howto about the current flowmap >and I need to give you context in order to make you partecipate in the >discussion, I'll write a basic explaination of what's going on. > > - oooo - > >How Ovidiu implemented the flowmap concept >------------------------------------------ > >First of all, do a 'cvs checkout' of HEAD if you haven't done so. I'm >referring to the samples that you find in > > /xml-cocoon2/src/webapp/samples/flow/examples/calc/ > >which is a sample about a very simple web application that implements a >calculator using the flowmap. > >First of all, I'll outline the 'procedural flow logic' of this >application using highly-pseudo code: > > 1) tell me the first operand > 2) tell me the second operand > 3) tell me the operation to apply > 4) here is your result > >You'll see how much similar to the actual implementing code this will >look like. This is probably already a great advantage over anything that >we had before. > >Let us look at the sitemap: > ><map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0"> > > [skipping component declaration] > > <map:resources> > <map:resource name="flow"> > <map:script src="calc.js"/> > </map:resource> > </map:resources> > > <map:pipelines> > <map:pipeline> > <map:match pattern="kont/*"> > <map:continue with="{1}"/> > </map:match> > > <map:match pattern=""> > <map:call function="calculator"> > <map:parameter name="prefix" >value="/samples/flow/examples/calc/"/> > </map:call> > </map:match> > > <map:match pattern="*.html"> > <map:generate src="{1}.xsp" type="serverpages"/> > <map:serialize/> > </map:match> > </map:pipeline> > </map:pipelines> ></map:sitemap> > >So, Ovidiu added three concepts that weren't found in the previous >sitemap implementations: > > 1) a new "map:script" component connects a sitemap resource with a >flowmap (which is here implemented as a javascript program) > > 2) a new attribute "map:call/@function" allows you to pass control from >the sitemap to the flowmap, calling the function defined in the >attribute and passing the nested "map:parameter" to the function as a >regular call. > > 3) a "map:continue" element indicates that the flow must be continued >with the continuation passed in the attribute "@with". > >Let's look at the flowmap: > > var prefix; > > function calculator(uriPrefix) > { > prefix = uriPrefix; > var a = getNumber("a"); > var b = getNumber("b", a); > var op = getOperator(a, b); > > if (op == "plus") > sendResult(a, b, op, a + b); > else if (op == "minus") > sendResult(a, b, op, a - b); > else if (op == "multiply") > sendResult(a, b, op, a * b); > else if (op == "divide") > sendResult(a, b, op, a / b); > else > sendResult("Error: Unkown operator!"); > } > >the 'calculator' function is the one that is called from the sitemap. As >you can see, the procedural logic of your flow is *very well* described: >I'm sure that it would takes a few minutes for anybody to understand >what your application is doing. > >This is *NOT* possible with any other FSM-based approach. > >If you think about it, in Cocoon 1.x we used PI to encode state >transitions in every stage, then we identified this as a problem and we >centralized it into the sitemap: the location where you can understand >what your URI does in a central and confortable location. > >Here we are doing it again, but instead of contralizing declarative >client/server behavior, we are centralizing procedural web-app flow. > >But let's keep looking into the flowmap: > > function getNumber(name, a, b) > { >1 var uri = prefix + "getNumber" + name.toUpperCase() + ".html"; >2 sendPage(uri, { "a" : a, "b" : b }); >3 return parseFloat(cocoon.request.getParameter(name)); > } > >This function collects the number required by the flow: > >line 1: the URI of the resource to use is created >line 2: the URI is sent to the client, along with some parameters in a >map >line 3: a float is returned from the cocoon request parameter named with >the given name > >Anybody who ever wrote a webapp would think we are nuts: line 2 >generates a response and line 3 reads a request. But here is where the >flowmap gets magic, there are bunch of things that you don't see >happening. > >So, let's look at that function from what really happens behind the >lines, let us suppose we call > > var a = getNumber("a"); > >then > >a) the sitemap is called to process a the URI 'getNumberA.html' >b) the sitemap matches with this matcher > > <map:match pattern="*.html"> > <map:generate src="{1}.xsp" type="serverpages"/> > <map:serialize/> > </map:match> > >c) the sitemap executes the "getNumberA.xsp", which is given by > ><xsp:page > language="java" > xmlns:xsp="http://apache.org/xsp" > xmlns:jpath="http://apache.org/xsp/jpath/1.0" > > > ><document> > <body> > <s1 title="Calculator"> > <form> > <xsp:attribute name="action"> > <xsp:expr>"kont/" + <jpath:continuation/></xsp:expr> > </xsp:attribute> > > <p>Enter value of <strong>a</strong>: > <input type="text" name="a"/></p> > <input type="submit" name="submit" value="Enter"/> > </form> > </s1> > </body> ></document> ></xsp:page> > >where the "jpath" logicsheet is used to obtain the "continuation" of the >current flow and is then encoded in the URI called. > >So, when the users hits 'submit', Cocoon will receive a request for an >hypotetical URI "kont/39849834983498", then Cocoon will match it with: > > <map:match pattern="kont/*"> > <map:continue with="{1}"/> > </map:match> > >and resurrect the flow logic from where it was left. So, again, between > > function getNumber(name, a, b) > { >1 var uri = prefix + "getNumber" + name.toUpperCase() + ".html"; >2 sendPage(uri, { "a" : a, "b" : b }); >3 return parseFloat(cocoon.request.getParameter(name)); > } > >line 2 and line 3, several things happen > > 1) control is given to the sitemap > 2) the sitemap produces a response which encodes the continuation > 3) this response is sent to the client > 4) the client acts with the response > 5) cocoon receives a request for a continuation-decoding URI > 6) the flowmap is called with the given continuation (think of it as a >starting point) > >If you think of the above as a command line environment, line 2 gives >you the dialog where to enter the number and line 3 uses the number >returned from the user. > >[the rest of the flowmap is easy to understand if you understood so far, >so I'll skip it] > > - oooo - > >The problems with this approach >------------------------------- > >First of all, let me say that I consider the above concept the biggest >advancement in server-side web technology since servlets. > >This design not only makes it a breeze to implement MVC, but it shows >you how natural and clear things become once you separate the procedural >flow, from the declarative serving of resources. > >At the same time, I think there are a number of issues that we might >solve before freezing the concept in a beta release: > >1) the semantics to call a flowmap from a sitemap are too implicit: >users must assume to much from what they read (ie self-readability of >the concept is very poor). > >2) the concept of continuations is not transparent, there is concern >overlap between the view designers and the sitemap managers since the >view designers must be aware of the URI location of the >continuation-decoding URI. > >[NOTE: it is *not* required that you use continuations for your flow >logic, you can use whatever means you have to control state as you did >previously, such as REST-like passing style, sessions or cookies] > >3) there is currently only one way to implement the MVC "view" and that >forces you to use XSP. This might not be a performance problem, but it >might become a usability problem. > >Let's talk about each one of them independently. > >[NOTE: Giacomo and I spent a full evening and the next day (during >"Italy vs. Mexico"! consider that!) talking about these things, so the >above reflects design concepts of both of us] > >More explicit sitemap markup >---------------------------- > >Here is what I think would be a much better approach to connect a >sitemap and a flowmap: > ><map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0"> > > <map:flowmaps default="calculator"> > <map:flowmap name="calculator" src="calc.js" language="javascript"/> > </map:flowmaps> > > <map:pipelines> > <map:pipeline> > <map:match pattern=""> > <map:call function="calculator('prefix','/kont')"/> > </map:match> > > <map:match pattern="kont/*"> > <map:call with-continuation="{1}"/> > </map:match> > > <map:match pattern="*.html"> > <map:generate src="{1}.xsp" type="serverpages"/> > <map:serialize/> > </map:match> > </map:pipeline> > </map:pipelines> > ></map:sitemap> > >There are a couple of major differences: > > 1) a flowmap isn't a sitemap resource, but it's something else. The >above semantics reflect this. > > 2) you can have more than one flowmap in a sitemap (then you can define >a default one or use a 'flowmap' attribute in "map:call" to identify >which flowmap you are calling) > >[of course, in order to accomplish this, the implementation must >completely isolate the different flowmaps and its global variables] > > 3) the "map:call" element is used to call sitemap resources (pipelines) >and flowmap resources (functions), an attribute is used to indicate the >behavior that should be used and it's consistent with the rest of the >sitemap. > > 4) the "map:call" element can use both nested map:parameters or >directly using the 'function(param, param)' syntax inside the attribute. >This makes it more readable in some cases. > >Making continuations transparent >-------------------------------- > >I personally don't have a clear view of the usability of this concept >myself: I like it very much, it's clear and consistent and it's similar >to the session concept. > >The only thing is that we might provide a >"ContinuationURLEncodingTransformer" of some sort to separate the >concern of those who write the forms and those who write the sitemap, >even if, passing the 'kont/' prefix as I showed above allows to keep the >URI space totally self-contained in the sitemap. > >I'd be happy to hear more comments in this area (Daniel?) > >More ways to get flowmap data >----------------------------- > >Currently, in order to have access to flowmap data (parameters or >continuations), you need to use the XSP or write java code yourself (I'm >not even sure the latest is possible, Ovidiu?) > >I'd like to have at least a few others: > > 1) XSTL > 2) Velocity > 3) JSP? > >I don't know how hard it is to implement them and I'd like to have >suggestions on how to implement at least the first one (the problem with >velocity is that its output must be parsed, unlike XSP, so Velocity >templates are inherently slower than a compiled XSP, but at least they >are easier to understand and to use for many, expecially HTML >designers). > >Using JSP as an MVC view makes sense in those cases where a tool is >required for HTML designers to connect to the parameters passed to the >JSP. I personally don't care but others might. > > - oooo - > >Ok, almost there. > >There is only one big thing missing: when I thought originally at the >flowmap concept, I wanted it to be interchangeable with the sitemap, now >I've changed my mind and I think it makes sense to have a sitemap always >up front, no matter how 'procedural' your web application is (might even >have a single URI for the whole thing and handle everything inside the >flowmap) > >At the same time, when I was explaining the flowmap concept to the guys >at SwissRisk, we came up with an idea [gosh, forgot the name of the guy >who suggested me to think in that direction, hope he is subscribed and >makes himself known!]. > >Consider this flowmap call > > sendPage("hello.html"); > >this means: > > 1) ask the sitemap to redirect to "hello.html" > 2) send the output to the client > 3) wait for a request to make me continue > >Now, suppose we do this > > callPipeline("hello.html", input, output); > >where we mean: > > 1) call the internal "hello.html" URI connecting the input and output >that I give you. > 2) come back here without sending anything to the client > ><drum-roll/> > >VOILA'! We have the ability to use serializers to write on disk, without >even touching the sitemap! > >So, consider this sitemap: > ><map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0"> > > <map:flowmaps default="editor"> > <map:flowmap name="editor" src="editor.js" language="javascript"/> > </map:flowmaps> > > <map:pipelines> > > <map:pipeline internal="true"> > <map:match pattern="save2disk"> > <map:generate type="stream"> > <map:parameter name="content" value="content"/> > </map:generate> > <map:serialize type="xml"/> > </map:match> > </map:pipeline> > > <map:pipeline> > <map:match pattern="save"> > <map:call function="save2disk()"/> > </map:match> > </map:pipeline> > > </map:pipelines> ></map:sitemap> > >and your flowmap is something like > >function save2disk() { > OutputStream output = new FileOutputStream("/usr/local/docs"); > callPipeline("save",cocoon.request, output); >} > >it would be *THAT* easy! > >[NOTE: the 'input' and 'output' parameters of the callPipeline() method >will have to be carefully choosen, here I'm just making this up as an >example, don't take this as a complete proposal, but just a way to >sparkle discussion] > > - oooo - > >There are a few important issues with the flowmap: > > 1) documentation must be provided on the FOM (flowmap object model), >sort of a DOM for flowmaps. Currently, objects like 'cocoon', 'log' and >others are provided, but there is no documentation presenting this > > 2) mappings between java and javascript: I don't know how much coupling >can be done between java and javascript in the flowmap, this must be >documented more. > > - oooo - > >Ok, please, send your comments. > >Ciao. > > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]