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.
Example 3.9. Distinguishing between text and references
## 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.10. 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.11. Escaping VTL references
$a ## $a is a reference but an unbound one (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 ## ... then it renders as 10 ...
\$a ## ... and gets escaped and now renders as $a.Escaping VTL statements works in the same way.
Example 3.12. 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 multi-line 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.13. Escaping Velocimacros
#apple ## Renders as #apple, because it is not a VTL
## statement
\#apple ## Renders as \#apple
#macro(apple)
Apple
#end
#apple ## This is now a syntax error
## (#apple Velocimacro invocation needs brackets)
#apple() ## Renders as Apple (invocation of a Velocimacro)
\#apple ## renders as #apple, because it is now a VTL
## statement after Velocimacro 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...