You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by Mike Williams <mi...@cortexebusiness.com.au> on 2001/11/08 04:41:53 UTC

#set silently fails if RHS is null

I have a loop that looks something like this:

    #foreach( $item in $items )
    #set( $colour = $item.colour )
    #if( $colour ) {
        A $colour ${item.name}
    #end
    #end

Now say I have the following list of items:

    #1 name="hammer"
    #2 name="wheelbarrow" colour="blue"
    #3 name="wheelbarrow" colour="red"
    #4 name="screwdriver"

I expected the output to be

    A blue wheelbarrow
    A red wheelbarrow

But, in fact it's

    A blue wheelbarrow
    A red wheelbarrow
    A red screwdriver

The problem is that Velocity skips the #set if the RHS is null (well, this
is what the logs tell me).  This seems to be pretty counter-intuitive
behaviour ... is there a reason for it?  What's the best work-around?

-- 
cheers, Mike


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by Dan Bachelder <ch...@chowda.net>.
will this work for you...

#if($item.colour) $color #end


----- Original Message -----
From: "Mike Williams" <mi...@cortexebusiness.com.au>
To: <ve...@jakarta.apache.org>
Sent: Wednesday, November 07, 2001 10:41 PM
Subject: #set silently fails if RHS is null


> I have a loop that looks something like this:
>
>     #foreach( $item in $items )
>     #set( $colour = $item.colour )
>     #if( $colour ) {
>         A $colour ${item.name}
>     #end
>     #end
>
> Now say I have the following list of items:
>
>     #1 name="hammer"
>     #2 name="wheelbarrow" colour="blue"
>     #3 name="wheelbarrow" colour="red"
>     #4 name="screwdriver"
>
> I expected the output to be
>
>     A blue wheelbarrow
>     A red wheelbarrow
>
> But, in fact it's
>
>     A blue wheelbarrow
>     A red wheelbarrow
>     A red screwdriver
>
> The problem is that Velocity skips the #set if the RHS is null (well, this
> is what the logs tell me).  This seems to be pretty counter-intuitive
> behaviour ... is there a reason for it?  What's the best work-around?
>
> --
> cheers, Mike
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>
>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by "Henning P. Schmiedehausen" <ma...@hometree.net>.
"Geir Magnusson Jr." <ge...@optonline.net> writes:

>I have abhorred this aspect of things for a long time - I think of it as a
>bug in a sense because what happens is that he #set() 'fails' based on data,
>which is equally as bad as configurable language semantics...

>I.e. Looking at 

>#set($bar = "woogie")
>#set($bar = $this.couldReturnNull() )

>Means I have *no clue* what $bar has.  It could contain the result of the
>couldReturnNull() method, or not, and be unchanged.  That¹s weird for an
>assignment in any language.

But the main problem here is (IMHO) the fact that null values are
treated specially. 

I worked around a complicated (looking) problem with Turbine and
Velocity (I wrote about it a while ago, the Subject was "what is a
velocity reference", on th dev mailinglist) by using a wrapper class
that is guranteed to be never null:

--- cut ---
public class VeloWrapper
{
  Object obj = null;

  public VeloWrapper(Object obj)
  {
    this.obj = obj;
  }

  public Object get()
  {
    return this.obj;
  }

  public void put(Object obj)
  {
    this.obj = obj;
  }
}
--- cut ---

and now use an Intake Tool like this:

--- cut ---
public class VeloIntakeTool extends IntakeTool
{
  public Group veloMapper(VeloWrapper v, String name) throws Exception
  {
    Object obj = v.get();
    IntakeTool.PullHelper ph = (IntakeTool.PullHelper)get(name);

    return (obj == null) ? ph.getDefault() : ph.mapTo((Retrievable)obj);
  }
}
--- cut ---

Now I use the following code to the assured happiness of web template
designers and business logic programmers:

--- cut ---
public class myScreen extends VelocityScreen
{
  public void doBuildTemplate(RunData data, Context ctx)
    throws Exception
  {
    VeloWrapper v = (VeloWrapper)ctx.get("bl");
    BusinessLogicData bl = null;

    if(v != null)
      bl = (BusinessLogicData)v.get();

    ctx.put("bl", new VeloWrapper(bl));
  } 
}
--- cut ---

and

--- cut ---
#set ($frm = $intake.veloMapper($bl, "businessLogicForm"))

[... the form itself ...]
--- cut --

If I don't have an object, I get the default values for my form (from
intake). If I have an object, I get the values of the object mapped by
intake for my form.

_One_ line of code in the tempate itself. I never asked for more. ;-)
If Velocity would be able to work with null values for keys, I
wouldn't need the wrapper classes above. I consider these "jumping
through unneccessary loops". :-)

	Regards
		Henning

-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen       -- Geschaeftsfuehrer
INTERMETA - Gesellschaft fuer Mehrwertdienste mbH     hps@intermeta.de

Am Schwabachgrund 22  Fon.: 09131 / 50654-0   info@intermeta.de
D-91054 Buckenhof     Fax.: 09131 / 50654-20   

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by Dan Bachelder <ch...@chowda.net>.
no.. but i can think of a bunch of places where i have had to hack around it
:)

> Agreed.  I wonder if anyone has templates that depend on this behaviour
> ... I would sincerely hope not.  Can anyone think of a example where
> skipping the #set actually makes things clearer?
>
> --
> cheers, Mike
>
> "Life is like an analogy."
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>
>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by Mike Williams <mi...@cortexebusiness.com.au>.
  >>> On Fri, 09 Nov 2001 13:39:47 -0500,
  >>> "Geir" == "Geir Magnusson Jr." <ge...@optonline.net> wrote:

  Geir> I have abhorred this aspect of things for a long time - I think of
  Geir> it as a bug in a sense because what happens is that he #set()
  Geir> 'fails' based on data, which is equally as bad as configurable
  Geir> language semantics...
  Geir> 
  Geir> Looking at 
  Geir> 
  Geir> #set($bar = "woogie")
  Geir> #set($bar = $this.couldReturnNull() )
  Geir> 
  Geir> Means I have *no clue* what $bar has. 

Agreed.  I wonder if anyone has templates that depend on this behaviour
... I would sincerely hope not.  Can anyone think of a example where
skipping the #set actually makes things clearer?

-- 
cheers, Mike

"Life is like an analogy."


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
On 11/9/01 11:48 AM, "Sean Legassick" <se...@informage.net> wrote:

> In message <B8...@optonline.net>, Geir Magnusson Jr.
> <ge...@optonline.net> writes
>> The problem is that this is a 180 degree switch, so it won't do to just
>> throw it in there.  By adding a switch, we can play with it and see if it
>> really solves problems, and it prevents things from going haywire for people
>> if they get a new nightly or something for a bugfix.
> 
> Sure - but I suspect unless people want the behaviour, they'll leave it
> switched off and so the effect won't be tested.
> 
>> I say 'play with it' because the problem can easily be worked around via a
>> tool, but that makes for funny templates.
> 
> But sure it makes it easy to try it both ways.
> 
>> One solution is adding an event handler to let the programmer make the
>> decision...
> 
> That could also do it.
> 
> I don't have a strong view on the behaviour, personally saying that #set
> with a RHS of null removes the object from the context works fine
> conceptually. But I don't particularly mind the current behaviour
> either.
> 
> I do feel strongly though that opening the door to configurable language
> semantics is a bad move, it creates a precedent for people to suggest
> all kinds of little switches and soon it will be impossible to tell what
> a VTL template does just by looking at it.

I agree.  I just want to play with it.

I have abhorred this aspect of things for a long time - I think of it as a
bug in a sense because what happens is that he #set() 'fails' based on data,
which is equally as bad as configurable language semantics...

I.e. Looking at 

#set($bar = "woogie")
#set($bar = $this.couldReturnNull() )

Means I have *no clue* what $bar has.  It could contain the result of the
couldReturnNull() method, or not, and be unchanged.  That¹s weird for an
assignment in any language.

Some would argue the ambiguity of

#if( $foo )

is ok.  I can go both ways on this as if you keep to the original
philosophy, its ok - and it's a trivial solution to do

#if($tool.inContext($foo))

Which makes it really clear what you are trying to figure out...

> 
> (standard $0.02 type disclaimer)

-- 
Geir Magnusson Jr.     geirm@optonline.net
System and Software Consulting
"Whoever would overthrow the liberty of a nation must begin by subduing the
freeness of speech." - Benjamin Franklin



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by Sean Legassick <se...@informage.net>.
In message <B8...@optonline.net>, Geir Magnusson Jr. 
<ge...@optonline.net> writes
>The problem is that this is a 180 degree switch, so it won't do to just
>throw it in there.  By adding a switch, we can play with it and see if it
>really solves problems, and it prevents things from going haywire for people
>if they get a new nightly or something for a bugfix.

Sure - but I suspect unless people want the behaviour, they'll leave it 
switched off and so the effect won't be tested.

>I say 'play with it' because the problem can easily be worked around via a
>tool, but that makes for funny templates.

But sure it makes it easy to try it both ways.

>One solution is adding an event handler to let the programmer make the
>decision...

That could also do it.

I don't have a strong view on the behaviour, personally saying that #set 
with a RHS of null removes the object from the context works fine 
conceptually. But I don't particularly mind the current behaviour 
either.

I do feel strongly though that opening the door to configurable language 
semantics is a bad move, it creates a precedent for people to suggest 
all kinds of little switches and soon it will be impossible to tell what 
a VTL template does just by looking at it.

(standard $0.02 type disclaimer)

-- 
Sean Legassick
sean@informage.net
         ignorance is not bliss

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
On 11/8/01 1:53 PM, "Sean Legassick" <se...@informage.net> wrote:

> In message <B8...@optonline.net>, Geir Magnusson Jr.
> <ge...@optonline.net> writes
>> If no one really objects, I can add this as a default-off switch to allow,
>> when turned on, a null value on the RHS to remove the reference from the
>> context, so things will behave as you expect.
> 
> I personally don't like the idea of using a configuration parameter to
> determine language semantics. It seems a potential cause of nasty
> hard-to-track bugs when moving templates from one site to another for
> example.
> 
> Is there actually any reasonable use of the non-removing semantics? That
> is, does anyone really write templates that take advantage of a #set
> failing where the RHS is null? If not why not just change the behaviour
> so at least it keeps VTL semantically consistent for a given release of
> Velocity.


The problem is that this is a 180 degree switch, so it won't do to just
throw it in there.  By adding a switch, we can play with it and see if it
really solves problems, and it prevents things from going haywire for people
if they get a new nightly or something for a bugfix.

I say 'play with it' because the problem can easily be worked around via a
tool, but that makes for funny templates.

One solution is adding an event handler to let the programmer make the
decision...

Hm.

-- 
Geir Magnusson Jr.                                     geirm@optonline.net
System and Software Consulting
"They that can give up essential liberty to obtain a little temporary safety
deserve neither liberty nor safety." - Benjamin Franklin



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by Sean Legassick <se...@informage.net>.
In message <B8...@optonline.net>, Geir Magnusson Jr. 
<ge...@optonline.net> writes
>If no one really objects, I can add this as a default-off switch to allow,
>when turned on, a null value on the RHS to remove the reference from the
>context, so things will behave as you expect.

I personally don't like the idea of using a configuration parameter to 
determine language semantics. It seems a potential cause of nasty 
hard-to-track bugs when moving templates from one site to another for 
example.

Is there actually any reasonable use of the non-removing semantics? That 
is, does anyone really write templates that take advantage of a #set 
failing where the RHS is null? If not why not just change the behaviour 
so at least it keeps VTL semantically consistent for a given release of 
Velocity.

-- 
Sean Legassick
sean@informage.net
         ignorance is not bliss

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by Mike Williams <mi...@cortexebusiness.com.au>.
  >>> On Thu, 08 Nov 2001 00:07:10 -0500,
  >>> "Geir" == "Geir Magnusson Jr." <ge...@optonline.net> wrote:

  Geir> If no one really objects, I can add this as a default-off switch to
  Geir> allow, when turned on, a null value on the RHS to remove the
  Geir> reference from the context, so things will behave as you expect.

You've got my vote!

-- 
cheers, Mike


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by Christoph Reck <Ch...@dlr.de>.
"Geir Magnusson Jr." wrote:
> If no one really objects, I can add this as a default-off switch to allow,
> when turned on, a null value on the RHS to remove the reference from the
> context, so things will behave as you expect.

+1, for what my 2c count!

I had submitted a similar patch some months ago.

:) Christoph

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
On 11/7/01 11:43 PM, "Mike Williams" <mi...@cortexebusiness.com.au> wrote:

>>>> On Wed, 07 Nov 2001 22:46:37 -0500,
>>>> "Geir" == "Geir Magnusson Jr." <ge...@optonline.net> wrote:
> 
> Geir> The logs don't lie.
> 
> I value their honesty :-)
> 
> Geir> How about
> 
> Geir> #foreach( $item in $items )
> Geir>   #if( $item.color)
> Geir>      A $item.color $item.name
> Geir>   #end
> Geir> #end
> 
> Yep, that works.  However, as you may have guessed, my previous example was
> a slightly artificial one.

I suspected :)

> The actual template I'm having problems with
> has a construct like this:
> 
> #set( $remoteName = $class.getTag("@ejb:remote-interface").getParam("name") )
> #if( $remoteName )
>   REMOTE $remoteName
> #end
> 
> and I was hoping to avoid
> 
> #if( $class.getTag("@ejb:remote-interface").getParam("name") )
>   REMOTE $class.getTag("@ejb:remote-interface").getParam("name")
> #end
> 

That could be expensive...

> Should I be thinking about simplifying my model?

Maybe.  The problem is that things in the context don't have null values -
it's either in the context with a non-null value, or not in the context.

It's kind of weird to let a #set() remove something from the context, but
that is effectively what would need to happen because of our definition of
'in the context'.

However, on operations that are heavy lifting, like what I assume your
example above is, or something that changes the state of something, you
*don¹t* want to do it twice.

Now, the standard, basic Context interface does support this with the
remove() [thank goodness...] so we could do it w/o any real harm.

If no one really objects, I can add this as a default-off switch to allow,
when turned on, a null value on the RHS to remove the reference from the
context, so things will behave as you expect.

geir

-- 
Geir Magnusson Jr.                                     geirm@optonline.net
System and Software Consulting
"He who throws mud only loses ground." - Fat Albert


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by Mike Williams <mi...@cortexebusiness.com.au>.
  >>> On Wed, 07 Nov 2001 22:46:37 -0500,
  >>> "Geir" == "Geir Magnusson Jr." <ge...@optonline.net> wrote:

  Geir> The logs don't lie.

I value their honesty :-)

  Geir> How about

  Geir> #foreach( $item in $items )
  Geir>   #if( $item.color)
  Geir>      A $item.color $item.name
  Geir>   #end
  Geir> #end

Yep, that works.  However, as you may have guessed, my previous example was
a slightly artificial one.  The actual template I'm having problems with
has a construct like this:

  #set( $remoteName = $class.getTag("@ejb:remote-interface").getParam("name") )
  #if( $remoteName )
    REMOTE $remoteName
  #end

and I was hoping to avoid

  #if( $class.getTag("@ejb:remote-interface").getParam("name") )
    REMOTE $class.getTag("@ejb:remote-interface").getParam("name")
  #end

Should I be thinking about simplifying my model?

-- 
cheers, Mike


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: #set silently fails if RHS is null

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
On 11/7/01 10:41 PM, "Mike Williams" <mi...@cortexebusiness.com.au> wrote:

> I have a loop that looks something like this:
> 
>   #foreach( $item in $items )
>   #set( $colour = $item.colour )
>   #if( $colour ) {
>       A $colour ${item.name}
>   #end
>   #end
> 
> Now say I have the following list of items:
> 
>   #1 name="hammer"
>   #2 name="wheelbarrow" colour="blue"
>   #3 name="wheelbarrow" colour="red"
>   #4 name="screwdriver"
> 
> I expected the output to be
> 
>   A blue wheelbarrow
>   A red wheelbarrow
> 
> But, in fact it's
> 
>   A blue wheelbarrow
>   A red wheelbarrow
>   A red screwdriver
> 
> The problem is that Velocity skips the #set if the RHS is null (well, this
> is what the logs tell me).  This seems to be pretty counter-intuitive
> behaviour ... is there a reason for it?  What's the best work-around?

The logs don¹t lie.

How about

#foreach( $item in $items )
  #if( $item.color)
     A $item.color $item.name
  #end
#end

?


-- 
Geir Magnusson Jr.                                     geirm@optonline.net
System and Software Consulting
"They that can give up essential liberty to obtain a little temporary safety
deserve neither liberty nor safety." - Benjamin Franklin



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>