You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Tim Olson <to...@marketingforce.com> on 2003/11/12 20:20:44 UTC

RE: [vote] forbidding flowscripts with no sendpage redirects (was Re: Saving pipeline output to a temp file...)

sorry i'm so late in commenting on this but
please NO NO NO!

we are using javascript not as a flow engine but as a simple scripting
controller.  we have one main pipeline which does auth, i18n, etc, and which
calls specific pipeline fragments for each page.  typical subsitemap code
looks like

<map:match action="*/profile/edit">
  <map:call function="dumpUserData"/>
  <map:generate src="cocoon://generate"/>
  <map:transform src="profileForm.xsl"/>
  <map:serialize/>
</map:match>



function dumpUserData()
{
  userID = util.getRequestParam("userID") - 0
  userHome = util.lookupHome("User")
  user = userHome.findByPrimaryKey(userID)
  util.set( "user", user.getValueObject() )
}


our generator is generic and takes the values set by the utility object and
marshalls them into XML which is fed to the XSLT...

by enforcing the use of sendPage(), you would force us to break all of our
subsitemap blocks into two pieces

<map:match action="*/profile/edit">
  <map:call function="dumpUserData"/>
</map:match>

<map:match action="*/profile/edit2">
  <map:generate src="cocoon://generate"/>
  <map:transform src="profileForm.xsl"/>
  <map:serialize/>
</map:match>

(with the addition of sendPage("edit2") in our javascript)


this is heinous and unnecessarily complicates our nice structure.

also, we have cases where we call several javascript controller modules to
get various data needed by the xslt:

<map:match action="*/profile/edit">
  <map:call function="dumpUserData"/>
  <map:call function="dumpOrderData"/>
  <map:call function="dumpNewsItems"/>
  <map:generate src="cocoon://generate"/>
  <map:transform src="homePage.xsl"/>
  <map:serialize/>
</map:match>

currently, we can easily tack on a javascript module to add XML data to the
transformation pipeline, but how could this work if every js was required to
sendPage()?  it makes our usage pattern seem impossible, but we find this
way of using javascript to be quite wonderful, and quite independent of flow
concerns.



> -----Original Message-----
> From: Sylvain Wallez [mailto:sylvain@apache.org]
> Sent: Tuesday, November 11, 2003 5:00 PM
> To: dev@cocoon.apache.org
> Subject: Re: [vote] forbidding flowscripts with no sendpage redirects
> (was Re: Saving pipeline output to a temp file...)
> 
> 
> Sylvain Wallez wrote:
> 
> > Let's reformulate this into a proper vote.
> >
> > Do you want to enforce the fact that flowscript calls (either 
> > "function" or "continuation") *must* redirect using sendPage, 
> > sendPageAndWait or redirectTo and that, should it not be 
> the case, a 
> > ProcessingException be raised?
> 
> 
> So far, we have the following results :
> 
> 8 votes to enforce it in 2.1.3,
> 1 vote to enforce it in 2.1.4,
> and a "-0" and "-0.5" on enforcing (Vadim and Geoff)
> 
> So, the community has decided that this should be enforced 
> sooner than 
> later. Quoting Antonio, "earlier means less pain in the future".
> 
> I just committed the patch. Samples seem to behave correctly. Please 
> cross-check.
> 
> Sylvain
> 
> -- 
> Sylvain Wallez                                  Anyware Technologies
> http://www.apache.org/~sylvain           http://www.anyware-tech.com
> { XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }
> Orixo, the opensource XML business alliance  -  http://www.orixo.com
> 
> 

Re: [vote] forbidding flowscripts with no sendpage redirects (was Re: Saving pipeline output to a temp file...)

Posted by Sylvain Wallez <sy...@apache.org>.
Stefano Mazzocchi wrote:

<snip/>

> 2) the first, while more verbose, forces you to separate clearly 
> "controller logic" from the "presentation" logic. I wouldn't write it 
> like the above but like
>
>  <pipeline internal-only="true">
>   <match pattern="screen/edit">
>    <generate src="cocoon://generate"/>
>    <transform src="profileForm.xsl"/>
>    <serialize/>
>   </match>
>  </pipeline>
>
>  <pipeline>
>   <match pattern="*/profile/*">
>    <call function="main">
>     <param name="action" value="{2}"/>
>    </call>
>   </match>
>  </pipeline>
>
> function main(action) {
>     func = this[action];
>     if (func != undefined) func.apply(this,args);
>     cocoon.sendPage("screen/" + action);
> }
>
> function edit() {
>   userID = util.getRequestParam("userID") - 0;
>   userHome = util.lookupHome("User");
>   user = userHome.findByPrimaryKey(userID);
>   util.set( "user", user.getValueObject() );
> }
>
> which seems more verbose, but it's, IMO, much cleaner as the main() 
> method acts as a dispatcher for screens and you can overload them if 
> you need to.
>
> this is the approach that I've used in all my flowscripts and it has 
> been working quite nicely (that is, couldn't find out a cleaner way of 
> doing the same).


Just remember the issue I raised between named parameters in the sitemap 
and positional arguments in the function declaration: unfortunately it's 
way too late to forbid this, but it should be discouraged because 
potentially leading to bugs very difficult to find.

So your main function should be written:
  function main() {
    func = this[cocoon.parameters.get("action")];
    if (func != undefined) func.apply(this,args);
    cocoon.sendPage("screen/" + action);
  }

IIRC, cocoon.parameters["action"] should work also, but I'm not sure.

Sylvain

-- 
Sylvain Wallez                                  Anyware Technologies
http://www.apache.org/~sylvain           http://www.anyware-tech.com
{ XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }
Orixo, the opensource XML business alliance  -  http://www.orixo.com



Re: [vote] forbidding flowscripts with no sendpage redirects (was Re: Saving pipeline output to a temp file...)

Posted by Stefano Mazzocchi <st...@apache.org>.
On 12 Nov 2003, at 20:20, Tim Olson wrote:

> sorry i'm so late in commenting on this but
> please NO NO NO!
>
> we are using javascript not as a flow engine but as a simple scripting
> controller.  we have one main pipeline which does auth, i18n, etc, and 
> which
> calls specific pipeline fragments for each page.  typical subsitemap 
> code
> looks like
>
> <map:match action="*/profile/edit">
>   <map:call function="dumpUserData"/>
>   <map:generate src="cocoon://generate"/>
>   <map:transform src="profileForm.xsl"/>
>   <map:serialize/>
> </map:match>
>
>
>
> function dumpUserData()
> {
>   userID = util.getRequestParam("userID") - 0
>   userHome = util.lookupHome("User")
>   user = userHome.findByPrimaryKey(userID)
>   util.set( "user", user.getValueObject() )
> }
>
>
> our generator is generic and takes the values set by the utility 
> object and
> marshalls them into XML which is fed to the XSLT...
>
> by enforcing the use of sendPage(), you would force us to break all of 
> our
> subsitemap blocks into two pieces
>
> <map:match action="*/profile/edit">
>   <map:call function="dumpUserData"/>
> </map:match>
>
> <map:match action="*/profile/edit2">
>   <map:generate src="cocoon://generate"/>
>   <map:transform src="profileForm.xsl"/>
>   <map:serialize/>
> </map:match>
>
> (with the addition of sendPage("edit2") in our javascript)
>
>
> this is heinous and unnecessarily complicates our nice structure.
>
> also, we have cases where we call several javascript controller 
> modules to
> get various data needed by the xslt:
>
> <map:match action="*/profile/edit">
>   <map:call function="dumpUserData"/>
>   <map:call function="dumpOrderData"/>
>   <map:call function="dumpNewsItems"/>
>   <map:generate src="cocoon://generate"/>
>   <map:transform src="homePage.xsl"/>
>   <map:serialize/>
> </map:match>
>
> currently, we can easily tack on a javascript module to add XML data 
> to the
> transformation pipeline, but how could this work if every js was 
> required to
> sendPage()?  it makes our usage pattern seem impossible, but we find 
> this
> way of using javascript to be quite wonderful, and quite independent 
> of flow
> concerns.

The above was the original reason to introduce actions. Actions were 
just empty tags. Were later shaped to contain pipelines and do all 
sorts of things, but the above was the spirit.

Now, I understand that it appears shameful to have to force people to do

> <map:match pattern="*/profile/edit">
>   <map:call function="dumpUserData"/>
> </map:match>
>
> <map:match pattern="*/profile/edit2">
>   <map:generate src="cocoon://generate"/>
>   <map:transform src="profileForm.xsl"/>
>   <map:serialize/>
> </map:match>

instead of simply

> <map:match action="*/profile/edit">
>   <map:call function="dumpUserData"/>
>   <map:generate src="cocoon://generate"/>
>   <map:transform src="profileForm.xsl"/>
>   <map:serialize/>
> </map:match>

but you forget to look at a few thing:

1) what if the dumpUserData is later changed to call "sendPage()"? it 
would never return there and you'll find it really hard to understand 
why.

2) the first, while more verbose, forces you to separate clearly 
"controller logic" from the "presentation" logic. I wouldn't write it 
like the above but like

  <pipeline internal-only="true">
   <match pattern="screen/edit">
    <generate src="cocoon://generate"/>
    <transform src="profileForm.xsl"/>
    <serialize/>
   </match>
  </pipeline>

  <pipeline>
   <match pattern="*/profile/*">
    <call function="main">
     <param name="action" value="{2}"/>
    </call>
   </match>
  </pipeline>

function main(action) {
     func = this[action];
     if (func != undefined) func.apply(this,args);
     cocoon.sendPage("screen/" + action);
}

function edit() {
   userID = util.getRequestParam("userID") - 0;
   userHome = util.lookupHome("User");
   user = userHome.findByPrimaryKey(userID);
   util.set( "user", user.getValueObject() );
}

which seems more verbose, but it's, IMO, much cleaner as the main() 
method acts as a dispatcher for screens and you can overload them if 
you need to.

this is the approach that I've used in all my flowscripts and it has 
been working quite nicely (that is, couldn't find out a cleaner way of 
doing the same).

HTH

--
Stefano.


Re: [vote] forbidding flowscripts with no sendpage redirects (was Re: Saving pipeline output to a temp file...)

Posted by Stefano Mazzocchi <st...@apache.org>.
On 13 Nov 2003, at 00:20, Andrzej Jan Taramina wrote:

> Ugo suggested:
>
>>   <map:match pattern="*/profile/edit">
>>     <map:call function="dumpData"/>
>>   </map:match>
>>
>>   <map:match pattern="view">
>>     <map:generate src="cocoon://generate"/>
>>     <map:transform src="homePage.xsl"/>
>>     <map:serialize/>
>>   </map:match>
>>
>> function dumpData() {
>>    dumpUserData();
>>    dumpOrderData();
>>    dumpNewsItems();
>>    cocoon.sendPage("view");
>> }
>>
>
> The main problem I have with this approach is that without looking at 
> the
> script code, there is no easy way of telling that the first match will 
> end up
> calling the second one and so the flow of the application becomes more
> opaque...and thus harder to understand and maintain.

True. [see the other thread on flow polluting sitemap readability]

> I like Tim's approach much better....where everything is in one place 
> and the
> high level flow of control is quite clear and transparent.

nah, it follows the same patter of action: it's cool when it's nice and 
clean and simple... but the more complex it becomes the more it blows 
in your face, we must be more creative to solve this issue.

> also glad to see that I am not the only one that has used this 
> paradigm.
> <grins>

yeah, sounds like "millions of outlook users can't be wrong" as an add 
campaign ;-)

> An action that will call a flowscript for you without the sendPage
> restriction would seem to be a reasonable alternative, in which case 
> Tony's
> code then looks like:
>
> <map:match action="*/profile/edit">
> 	<map:act type="FlowscriptAction"  function="dumpUserData">
> 		<map:call function="dumpOrderData"/>
> 		<map:call function="dumpNewsItems"/>
> 		<map:generate src="cocoon://generate"/>
> 		<map:transform src="homePage.xsl"/>
> 		<map:serialize/>
> 	</map:act>
> 	... error stuff can go here...
> </map:match>

you all the function twice? c'mon.

> Which I like even better...since you have the ability to branch the 
> flow
> based on success/failure of the action.  You could also allow 
> parameters as
> input to the function by doing something like:
>
> <map:act type="FlowscriptAction"  function="dumpUserData">
> 	<map:parameter value="xxx"/> <!-- name attribute could be ignored -->
> 	<map:parameter value="yyy"/>
>      .... as before

here you go, told you.

> where the method signature of dumpUserData would look like
>
> 	function dumpUserData( xValue, yValue ) {....}
>
> Clean...crisp...understandable...functional....and doesn't clutter the
> architecture.

bah, we have different tastes.

> +1 from me for the FlowscriptAction approach and soon too!

I think the selector idea is much better, let's work on that.

--
Stefano.

Re: [vote] forbidding flowscripts with no sendpage redirects (was Re: Saving pipeline output to a temp file...)

Posted by Joerg Heinicke <jh...@virbus.de>.
On 13.11.2003 00:20, Andrzej Jan Taramina wrote:

>>  <map:match pattern="*/profile/edit">
>>    <map:call function="dumpData"/>
>>  </map:match>
>>
>>  <map:match pattern="view">
>>    <map:generate src="cocoon://generate"/>
>>    <map:transform src="homePage.xsl"/>
>>    <map:serialize/>
>>  </map:match>
>>
>>function dumpData() {
>>   dumpUserData();
>>   dumpOrderData();
>>   dumpNewsItems();
>>   cocoon.sendPage("view");
>>}
>>
> 
> 
> The main problem I have with this approach is that without looking at the 
> script code, there is no easy way of telling that the first match will end up 
> calling the second one and so the flow of the application becomes more 
> opaque...and thus harder to understand and maintain.
> 
> I like Tim's approach much better....where everything is in one place and the 
> high level flow of control is quite clear and transparent.

For the moment it's better to have this that restrictive. But have a 
look at the recent thread "[RT] Is flowscript polluting sitemap 
readability?". Maybe, but really only maybe as it was only a random 
thought and we must think about the concept, there will be a Selector in 
the future that leads the sitemap flow depending on the result of the 
flow script. This brings the light back to the sitemap and can reduce 
opaqueness ;-)

And this will remove the need for such an action-like behaviour you and 
Tim relied on. BTW what exactly should the FlowAction do? I didn't 
follow the thread closely. If it does that what I imagine (or fear) we 
are back to actions and don't need any flow. I like the Selector 
approach much more. But let's discuss it at that thread.

Joerg


Re: [vote] forbidding flowscripts with no sendpage redirects (was Re: Saving pipeline output to a temp file...)

Posted by Ugo Cei <u....@cbim.it>.
Reinhard Poetz wrote:
> I don't like it that we blur the Flowscript concept to achieve things
> that can already be done today nearly in the same way some of you
> propose. In the long run I fear that nobody knows what the Cocoon
> Control flow is about and everybody talks about different things. I
> think this harms Cocoon more than it helps. So please come up with
> usecases which make it really necessary to go this way!

Amen brother ;-).

> ... but maybe I'm the only one with these thoughts ...

We are at least two.

	Ugo


-- 
Ugo Cei - Consorzio di Bioingegneria e Informatica Medica
P.le Volontari del Sangue, 2 - 27100 Pavia - Italy
Phone: +39.0382.525100 - E-mail: u.cei@cbim.it


RE: [vote] forbidding flowscripts with no sendpage redirects (was Re: Saving pipeline output to a temp file...)

Posted by Reinhard Poetz <re...@apache.org>.
From: Andrzej Jan Taramina
 
> Ugo suggested:
> 
> >   <map:match pattern="*/profile/edit">
> >     <map:call function="dumpData"/>
> >   </map:match>
> > 
> >   <map:match pattern="view">
> >     <map:generate src="cocoon://generate"/>
> >     <map:transform src="homePage.xsl"/>
> >     <map:serialize/>
> >   </map:match>
> > 
> > function dumpData() {
> >    dumpUserData();
> >    dumpOrderData();
> >    dumpNewsItems();
> >    cocoon.sendPage("view");
> > }
> > 
> 
> The main problem I have with this approach is that without 
> looking at the 
> script code, there is no easy way of telling that the first 
> match will end up 
> calling the second one and so the flow of the application 
> becomes more 
> opaque...and thus harder to understand and maintain.
> 
> I like Tim's approach much better....where everything is in 
> one place and the 
> high level flow of control is quite clear and transparent.
> 
> also glad to see that I am not the only one that has used 
> this paradigm.  
> <grins>
> 
> An action that will call a flowscript for you without the sendPage 
> restriction would seem to be a reasonable alternative, in 
> which case Tony's 
> code then looks like:
> 
> <map:match action="*/profile/edit">
> 	<map:act type="FlowscriptAction"  function="dumpUserData">
> 		<map:call function="dumpOrderData"/>
> 		<map:call function="dumpNewsItems"/>
> 		<map:generate src="cocoon://generate"/>
> 		<map:transform src="homePage.xsl"/>
> 		<map:serialize/>
> 	</map:act>
> 	... error stuff can go here...
> </map:match>
> 
> Which I like even better...since you have the ability to 
> branch the flow 
> based on success/failure of the action.  You could also allow 
> parameters as 
> input to the function by doing something like:
> 
> <map:act type="FlowscriptAction"  function="dumpUserData">
> 	<map:parameter value="xxx"/> <!-- name attribute could 
> be ignored -->
> 	<map:parameter value="yyy"/>
>      .... as before
> 
> where the method signature of dumpUserData would look like
> 
> 	function dumpUserData( xValue, yValue ) {....}
> 
> Clean...crisp...understandable...functional....and doesn't 
> clutter the 
> architecture.
> 
> +1 from me for the FlowscriptAction approach and soon too!


I followed this discussion the last days and I'm still wondering why you
need this "FlowscriptAction". If you need an Action then use an Action.
What's the problem? If you say you want the fast development cycles of
Flowscript because it is interpreted then use an XSP-Action (which
should be nearly as fast)[1]

I don't like it that we blur the Flowscript concept to achieve things
that can already be done today nearly in the same way some of you
propose. In the long run I fear that nobody knows what the Cocoon
Control flow is about and everybody talks about different things. I
think this harms Cocoon more than it helps. So please come up with
usecases which make it really necessary to go this way!

... but maybe I'm the only one with these thoughts ...

--
Reinhard


[1] I've to admit that I have never used it but only read about it
(http://wiki.cocoondev.org/Wiki.jsp?page=XSPAction)


Re: [vote] forbidding flowscripts with no sendpage redirects (was Re: Saving pipeline output to a temp file...)

Posted by Andrzej Jan Taramina <an...@chaeron.com>.
Ugo suggested:

>   <map:match pattern="*/profile/edit">
>     <map:call function="dumpData"/>
>   </map:match>
> 
>   <map:match pattern="view">
>     <map:generate src="cocoon://generate"/>
>     <map:transform src="homePage.xsl"/>
>     <map:serialize/>
>   </map:match>
> 
> function dumpData() {
>    dumpUserData();
>    dumpOrderData();
>    dumpNewsItems();
>    cocoon.sendPage("view");
> }
> 

The main problem I have with this approach is that without looking at the 
script code, there is no easy way of telling that the first match will end up 
calling the second one and so the flow of the application becomes more 
opaque...and thus harder to understand and maintain.

I like Tim's approach much better....where everything is in one place and the 
high level flow of control is quite clear and transparent.

also glad to see that I am not the only one that has used this paradigm.  
<grins>

An action that will call a flowscript for you without the sendPage 
restriction would seem to be a reasonable alternative, in which case Tony's 
code then looks like:

<map:match action="*/profile/edit">
	<map:act type="FlowscriptAction"  function="dumpUserData">
		<map:call function="dumpOrderData"/>
		<map:call function="dumpNewsItems"/>
		<map:generate src="cocoon://generate"/>
		<map:transform src="homePage.xsl"/>
		<map:serialize/>
	</map:act>
	... error stuff can go here...
</map:match>

Which I like even better...since you have the ability to branch the flow 
based on success/failure of the action.  You could also allow parameters as 
input to the function by doing something like:

<map:act type="FlowscriptAction"  function="dumpUserData">
	<map:parameter value="xxx"/> <!-- name attribute could be ignored -->
	<map:parameter value="yyy"/>
     .... as before

where the method signature of dumpUserData would look like

	function dumpUserData( xValue, yValue ) {....}

Clean...crisp...understandable...functional....and doesn't clutter the 
architecture.

+1 from me for the FlowscriptAction approach and soon too!


Andrzej Jan Taramina
Chaeron Corporation: Enterprise System Solutions
http://www.chaeron.com


Re: [vote] forbidding flowscripts with no sendpage redirects (was Re: Saving pipeline output to a temp file...)

Posted by Ugo Cei <u....@cbim.it>.
Tim Olson wrote:
> <map:match action="*/profile/edit">
>   <map:call function="dumpUserData"/>
>   <map:call function="dumpOrderData"/>
>   <map:call function="dumpNewsItems"/>
>   <map:generate src="cocoon://generate"/>
>   <map:transform src="homePage.xsl"/>
>   <map:serialize/>
> </map:match>

  <map:match pattern="*/profile/edit">
    <map:call function="dumpData"/>
  </map:match>

  <map:match pattern="view">
    <map:generate src="cocoon://generate"/>
    <map:transform src="homePage.xsl"/>
    <map:serialize/>
  </map:match>

function dumpData() {
   dumpUserData();
   dumpOrderData();
   dumpNewsItems();
   cocoon.sendPage("view");
}

      Ugo