You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by Boris Partensky <bo...@gmail.com> on 2012/04/30 17:49:39 UTC

upgrading from 1.5 to 1.7 compatibility issues

Hello, while going through the upgrade I noticed an incompatible
behavior during nested macro evaluation. Looks like in 1.7 (all
default properties) child macro has access to variables set in parent
macro scope (and those take precedence over globals), and 1.5 sees
globals. In the following example, in 1.5 unit test the following
template will evaluate to "globalvar", and in 1.7 - to
"outermacroparam". Is this expected behavior?


1.5 test case


public void testVelocityNestedMacroScope() throws Exception
    {
        VelocityEngine ve = new VelocityEngine();

        ve.init();

        String template = "#macro(outerMacro $arg1)"+
                          "#innerMacro('blah')"+
                          "#end"+
                          "#macro(innerMacro $arg2)$arg1#end"+

"#set($arg1='globalval')#outerMacro('outermacroparam')";
        StringWriter eval = new StringWriter();
        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
        assertEquals(eval.toString(), "globalval", eval.toString());

    }

1.7 test case


 public void testVelocityNestedMacroScope()
    {
        String template = "#macro(outerMacro $arg1)"+
                          "#innerMacro('blah')"+
                          "#end"+
                          "#macro(innerMacro $arg2)$arg1#end"+

"#set($arg1='globalvar')#outerMacro('outermacroparam')";
        String eval = evaluate(template);
        assertEquals(eval, "outermacroparam", eval);

    }

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Nathan Bubna <nb...@gmail.com>.
This might be of use too:
http://velocity.apache.org/engine/releases/velocity-1.7/upgrading.html

On Mon, Apr 30, 2012 at 12:51 PM, Nathan Bubna <nb...@gmail.com> wrote:
> http://velocity.apache.org/engine/devel/changes-report.html#a1.7
>
> On Mon, Apr 30, 2012 at 12:37 PM, Boris Partensky
> <bo...@gmail.com> wrote:
>> No problem, thanks for making things clear.
>>
>> << we decided to forego it and notify users of the non-BC change when
>> we released 1.7.
>>
>> which notification are you referring to? Wonder if there is something
>> else in there I am not aware of.
>>
>>
>> On Mon, Apr 30, 2012 at 2:34 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>> Congratulations, Boris.  You are the corner case we feared.  :-/  We
>>> knew when we went ahead with this that providing a migration path
>>> would be difficult.  We knew most users didn't have extreme numbers of
>>> macros and hoped that those who didn't frequently nest them, in part
>>> because of the complexities of heavy scoping in a language that often
>>> treated scoping as a second-class feature, and in part because of the
>>> performance issues macros had prior to 1.6.  #parse,
>>> VelocityLayoutServlet and even custom tools, which lack the implicit
>>> scoping support, tended to be more performant and encouraged for
>>> simplifying complicated tools.  Considering those things and the
>>> difficulty of implementing a BC switch for implicit scoping, we
>>> decided to forego it and notify users of the non-BC change when we
>>> released 1.7.
>>>
>>> Sorry.  It sounds like it's going to take some legwork to upgrade in
>>> the cases where you nested your macros.
>>>
>>> On Mon, Apr 30, 2012 at 11:16 AM, Boris Partensky
>>> <bo...@gmail.com> wrote:
>>>> Yep, I am afraid we do set globals from within macros...
>>>>
>>>> On Mon, Apr 30, 2012 at 2:05 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>> Can you set velocimacro.context.localscope = true or is it important
>>>>> for your system to be able to #set global stuff from within macros?
>>>>>
>>>>> On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky
>>>>> <bo...@gmail.com> wrote:
>>>>>> Thanks Nathan, I think I do get the whole scoping idea, but my
>>>>>> understanding was that one of the reasons to turn all scoping off by
>>>>>> default (and have those properties to begin with) was to provide
>>>>>> backward compatibility - as in: I upgrade to 1.7 and then I start
>>>>>> turning on all those nice bells and whistles and use scopes and what
>>>>>> not. Not so seems like? I also find somewhat strange that a a formal
>>>>>> argument to a macro takes precedence and overwrites a global variable
>>>>>> with the same name. How would one go about upgrading existing systems?
>>>>>> We have roughly 1900 macros, big chunk of those are nested... Maybe I
>>>>>> am misunderstanding something, but this issue makes it almost
>>>>>> impossible to upgrade (at least for us).
>>>>>>
>>>>>>
>>>>>> Thanks
>>>>>> Boris
>>>>>>
>>>>>> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>>>> Yeah, it was intended, and part of an overall move toward
>>>>>>> fixing/simplifying Velocity's variable scoping, avoiding the
>>>>>>> complexities and costs (performance, yes, but mostly time/brainpower
>>>>>>> for users and devs alike) of more programming language type behavior.
>>>>>>> Velocity has long aspired to be a straightfoward template engine and
>>>>>>> avoid being a complete scripting language.  (Implicit) variable
>>>>>>> scoping, as seen in 1.5, was seen as a necessary compromise toward the
>>>>>>> latter; after all, one big fat namespace is always unmanageable,
>>>>>>> right?  Well, there's ways to make that easy to manage. :)  Let's call
>>>>>>> it "optional, provided, explicit scoping", explicit because you don't
>>>>>>> have to grok the contextual scope to understand a reference, optional
>>>>>>> because you can ignore it, and provided because Velocity does the work
>>>>>>> of choosing "prefixes" and creating/destroying the scopes (as any
>>>>>>> implicit scoping system does).  So everything is becoming globally
>>>>>>> scoped, but it is now trivial to turn on automatic, explicit scopes or
>>>>>>> namespaces that you can use when you don't want things to live in the
>>>>>>> global scope.
>>>>>>>
>>>>>>> Here's an example...  Do you use $velocityCount to get an index of
>>>>>>> sorts inside of #foreach directives?  Well, that's an example of mixed
>>>>>>> implicit/explicit namespacing that gets messy when you nest
>>>>>>> #foreach's, with no good way to get the parent's count and
>>>>>>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
>>>>>>> so on.  Now, we automatically manage a $foreach var that not only has
>>>>>>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
>>>>>>> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>>>>>>>  It also, of course, accepts any property you want to set on it (like
>>>>>>> any map).  This makes templates instantly understandable, making
>>>>>>> debugging much better.  You always know exactly what you are referring
>>>>>>> to, and so does anyone else reading the template.
>>>>>>>
>>>>>>> #foreach is the only 'content directive' that has its explicit scope
>>>>>>> automatically turned on, but all content containing directives
>>>>>>> (including custom body macros) can have their own explicit,
>>>>>>> auto-managed scope, named after themselves.  for example, you can flip
>>>>>>> the macro scope on:
>>>>>>>
>>>>>>> macro.provide.scope.control = true
>>>>>>>
>>>>>>> and do:
>>>>>>>
>>>>>>> #macro( outer $arg )
>>>>>>>  #set( $macro.arg = $arg )
>>>>>>>  #inner( 'inner' )
>>>>>>> #end
>>>>>>> #macro( inner $arg )
>>>>>>>  #set( $macro.arg = $arg)
>>>>>>>  inner: $macro.arg
>>>>>>>  #if( $macro.parent )outer: $macro.parent.arg#end
>>>>>>> #end
>>>>>>>
>>>>>>> #outer( 'outer' )
>>>>>>> #inner( 'just inner' )
>>>>>>>
>>>>>>> and get
>>>>>>>
>>>>>>>  inner: inner
>>>>>>>  outer: outer
>>>>>>>  inner: just inner
>>>>>>>
>>>>>>> Hope this helps...
>>>>>>>
>>>>>>> In any case, there was plenty of thought and discussion that went into
>>>>>>> this change.  Search http://velocity.markmail.org for 'scope' and you
>>>>>>> should find more on this.
>>>>>>>
>>>>>>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
>>>>>>> <bo...@gmail.com> wrote:
>>>>>>>> Hello, while going through the upgrade I noticed an incompatible
>>>>>>>> behavior during nested macro evaluation. Looks like in 1.7 (all
>>>>>>>> default properties) child macro has access to variables set in parent
>>>>>>>> macro scope (and those take precedence over globals), and 1.5 sees
>>>>>>>> globals. In the following example, in 1.5 unit test the following
>>>>>>>> template will evaluate to "globalvar", and in 1.7 - to
>>>>>>>> "outermacroparam". Is this expected behavior?
>>>>>>>>
>>>>>>>>
>>>>>>>> 1.5 test case
>>>>>>>>
>>>>>>>>
>>>>>>>> public void testVelocityNestedMacroScope() throws Exception
>>>>>>>>    {
>>>>>>>>        VelocityEngine ve = new VelocityEngine();
>>>>>>>>
>>>>>>>>        ve.init();
>>>>>>>>
>>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>>                          "#end"+
>>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>>
>>>>>>>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>>>>>>>        StringWriter eval = new StringWriter();
>>>>>>>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>>>>>>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>>>>>>>
>>>>>>>>    }
>>>>>>>>
>>>>>>>> 1.7 test case
>>>>>>>>
>>>>>>>>
>>>>>>>>  public void testVelocityNestedMacroScope()
>>>>>>>>    {
>>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>>                          "#end"+
>>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>>
>>>>>>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>>>>>>>        String eval = evaluate(template);
>>>>>>>>        assertEquals(eval, "outermacroparam", eval);
>>>>>>>>
>>>>>>>>    }
>>>>>>>>
>>>>>>>> ---------------------------------------------------------------------
>>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>>
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Nathan Bubna <nb...@gmail.com>.
On Tue, May 1, 2012 at 7:59 AM, Boris Partensky
<bo...@gmail.com> wrote:
>> Yes, compatibility was and is a goal, but with limited resources,
>> continuing support for implicit scoping in macros didn't make the cut.
>
> Ok. Are there any BC corner cases other than nested macros I should be
> aware of? I could not really find the No-BC notification you had
> mentioned.

Hmm.  I think the #evaluate directive also lost its implicit scope,
but i'd have to double check on that.

>>> * When scopes of the same type are nested make the parent Scope
>>> available through the child (e.g. $foreach.parent or
>>> $foreach.topmost).
>
> Thanks. So, with macro.provide.scope.control =true scoping behavior
> should stay the same, and I'd have to explicitly use scope handles to
> reach different scopes, like $mymacroname.parent for example, or
> $macro.parent. Is this correct?

Yep.  Explicit read/write is the name of the game.  And just to make
sure we're on the same page, $mymacroname scope control would only be
provided when using #macro( mymacroname ) as a macro with a body
(#@mymacroname() $mymacroname #end) and you set

mymacroname.provide.scope.control = true

and $mymacroname.parent would only exist if you are nesting calls to
#@mymacroname

:)


> Thanks
> Boris
>
>
>
> On Mon, Apr 30, 2012 at 5:08 PM, Nathan Bubna <nb...@gmail.com> wrote:
>> On Mon, Apr 30, 2012 at 1:06 PM, Boris Partensky
>> <bo...@gmail.com> wrote:
>>> I am seeing 3 bullet points there pertinent to this issue and all 3
>>> seem to indicate that being compatible was the intention there, or am
>>> I wrong ? The way I read #2 and #3 is that the parent scope should
>>> only be available if I explicitly specify the scope I want (parent or
>>> topmost or replaced).
>>
>> Yes, compatibility was and is a goal, but with limited resources,
>> continuing support for implicit scoping in macros didn't make the cut.
>>
>>> * For performance and compatibility these are all off by default,
>>> *except* for $foreach. The others may be enabled by setting a velocity
>>> property like:macro.provide.scope.control = true
>>
>> "off for compatibility" here means reduced chance of squashing
>> someone's previous $macro or $template var, or more realistically $foo
>> when there is a body macro call #foo
>>
>>> * When scopes of the same type are nested make the parent Scope
>>> available through the child (e.g. $foreach.parent or
>>> $foreach.topmost).
>>
>> $<scope>.parent is always and only made available when there actually
>> is an explicit parent scope provided. e.g.
>>
>> #foreach( $a in $b )
>>   #foreach( $c in $d )
>>     $foreach.parent here == $foreach.topmost
>>   #end
>>  $foreach here == $foreach.topmost
>> #end
>>
>> Think parent and topmost as ways to navigate the scope stack, which
>> only exists when <scope>.provide.scope.control = true
>>
>>> * When a Scope reference overrides an existing reference that is not a
>>> Scope, make it available through the Scope (e.g. $foreach.replaced).
>>
>> $<scope>.replaced is not a parent scope, but is 'bar' in the example:
>> #set($foo='bar') #@foo $foo.replaced #end
>>
>> This is a workaround for incompatibilities/migrations/etc.  It doesn't
>> provide any compatibility with the older implicit system of scoping.
>>
>>> On Mon, Apr 30, 2012 at 3:51 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>> http://velocity.apache.org/engine/devel/changes-report.html#a1.7
>>>>
>>>> On Mon, Apr 30, 2012 at 12:37 PM, Boris Partensky
>>>> <bo...@gmail.com> wrote:
>>>>> No problem, thanks for making things clear.
>>>>>
>>>>> << we decided to forego it and notify users of the non-BC change when
>>>>> we released 1.7.
>>>>>
>>>>> which notification are you referring to? Wonder if there is something
>>>>> else in there I am not aware of.
>>>>>
>>>>>
>>>>> On Mon, Apr 30, 2012 at 2:34 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>>> Congratulations, Boris.  You are the corner case we feared.  :-/  We
>>>>>> knew when we went ahead with this that providing a migration path
>>>>>> would be difficult.  We knew most users didn't have extreme numbers of
>>>>>> macros and hoped that those who didn't frequently nest them, in part
>>>>>> because of the complexities of heavy scoping in a language that often
>>>>>> treated scoping as a second-class feature, and in part because of the
>>>>>> performance issues macros had prior to 1.6.  #parse,
>>>>>> VelocityLayoutServlet and even custom tools, which lack the implicit
>>>>>> scoping support, tended to be more performant and encouraged for
>>>>>> simplifying complicated tools.  Considering those things and the
>>>>>> difficulty of implementing a BC switch for implicit scoping, we
>>>>>> decided to forego it and notify users of the non-BC change when we
>>>>>> released 1.7.
>>>>>>
>>>>>> Sorry.  It sounds like it's going to take some legwork to upgrade in
>>>>>> the cases where you nested your macros.
>>>>>>
>>>>>> On Mon, Apr 30, 2012 at 11:16 AM, Boris Partensky
>>>>>> <bo...@gmail.com> wrote:
>>>>>>> Yep, I am afraid we do set globals from within macros...
>>>>>>>
>>>>>>> On Mon, Apr 30, 2012 at 2:05 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>>>>> Can you set velocimacro.context.localscope = true or is it important
>>>>>>>> for your system to be able to #set global stuff from within macros?
>>>>>>>>
>>>>>>>> On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky
>>>>>>>> <bo...@gmail.com> wrote:
>>>>>>>>> Thanks Nathan, I think I do get the whole scoping idea, but my
>>>>>>>>> understanding was that one of the reasons to turn all scoping off by
>>>>>>>>> default (and have those properties to begin with) was to provide
>>>>>>>>> backward compatibility - as in: I upgrade to 1.7 and then I start
>>>>>>>>> turning on all those nice bells and whistles and use scopes and what
>>>>>>>>> not. Not so seems like? I also find somewhat strange that a a formal
>>>>>>>>> argument to a macro takes precedence and overwrites a global variable
>>>>>>>>> with the same name. How would one go about upgrading existing systems?
>>>>>>>>> We have roughly 1900 macros, big chunk of those are nested... Maybe I
>>>>>>>>> am misunderstanding something, but this issue makes it almost
>>>>>>>>> impossible to upgrade (at least for us).
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Thanks
>>>>>>>>> Boris
>>>>>>>>>
>>>>>>>>> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>>>>>>> Yeah, it was intended, and part of an overall move toward
>>>>>>>>>> fixing/simplifying Velocity's variable scoping, avoiding the
>>>>>>>>>> complexities and costs (performance, yes, but mostly time/brainpower
>>>>>>>>>> for users and devs alike) of more programming language type behavior.
>>>>>>>>>> Velocity has long aspired to be a straightfoward template engine and
>>>>>>>>>> avoid being a complete scripting language.  (Implicit) variable
>>>>>>>>>> scoping, as seen in 1.5, was seen as a necessary compromise toward the
>>>>>>>>>> latter; after all, one big fat namespace is always unmanageable,
>>>>>>>>>> right?  Well, there's ways to make that easy to manage. :)  Let's call
>>>>>>>>>> it "optional, provided, explicit scoping", explicit because you don't
>>>>>>>>>> have to grok the contextual scope to understand a reference, optional
>>>>>>>>>> because you can ignore it, and provided because Velocity does the work
>>>>>>>>>> of choosing "prefixes" and creating/destroying the scopes (as any
>>>>>>>>>> implicit scoping system does).  So everything is becoming globally
>>>>>>>>>> scoped, but it is now trivial to turn on automatic, explicit scopes or
>>>>>>>>>> namespaces that you can use when you don't want things to live in the
>>>>>>>>>> global scope.
>>>>>>>>>>
>>>>>>>>>> Here's an example...  Do you use $velocityCount to get an index of
>>>>>>>>>> sorts inside of #foreach directives?  Well, that's an example of mixed
>>>>>>>>>> implicit/explicit namespacing that gets messy when you nest
>>>>>>>>>> #foreach's, with no good way to get the parent's count and
>>>>>>>>>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
>>>>>>>>>> so on.  Now, we automatically manage a $foreach var that not only has
>>>>>>>>>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
>>>>>>>>>> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>>>>>>>>>>  It also, of course, accepts any property you want to set on it (like
>>>>>>>>>> any map).  This makes templates instantly understandable, making
>>>>>>>>>> debugging much better.  You always know exactly what you are referring
>>>>>>>>>> to, and so does anyone else reading the template.
>>>>>>>>>>
>>>>>>>>>> #foreach is the only 'content directive' that has its explicit scope
>>>>>>>>>> automatically turned on, but all content containing directives
>>>>>>>>>> (including custom body macros) can have their own explicit,
>>>>>>>>>> auto-managed scope, named after themselves.  for example, you can flip
>>>>>>>>>> the macro scope on:
>>>>>>>>>>
>>>>>>>>>> macro.provide.scope.control = true
>>>>>>>>>>
>>>>>>>>>> and do:
>>>>>>>>>>
>>>>>>>>>> #macro( outer $arg )
>>>>>>>>>>  #set( $macro.arg = $arg )
>>>>>>>>>>  #inner( 'inner' )
>>>>>>>>>> #end
>>>>>>>>>> #macro( inner $arg )
>>>>>>>>>>  #set( $macro.arg = $arg)
>>>>>>>>>>  inner: $macro.arg
>>>>>>>>>>  #if( $macro.parent )outer: $macro.parent.arg#end
>>>>>>>>>> #end
>>>>>>>>>>
>>>>>>>>>> #outer( 'outer' )
>>>>>>>>>> #inner( 'just inner' )
>>>>>>>>>>
>>>>>>>>>> and get
>>>>>>>>>>
>>>>>>>>>>  inner: inner
>>>>>>>>>>  outer: outer
>>>>>>>>>>  inner: just inner
>>>>>>>>>>
>>>>>>>>>> Hope this helps...
>>>>>>>>>>
>>>>>>>>>> In any case, there was plenty of thought and discussion that went into
>>>>>>>>>> this change.  Search http://velocity.markmail.org for 'scope' and you
>>>>>>>>>> should find more on this.
>>>>>>>>>>
>>>>>>>>>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
>>>>>>>>>> <bo...@gmail.com> wrote:
>>>>>>>>>>> Hello, while going through the upgrade I noticed an incompatible
>>>>>>>>>>> behavior during nested macro evaluation. Looks like in 1.7 (all
>>>>>>>>>>> default properties) child macro has access to variables set in parent
>>>>>>>>>>> macro scope (and those take precedence over globals), and 1.5 sees
>>>>>>>>>>> globals. In the following example, in 1.5 unit test the following
>>>>>>>>>>> template will evaluate to "globalvar", and in 1.7 - to
>>>>>>>>>>> "outermacroparam". Is this expected behavior?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> 1.5 test case
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> public void testVelocityNestedMacroScope() throws Exception
>>>>>>>>>>>    {
>>>>>>>>>>>        VelocityEngine ve = new VelocityEngine();
>>>>>>>>>>>
>>>>>>>>>>>        ve.init();
>>>>>>>>>>>
>>>>>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>>>>>                          "#end"+
>>>>>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>>>>>
>>>>>>>>>>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>>>>>>>>>>        StringWriter eval = new StringWriter();
>>>>>>>>>>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>>>>>>>>>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>>>>>>>>>>
>>>>>>>>>>>    }
>>>>>>>>>>>
>>>>>>>>>>> 1.7 test case
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>  public void testVelocityNestedMacroScope()
>>>>>>>>>>>    {
>>>>>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>>>>>                          "#end"+
>>>>>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>>>>>
>>>>>>>>>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>>>>>>>>>>        String eval = evaluate(template);
>>>>>>>>>>>        assertEquals(eval, "outermacroparam", eval);
>>>>>>>>>>>
>>>>>>>>>>>    }
>>>>>>>>>>>
>>>>>>>>>>> ---------------------------------------------------------------------
>>>>>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> ---------------------------------------------------------------------
>>>>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> ---------------------------------------------------------------------
>>>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>>>
>>>>>>>>
>>>>>>>> ---------------------------------------------------------------------
>>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>>
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Boris Partensky <bo...@gmail.com>.
> Yes, compatibility was and is a goal, but with limited resources,
> continuing support for implicit scoping in macros didn't make the cut.

Ok. Are there any BC corner cases other than nested macros I should be
aware of? I could not really find the No-BC notification you had
mentioned.

>> * When scopes of the same type are nested make the parent Scope
>> available through the child (e.g. $foreach.parent or
>> $foreach.topmost).

Thanks. So, with macro.provide.scope.control =true scoping behavior
should stay the same, and I'd have to explicitly use scope handles to
reach different scopes, like $mymacroname.parent for example, or
$macro.parent. Is this correct?

Thanks
Boris



On Mon, Apr 30, 2012 at 5:08 PM, Nathan Bubna <nb...@gmail.com> wrote:
> On Mon, Apr 30, 2012 at 1:06 PM, Boris Partensky
> <bo...@gmail.com> wrote:
>> I am seeing 3 bullet points there pertinent to this issue and all 3
>> seem to indicate that being compatible was the intention there, or am
>> I wrong ? The way I read #2 and #3 is that the parent scope should
>> only be available if I explicitly specify the scope I want (parent or
>> topmost or replaced).
>
> Yes, compatibility was and is a goal, but with limited resources,
> continuing support for implicit scoping in macros didn't make the cut.
>
>> * For performance and compatibility these are all off by default,
>> *except* for $foreach. The others may be enabled by setting a velocity
>> property like:macro.provide.scope.control = true
>
> "off for compatibility" here means reduced chance of squashing
> someone's previous $macro or $template var, or more realistically $foo
> when there is a body macro call #foo
>
>> * When scopes of the same type are nested make the parent Scope
>> available through the child (e.g. $foreach.parent or
>> $foreach.topmost).
>
> $<scope>.parent is always and only made available when there actually
> is an explicit parent scope provided. e.g.
>
> #foreach( $a in $b )
>   #foreach( $c in $d )
>     $foreach.parent here == $foreach.topmost
>   #end
>  $foreach here == $foreach.topmost
> #end
>
> Think parent and topmost as ways to navigate the scope stack, which
> only exists when <scope>.provide.scope.control = true
>
>> * When a Scope reference overrides an existing reference that is not a
>> Scope, make it available through the Scope (e.g. $foreach.replaced).
>
> $<scope>.replaced is not a parent scope, but is 'bar' in the example:
> #set($foo='bar') #@foo $foo.replaced #end
>
> This is a workaround for incompatibilities/migrations/etc.  It doesn't
> provide any compatibility with the older implicit system of scoping.
>
>> On Mon, Apr 30, 2012 at 3:51 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>> http://velocity.apache.org/engine/devel/changes-report.html#a1.7
>>>
>>> On Mon, Apr 30, 2012 at 12:37 PM, Boris Partensky
>>> <bo...@gmail.com> wrote:
>>>> No problem, thanks for making things clear.
>>>>
>>>> << we decided to forego it and notify users of the non-BC change when
>>>> we released 1.7.
>>>>
>>>> which notification are you referring to? Wonder if there is something
>>>> else in there I am not aware of.
>>>>
>>>>
>>>> On Mon, Apr 30, 2012 at 2:34 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>> Congratulations, Boris.  You are the corner case we feared.  :-/  We
>>>>> knew when we went ahead with this that providing a migration path
>>>>> would be difficult.  We knew most users didn't have extreme numbers of
>>>>> macros and hoped that those who didn't frequently nest them, in part
>>>>> because of the complexities of heavy scoping in a language that often
>>>>> treated scoping as a second-class feature, and in part because of the
>>>>> performance issues macros had prior to 1.6.  #parse,
>>>>> VelocityLayoutServlet and even custom tools, which lack the implicit
>>>>> scoping support, tended to be more performant and encouraged for
>>>>> simplifying complicated tools.  Considering those things and the
>>>>> difficulty of implementing a BC switch for implicit scoping, we
>>>>> decided to forego it and notify users of the non-BC change when we
>>>>> released 1.7.
>>>>>
>>>>> Sorry.  It sounds like it's going to take some legwork to upgrade in
>>>>> the cases where you nested your macros.
>>>>>
>>>>> On Mon, Apr 30, 2012 at 11:16 AM, Boris Partensky
>>>>> <bo...@gmail.com> wrote:
>>>>>> Yep, I am afraid we do set globals from within macros...
>>>>>>
>>>>>> On Mon, Apr 30, 2012 at 2:05 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>>>> Can you set velocimacro.context.localscope = true or is it important
>>>>>>> for your system to be able to #set global stuff from within macros?
>>>>>>>
>>>>>>> On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky
>>>>>>> <bo...@gmail.com> wrote:
>>>>>>>> Thanks Nathan, I think I do get the whole scoping idea, but my
>>>>>>>> understanding was that one of the reasons to turn all scoping off by
>>>>>>>> default (and have those properties to begin with) was to provide
>>>>>>>> backward compatibility - as in: I upgrade to 1.7 and then I start
>>>>>>>> turning on all those nice bells and whistles and use scopes and what
>>>>>>>> not. Not so seems like? I also find somewhat strange that a a formal
>>>>>>>> argument to a macro takes precedence and overwrites a global variable
>>>>>>>> with the same name. How would one go about upgrading existing systems?
>>>>>>>> We have roughly 1900 macros, big chunk of those are nested... Maybe I
>>>>>>>> am misunderstanding something, but this issue makes it almost
>>>>>>>> impossible to upgrade (at least for us).
>>>>>>>>
>>>>>>>>
>>>>>>>> Thanks
>>>>>>>> Boris
>>>>>>>>
>>>>>>>> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>>>>>> Yeah, it was intended, and part of an overall move toward
>>>>>>>>> fixing/simplifying Velocity's variable scoping, avoiding the
>>>>>>>>> complexities and costs (performance, yes, but mostly time/brainpower
>>>>>>>>> for users and devs alike) of more programming language type behavior.
>>>>>>>>> Velocity has long aspired to be a straightfoward template engine and
>>>>>>>>> avoid being a complete scripting language.  (Implicit) variable
>>>>>>>>> scoping, as seen in 1.5, was seen as a necessary compromise toward the
>>>>>>>>> latter; after all, one big fat namespace is always unmanageable,
>>>>>>>>> right?  Well, there's ways to make that easy to manage. :)  Let's call
>>>>>>>>> it "optional, provided, explicit scoping", explicit because you don't
>>>>>>>>> have to grok the contextual scope to understand a reference, optional
>>>>>>>>> because you can ignore it, and provided because Velocity does the work
>>>>>>>>> of choosing "prefixes" and creating/destroying the scopes (as any
>>>>>>>>> implicit scoping system does).  So everything is becoming globally
>>>>>>>>> scoped, but it is now trivial to turn on automatic, explicit scopes or
>>>>>>>>> namespaces that you can use when you don't want things to live in the
>>>>>>>>> global scope.
>>>>>>>>>
>>>>>>>>> Here's an example...  Do you use $velocityCount to get an index of
>>>>>>>>> sorts inside of #foreach directives?  Well, that's an example of mixed
>>>>>>>>> implicit/explicit namespacing that gets messy when you nest
>>>>>>>>> #foreach's, with no good way to get the parent's count and
>>>>>>>>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
>>>>>>>>> so on.  Now, we automatically manage a $foreach var that not only has
>>>>>>>>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
>>>>>>>>> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>>>>>>>>>  It also, of course, accepts any property you want to set on it (like
>>>>>>>>> any map).  This makes templates instantly understandable, making
>>>>>>>>> debugging much better.  You always know exactly what you are referring
>>>>>>>>> to, and so does anyone else reading the template.
>>>>>>>>>
>>>>>>>>> #foreach is the only 'content directive' that has its explicit scope
>>>>>>>>> automatically turned on, but all content containing directives
>>>>>>>>> (including custom body macros) can have their own explicit,
>>>>>>>>> auto-managed scope, named after themselves.  for example, you can flip
>>>>>>>>> the macro scope on:
>>>>>>>>>
>>>>>>>>> macro.provide.scope.control = true
>>>>>>>>>
>>>>>>>>> and do:
>>>>>>>>>
>>>>>>>>> #macro( outer $arg )
>>>>>>>>>  #set( $macro.arg = $arg )
>>>>>>>>>  #inner( 'inner' )
>>>>>>>>> #end
>>>>>>>>> #macro( inner $arg )
>>>>>>>>>  #set( $macro.arg = $arg)
>>>>>>>>>  inner: $macro.arg
>>>>>>>>>  #if( $macro.parent )outer: $macro.parent.arg#end
>>>>>>>>> #end
>>>>>>>>>
>>>>>>>>> #outer( 'outer' )
>>>>>>>>> #inner( 'just inner' )
>>>>>>>>>
>>>>>>>>> and get
>>>>>>>>>
>>>>>>>>>  inner: inner
>>>>>>>>>  outer: outer
>>>>>>>>>  inner: just inner
>>>>>>>>>
>>>>>>>>> Hope this helps...
>>>>>>>>>
>>>>>>>>> In any case, there was plenty of thought and discussion that went into
>>>>>>>>> this change.  Search http://velocity.markmail.org for 'scope' and you
>>>>>>>>> should find more on this.
>>>>>>>>>
>>>>>>>>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
>>>>>>>>> <bo...@gmail.com> wrote:
>>>>>>>>>> Hello, while going through the upgrade I noticed an incompatible
>>>>>>>>>> behavior during nested macro evaluation. Looks like in 1.7 (all
>>>>>>>>>> default properties) child macro has access to variables set in parent
>>>>>>>>>> macro scope (and those take precedence over globals), and 1.5 sees
>>>>>>>>>> globals. In the following example, in 1.5 unit test the following
>>>>>>>>>> template will evaluate to "globalvar", and in 1.7 - to
>>>>>>>>>> "outermacroparam". Is this expected behavior?
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> 1.5 test case
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> public void testVelocityNestedMacroScope() throws Exception
>>>>>>>>>>    {
>>>>>>>>>>        VelocityEngine ve = new VelocityEngine();
>>>>>>>>>>
>>>>>>>>>>        ve.init();
>>>>>>>>>>
>>>>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>>>>                          "#end"+
>>>>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>>>>
>>>>>>>>>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>>>>>>>>>        StringWriter eval = new StringWriter();
>>>>>>>>>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>>>>>>>>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>>>>>>>>>
>>>>>>>>>>    }
>>>>>>>>>>
>>>>>>>>>> 1.7 test case
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>  public void testVelocityNestedMacroScope()
>>>>>>>>>>    {
>>>>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>>>>                          "#end"+
>>>>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>>>>
>>>>>>>>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>>>>>>>>>        String eval = evaluate(template);
>>>>>>>>>>        assertEquals(eval, "outermacroparam", eval);
>>>>>>>>>>
>>>>>>>>>>    }
>>>>>>>>>>
>>>>>>>>>> ---------------------------------------------------------------------
>>>>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> ---------------------------------------------------------------------
>>>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>>>
>>>>>>>>
>>>>>>>> ---------------------------------------------------------------------
>>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>>
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Nathan Bubna <nb...@gmail.com>.
On Mon, Apr 30, 2012 at 1:06 PM, Boris Partensky
<bo...@gmail.com> wrote:
> I am seeing 3 bullet points there pertinent to this issue and all 3
> seem to indicate that being compatible was the intention there, or am
> I wrong ? The way I read #2 and #3 is that the parent scope should
> only be available if I explicitly specify the scope I want (parent or
> topmost or replaced).

Yes, compatibility was and is a goal, but with limited resources,
continuing support for implicit scoping in macros didn't make the cut.

> * For performance and compatibility these are all off by default,
> *except* for $foreach. The others may be enabled by setting a velocity
> property like:macro.provide.scope.control = true

"off for compatibility" here means reduced chance of squashing
someone's previous $macro or $template var, or more realistically $foo
when there is a body macro call #foo

> * When scopes of the same type are nested make the parent Scope
> available through the child (e.g. $foreach.parent or
> $foreach.topmost).

$<scope>.parent is always and only made available when there actually
is an explicit parent scope provided. e.g.

#foreach( $a in $b )
   #foreach( $c in $d )
     $foreach.parent here == $foreach.topmost
   #end
  $foreach here == $foreach.topmost
#end

Think parent and topmost as ways to navigate the scope stack, which
only exists when <scope>.provide.scope.control = true

> * When a Scope reference overrides an existing reference that is not a
> Scope, make it available through the Scope (e.g. $foreach.replaced).

$<scope>.replaced is not a parent scope, but is 'bar' in the example:
#set($foo='bar') #@foo $foo.replaced #end

This is a workaround for incompatibilities/migrations/etc.  It doesn't
provide any compatibility with the older implicit system of scoping.

> On Mon, Apr 30, 2012 at 3:51 PM, Nathan Bubna <nb...@gmail.com> wrote:
>> http://velocity.apache.org/engine/devel/changes-report.html#a1.7
>>
>> On Mon, Apr 30, 2012 at 12:37 PM, Boris Partensky
>> <bo...@gmail.com> wrote:
>>> No problem, thanks for making things clear.
>>>
>>> << we decided to forego it and notify users of the non-BC change when
>>> we released 1.7.
>>>
>>> which notification are you referring to? Wonder if there is something
>>> else in there I am not aware of.
>>>
>>>
>>> On Mon, Apr 30, 2012 at 2:34 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>> Congratulations, Boris.  You are the corner case we feared.  :-/  We
>>>> knew when we went ahead with this that providing a migration path
>>>> would be difficult.  We knew most users didn't have extreme numbers of
>>>> macros and hoped that those who didn't frequently nest them, in part
>>>> because of the complexities of heavy scoping in a language that often
>>>> treated scoping as a second-class feature, and in part because of the
>>>> performance issues macros had prior to 1.6.  #parse,
>>>> VelocityLayoutServlet and even custom tools, which lack the implicit
>>>> scoping support, tended to be more performant and encouraged for
>>>> simplifying complicated tools.  Considering those things and the
>>>> difficulty of implementing a BC switch for implicit scoping, we
>>>> decided to forego it and notify users of the non-BC change when we
>>>> released 1.7.
>>>>
>>>> Sorry.  It sounds like it's going to take some legwork to upgrade in
>>>> the cases where you nested your macros.
>>>>
>>>> On Mon, Apr 30, 2012 at 11:16 AM, Boris Partensky
>>>> <bo...@gmail.com> wrote:
>>>>> Yep, I am afraid we do set globals from within macros...
>>>>>
>>>>> On Mon, Apr 30, 2012 at 2:05 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>>> Can you set velocimacro.context.localscope = true or is it important
>>>>>> for your system to be able to #set global stuff from within macros?
>>>>>>
>>>>>> On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky
>>>>>> <bo...@gmail.com> wrote:
>>>>>>> Thanks Nathan, I think I do get the whole scoping idea, but my
>>>>>>> understanding was that one of the reasons to turn all scoping off by
>>>>>>> default (and have those properties to begin with) was to provide
>>>>>>> backward compatibility - as in: I upgrade to 1.7 and then I start
>>>>>>> turning on all those nice bells and whistles and use scopes and what
>>>>>>> not. Not so seems like? I also find somewhat strange that a a formal
>>>>>>> argument to a macro takes precedence and overwrites a global variable
>>>>>>> with the same name. How would one go about upgrading existing systems?
>>>>>>> We have roughly 1900 macros, big chunk of those are nested... Maybe I
>>>>>>> am misunderstanding something, but this issue makes it almost
>>>>>>> impossible to upgrade (at least for us).
>>>>>>>
>>>>>>>
>>>>>>> Thanks
>>>>>>> Boris
>>>>>>>
>>>>>>> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>>>>> Yeah, it was intended, and part of an overall move toward
>>>>>>>> fixing/simplifying Velocity's variable scoping, avoiding the
>>>>>>>> complexities and costs (performance, yes, but mostly time/brainpower
>>>>>>>> for users and devs alike) of more programming language type behavior.
>>>>>>>> Velocity has long aspired to be a straightfoward template engine and
>>>>>>>> avoid being a complete scripting language.  (Implicit) variable
>>>>>>>> scoping, as seen in 1.5, was seen as a necessary compromise toward the
>>>>>>>> latter; after all, one big fat namespace is always unmanageable,
>>>>>>>> right?  Well, there's ways to make that easy to manage. :)  Let's call
>>>>>>>> it "optional, provided, explicit scoping", explicit because you don't
>>>>>>>> have to grok the contextual scope to understand a reference, optional
>>>>>>>> because you can ignore it, and provided because Velocity does the work
>>>>>>>> of choosing "prefixes" and creating/destroying the scopes (as any
>>>>>>>> implicit scoping system does).  So everything is becoming globally
>>>>>>>> scoped, but it is now trivial to turn on automatic, explicit scopes or
>>>>>>>> namespaces that you can use when you don't want things to live in the
>>>>>>>> global scope.
>>>>>>>>
>>>>>>>> Here's an example...  Do you use $velocityCount to get an index of
>>>>>>>> sorts inside of #foreach directives?  Well, that's an example of mixed
>>>>>>>> implicit/explicit namespacing that gets messy when you nest
>>>>>>>> #foreach's, with no good way to get the parent's count and
>>>>>>>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
>>>>>>>> so on.  Now, we automatically manage a $foreach var that not only has
>>>>>>>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
>>>>>>>> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>>>>>>>>  It also, of course, accepts any property you want to set on it (like
>>>>>>>> any map).  This makes templates instantly understandable, making
>>>>>>>> debugging much better.  You always know exactly what you are referring
>>>>>>>> to, and so does anyone else reading the template.
>>>>>>>>
>>>>>>>> #foreach is the only 'content directive' that has its explicit scope
>>>>>>>> automatically turned on, but all content containing directives
>>>>>>>> (including custom body macros) can have their own explicit,
>>>>>>>> auto-managed scope, named after themselves.  for example, you can flip
>>>>>>>> the macro scope on:
>>>>>>>>
>>>>>>>> macro.provide.scope.control = true
>>>>>>>>
>>>>>>>> and do:
>>>>>>>>
>>>>>>>> #macro( outer $arg )
>>>>>>>>  #set( $macro.arg = $arg )
>>>>>>>>  #inner( 'inner' )
>>>>>>>> #end
>>>>>>>> #macro( inner $arg )
>>>>>>>>  #set( $macro.arg = $arg)
>>>>>>>>  inner: $macro.arg
>>>>>>>>  #if( $macro.parent )outer: $macro.parent.arg#end
>>>>>>>> #end
>>>>>>>>
>>>>>>>> #outer( 'outer' )
>>>>>>>> #inner( 'just inner' )
>>>>>>>>
>>>>>>>> and get
>>>>>>>>
>>>>>>>>  inner: inner
>>>>>>>>  outer: outer
>>>>>>>>  inner: just inner
>>>>>>>>
>>>>>>>> Hope this helps...
>>>>>>>>
>>>>>>>> In any case, there was plenty of thought and discussion that went into
>>>>>>>> this change.  Search http://velocity.markmail.org for 'scope' and you
>>>>>>>> should find more on this.
>>>>>>>>
>>>>>>>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
>>>>>>>> <bo...@gmail.com> wrote:
>>>>>>>>> Hello, while going through the upgrade I noticed an incompatible
>>>>>>>>> behavior during nested macro evaluation. Looks like in 1.7 (all
>>>>>>>>> default properties) child macro has access to variables set in parent
>>>>>>>>> macro scope (and those take precedence over globals), and 1.5 sees
>>>>>>>>> globals. In the following example, in 1.5 unit test the following
>>>>>>>>> template will evaluate to "globalvar", and in 1.7 - to
>>>>>>>>> "outermacroparam". Is this expected behavior?
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> 1.5 test case
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> public void testVelocityNestedMacroScope() throws Exception
>>>>>>>>>    {
>>>>>>>>>        VelocityEngine ve = new VelocityEngine();
>>>>>>>>>
>>>>>>>>>        ve.init();
>>>>>>>>>
>>>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>>>                          "#end"+
>>>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>>>
>>>>>>>>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>>>>>>>>        StringWriter eval = new StringWriter();
>>>>>>>>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>>>>>>>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>>>>>>>>
>>>>>>>>>    }
>>>>>>>>>
>>>>>>>>> 1.7 test case
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>  public void testVelocityNestedMacroScope()
>>>>>>>>>    {
>>>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>>>                          "#end"+
>>>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>>>
>>>>>>>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>>>>>>>>        String eval = evaluate(template);
>>>>>>>>>        assertEquals(eval, "outermacroparam", eval);
>>>>>>>>>
>>>>>>>>>    }
>>>>>>>>>
>>>>>>>>> ---------------------------------------------------------------------
>>>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>>>
>>>>>>>>
>>>>>>>> ---------------------------------------------------------------------
>>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>>
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Boris Partensky <bo...@gmail.com>.
I am seeing 3 bullet points there pertinent to this issue and all 3
seem to indicate that being compatible was the intention there, or am
I wrong ? The way I read #2 and #3 is that the parent scope should
only be available if I explicitly specify the scope I want (parent or
topmost or replaced).

* For performance and compatibility these are all off by default,
*except* for $foreach. The others may be enabled by setting a velocity
property like:macro.provide.scope.control = true
* When scopes of the same type are nested make the parent Scope
available through the child (e.g. $foreach.parent or
$foreach.topmost).
* When a Scope reference overrides an existing reference that is not a
Scope, make it available through the Scope (e.g. $foreach.replaced).

On Mon, Apr 30, 2012 at 3:51 PM, Nathan Bubna <nb...@gmail.com> wrote:
> http://velocity.apache.org/engine/devel/changes-report.html#a1.7
>
> On Mon, Apr 30, 2012 at 12:37 PM, Boris Partensky
> <bo...@gmail.com> wrote:
>> No problem, thanks for making things clear.
>>
>> << we decided to forego it and notify users of the non-BC change when
>> we released 1.7.
>>
>> which notification are you referring to? Wonder if there is something
>> else in there I am not aware of.
>>
>>
>> On Mon, Apr 30, 2012 at 2:34 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>> Congratulations, Boris.  You are the corner case we feared.  :-/  We
>>> knew when we went ahead with this that providing a migration path
>>> would be difficult.  We knew most users didn't have extreme numbers of
>>> macros and hoped that those who didn't frequently nest them, in part
>>> because of the complexities of heavy scoping in a language that often
>>> treated scoping as a second-class feature, and in part because of the
>>> performance issues macros had prior to 1.6.  #parse,
>>> VelocityLayoutServlet and even custom tools, which lack the implicit
>>> scoping support, tended to be more performant and encouraged for
>>> simplifying complicated tools.  Considering those things and the
>>> difficulty of implementing a BC switch for implicit scoping, we
>>> decided to forego it and notify users of the non-BC change when we
>>> released 1.7.
>>>
>>> Sorry.  It sounds like it's going to take some legwork to upgrade in
>>> the cases where you nested your macros.
>>>
>>> On Mon, Apr 30, 2012 at 11:16 AM, Boris Partensky
>>> <bo...@gmail.com> wrote:
>>>> Yep, I am afraid we do set globals from within macros...
>>>>
>>>> On Mon, Apr 30, 2012 at 2:05 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>> Can you set velocimacro.context.localscope = true or is it important
>>>>> for your system to be able to #set global stuff from within macros?
>>>>>
>>>>> On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky
>>>>> <bo...@gmail.com> wrote:
>>>>>> Thanks Nathan, I think I do get the whole scoping idea, but my
>>>>>> understanding was that one of the reasons to turn all scoping off by
>>>>>> default (and have those properties to begin with) was to provide
>>>>>> backward compatibility - as in: I upgrade to 1.7 and then I start
>>>>>> turning on all those nice bells and whistles and use scopes and what
>>>>>> not. Not so seems like? I also find somewhat strange that a a formal
>>>>>> argument to a macro takes precedence and overwrites a global variable
>>>>>> with the same name. How would one go about upgrading existing systems?
>>>>>> We have roughly 1900 macros, big chunk of those are nested... Maybe I
>>>>>> am misunderstanding something, but this issue makes it almost
>>>>>> impossible to upgrade (at least for us).
>>>>>>
>>>>>>
>>>>>> Thanks
>>>>>> Boris
>>>>>>
>>>>>> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>>>> Yeah, it was intended, and part of an overall move toward
>>>>>>> fixing/simplifying Velocity's variable scoping, avoiding the
>>>>>>> complexities and costs (performance, yes, but mostly time/brainpower
>>>>>>> for users and devs alike) of more programming language type behavior.
>>>>>>> Velocity has long aspired to be a straightfoward template engine and
>>>>>>> avoid being a complete scripting language.  (Implicit) variable
>>>>>>> scoping, as seen in 1.5, was seen as a necessary compromise toward the
>>>>>>> latter; after all, one big fat namespace is always unmanageable,
>>>>>>> right?  Well, there's ways to make that easy to manage. :)  Let's call
>>>>>>> it "optional, provided, explicit scoping", explicit because you don't
>>>>>>> have to grok the contextual scope to understand a reference, optional
>>>>>>> because you can ignore it, and provided because Velocity does the work
>>>>>>> of choosing "prefixes" and creating/destroying the scopes (as any
>>>>>>> implicit scoping system does).  So everything is becoming globally
>>>>>>> scoped, but it is now trivial to turn on automatic, explicit scopes or
>>>>>>> namespaces that you can use when you don't want things to live in the
>>>>>>> global scope.
>>>>>>>
>>>>>>> Here's an example...  Do you use $velocityCount to get an index of
>>>>>>> sorts inside of #foreach directives?  Well, that's an example of mixed
>>>>>>> implicit/explicit namespacing that gets messy when you nest
>>>>>>> #foreach's, with no good way to get the parent's count and
>>>>>>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
>>>>>>> so on.  Now, we automatically manage a $foreach var that not only has
>>>>>>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
>>>>>>> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>>>>>>>  It also, of course, accepts any property you want to set on it (like
>>>>>>> any map).  This makes templates instantly understandable, making
>>>>>>> debugging much better.  You always know exactly what you are referring
>>>>>>> to, and so does anyone else reading the template.
>>>>>>>
>>>>>>> #foreach is the only 'content directive' that has its explicit scope
>>>>>>> automatically turned on, but all content containing directives
>>>>>>> (including custom body macros) can have their own explicit,
>>>>>>> auto-managed scope, named after themselves.  for example, you can flip
>>>>>>> the macro scope on:
>>>>>>>
>>>>>>> macro.provide.scope.control = true
>>>>>>>
>>>>>>> and do:
>>>>>>>
>>>>>>> #macro( outer $arg )
>>>>>>>  #set( $macro.arg = $arg )
>>>>>>>  #inner( 'inner' )
>>>>>>> #end
>>>>>>> #macro( inner $arg )
>>>>>>>  #set( $macro.arg = $arg)
>>>>>>>  inner: $macro.arg
>>>>>>>  #if( $macro.parent )outer: $macro.parent.arg#end
>>>>>>> #end
>>>>>>>
>>>>>>> #outer( 'outer' )
>>>>>>> #inner( 'just inner' )
>>>>>>>
>>>>>>> and get
>>>>>>>
>>>>>>>  inner: inner
>>>>>>>  outer: outer
>>>>>>>  inner: just inner
>>>>>>>
>>>>>>> Hope this helps...
>>>>>>>
>>>>>>> In any case, there was plenty of thought and discussion that went into
>>>>>>> this change.  Search http://velocity.markmail.org for 'scope' and you
>>>>>>> should find more on this.
>>>>>>>
>>>>>>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
>>>>>>> <bo...@gmail.com> wrote:
>>>>>>>> Hello, while going through the upgrade I noticed an incompatible
>>>>>>>> behavior during nested macro evaluation. Looks like in 1.7 (all
>>>>>>>> default properties) child macro has access to variables set in parent
>>>>>>>> macro scope (and those take precedence over globals), and 1.5 sees
>>>>>>>> globals. In the following example, in 1.5 unit test the following
>>>>>>>> template will evaluate to "globalvar", and in 1.7 - to
>>>>>>>> "outermacroparam". Is this expected behavior?
>>>>>>>>
>>>>>>>>
>>>>>>>> 1.5 test case
>>>>>>>>
>>>>>>>>
>>>>>>>> public void testVelocityNestedMacroScope() throws Exception
>>>>>>>>    {
>>>>>>>>        VelocityEngine ve = new VelocityEngine();
>>>>>>>>
>>>>>>>>        ve.init();
>>>>>>>>
>>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>>                          "#end"+
>>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>>
>>>>>>>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>>>>>>>        StringWriter eval = new StringWriter();
>>>>>>>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>>>>>>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>>>>>>>
>>>>>>>>    }
>>>>>>>>
>>>>>>>> 1.7 test case
>>>>>>>>
>>>>>>>>
>>>>>>>>  public void testVelocityNestedMacroScope()
>>>>>>>>    {
>>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>>                          "#end"+
>>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>>
>>>>>>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>>>>>>>        String eval = evaluate(template);
>>>>>>>>        assertEquals(eval, "outermacroparam", eval);
>>>>>>>>
>>>>>>>>    }
>>>>>>>>
>>>>>>>> ---------------------------------------------------------------------
>>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>>
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Nathan Bubna <nb...@gmail.com>.
http://velocity.apache.org/engine/devel/changes-report.html#a1.7

On Mon, Apr 30, 2012 at 12:37 PM, Boris Partensky
<bo...@gmail.com> wrote:
> No problem, thanks for making things clear.
>
> << we decided to forego it and notify users of the non-BC change when
> we released 1.7.
>
> which notification are you referring to? Wonder if there is something
> else in there I am not aware of.
>
>
> On Mon, Apr 30, 2012 at 2:34 PM, Nathan Bubna <nb...@gmail.com> wrote:
>> Congratulations, Boris.  You are the corner case we feared.  :-/  We
>> knew when we went ahead with this that providing a migration path
>> would be difficult.  We knew most users didn't have extreme numbers of
>> macros and hoped that those who didn't frequently nest them, in part
>> because of the complexities of heavy scoping in a language that often
>> treated scoping as a second-class feature, and in part because of the
>> performance issues macros had prior to 1.6.  #parse,
>> VelocityLayoutServlet and even custom tools, which lack the implicit
>> scoping support, tended to be more performant and encouraged for
>> simplifying complicated tools.  Considering those things and the
>> difficulty of implementing a BC switch for implicit scoping, we
>> decided to forego it and notify users of the non-BC change when we
>> released 1.7.
>>
>> Sorry.  It sounds like it's going to take some legwork to upgrade in
>> the cases where you nested your macros.
>>
>> On Mon, Apr 30, 2012 at 11:16 AM, Boris Partensky
>> <bo...@gmail.com> wrote:
>>> Yep, I am afraid we do set globals from within macros...
>>>
>>> On Mon, Apr 30, 2012 at 2:05 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>> Can you set velocimacro.context.localscope = true or is it important
>>>> for your system to be able to #set global stuff from within macros?
>>>>
>>>> On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky
>>>> <bo...@gmail.com> wrote:
>>>>> Thanks Nathan, I think I do get the whole scoping idea, but my
>>>>> understanding was that one of the reasons to turn all scoping off by
>>>>> default (and have those properties to begin with) was to provide
>>>>> backward compatibility - as in: I upgrade to 1.7 and then I start
>>>>> turning on all those nice bells and whistles and use scopes and what
>>>>> not. Not so seems like? I also find somewhat strange that a a formal
>>>>> argument to a macro takes precedence and overwrites a global variable
>>>>> with the same name. How would one go about upgrading existing systems?
>>>>> We have roughly 1900 macros, big chunk of those are nested... Maybe I
>>>>> am misunderstanding something, but this issue makes it almost
>>>>> impossible to upgrade (at least for us).
>>>>>
>>>>>
>>>>> Thanks
>>>>> Boris
>>>>>
>>>>> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>>> Yeah, it was intended, and part of an overall move toward
>>>>>> fixing/simplifying Velocity's variable scoping, avoiding the
>>>>>> complexities and costs (performance, yes, but mostly time/brainpower
>>>>>> for users and devs alike) of more programming language type behavior.
>>>>>> Velocity has long aspired to be a straightfoward template engine and
>>>>>> avoid being a complete scripting language.  (Implicit) variable
>>>>>> scoping, as seen in 1.5, was seen as a necessary compromise toward the
>>>>>> latter; after all, one big fat namespace is always unmanageable,
>>>>>> right?  Well, there's ways to make that easy to manage. :)  Let's call
>>>>>> it "optional, provided, explicit scoping", explicit because you don't
>>>>>> have to grok the contextual scope to understand a reference, optional
>>>>>> because you can ignore it, and provided because Velocity does the work
>>>>>> of choosing "prefixes" and creating/destroying the scopes (as any
>>>>>> implicit scoping system does).  So everything is becoming globally
>>>>>> scoped, but it is now trivial to turn on automatic, explicit scopes or
>>>>>> namespaces that you can use when you don't want things to live in the
>>>>>> global scope.
>>>>>>
>>>>>> Here's an example...  Do you use $velocityCount to get an index of
>>>>>> sorts inside of #foreach directives?  Well, that's an example of mixed
>>>>>> implicit/explicit namespacing that gets messy when you nest
>>>>>> #foreach's, with no good way to get the parent's count and
>>>>>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
>>>>>> so on.  Now, we automatically manage a $foreach var that not only has
>>>>>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
>>>>>> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>>>>>>  It also, of course, accepts any property you want to set on it (like
>>>>>> any map).  This makes templates instantly understandable, making
>>>>>> debugging much better.  You always know exactly what you are referring
>>>>>> to, and so does anyone else reading the template.
>>>>>>
>>>>>> #foreach is the only 'content directive' that has its explicit scope
>>>>>> automatically turned on, but all content containing directives
>>>>>> (including custom body macros) can have their own explicit,
>>>>>> auto-managed scope, named after themselves.  for example, you can flip
>>>>>> the macro scope on:
>>>>>>
>>>>>> macro.provide.scope.control = true
>>>>>>
>>>>>> and do:
>>>>>>
>>>>>> #macro( outer $arg )
>>>>>>  #set( $macro.arg = $arg )
>>>>>>  #inner( 'inner' )
>>>>>> #end
>>>>>> #macro( inner $arg )
>>>>>>  #set( $macro.arg = $arg)
>>>>>>  inner: $macro.arg
>>>>>>  #if( $macro.parent )outer: $macro.parent.arg#end
>>>>>> #end
>>>>>>
>>>>>> #outer( 'outer' )
>>>>>> #inner( 'just inner' )
>>>>>>
>>>>>> and get
>>>>>>
>>>>>>  inner: inner
>>>>>>  outer: outer
>>>>>>  inner: just inner
>>>>>>
>>>>>> Hope this helps...
>>>>>>
>>>>>> In any case, there was plenty of thought and discussion that went into
>>>>>> this change.  Search http://velocity.markmail.org for 'scope' and you
>>>>>> should find more on this.
>>>>>>
>>>>>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
>>>>>> <bo...@gmail.com> wrote:
>>>>>>> Hello, while going through the upgrade I noticed an incompatible
>>>>>>> behavior during nested macro evaluation. Looks like in 1.7 (all
>>>>>>> default properties) child macro has access to variables set in parent
>>>>>>> macro scope (and those take precedence over globals), and 1.5 sees
>>>>>>> globals. In the following example, in 1.5 unit test the following
>>>>>>> template will evaluate to "globalvar", and in 1.7 - to
>>>>>>> "outermacroparam". Is this expected behavior?
>>>>>>>
>>>>>>>
>>>>>>> 1.5 test case
>>>>>>>
>>>>>>>
>>>>>>> public void testVelocityNestedMacroScope() throws Exception
>>>>>>>    {
>>>>>>>        VelocityEngine ve = new VelocityEngine();
>>>>>>>
>>>>>>>        ve.init();
>>>>>>>
>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>                          "#end"+
>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>
>>>>>>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>>>>>>        StringWriter eval = new StringWriter();
>>>>>>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>>>>>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>>>>>>
>>>>>>>    }
>>>>>>>
>>>>>>> 1.7 test case
>>>>>>>
>>>>>>>
>>>>>>>  public void testVelocityNestedMacroScope()
>>>>>>>    {
>>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>>                          "#innerMacro('blah')"+
>>>>>>>                          "#end"+
>>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>>
>>>>>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>>>>>>        String eval = evaluate(template);
>>>>>>>        assertEquals(eval, "outermacroparam", eval);
>>>>>>>
>>>>>>>    }
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Boris Partensky <bo...@gmail.com>.
No problem, thanks for making things clear.

<< we decided to forego it and notify users of the non-BC change when
we released 1.7.

which notification are you referring to? Wonder if there is something
else in there I am not aware of.


On Mon, Apr 30, 2012 at 2:34 PM, Nathan Bubna <nb...@gmail.com> wrote:
> Congratulations, Boris.  You are the corner case we feared.  :-/  We
> knew when we went ahead with this that providing a migration path
> would be difficult.  We knew most users didn't have extreme numbers of
> macros and hoped that those who didn't frequently nest them, in part
> because of the complexities of heavy scoping in a language that often
> treated scoping as a second-class feature, and in part because of the
> performance issues macros had prior to 1.6.  #parse,
> VelocityLayoutServlet and even custom tools, which lack the implicit
> scoping support, tended to be more performant and encouraged for
> simplifying complicated tools.  Considering those things and the
> difficulty of implementing a BC switch for implicit scoping, we
> decided to forego it and notify users of the non-BC change when we
> released 1.7.
>
> Sorry.  It sounds like it's going to take some legwork to upgrade in
> the cases where you nested your macros.
>
> On Mon, Apr 30, 2012 at 11:16 AM, Boris Partensky
> <bo...@gmail.com> wrote:
>> Yep, I am afraid we do set globals from within macros...
>>
>> On Mon, Apr 30, 2012 at 2:05 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>> Can you set velocimacro.context.localscope = true or is it important
>>> for your system to be able to #set global stuff from within macros?
>>>
>>> On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky
>>> <bo...@gmail.com> wrote:
>>>> Thanks Nathan, I think I do get the whole scoping idea, but my
>>>> understanding was that one of the reasons to turn all scoping off by
>>>> default (and have those properties to begin with) was to provide
>>>> backward compatibility - as in: I upgrade to 1.7 and then I start
>>>> turning on all those nice bells and whistles and use scopes and what
>>>> not. Not so seems like? I also find somewhat strange that a a formal
>>>> argument to a macro takes precedence and overwrites a global variable
>>>> with the same name. How would one go about upgrading existing systems?
>>>> We have roughly 1900 macros, big chunk of those are nested... Maybe I
>>>> am misunderstanding something, but this issue makes it almost
>>>> impossible to upgrade (at least for us).
>>>>
>>>>
>>>> Thanks
>>>> Boris
>>>>
>>>> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>>> Yeah, it was intended, and part of an overall move toward
>>>>> fixing/simplifying Velocity's variable scoping, avoiding the
>>>>> complexities and costs (performance, yes, but mostly time/brainpower
>>>>> for users and devs alike) of more programming language type behavior.
>>>>> Velocity has long aspired to be a straightfoward template engine and
>>>>> avoid being a complete scripting language.  (Implicit) variable
>>>>> scoping, as seen in 1.5, was seen as a necessary compromise toward the
>>>>> latter; after all, one big fat namespace is always unmanageable,
>>>>> right?  Well, there's ways to make that easy to manage. :)  Let's call
>>>>> it "optional, provided, explicit scoping", explicit because you don't
>>>>> have to grok the contextual scope to understand a reference, optional
>>>>> because you can ignore it, and provided because Velocity does the work
>>>>> of choosing "prefixes" and creating/destroying the scopes (as any
>>>>> implicit scoping system does).  So everything is becoming globally
>>>>> scoped, but it is now trivial to turn on automatic, explicit scopes or
>>>>> namespaces that you can use when you don't want things to live in the
>>>>> global scope.
>>>>>
>>>>> Here's an example...  Do you use $velocityCount to get an index of
>>>>> sorts inside of #foreach directives?  Well, that's an example of mixed
>>>>> implicit/explicit namespacing that gets messy when you nest
>>>>> #foreach's, with no good way to get the parent's count and
>>>>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
>>>>> so on.  Now, we automatically manage a $foreach var that not only has
>>>>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
>>>>> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>>>>>  It also, of course, accepts any property you want to set on it (like
>>>>> any map).  This makes templates instantly understandable, making
>>>>> debugging much better.  You always know exactly what you are referring
>>>>> to, and so does anyone else reading the template.
>>>>>
>>>>> #foreach is the only 'content directive' that has its explicit scope
>>>>> automatically turned on, but all content containing directives
>>>>> (including custom body macros) can have their own explicit,
>>>>> auto-managed scope, named after themselves.  for example, you can flip
>>>>> the macro scope on:
>>>>>
>>>>> macro.provide.scope.control = true
>>>>>
>>>>> and do:
>>>>>
>>>>> #macro( outer $arg )
>>>>>  #set( $macro.arg = $arg )
>>>>>  #inner( 'inner' )
>>>>> #end
>>>>> #macro( inner $arg )
>>>>>  #set( $macro.arg = $arg)
>>>>>  inner: $macro.arg
>>>>>  #if( $macro.parent )outer: $macro.parent.arg#end
>>>>> #end
>>>>>
>>>>> #outer( 'outer' )
>>>>> #inner( 'just inner' )
>>>>>
>>>>> and get
>>>>>
>>>>>  inner: inner
>>>>>  outer: outer
>>>>>  inner: just inner
>>>>>
>>>>> Hope this helps...
>>>>>
>>>>> In any case, there was plenty of thought and discussion that went into
>>>>> this change.  Search http://velocity.markmail.org for 'scope' and you
>>>>> should find more on this.
>>>>>
>>>>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
>>>>> <bo...@gmail.com> wrote:
>>>>>> Hello, while going through the upgrade I noticed an incompatible
>>>>>> behavior during nested macro evaluation. Looks like in 1.7 (all
>>>>>> default properties) child macro has access to variables set in parent
>>>>>> macro scope (and those take precedence over globals), and 1.5 sees
>>>>>> globals. In the following example, in 1.5 unit test the following
>>>>>> template will evaluate to "globalvar", and in 1.7 - to
>>>>>> "outermacroparam". Is this expected behavior?
>>>>>>
>>>>>>
>>>>>> 1.5 test case
>>>>>>
>>>>>>
>>>>>> public void testVelocityNestedMacroScope() throws Exception
>>>>>>    {
>>>>>>        VelocityEngine ve = new VelocityEngine();
>>>>>>
>>>>>>        ve.init();
>>>>>>
>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>                          "#innerMacro('blah')"+
>>>>>>                          "#end"+
>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>
>>>>>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>>>>>        StringWriter eval = new StringWriter();
>>>>>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>>>>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>>>>>
>>>>>>    }
>>>>>>
>>>>>> 1.7 test case
>>>>>>
>>>>>>
>>>>>>  public void testVelocityNestedMacroScope()
>>>>>>    {
>>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>>                          "#innerMacro('blah')"+
>>>>>>                          "#end"+
>>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>>
>>>>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>>>>>        String eval = evaluate(template);
>>>>>>        assertEquals(eval, "outermacroparam", eval);
>>>>>>
>>>>>>    }
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Nathan Bubna <nb...@gmail.com>.
Congratulations, Boris.  You are the corner case we feared.  :-/  We
knew when we went ahead with this that providing a migration path
would be difficult.  We knew most users didn't have extreme numbers of
macros and hoped that those who didn't frequently nest them, in part
because of the complexities of heavy scoping in a language that often
treated scoping as a second-class feature, and in part because of the
performance issues macros had prior to 1.6.  #parse,
VelocityLayoutServlet and even custom tools, which lack the implicit
scoping support, tended to be more performant and encouraged for
simplifying complicated tools.  Considering those things and the
difficulty of implementing a BC switch for implicit scoping, we
decided to forego it and notify users of the non-BC change when we
released 1.7.

Sorry.  It sounds like it's going to take some legwork to upgrade in
the cases where you nested your macros.

On Mon, Apr 30, 2012 at 11:16 AM, Boris Partensky
<bo...@gmail.com> wrote:
> Yep, I am afraid we do set globals from within macros...
>
> On Mon, Apr 30, 2012 at 2:05 PM, Nathan Bubna <nb...@gmail.com> wrote:
>> Can you set velocimacro.context.localscope = true or is it important
>> for your system to be able to #set global stuff from within macros?
>>
>> On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky
>> <bo...@gmail.com> wrote:
>>> Thanks Nathan, I think I do get the whole scoping idea, but my
>>> understanding was that one of the reasons to turn all scoping off by
>>> default (and have those properties to begin with) was to provide
>>> backward compatibility - as in: I upgrade to 1.7 and then I start
>>> turning on all those nice bells and whistles and use scopes and what
>>> not. Not so seems like? I also find somewhat strange that a a formal
>>> argument to a macro takes precedence and overwrites a global variable
>>> with the same name. How would one go about upgrading existing systems?
>>> We have roughly 1900 macros, big chunk of those are nested... Maybe I
>>> am misunderstanding something, but this issue makes it almost
>>> impossible to upgrade (at least for us).
>>>
>>>
>>> Thanks
>>> Boris
>>>
>>> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>>> Yeah, it was intended, and part of an overall move toward
>>>> fixing/simplifying Velocity's variable scoping, avoiding the
>>>> complexities and costs (performance, yes, but mostly time/brainpower
>>>> for users and devs alike) of more programming language type behavior.
>>>> Velocity has long aspired to be a straightfoward template engine and
>>>> avoid being a complete scripting language.  (Implicit) variable
>>>> scoping, as seen in 1.5, was seen as a necessary compromise toward the
>>>> latter; after all, one big fat namespace is always unmanageable,
>>>> right?  Well, there's ways to make that easy to manage. :)  Let's call
>>>> it "optional, provided, explicit scoping", explicit because you don't
>>>> have to grok the contextual scope to understand a reference, optional
>>>> because you can ignore it, and provided because Velocity does the work
>>>> of choosing "prefixes" and creating/destroying the scopes (as any
>>>> implicit scoping system does).  So everything is becoming globally
>>>> scoped, but it is now trivial to turn on automatic, explicit scopes or
>>>> namespaces that you can use when you don't want things to live in the
>>>> global scope.
>>>>
>>>> Here's an example...  Do you use $velocityCount to get an index of
>>>> sorts inside of #foreach directives?  Well, that's an example of mixed
>>>> implicit/explicit namespacing that gets messy when you nest
>>>> #foreach's, with no good way to get the parent's count and
>>>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
>>>> so on.  Now, we automatically manage a $foreach var that not only has
>>>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
>>>> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>>>>  It also, of course, accepts any property you want to set on it (like
>>>> any map).  This makes templates instantly understandable, making
>>>> debugging much better.  You always know exactly what you are referring
>>>> to, and so does anyone else reading the template.
>>>>
>>>> #foreach is the only 'content directive' that has its explicit scope
>>>> automatically turned on, but all content containing directives
>>>> (including custom body macros) can have their own explicit,
>>>> auto-managed scope, named after themselves.  for example, you can flip
>>>> the macro scope on:
>>>>
>>>> macro.provide.scope.control = true
>>>>
>>>> and do:
>>>>
>>>> #macro( outer $arg )
>>>>  #set( $macro.arg = $arg )
>>>>  #inner( 'inner' )
>>>> #end
>>>> #macro( inner $arg )
>>>>  #set( $macro.arg = $arg)
>>>>  inner: $macro.arg
>>>>  #if( $macro.parent )outer: $macro.parent.arg#end
>>>> #end
>>>>
>>>> #outer( 'outer' )
>>>> #inner( 'just inner' )
>>>>
>>>> and get
>>>>
>>>>  inner: inner
>>>>  outer: outer
>>>>  inner: just inner
>>>>
>>>> Hope this helps...
>>>>
>>>> In any case, there was plenty of thought and discussion that went into
>>>> this change.  Search http://velocity.markmail.org for 'scope' and you
>>>> should find more on this.
>>>>
>>>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
>>>> <bo...@gmail.com> wrote:
>>>>> Hello, while going through the upgrade I noticed an incompatible
>>>>> behavior during nested macro evaluation. Looks like in 1.7 (all
>>>>> default properties) child macro has access to variables set in parent
>>>>> macro scope (and those take precedence over globals), and 1.5 sees
>>>>> globals. In the following example, in 1.5 unit test the following
>>>>> template will evaluate to "globalvar", and in 1.7 - to
>>>>> "outermacroparam". Is this expected behavior?
>>>>>
>>>>>
>>>>> 1.5 test case
>>>>>
>>>>>
>>>>> public void testVelocityNestedMacroScope() throws Exception
>>>>>    {
>>>>>        VelocityEngine ve = new VelocityEngine();
>>>>>
>>>>>        ve.init();
>>>>>
>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>                          "#innerMacro('blah')"+
>>>>>                          "#end"+
>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>
>>>>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>>>>        StringWriter eval = new StringWriter();
>>>>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>>>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>>>>
>>>>>    }
>>>>>
>>>>> 1.7 test case
>>>>>
>>>>>
>>>>>  public void testVelocityNestedMacroScope()
>>>>>    {
>>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>>                          "#innerMacro('blah')"+
>>>>>                          "#end"+
>>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>>
>>>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>>>>        String eval = evaluate(template);
>>>>>        assertEquals(eval, "outermacroparam", eval);
>>>>>
>>>>>    }
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Boris Partensky <bo...@gmail.com>.
Yep, I am afraid we do set globals from within macros...

On Mon, Apr 30, 2012 at 2:05 PM, Nathan Bubna <nb...@gmail.com> wrote:
> Can you set velocimacro.context.localscope = true or is it important
> for your system to be able to #set global stuff from within macros?
>
> On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky
> <bo...@gmail.com> wrote:
>> Thanks Nathan, I think I do get the whole scoping idea, but my
>> understanding was that one of the reasons to turn all scoping off by
>> default (and have those properties to begin with) was to provide
>> backward compatibility - as in: I upgrade to 1.7 and then I start
>> turning on all those nice bells and whistles and use scopes and what
>> not. Not so seems like? I also find somewhat strange that a a formal
>> argument to a macro takes precedence and overwrites a global variable
>> with the same name. How would one go about upgrading existing systems?
>> We have roughly 1900 macros, big chunk of those are nested... Maybe I
>> am misunderstanding something, but this issue makes it almost
>> impossible to upgrade (at least for us).
>>
>>
>> Thanks
>> Boris
>>
>> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nb...@gmail.com> wrote:
>>> Yeah, it was intended, and part of an overall move toward
>>> fixing/simplifying Velocity's variable scoping, avoiding the
>>> complexities and costs (performance, yes, but mostly time/brainpower
>>> for users and devs alike) of more programming language type behavior.
>>> Velocity has long aspired to be a straightfoward template engine and
>>> avoid being a complete scripting language.  (Implicit) variable
>>> scoping, as seen in 1.5, was seen as a necessary compromise toward the
>>> latter; after all, one big fat namespace is always unmanageable,
>>> right?  Well, there's ways to make that easy to manage. :)  Let's call
>>> it "optional, provided, explicit scoping", explicit because you don't
>>> have to grok the contextual scope to understand a reference, optional
>>> because you can ignore it, and provided because Velocity does the work
>>> of choosing "prefixes" and creating/destroying the scopes (as any
>>> implicit scoping system does).  So everything is becoming globally
>>> scoped, but it is now trivial to turn on automatic, explicit scopes or
>>> namespaces that you can use when you don't want things to live in the
>>> global scope.
>>>
>>> Here's an example...  Do you use $velocityCount to get an index of
>>> sorts inside of #foreach directives?  Well, that's an example of mixed
>>> implicit/explicit namespacing that gets messy when you nest
>>> #foreach's, with no good way to get the parent's count and
>>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
>>> so on.  Now, we automatically manage a $foreach var that not only has
>>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
>>> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>>>  It also, of course, accepts any property you want to set on it (like
>>> any map).  This makes templates instantly understandable, making
>>> debugging much better.  You always know exactly what you are referring
>>> to, and so does anyone else reading the template.
>>>
>>> #foreach is the only 'content directive' that has its explicit scope
>>> automatically turned on, but all content containing directives
>>> (including custom body macros) can have their own explicit,
>>> auto-managed scope, named after themselves.  for example, you can flip
>>> the macro scope on:
>>>
>>> macro.provide.scope.control = true
>>>
>>> and do:
>>>
>>> #macro( outer $arg )
>>>  #set( $macro.arg = $arg )
>>>  #inner( 'inner' )
>>> #end
>>> #macro( inner $arg )
>>>  #set( $macro.arg = $arg)
>>>  inner: $macro.arg
>>>  #if( $macro.parent )outer: $macro.parent.arg#end
>>> #end
>>>
>>> #outer( 'outer' )
>>> #inner( 'just inner' )
>>>
>>> and get
>>>
>>>  inner: inner
>>>  outer: outer
>>>  inner: just inner
>>>
>>> Hope this helps...
>>>
>>> In any case, there was plenty of thought and discussion that went into
>>> this change.  Search http://velocity.markmail.org for 'scope' and you
>>> should find more on this.
>>>
>>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
>>> <bo...@gmail.com> wrote:
>>>> Hello, while going through the upgrade I noticed an incompatible
>>>> behavior during nested macro evaluation. Looks like in 1.7 (all
>>>> default properties) child macro has access to variables set in parent
>>>> macro scope (and those take precedence over globals), and 1.5 sees
>>>> globals. In the following example, in 1.5 unit test the following
>>>> template will evaluate to "globalvar", and in 1.7 - to
>>>> "outermacroparam". Is this expected behavior?
>>>>
>>>>
>>>> 1.5 test case
>>>>
>>>>
>>>> public void testVelocityNestedMacroScope() throws Exception
>>>>    {
>>>>        VelocityEngine ve = new VelocityEngine();
>>>>
>>>>        ve.init();
>>>>
>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>                          "#innerMacro('blah')"+
>>>>                          "#end"+
>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>
>>>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>>>        StringWriter eval = new StringWriter();
>>>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>>>
>>>>    }
>>>>
>>>> 1.7 test case
>>>>
>>>>
>>>>  public void testVelocityNestedMacroScope()
>>>>    {
>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>                          "#innerMacro('blah')"+
>>>>                          "#end"+
>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>
>>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>>>        String eval = evaluate(template);
>>>>        assertEquals(eval, "outermacroparam", eval);
>>>>
>>>>    }
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Nathan Bubna <nb...@gmail.com>.
Can you set velocimacro.context.localscope = true or is it important
for your system to be able to #set global stuff from within macros?

On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky
<bo...@gmail.com> wrote:
> Thanks Nathan, I think I do get the whole scoping idea, but my
> understanding was that one of the reasons to turn all scoping off by
> default (and have those properties to begin with) was to provide
> backward compatibility - as in: I upgrade to 1.7 and then I start
> turning on all those nice bells and whistles and use scopes and what
> not. Not so seems like? I also find somewhat strange that a a formal
> argument to a macro takes precedence and overwrites a global variable
> with the same name. How would one go about upgrading existing systems?
> We have roughly 1900 macros, big chunk of those are nested... Maybe I
> am misunderstanding something, but this issue makes it almost
> impossible to upgrade (at least for us).
>
>
> Thanks
> Boris
>
> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nb...@gmail.com> wrote:
>> Yeah, it was intended, and part of an overall move toward
>> fixing/simplifying Velocity's variable scoping, avoiding the
>> complexities and costs (performance, yes, but mostly time/brainpower
>> for users and devs alike) of more programming language type behavior.
>> Velocity has long aspired to be a straightfoward template engine and
>> avoid being a complete scripting language.  (Implicit) variable
>> scoping, as seen in 1.5, was seen as a necessary compromise toward the
>> latter; after all, one big fat namespace is always unmanageable,
>> right?  Well, there's ways to make that easy to manage. :)  Let's call
>> it "optional, provided, explicit scoping", explicit because you don't
>> have to grok the contextual scope to understand a reference, optional
>> because you can ignore it, and provided because Velocity does the work
>> of choosing "prefixes" and creating/destroying the scopes (as any
>> implicit scoping system does).  So everything is becoming globally
>> scoped, but it is now trivial to turn on automatic, explicit scopes or
>> namespaces that you can use when you don't want things to live in the
>> global scope.
>>
>> Here's an example...  Do you use $velocityCount to get an index of
>> sorts inside of #foreach directives?  Well, that's an example of mixed
>> implicit/explicit namespacing that gets messy when you nest
>> #foreach's, with no good way to get the parent's count and
>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
>> so on.  Now, we automatically manage a $foreach var that not only has
>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
>> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>>  It also, of course, accepts any property you want to set on it (like
>> any map).  This makes templates instantly understandable, making
>> debugging much better.  You always know exactly what you are referring
>> to, and so does anyone else reading the template.
>>
>> #foreach is the only 'content directive' that has its explicit scope
>> automatically turned on, but all content containing directives
>> (including custom body macros) can have their own explicit,
>> auto-managed scope, named after themselves.  for example, you can flip
>> the macro scope on:
>>
>> macro.provide.scope.control = true
>>
>> and do:
>>
>> #macro( outer $arg )
>>  #set( $macro.arg = $arg )
>>  #inner( 'inner' )
>> #end
>> #macro( inner $arg )
>>  #set( $macro.arg = $arg)
>>  inner: $macro.arg
>>  #if( $macro.parent )outer: $macro.parent.arg#end
>> #end
>>
>> #outer( 'outer' )
>> #inner( 'just inner' )
>>
>> and get
>>
>>  inner: inner
>>  outer: outer
>>  inner: just inner
>>
>> Hope this helps...
>>
>> In any case, there was plenty of thought and discussion that went into
>> this change.  Search http://velocity.markmail.org for 'scope' and you
>> should find more on this.
>>
>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
>> <bo...@gmail.com> wrote:
>>> Hello, while going through the upgrade I noticed an incompatible
>>> behavior during nested macro evaluation. Looks like in 1.7 (all
>>> default properties) child macro has access to variables set in parent
>>> macro scope (and those take precedence over globals), and 1.5 sees
>>> globals. In the following example, in 1.5 unit test the following
>>> template will evaluate to "globalvar", and in 1.7 - to
>>> "outermacroparam". Is this expected behavior?
>>>
>>>
>>> 1.5 test case
>>>
>>>
>>> public void testVelocityNestedMacroScope() throws Exception
>>>    {
>>>        VelocityEngine ve = new VelocityEngine();
>>>
>>>        ve.init();
>>>
>>>        String template = "#macro(outerMacro $arg1)"+
>>>                          "#innerMacro('blah')"+
>>>                          "#end"+
>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>
>>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>>        StringWriter eval = new StringWriter();
>>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>>
>>>    }
>>>
>>> 1.7 test case
>>>
>>>
>>>  public void testVelocityNestedMacroScope()
>>>    {
>>>        String template = "#macro(outerMacro $arg1)"+
>>>                          "#innerMacro('blah')"+
>>>                          "#end"+
>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>
>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>>        String eval = evaluate(template);
>>>        assertEquals(eval, "outermacroparam", eval);
>>>
>>>    }
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Boris Partensky <bo...@gmail.com>.
Thanks Nathan, I think I do get the whole scoping idea, but my
understanding was that one of the reasons to turn all scoping off by
default (and have those properties to begin with) was to provide
backward compatibility - as in: I upgrade to 1.7 and then I start
turning on all those nice bells and whistles and use scopes and what
not. Not so seems like? I also find somewhat strange that a a formal
argument to a macro takes precedence and overwrites a global variable
with the same name. How would one go about upgrading existing systems?
We have roughly 1900 macros, big chunk of those are nested... Maybe I
am misunderstanding something, but this issue makes it almost
impossible to upgrade (at least for us).


Thanks
Boris

On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nb...@gmail.com> wrote:
> Yeah, it was intended, and part of an overall move toward
> fixing/simplifying Velocity's variable scoping, avoiding the
> complexities and costs (performance, yes, but mostly time/brainpower
> for users and devs alike) of more programming language type behavior.
> Velocity has long aspired to be a straightfoward template engine and
> avoid being a complete scripting language.  (Implicit) variable
> scoping, as seen in 1.5, was seen as a necessary compromise toward the
> latter; after all, one big fat namespace is always unmanageable,
> right?  Well, there's ways to make that easy to manage. :)  Let's call
> it "optional, provided, explicit scoping", explicit because you don't
> have to grok the contextual scope to understand a reference, optional
> because you can ignore it, and provided because Velocity does the work
> of choosing "prefixes" and creating/destroying the scopes (as any
> implicit scoping system does).  So everything is becoming globally
> scoped, but it is now trivial to turn on automatic, explicit scopes or
> namespaces that you can use when you don't want things to live in the
> global scope.
>
> Here's an example...  Do you use $velocityCount to get an index of
> sorts inside of #foreach directives?  Well, that's an example of mixed
> implicit/explicit namespacing that gets messy when you nest
> #foreach's, with no good way to get the parent's count and
> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
> so on.  Now, we automatically manage a $foreach var that not only has
> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>  It also, of course, accepts any property you want to set on it (like
> any map).  This makes templates instantly understandable, making
> debugging much better.  You always know exactly what you are referring
> to, and so does anyone else reading the template.
>
> #foreach is the only 'content directive' that has its explicit scope
> automatically turned on, but all content containing directives
> (including custom body macros) can have their own explicit,
> auto-managed scope, named after themselves.  for example, you can flip
> the macro scope on:
>
> macro.provide.scope.control = true
>
> and do:
>
> #macro( outer $arg )
>  #set( $macro.arg = $arg )
>  #inner( 'inner' )
> #end
> #macro( inner $arg )
>  #set( $macro.arg = $arg)
>  inner: $macro.arg
>  #if( $macro.parent )outer: $macro.parent.arg#end
> #end
>
> #outer( 'outer' )
> #inner( 'just inner' )
>
> and get
>
>  inner: inner
>  outer: outer
>  inner: just inner
>
> Hope this helps...
>
> In any case, there was plenty of thought and discussion that went into
> this change.  Search http://velocity.markmail.org for 'scope' and you
> should find more on this.
>
> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
> <bo...@gmail.com> wrote:
>> Hello, while going through the upgrade I noticed an incompatible
>> behavior during nested macro evaluation. Looks like in 1.7 (all
>> default properties) child macro has access to variables set in parent
>> macro scope (and those take precedence over globals), and 1.5 sees
>> globals. In the following example, in 1.5 unit test the following
>> template will evaluate to "globalvar", and in 1.7 - to
>> "outermacroparam". Is this expected behavior?
>>
>>
>> 1.5 test case
>>
>>
>> public void testVelocityNestedMacroScope() throws Exception
>>    {
>>        VelocityEngine ve = new VelocityEngine();
>>
>>        ve.init();
>>
>>        String template = "#macro(outerMacro $arg1)"+
>>                          "#innerMacro('blah')"+
>>                          "#end"+
>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>
>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>        StringWriter eval = new StringWriter();
>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>
>>    }
>>
>> 1.7 test case
>>
>>
>>  public void testVelocityNestedMacroScope()
>>    {
>>        String template = "#macro(outerMacro $arg1)"+
>>                          "#innerMacro('blah')"+
>>                          "#end"+
>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>
>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>        String eval = evaluate(template);
>>        assertEquals(eval, "outermacroparam", eval);
>>
>>    }
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: upgrading from 1.5 to 1.7 compatibility issues

Posted by Nathan Bubna <nb...@gmail.com>.
Yeah, it was intended, and part of an overall move toward
fixing/simplifying Velocity's variable scoping, avoiding the
complexities and costs (performance, yes, but mostly time/brainpower
for users and devs alike) of more programming language type behavior.
Velocity has long aspired to be a straightfoward template engine and
avoid being a complete scripting language.  (Implicit) variable
scoping, as seen in 1.5, was seen as a necessary compromise toward the
latter; after all, one big fat namespace is always unmanageable,
right?  Well, there's ways to make that easy to manage. :)  Let's call
it "optional, provided, explicit scoping", explicit because you don't
have to grok the contextual scope to understand a reference, optional
because you can ignore it, and provided because Velocity does the work
of choosing "prefixes" and creating/destroying the scopes (as any
implicit scoping system does).  So everything is becoming globally
scoped, but it is now trivial to turn on automatic, explicit scopes or
namespaces that you can use when you don't want things to live in the
global scope.

Here's an example...  Do you use $velocityCount to get an index of
sorts inside of #foreach directives?  Well, that's an example of mixed
implicit/explicit namespacing that gets messy when you nest
#foreach's, with no good way to get the parent's count and
unwieldiness when you want to add $velocityIndex, $velocityHasNext and
so on.  Now, we automatically manage a $foreach var that not only has
a 'count' property, but an 'index', 'hasNext', 'parent', and so on
(see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
 It also, of course, accepts any property you want to set on it (like
any map).  This makes templates instantly understandable, making
debugging much better.  You always know exactly what you are referring
to, and so does anyone else reading the template.

#foreach is the only 'content directive' that has its explicit scope
automatically turned on, but all content containing directives
(including custom body macros) can have their own explicit,
auto-managed scope, named after themselves.  for example, you can flip
the macro scope on:

macro.provide.scope.control = true

and do:

#macro( outer $arg )
  #set( $macro.arg = $arg )
  #inner( 'inner' )
#end
#macro( inner $arg )
  #set( $macro.arg = $arg)
  inner: $macro.arg
  #if( $macro.parent )outer: $macro.parent.arg#end
#end

#outer( 'outer' )
#inner( 'just inner' )

and get

  inner: inner
  outer: outer
  inner: just inner

Hope this helps...

In any case, there was plenty of thought and discussion that went into
this change.  Search http://velocity.markmail.org for 'scope' and you
should find more on this.

On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
<bo...@gmail.com> wrote:
> Hello, while going through the upgrade I noticed an incompatible
> behavior during nested macro evaluation. Looks like in 1.7 (all
> default properties) child macro has access to variables set in parent
> macro scope (and those take precedence over globals), and 1.5 sees
> globals. In the following example, in 1.5 unit test the following
> template will evaluate to "globalvar", and in 1.7 - to
> "outermacroparam". Is this expected behavior?
>
>
> 1.5 test case
>
>
> public void testVelocityNestedMacroScope() throws Exception
>    {
>        VelocityEngine ve = new VelocityEngine();
>
>        ve.init();
>
>        String template = "#macro(outerMacro $arg1)"+
>                          "#innerMacro('blah')"+
>                          "#end"+
>                          "#macro(innerMacro $arg2)$arg1#end"+
>
> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>        StringWriter eval = new StringWriter();
>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>        assertEquals(eval.toString(), "globalval", eval.toString());
>
>    }
>
> 1.7 test case
>
>
>  public void testVelocityNestedMacroScope()
>    {
>        String template = "#macro(outerMacro $arg1)"+
>                          "#innerMacro('blah')"+
>                          "#end"+
>                          "#macro(innerMacro $arg2)$arg1#end"+
>
> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>        String eval = evaluate(template);
>        assertEquals(eval, "outermacroparam", eval);
>
>    }
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org