velocity-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Nathan Bubna <nbu...@gmail.com>
Subject Re: upgrading from 1.5 to 1.7 compatibility issues
Date Mon, 30 Apr 2012 21:08:43 GMT
On Mon, Apr 30, 2012 at 1:06 PM, Boris Partensky
<boris.partensky@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 <nbubna@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
>> <boris.partensky@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 <nbubna@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
>>>> <boris.partensky@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 <nbubna@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
>>>>>> <boris.partensky@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 <nbubna@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
>>>>>>>> <boris.partensky@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


Mime
View raw message