Re: RT: map:call as generic non-redirecting controller code
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
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
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
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
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
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
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
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
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
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
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
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
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
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=sayNo/ 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
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
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
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
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-startupresource://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 !-- debuggerenabled/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
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
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
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
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
Re: RT: map:call as generic non-redirecting controller code
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
On 7/4/07, Daniel Fagerstrom [EMAIL PROTECTED] 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
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=10684956638r=1w=2 and then the error check was introduced: http://marc.info/?l=xml-cocoon-cvsm=106858783407241w=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=10684956638r=1w=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
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=10684956638r=1w=2 and then the error check was introduced: http://marc.info/?l=xml-cocoon-cvsm=106858783407241w=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=10684956638r=1w=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