You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Ellis Pritchard <el...@nukinetics.com> on 2007/07/03 12:39:12 UTC

Re: RT: map:call as generic non-redirecting controller code

Hi,

Yes, looking at that thread makes the decision look at best  
arbitrary, at worst spiteful for those who were doing something quite  
elegant with the former behaviour!

But it's actually not so bad for the 'facists' out there (see the  
thread for why I use this term!!):

It is the CallFunctionNode which enforces the contract of  
redirection, not any higher level flow construct; therefore we  
*could* leave that contract alone, and instead implement this  
functionality (ironically) with an Action, which then defines exactly  
the semantics as discussed (or, if actions are really to be frowned  
upon, an entirely new type of sitemap node).

So at the minimum we'd only need to:
a) change the Interpreter API to allow a function to return a value.
b) write an Action to allow calling the function and returning the  
value to the nested sitemap.

Ellis.




On 28 Jun 2007, at 17:17, Daniel Fagerstrom wrote:

> Ellis Pritchard skrev:
>> Hi,
>>
>> I've often wondered why <map:call function="xxx"> has been  
>> implemented so that it is an error to return without sending a  
>> redirect to a pipeline.
> In the original design the flowscript where intended to work as it  
> does today. By mistake the above mentioned error check wasn't  
> implemented from the beginning. When people saw that, there was a  
> vote about introducing it: http://marc.info/? 
> t=106849566300008&r=1&w=2 and then the error check was introduced:  
> http://marc.info/?l=xml-cocoon-cvs&m=106858783407241&w=2.
>
> In the meantime some people had start to used flowscripts as action  
> an where quite happy about it. But they didn't succeed in  
> convincing the community that it should be allowed. The end of the  
> thread http://marc.info/?t=106849566300008&r=1&w=2, starting with  
> Tim Olson's mail contains a discussion. While rereading it I find  
> the arguments for forbidding "flowscripts as actions" quite weak.
>
>> I presume this is a design decision dating back to the beginning  
>> of Cocoon Flow.
>>
>> However, it looks to me that this would be something generally  
>> useful, and could completely replace the use of custom Actions,  
>> and improve the flow-sitemap interaction.
> Agree completely. I have taught Cocoon to a number of people and  
> most of them have found this limitation of flowscript use  
> frustrating. It also makes the sitemap unnecessarily hard to follow  
> in many cases.
>
>> Examples include:
>>
>>     - all the normal Action things (propagating parameters, login  
>> state etc.)
>>     - complicated logic for determining branching in a pipeline  
>> e.g. a or b or (a and b) or !(a or b) selects different rendering  
>> pipelines logic.
>>
>> The Interpreter interface currently has a callFunction method with  
>> a void return; certainly the underlying JavaScript implementation  
>> can return an Object, as can any Java implementation, so there's  
>> no reason why a Flow function couldn't return a Map (e.g. JS  
>> Object) which would be used for parameterisation of a nested  
>> pipeline in exactly the same way as Actions do. There's also no  
>> reason why the function could not continue to be able to redirect,  
>> as Actions do.
>>
>> In the case where map:call is not being used as part of a  
>> continuation, the requirement for redirection simply adds a  
>> superfluous match in the pipeline, which may well not be valid in  
>> any other context of invocation (e.g. it relies on flow-attributes).
>>
>> Personally, I also hate having to put those redirection URIs in  
>> the Flow, even if passed by parameter, rather than, for example  
>> returning navigation ids (cf. struts, JSF) which could then be  
>> used to allow the sitemap to select the appropriate rendering  
>> pipeline. If someone re-factors the sitemap, they may have no idea  
>> as to where the URI is used in a FlowScript, and therefore will  
>> easily break the application. It also, I think, breaks SoC by  
>> mixing logic with stuff normally handled by the sitemap.
>>
>> For instance, in a simple non-CForms flow I may wish to  
>> distinguish between the rendering pipeline taken if in an AJAX  
>> request, and the rendering pipeline taken in a non-AJAX request.  
>> So I could pass two URIs through to the flow as parameters and  
>> then choose between them when doing a sendPage*(); however, then  
>> again, I may now wish to use different rendering pipelines when  
>> using CForms: since the sendFormAndWait() function doesn't return  
>> until a terminating submit button is pressed, I don't have that  
>> level of control on a per-request basis (e.g. my first show uses  
>> the page-level rendering pipeline which is a huge aggregation,  
>> subsequent AJAX-request shows just need to render the form itself,  
>> thus saving the (expensive) aggregation. Using return ids instead  
>> of redirection would allow the sitemap to make that rendering  
>> decision.
>>
>>
>> Would anyone else like to share their thoughts?
> I agree with your ideas and think we should implement them.
>
> /Daniel
>


Re: RT: map:call as generic non-redirecting controller code

Posted by Dev at weitling <de...@weitling.net>.

Grzegorz Kossakowski wrote:
> Dev at weitling pisze:
>> I'm not against processing data, I want to avoid introducing a new
>> protocol. 
>
> I think that we already have such a protocol, are you aware of
> xmodule:flow-attr combo?

Not, but it looks interesting. Will have a look on it.

>> And functions returning values the classical way (return
>> myBestStuff;) will reduce readability of the pipeline. For few and/or
>> small values I'd prefer variables, for many and/or big values one should
>> think about introduce a generator or transformer weaving the data
>> directly into the pipeline.
>
> By variables do you mean something like {someVar} construct in sitemap
> and someVar can only contain string value?

Ok, you caught me red-handed. I still don't dream at night of the
various variable types in Cocoon. I meant a kind of business variable
cntaining Java objects.

>> Giving even void functions a sense: Doing something when a certain point
>> in a pipeline is reached not directly touching data flowing through the
>> pipe.
>
> That's what I would be against to. Side effects is the last thing we
> need in pipelines, IMHO. Personally I would like to see possibility to
> call function only at the *beginning* of the pipeline and *before*
> data is even processed. Exactly the same way actions are called today.
>
> The point about implementing generator is valid only if you want to
> implement something generic enough to call it component (generators
> are components). Implementing use-it-once components is anti-pattern,
> IMHO.

Yes, of course, implementing a use-it-once component is anti-pattern.
What about this:

<map:call function="sayHelloToAuntBerta"/>
<map:generate type="kissPrepare"/>
<map:call function="sayNooooo"/>
<map:transform type="kissApply"/>
<map:serialize type="chubbyFacePincher"/>
<map:call function="makeNoteNeverToTantalizeLittleChildrenWhenGrownUp"/>

... where the functions just print something to a file, let the computer
make weird noises, whatever, but NOT process those big humid kisses...
The concept of pipelines is creating sax event, modifying and
serializing sax events. Extensive use of functions injecting data would
open a new parallel kind of pipeline.

As Ellis Pritchard pointed out in his first post: It's about control
flow not processing data.

BTW: Will Actions be replaced by something more readable in future or
did I miss the discussion about?

Florian

Re: RT: map:call as generic non-redirecting controller code

Posted by Grzegorz Kossakowski <gk...@apache.org>.
Dev at weitling pisze:
> I'm not against processing data, I want to avoid introducing a new
> protocol. 

I think that we already have such a protocol, are you aware of xmodule:flow-attr combo?

> And functions returning values the classical way (return
> myBestStuff;) will reduce readability of the pipeline. For few and/or
> small values I'd prefer variables, for many and/or big values one should
> think about introduce a generator or transformer weaving the data
> directly into the pipeline.

By variables do you mean something like {someVar} construct in sitemap and someVar can only contain string value?

> Giving even void functions a sense: Doing something when a certain point
> in a pipeline is reached not directly touching data flowing through the
> pipe.

That's what I would be against to. Side effects is the last thing we need in pipelines, IMHO. Personally I would like to see possibility to 
call function only at the *beginning* of the pipeline and *before* data is even processed. Exactly the same way actions are called today.

The point about implementing generator is valid only if you want to implement something generic enough to call it component (generators are 
components). Implementing use-it-once components is anti-pattern, IMHO.

> Hope this was not even more obfuscating :-)

No, it clears your position a little. :-)

-- 
Grzegorz Kossakowski
http://reflectingonthevicissitudes.wordpress.com/

Re: RT: map:call as generic non-redirecting controller code

Posted by Dev at weitling <de...@weitling.net>.

Grzegorz Kossakowski wrote:
> Dev at weitling pisze:
>> To be able to put a function call anywhere in a pipeline would be great,
>> having access to all the variables defined up till then. To return data
>> to the pipeline for further processing via a special protocol doesn't
>> look like the best way to go (IMO). Functions should only return (in the
>> classical way) data to other functions calling them.
>
> Florian, I'm not sure if I understand you correctly. What's the use to
> return data from function call if you can't process it later?

I'm not against processing data, I want to avoid introducing a new
protocol. And functions returning values the classical way (return
myBestStuff;) will reduce readability of the pipeline. For few and/or
small values I'd prefer variables, for many and/or big values one should
think about introduce a generator or transformer weaving the data
directly into the pipeline.
Giving even void functions a sense: Doing something when a certain point
in a pipeline is reached not directly touching data flowing through the
pipe.

Hope this was not even more obfuscating :-)
Florian

Re: RT: map:call as generic non-redirecting controller code

Posted by Grzegorz Kossakowski <gk...@apache.org>.
Dev at weitling pisze:
> 
> Time for my 2 cents, sorry:
> To be able to put a function call anywhere in a pipeline would be great,
> having access to all the variables defined up till then. To return data
> to the pipeline for further processing via a special protocol doesn't
> look like the best way to go (IMO). Functions should only return (in the
> classical way) data to other functions calling them.

Florian, I'm not sure if I understand you correctly. What's the use to return data from function call if you can't process it later?

-- 
Grzegorz Kossakowski
http://reflectingonthevicissitudes.wordpress.com/

Re: RT: map:call as generic non-redirecting controller code

Posted by Dev at weitling <de...@weitling.net>.

Grzegorz Kossakowski wrote:
> Just to be sure, do you want to implement something like:
> <map:match pattern="sth">
>   <map:call function="prepareData"/>
>   <map:generate src="..."/> <- some protocol to obtain the prepared data
>   [...]
> </map:match>
>
> Such construct introduces new semantics for sitemap because data
> returned by <map:call> will be available _outside_ <map:call> element.
> Now it is important what is the scope where the data will be visible.
> Have you thought about it already?

Time for my 2 cents, sorry:
To be able to put a function call anywhere in a pipeline would be great,
having access to all the variables defined up till then. To return data
to the pipeline for further processing via a special protocol doesn't
look like the best way to go (IMO). Functions should only return (in the
classical way) data to other functions calling them.

Bye,
Florian

Re: RT: map:call as generic non-redirecting controller code

Posted by Ralph Goers <Ra...@dslextreme.com>.
Grzegorz Kossakowski wrote:
>
>> Instead, I would simply like to see map:call expanded so that the 
>> target function can be a bit more generic than an Interpreter (i.e - 
>> it is easier to implement things like the JSF block, which uses an 
>> action or Spring webflow).
>
> What more generic than Interpreter interface you need?
Good question. Unfortunately, I haven't had a huge amount of time to see 
what it would really take to invoke Spring webflow this way. However, it 
certainly doesn't have continuations, so I doubt handleContinuation is 
of much use. On the other hand, webflow does have event ids that need to 
be passed in. 

I also notice that (at least in 2.1) you have to declare

  <flow-interpreters default="javascript" logger="flow">
    <!-- FOM (Flow Object Model) -->
    <component-instance 
class="org.apache.cocoon.components.flow.javascript.fom.FOM_JavaScriptInterpreter" 
name="javascript">
      
<load-on-startup>resource://org/apache/cocoon/components/flow/javascript/fom/fom_system.js</load-on-startup>
      <reload-scripts>${javascript.reload-scripts}</reload-scripts>
      <check-time>${javascript.check-time}</check-time>
      <!--  <debugger>enabled</debugger> -->  <!-- JavaScript Debugger 
support -->
    </component-instance>
</flow-interpreters>

in cocoon.xconf and then add

  <map:flow language="javascript">
    <map:script src="calc.js"/>
  </map:flow>

to your sitemap for this to work. webflow wouldn't have a "script". 
Instead it would have a flow configuration. This could be similar enough 
that it would work, but it would feel weird to have to code 
language="webflow".

Ralph

Re: RT: map:call as generic non-redirecting controller code

Posted by Grzegorz Kossakowski <gk...@apache.org>.
Ralph Goers pisze:
> Grzegorz Kossakowski wrote:
>> Just to be sure, do you want to implement something like:
>> <map:match pattern="sth">
>>   <map:call function="prepareData"/>
>>   <map:generate src="..."/> <- some protocol to obtain the prepared data
>>   [...]
>> </map:match>
>>
>> Such construct introduces new semantics for sitemap because data 
>> returned by <map:call> will be available _outside_ <map:call> element. 
>> Now it is important what is the scope where the data will be visible. 
>> Have you thought about it already?
> Actually, I have been thinking about this for a while as I have been 
> toying about trying to figure out the best way to integrate Spring 
> webflow with cocoon. One option was to use the Interpreter interface 
> (which seemed very awkward, since this isn't really an interpreter) and 
> use map:call.  IIRC, it seemed that most (all?) of the flowscript usages 
> I looked at don't follow the paradigm above. Rather, map:call is sort of 
> an end point. It invokes other Cocoon pipelines to generate views but a 
> pipeline doesn't follow it in the sitemap. I actually prefer this over 
> the above. All this syntax does is provide a little bit more flexible 
> action while still encouraging users to use the sitemap as the complete 
> controller, even for business logic, which I hope we all know by now is 
> a mistake.

I understand your point and even share it. ;)
I asked about that syntax because of deja vu effect (I have been reading some related discussions in archives to see what people said earlier).

After re-reading Ellis'es original proposal I would say that I'm more than fine with it. Go ahead, Ellis!

> Instead, I would simply like to see map:call expanded so that the target 
> function can be a bit more generic than an Interpreter (i.e - it is 
> easier to implement things like the JSF block, which uses an action or 
> Spring webflow).

What more generic than Interpreter interface you need?

-- 
Grzegorz Kossakowski
http://reflectingonthevicissitudes.wordpress.com/

Re: RT: map:call as generic non-redirecting controller code

Posted by Ralph Goers <Ra...@dslextreme.com>.
Grzegorz Kossakowski wrote:
> Just to be sure, do you want to implement something like:
> <map:match pattern="sth">
>   <map:call function="prepareData"/>
>   <map:generate src="..."/> <- some protocol to obtain the prepared data
>   [...]
> </map:match>
>
> Such construct introduces new semantics for sitemap because data 
> returned by <map:call> will be available _outside_ <map:call> element. 
> Now it is important what is the scope where the data will be visible. 
> Have you thought about it already?
Actually, I have been thinking about this for a while as I have been 
toying about trying to figure out the best way to integrate Spring 
webflow with cocoon. One option was to use the Interpreter interface 
(which seemed very awkward, since this isn't really an interpreter) and 
use map:call.  IIRC, it seemed that most (all?) of the flowscript usages 
I looked at don't follow the paradigm above. Rather, map:call is sort of 
an end point. It invokes other Cocoon pipelines to generate views but a 
pipeline doesn't follow it in the sitemap. I actually prefer this over 
the above. All this syntax does is provide a little bit more flexible 
action while still encouraging users to use the sitemap as the complete 
controller, even for business logic, which I hope we all know by now is 
a mistake.

Instead, I would simply like to see map:call expanded so that the target 
function can be a bit more generic than an Interpreter (i.e - it is 
easier to implement things like the JSF block, which uses an action or 
Spring webflow).

Ralph

Re: RT: map:call as generic non-redirecting controller code

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Grzegorz Kossakowski skrev:
> Ellis Pritchard pisze:
>>> Do you mean that you would have flowscripts like:
>>>
>>> myFlowAction() {
>>>   var result = calculateSomething();
>>>   setReturnData(result);
>>> }
>>>
>>> I would much prefer to just use the return value of the flowscript:
>>>
>>> myFlowAction() {
>>>   return calculateSomething();
>>> }
>>
>> Agreed, the former is clumsy, but easier/less disruptive to 
>> implement, the latter is much more natural and what I was originally 
>> aiming at.
>>
>> Ok, I'll look out for further feedback, but otherwise submit a patch 
>> using the direct return method for people to review.
>
> Just to be sure, do you want to implement something like:
> <map:match pattern="sth">
>   <map:call function="prepareData"/>
>   <map:generate src="..."/> <- some protocol to obtain the prepared data
>   [...]
> </map:match>
I got the impression that Ellis leaned towards using a special flow 
action instead.

> Such construct introduces new semantics for sitemap because data 
> returned by <map:call> will be available _outside_ <map:call> element. 
> Now it is important what is the scope where the data will be visible. 
> Have you thought about it already?
When you call a pipeline within a flowscript the object model is 
extended with the "bizData". The business data is then available in 
JXTemplate. I think we should use the same mechanism for "flow actions". 
The return value from the flow script is the business data. This should 
then be inserted in the object model see 
org.apache.cocoon.components.flow.AbstractInterpreter.forwardTo 
http://svn.apache.org/repos/asf/cocoon/trunk/core/cocoon-sitemap/cocoon-sitemap-impl/src/main/java/org/apache/cocoon/components/flow/AbstractInterpreter.java. 
By doing that we can use a JXTemplateGenerator after the action and 
extract the needed data.

Of course it should be possible to obtain data from some protocol as 
well. But in many cases it is quite inconvenient to serialize business 
beans to XML and the extract the needed fields with XSLT, it might be 
easier to just access the fields directly with the expression language 
in JXTemplate.

/Daniel


Re: RT: map:call as generic non-redirecting controller code

Posted by Grzegorz Kossakowski <gk...@apache.org>.
Ellis Pritchard pisze:
>> Do you mean that you would have flowscripts like:
>>
>> myFlowAction() {
>>   var result = calculateSomething();
>>   setReturnData(result);
>> }
>>
>> I would much prefer to just use the return value of the flowscript:
>>
>> myFlowAction() {
>>   return calculateSomething();
>> }
> 
> Agreed, the former is clumsy, but easier/less disruptive to implement, 
> the latter is much more natural and what I was originally aiming at.
> 
> Ok, I'll look out for further feedback, but otherwise submit a patch 
> using the direct return method for people to review.

Just to be sure, do you want to implement something like:
<map:match pattern="sth">
   <map:call function="prepareData"/>
   <map:generate src="..."/> <- some protocol to obtain the prepared data
   [...]
</map:match>

Such construct introduces new semantics for sitemap because data returned by <map:call> will be available _outside_ <map:call> element. Now 
it is important what is the scope where the data will be visible. Have you thought about it already?

-- 
Grzegorz Kossakowski
http://reflectingonthevicissitudes.wordpress.com/

Re: RT: map:call as generic non-redirecting controller code

Posted by Ellis Pritchard <el...@nukinetics.com>.
On 5 Jul 2007, at 22:33, Daniel Fagerstrom wrote:

> Ellis Pritchard skrev:
>> Hi,
>> Ok, that looks interesting (head spin); presumably that's a 2.2.  
>> thing with no plans to port back to cocoon 2.1.x?
>> Adding a new non-void method to Interpreter alongside the old one  
>> does seem a bit pointless; currently I've implemented the old  
>> method as just calling the new one: unless this API method is  
>> really set in stone, it would seem to be better to re-factor the  
>> signature of the existing method.
>
> I wouldn't have any problem with such a small refactoring of the  
> API. But I have no expertise in "API development" policy. If anyone  
> have, please give your advice. At least some headup would be needed  
> before doing such s change, so that people that maybe don't follow  
> a detailed technical discussion like this one, can give their  
> feedback.

Yes, but I guess I can always submit a patch and people can vote on  
it afterwards...

>
>> There is an alternative option I haven't previously mentioned;  
>> simply returning values in the same way as 'bizData' is passed to  
>> a sendPage*(), i.e. via the Flow context object. Thus (Grzegorz'  
>> refactorings aside), the only change would be (for convenience) to  
>> add a 'setReturnData()' JS method to call  
>> FlowHelper.setContextObject() (Apples and JavaFlow would just use  
>> FlowHelper) and write a very simple Action to call the flow  
>> function. The flow-attr: module could then be used to access the  
>> returned values in the normal way.
>
> Do you mean that you would have flowscripts like:
>
> myFlowAction() {
>   var result = calculateSomething();
>   setReturnData(result);
> }
>
> I would much prefer to just use the return value of the flowscript:
>
> myFlowAction() {
>   return calculateSomething();
> }

Agreed, the former is clumsy, but easier/less disruptive to  
implement, the latter is much more natural and what I was originally  
aiming at.

Ok, I'll look out for further feedback, but otherwise submit a patch  
using the direct return method for people to review.

Ellis.


Re: RT: map:call as generic non-redirecting controller code

Posted by Vadim Gritsenko <va...@reverycodes.com>.
Daniel Fagerstrom wrote:
> Vadim Gritsenko skrev:

<snip/>

>>   function baz() {
>>     // This will work:
>>     cocoon.result = { one: "one.xml", two: "two.xslt" };
>>     FOM_Cocoon.suicide();
>>
>>     // This does not, without refactoring all of the methods above :)
>>     return { one: "one.xml", two: "two.xslt" };
>>   }
> 
> I think I understand. I haven't used flowscripts in such a low level 
> way. Where is the cocoon.result mechanism implemented?

It's not -- it was one of suggested ways to return result back to sitemap :)


>> If you have non trivial amount of javascript already written, it won't 
>> be possible to use new flowscript actions stuff if they do not work 
>> with suicide() method.
> 
> I guess that the flow action could look for the cocoon.result value in 
> cases where there is no return value from the function. Don't know how 
> to deal with the, FOM_Cocoon.suicide(). Does it have to be dealt with? 

No;

> Doesn't it just work as a break command?

Yes, exactly. Sorta like "jump out of flowscript", but you don't get a return 
result with it.

Vadim

Re: RT: map:call as generic non-redirecting controller code

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Vadim Gritsenko skrev:
> Daniel Fagerstrom wrote:
>> Vadim Gritsenko skrev:
>>> Daniel Fagerstrom wrote:
>>>> I would much prefer to just use the return value of the flowscript:
>>>>
>>>> myFlowAction() {
>>>>   return calculateSomething();
>>>> }
>>>
>>> I don't think this will work with FOM_Cocoon.suicide()
>>
>> That was a cryptic message ;) I need some more details to see what is 
>> the problem.
> 
> Sorry :)
> 
>> To give some context: we are not discussing any changes in how you use 
>> flowscripts. What we discuss is adding an action that reuses the flow 
>> infrastructure. This is for making it easier to write stateless webapps. 
> ...
>> Does the problem you see still apply in the "flow action" scenario?
> 
> Yes; here is minimal example of the situation [1]:
> 
>   <map:act function="foo">
>     <map:generate src="{one}"/>
>     <map:transform src="{two}"/>
>     <map:serialize/>
>   </map:act>
> 
>   function foo() {
>     bar();
>   }
> 
>   function bar() {
>     baz();
>   }
> 
>   function baz() {
>     // This will work:
>     cocoon.result = { one: "one.xml", two: "two.xslt" };
>     FOM_Cocoon.suicide();
> 
>     // This does not, without refactoring all of the methods above :)
>     return { one: "one.xml", two: "two.xslt" };
>   }

I think I understand. I haven't used flowscripts in such a low level 
way. Where is the cocoon.result mechanism implemented?

> 
> If you have non trivial amount of javascript already written, it won't 
> be possible to use new flowscript actions stuff if they do not work with 
> suicide() method.

I guess that the flow action could look for the cocoon.result value in 
cases where there is no return value from the function. Don't know how 
to deal with the, FOM_Cocoon.suicide(). Does it have to be dealt with? 
Doesn't it just work as a break command?

Any suggestion about how to deal with it?

/Daniel


Re: RT: map:call as generic non-redirecting controller code

Posted by Vadim Gritsenko <va...@reverycodes.com>.
Ellis Pritchard wrote:
> 
> On 10 Jul 2007, at 00:03, Vadim Gritsenko wrote:
> 
>>>    <map:transform ...>
>>> </map:act>
>>> where foo() is:
>>> function foo() {
>>>     var a = cocoon.parameters['operand-a'];
>>>     ...
>>>     return {'result-a': 1, 'result-b': 'abc'};
>>> }
>>> Note that map:act has a @src attribute I haven't seen used much; I 
>>> wasn't proposing to add a @function, since this would require 
>>> changing the Action interface (arghh!), but I might (as well) use 
>>> @src to pass the function name.
>>
>> True, attributes on map:act are not passed. But this (@function) can 
>> be implemented fairly easily by changing tree builder. CallNodeBuilder 
>> already does same thing - reacts on presence of @resource, @function 
>> attributes.
> 
> Ok, but doesn't that mean having the Flow Action effectively 'hardwired' 
> by the builder, rather than just a using standard Action with a certain 
> calling convention?

One does not preclude another, isn't it? Action can accept "function" parameter 
and be called as usual; or be hardwired by tree processor - so regardless of 
chosen integration approach, action can be the same.


> I'm not really sure why that is necessary for the 
> sake of a little bit of semantics...

There is a bunch of hard wired components - <aggregator>, <notifier>, 
<translator>, <gatherer>... For the sake of a little bit of semantics :)

Vadim

Re: RT: map:call as generic non-redirecting controller code

Posted by Ellis Pritchard <el...@nukinetics.com>.
On 10 Jul 2007, at 00:03, Vadim Gritsenko wrote:

>>    <map:transform ...>
>> </map:act>
>> where foo() is:
>> function foo() {
>>     var a = cocoon.parameters['operand-a'];
>>     ...
>>     return {'result-a': 1, 'result-b': 'abc'};
>> }
>> Note that map:act has a @src attribute I haven't seen used much; I  
>> wasn't proposing to add a @function, since this would require  
>> changing the Action interface (arghh!), but I might (as well) use  
>> @src to pass the function name.
>
> True, attributes on map:act are not passed. But this (@function)  
> can be implemented fairly easily by changing tree builder.  
> CallNodeBuilder already does same thing - reacts on presence of  
> @resource, @function attributes.

Ok, but doesn't that mean having the Flow Action effectively  
'hardwired' by the builder, rather than just a using standard Action  
with a certain calling convention? I'm not really sure why that is  
necessary for the sake of a little bit of semantics...

Ellis.


Re: RT: map:call as generic non-redirecting controller code

Posted by Vadim Gritsenko <va...@reverycodes.com>.
Ellis Pritchard wrote:
> <map:act type="flow">
>   <map:parameter name="function" value="foo"/>

I suggest <map:act function="flow"> -- see below...


>   <map:parameter name="operand-a" value="{request-param:a}"/>
>   <map:parameter name="operand-b" value="{request-param:a}"/>
> 
>    <map:generate src="bar/{result-a}/{result-b}"/>

Yes that's how I see it too.


>    <map:transform ...>
> </map:act>
> 
> where foo() is:
> 
> function foo() {
>     var a = cocoon.parameters['operand-a'];
>     ...
> 
>     return {'result-a': 1, 'result-b': 'abc'};
> }
> 
> Note that map:act has a @src attribute I haven't seen used much; I 
> wasn't proposing to add a @function, since this would require changing 
> the Action interface (arghh!), but I might (as well) use @src to pass 
> the function name.

True, attributes on map:act are not passed. But this (@function) can be 
implemented fairly easily by changing tree builder. CallNodeBuilder already does 
same thing - reacts on presence of @resource, @function attributes.


Vadim

Re: RT: map:call as generic non-redirecting controller code

Posted by Ellis Pritchard <el...@nukinetics.com>.
Hi all,

To clarify, I wasn't proposing that the 'Flow Action' would reuse  
existing flow code, nor that it would be compatible with  
continuations; this would be a new facility for new code, and only  
used in a functional context, and with map:act, not with map:call  
(which is already too overloaded anyway).

I'm not aware of any other restrictions, however when I get two  
seconds to test my proposed modifications, I'll let you know ;)

For the record I am proposing:

<map:act type="flow">
    <map:parameter name="function" value="foo"/>
   <map:parameter name="operand-a" value="{request-param:a}"/>
   <map:parameter name="operand-b" value="{request-param:a}"/>

    <map:generate src="bar/{result-a}/{result-b}"/>
    <map:transform ...>
</map:act>

where foo() is:

function foo() {
	var a = cocoon.parameters['operand-a'];
	...

	return {'result-a': 1, 'result-b': 'abc'};
}

Note that map:act has a @src attribute I haven't seen used much; I  
wasn't proposing to add a @function, since this would require  
changing the Action interface (arghh!), but I might (as well) use  
@src to pass the function name.

Ellis.



On 8 Jul 2007, at 03:26, Vadim Gritsenko wrote:

> Daniel Fagerstrom wrote:
>> Vadim Gritsenko skrev:
>>> Daniel Fagerstrom wrote:
>>>> I would much prefer to just use the return value of the flowscript:
>>>>
>>>> myFlowAction() {
>>>>   return calculateSomething();
>>>> }
>>>
>>> I don't think this will work with FOM_Cocoon.suicide()
>> That was a cryptic message ;) I need some more details to see what  
>> is the problem.
>
> Sorry :)
>
>> To give some context: we are not discussing any changes in how you  
>> use flowscripts. What we discuss is adding an action that reuses  
>> the flow infrastructure. This is for making it easier to write  
>> stateless webapps.
> ...
>> Does the problem you see still apply in the "flow action" scenario?
>
> Yes; here is minimal example of the situation [1]:
>
>   <map:act function="foo">
>     <map:generate src="{one}"/>
>     <map:transform src="{two}"/>
>     <map:serialize/>
>   </map:act>
>
>   function foo() {
>     bar();
>   }
>
>   function bar() {
>     baz();
>   }
>
>   function baz() {
>     // This will work:
>     cocoon.result = { one: "one.xml", two: "two.xslt" };
>     FOM_Cocoon.suicide();
>
>     // This does not, without refactoring all of the methods above :)
>     return { one: "one.xml", two: "two.xslt" };
>   }
>
> If you have non trivial amount of javascript already written, it  
> won't be possible to use new flowscript actions stuff if they do  
> not work with suicide() method.
>
> [1] Here I suggest using different syntax for flowscript actions,  
> not regular map:call, to remove any possible confusion, and we can  
> preserve existing behavior of map:call.
>
> Vadim


Re: RT: map:call as generic non-redirecting controller code

Posted by Vadim Gritsenko <va...@reverycodes.com>.
Daniel Fagerstrom wrote:
> Vadim Gritsenko skrev:
>> Daniel Fagerstrom wrote:
>>> I would much prefer to just use the return value of the flowscript:
>>>
>>> myFlowAction() {
>>>   return calculateSomething();
>>> }
>>
>> I don't think this will work with FOM_Cocoon.suicide()
> 
> That was a cryptic message ;) I need some more details to see what is 
> the problem.

Sorry :)

> To give some context: we are not discussing any changes in how you use 
> flowscripts. What we discuss is adding an action that reuses the flow 
> infrastructure. This is for making it easier to write stateless webapps. 
...
> Does the problem you see still apply in the "flow action" scenario?

Yes; here is minimal example of the situation [1]:

   <map:act function="foo">
     <map:generate src="{one}"/>
     <map:transform src="{two}"/>
     <map:serialize/>
   </map:act>

   function foo() {
     bar();
   }

   function bar() {
     baz();
   }

   function baz() {
     // This will work:
     cocoon.result = { one: "one.xml", two: "two.xslt" };
     FOM_Cocoon.suicide();

     // This does not, without refactoring all of the methods above :)
     return { one: "one.xml", two: "two.xslt" };
   }

If you have non trivial amount of javascript already written, it won't be 
possible to use new flowscript actions stuff if they do not work with suicide() 
method.

[1] Here I suggest using different syntax for flowscript actions, not regular 
map:call, to remove any possible confusion, and we can preserve existing 
behavior of map:call.

Vadim

Re: RT: map:call as generic non-redirecting controller code

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Vadim Gritsenko skrev:
> Daniel Fagerstrom wrote:
>> I would much prefer to just use the return value of the flowscript:
>>
>> myFlowAction() {
>>   return calculateSomething();
>> }
> 
> I don't think this will work with FOM_Cocoon.suicide()

That was a cryptic message ;) I need some more details to see what is 
the problem.

To give some context: we are not discussing any changes in how you use 
flowscripts. What we discuss is adding an action that reuses the flow 
infrastructure. This is for making it easier to write stateless webapps. 
I'm of course aware of that you can write stateless webapps with the 
flowscript of today by using sendPage. But some of us find that rather 
clumsy and think a flow action would be a worthwhile improvement.

Does the problem you see still apply in the "flow action" scenario?

/Daniel

Re: RT: map:call as generic non-redirecting controller code

Posted by Vadim Gritsenko <va...@reverycodes.com>.
Daniel Fagerstrom wrote:
> I would much prefer to just use the return value of the flowscript:
> 
> myFlowAction() {
>   return calculateSomething();
> }

I don't think this will work with FOM_Cocoon.suicide()

Vadim

Re: RT: map:call as generic non-redirecting controller code

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Ellis Pritchard skrev:
> Hi,
> 
> Ok, that looks interesting (head spin); presumably that's a 2.2. thing 
> with no plans to port back to cocoon 2.1.x?
> 
> Adding a new non-void method to Interpreter alongside the old one does 
> seem a bit pointless; currently I've implemented the old method as just 
> calling the new one: unless this API method is really set in stone, it 
> would seem to be better to re-factor the signature of the existing method.

I wouldn't have any problem with such a small refactoring of the API. 
But I have no expertise in "API development" policy. If anyone have, 
please give your advice. At least some headup would be needed before 
doing such s change, so that people that maybe don't follow a detailed 
technical discussion like this one, can give their feedback.

> Both FlowScript and JavaFlow don't have a problem with this, it won't 
> break anything, but Apples has both an Interpreter implementation 
> (ApplesProcessor) and its own AppleController interface, which is also 
> returning a void. This is more of a problem since this is a 'hard' void 
> rather than the 'soft' void via ScriptRuntime.call() and 
> Method.invoke(): without breaking all Apples, the only way to implement 
> this would be to use the AppleResponse object to set a return value, in 
> much the same way as it is used to set the redirect etc. A little 
> refactoring of ApplesProcessor then needs to pass back this value.

Seem OK to me. But don't know much about Apples.

> However....
> 
> There is an alternative option I haven't previously mentioned; simply 
> returning values in the same way as 'bizData' is passed to a 
> sendPage*(), i.e. via the Flow context object. Thus (Grzegorz' 
> refactorings aside), the only change would be (for convenience) to add a 
> 'setReturnData()' JS method to call FlowHelper.setContextObject() 
> (Apples and JavaFlow would just use FlowHelper) and write a very simple 
> Action to call the flow function. The flow-attr: module could then be 
> used to access the returned values in the normal way.

Do you mean that you would have flowscripts like:

myFlowAction() {
   var result = calculateSomething();
   setReturnData(result);
}

I would much prefer to just use the return value of the flowscript:

myFlowAction() {
   return calculateSomething();
}

/Daniel

Re: RT: map:call as generic non-redirecting controller code

Posted by Ellis Pritchard <el...@nukinetics.com>.
Hi,

Ok, that looks interesting (head spin); presumably that's a 2.2.  
thing with no plans to port back to cocoon 2.1.x?

Adding a new non-void method to Interpreter alongside the old one  
does seem a bit pointless; currently I've implemented the old method  
as just calling the new one: unless this API method is really set in  
stone, it would seem to be better to re-factor the signature of the  
existing method.

Both FlowScript and JavaFlow don't have a problem with this, it won't  
break anything, but Apples has both an Interpreter implementation  
(ApplesProcessor) and its own AppleController interface, which is  
also returning a void. This is more of a problem since this is a  
'hard' void rather than the 'soft' void via ScriptRuntime.call() and  
Method.invoke(): without breaking all Apples, the only way to  
implement this would be to use the AppleResponse object to set a  
return value, in much the same way as it is used to set the redirect  
etc. A little refactoring of ApplesProcessor then needs to pass back  
this value.

However....

There is an alternative option I haven't previously mentioned; simply  
returning values in the same way as 'bizData' is passed to a sendPage* 
(), i.e. via the Flow context object. Thus (Grzegorz' refactorings  
aside), the only change would be (for convenience) to add a  
'setReturnData()' JS method to call FlowHelper.setContextObject()  
(Apples and JavaFlow would just use FlowHelper) and write a very  
simple Action to call the flow function. The flow-attr: module could  
then be used to access the returned values in the normal way.

So revolution or evolution?

Ellis.


On 4 Jul 2007, at 14:57, Grzegorz Kossakowski wrote:

> Daniel Fagerstrom pisze:
>> Ellis Pritchard skrev:
>>> Hi,
>>>
>>> Yes, looking at that thread makes the decision look at best  
>>> arbitrary, at worst spiteful for those who were doing something  
>>> quite elegant with the former behaviour!
>>>
>>> But it's actually not so bad for the 'facists' out there (see the  
>>> thread for why I use this term!!):
>> During a period Cocoon grow explosively, so I think the community  
>> tried to keep some control over the basic contracts. The bad part  
>> was that the community during a period was a little bit to keen to  
>> forbid things. But that attitude disappeared after a while.
>>> It is the CallFunctionNode which enforces the contract of  
>>> redirection, not any higher level flow construct; therefore we  
>>> *could* leave that contract alone, and instead implement this  
>>> functionality (ironically) with an Action, which then defines  
>>> exactly the semantics as discussed (or, if actions are really to  
>>> be frowned upon, an entirely new type of sitemap node).
>> Actions would be OK, (so would IMO modifying the use of call as  
>> well, but that would require a new vote I guess).
>>> So at the minimum we'd only need to:
>>> a) change the Interpreter API to allow a function to return a value.
>> I think that Interpreter is part of our "official" API, so we must  
>> consider back compatibility and our deprecation policy. Does  
>> changing the return value from void to Object create back  
>> incompatibility? If it does the simplest way is probably to add a  
>> new method that has a return value, and possibly deprecating the  
>> current one. Also one have to keep in mind that javaflow and  
>> apples depends on the flow API.
>>> b) write an Action to allow calling the function and returning  
>>> the value to the nested sitemap.
>> Sound good. Your suggestions would IMO be a great addition to  
>> Cocoon which would simplify usage and learning curve. Patches  
>> would be welcome ;)
>
> +1 for all the above. Ellis, if you are going to implement what you  
> proposed it would be helpful to discuss returning and passing  
> values from flowscript. I do not know if you have been reading  
> discussion about planned modifications to Object Model handling. I  
> suggest to read that thread because my modifications are going to  
> affect your work, see: http://thread.gmane.org/ 
> gmane.text.xml.cocoon.devel/73700
>
> -- 
> Grzegorz Kossakowski
> http://reflectingonthevicissitudes.wordpress.com/


Re: RT: map:call as generic non-redirecting controller code

Posted by Grzegorz Kossakowski <gk...@apache.org>.
Daniel Fagerstrom pisze:
> Ellis Pritchard skrev:
>> Hi,
>>
>> Yes, looking at that thread makes the decision look at best arbitrary, 
>> at worst spiteful for those who were doing something quite elegant 
>> with the former behaviour!
>>
>> But it's actually not so bad for the 'facists' out there (see the 
>> thread for why I use this term!!):
> During a period Cocoon grow explosively, so I think the community tried 
> to keep some control over the basic contracts. The bad part was that the 
> community during a period was a little bit to keen to forbid things. But 
> that attitude disappeared after a while.
> 
>> It is the CallFunctionNode which enforces the contract of redirection, 
>> not any higher level flow construct; therefore we *could* leave that 
>> contract alone, and instead implement this functionality (ironically) 
>> with an Action, which then defines exactly the semantics as discussed 
>> (or, if actions are really to be frowned upon, an entirely new type of 
>> sitemap node).
> Actions would be OK, (so would IMO modifying the use of call as well, 
> but that would require a new vote I guess).
> 
>> So at the minimum we'd only need to:
>> a) change the Interpreter API to allow a function to return a value.
> I think that Interpreter is part of our "official" API, so we must 
> consider back compatibility and our deprecation policy. Does changing 
> the return value from void to Object create back incompatibility? If it 
> does the simplest way is probably to add a new method that has a return 
> value, and possibly deprecating the current one. Also one have to keep 
> in mind that javaflow and apples depends on the flow API.
> 
>> b) write an Action to allow calling the function and returning the 
>> value to the nested sitemap.
> 
> Sound good. Your suggestions would IMO be a great addition to Cocoon 
> which would simplify usage and learning curve. Patches would be welcome ;)

+1 for all the above. Ellis, if you are going to implement what you proposed it would be helpful to discuss returning and passing values 
from flowscript. I do not know if you have been reading discussion about planned modifications to Object Model handling. I suggest to read 
that thread because my modifications are going to affect your work, see: http://thread.gmane.org/gmane.text.xml.cocoon.devel/73700

-- 
Grzegorz Kossakowski
http://reflectingonthevicissitudes.wordpress.com/

Re: RT: map:call as generic non-redirecting controller code

Posted by Peter Hunsberger <pe...@gmail.com>.
On 7/4/07, Daniel Fagerstrom <da...@nada.kth.se> wrote:

<snip/>

> > So at the minimum we'd only need to:
> > a) change the Interpreter API to allow a function to return a value.

> I think that Interpreter is part of our "official" API, so we must
> consider back compatibility and our deprecation policy. Does changing
> the return value from void to Object create back incompatibility? If it
> does the simplest way is probably to add a new method that has a return
> value, and possibly deprecating the current one. Also one have to keep
> in mind that javaflow and apples depends on the flow API.
>

I think we had this discussion once before (though I'm too lazy to go
look it up)?  I don't see how adding a returned object could break
anything if a function currently returns void?  I'd say you don't need
a new method, but you may need to put it to a vote...

<snip/>

-- 
Peter Hunsberger

Re: RT: map:call as generic non-redirecting controller code

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Ellis Pritchard skrev:
> Hi,
>
> Yes, looking at that thread makes the decision look at best arbitrary, 
> at worst spiteful for those who were doing something quite elegant 
> with the former behaviour!
>
> But it's actually not so bad for the 'facists' out there (see the 
> thread for why I use this term!!):
During a period Cocoon grow explosively, so I think the community tried 
to keep some control over the basic contracts. The bad part was that the 
community during a period was a little bit to keen to forbid things. But 
that attitude disappeared after a while.

> It is the CallFunctionNode which enforces the contract of redirection, 
> not any higher level flow construct; therefore we *could* leave that 
> contract alone, and instead implement this functionality (ironically) 
> with an Action, which then defines exactly the semantics as discussed 
> (or, if actions are really to be frowned upon, an entirely new type of 
> sitemap node).
Actions would be OK, (so would IMO modifying the use of call as well, 
but that would require a new vote I guess).

> So at the minimum we'd only need to:
> a) change the Interpreter API to allow a function to return a value.
I think that Interpreter is part of our "official" API, so we must 
consider back compatibility and our deprecation policy. Does changing 
the return value from void to Object create back incompatibility? If it 
does the simplest way is probably to add a new method that has a return 
value, and possibly deprecating the current one. Also one have to keep 
in mind that javaflow and apples depends on the flow API.

> b) write an Action to allow calling the function and returning the 
> value to the nested sitemap.

Sound good. Your suggestions would IMO be a great addition to Cocoon 
which would simplify usage and learning curve. Patches would be welcome ;)

/Daniel