Most of the time, there is no problem, rendering a Velocity template because the rendering engine is quite smart about finding Velocity Statements and References and distinguishing them from regular text.
## Renders as normal text, because the dollar sign ## is not followed by a letter. I bought a 4 lb. sack of potatoes for only $2.50! ## Renders as variable I bought a 4 lb. sack of potatoes for only $money.
Velocity allows for explicit escaping of References and Directives
using the
(backslash) character.
If the character following the \
\
would start a new
directive or reference, then this character is output verbatim. This can
lead to some unexpected behaviour, especially with directives.
Example 3.4. VTL escaping examples
\ ## Renders as a single backslash (no # or $ follows) \\ \# \$ ## Renders as \\ \# \$ (no directive or reference follows) \#end ## Renders as #end, backslash escapes an existing directive
Unfortunately, the escaping of VTL elements contains a number of
quirks that make them actually hard to use[2]. As you have seen, the behaviour of the
\
differs whether a directive or just text
follows:
Example 3.5. Escaping VTL references
$a ## $a is a reference but an unbound on (it has no value) ## This renders as $a in the output \$a ## Escaping an unbound reference renders it as \$a #set($a = 10) ## When a value is assigned to the reference... $a ## Now renders as 10 \$a ## Now renders as $a
Escaping VTL statements works in the same way.
Example 3.6. Escaping VTL statements
\#end ## Renders as #end \# end ## Renders as \# end (note the space) \#set ($a = 10) ## Renders as #set ($a = 10) ## If $a has been assigned a value: #set ($a = 10) \#set ($a = 20) ## Renders as #set (10 = 20) ## The backslash does not escape a whole multiline statement ## This is a syntax error: (#end without a starting statement) \#if ($a == 10) #end
Using Velocity
Macros, the behaviour of escaping #
changes a
bit:[3]
Example 3.7. Escaping Macros
#apple ## Renders as #apple, because it is not a VTL ## statement \#apple ## Renders as \#apple #macro(apple) Apple #end #apple ## This is now an syntax error (#apple needs now ## brackets because it's a macro) #apple() ## Renders as Apple (VTL Macro) \#apple ## renders as #apple, because it is now a VTL ## statement after macro definition.
[2] It is really mind-boggling how we came up with this. It is tied more to the internal workings of the Velocity engine than any user-friendlyness. This is definitely subject to change in future Velocity versions. Until then, please be kind to our mistakes.
[3] ...and you probably thought, the worst part was over...