Velocity ${formal.notation} invites syntax errors: use it wisely

SanfordWhiteman
Level 10 - Community Moderator
Level 10 - Community Moderator

There are 2 ways to access references (i.e. variables) in Velocity.

(1) Simple/shorthand notation, prefixed with a $:

$variableName

$variable.property

$variable.method()

$variable.property.method()

(2) Formal/longhand notation, prefixed with $ and wrapped in {} (curly braces):

${variableName}

${variable.property}

${variable.method()}

${variable.property.method()}

Simple notation should be your default. Formal notation should only be used when there's no alternative. As the Velocity docs say:

In almost all cases you will use the shorthand notation for references, but in some cases the formal notation is required for correct processing.

I'd go further: when used unnecessarily, formal notation can make your code confusing and fragile. Unfortunately, Marketo's script editor doesn't encourage best practices, because when you drag a field from the field tree to the editor canvas, it's automatically  wrapped in ${}:

5acbd8e898b1d0002262929b_vtl_formal_scripted.png

My recommendation: remove the curly braces right away, and only restore them if it proves necessary during development.

What can go wrong?

A recent Community post shows how confusing things can get when you use formal notation unnecessarily (note how the poster titled it "... tokens behave unexpectedly" when it's actually established behavior, if not well-circulated).

The catch: a reference enclosed in ${formal.notation} cannot be chained with a method/property outside the curly braces.

OK, that probably didn't make sense unless you're fluent in OO-speak! Let's look at some examples.

This does work with simple notation:

#if( $lead.FirstName.isEmpty() )

It doesn't work if you only enclose part of the expression in formal notation:

#if( ${lead.FirstName}.isEmpty() )

Sure, it would work if you happened to enclose the entire expression in curlies

#if( ${lead.FirstName.isEmpty()} )

but you should just use simple notation instead, because it's harder to mess up during refactoring.

Don't believe me? (You probably do, or I'd like to hear who's more authoritative about Velocity.) Consider what happens when you move from a not-best-practice, but syntax-error-free, comparison using double-equals ==:

#(if ${lead.numberOfProducts} == 0 )

to a more forward-looking equals():

#if( ${lead.numberOfProducts}.equals(0) )

Suddenly, your Velocity token stops working because you can't have a . after a }. It may be clear, to you as a human, what you meant, but VTL doesn't allow it. If you'd used simple notation from the start you wouldn't have to make such adjustments.

When do you need to go formal?

Formal notation should only be considered inside strings or output, and only used when the separation between variables and static text would otherwise be unclear.

If you're in a line of code starting with #if or #set chances are very slim that you should be using formal notation.

Here's one case where it is necessary...

Read the full post on pastedImage_12.png

1683
0