Three Minor Velocity Peeves

by Charles Miller on March 30, 2004

It took me a little too long to embrace the Velocity web templating langauge. I place all the blame on "You Make the Decision", a piece of blatant propaganda that has since been tidied up, but when I first read it was a masterful exercise in comparing blatantly "worst-practices" JSP with carefully crafted Velocity replacements.

I finally fell head-first into a Velocity-based project in December, though, and haven't looked back since. For those who aren't Velocity-aware, it takes the refreshing approach amongst web templating languages of throwing away angle-brackets entirely, which leaves you with surprisingly readable templates as a result. I've thoroughly enjoyed using Velocity, and wouldn't hesitate to recommend it as a vastly less annoying alternative to JSP.

There are, however, three gotchas I discovered while working on Confluence.

  1. #set ($foo = $bar) does not always assign the value of $bar to the $foo variable. If $bar is null, no assignment will occur, Velocity will log a warning, and $foo will continue to have its original value.
  2. #parse("/includes/header.vm") will include the contents of header.vm in the current page with no apparent change of scope, but any macros defined in header.vm will not be available in the parent page due to Velocity's order of parsing and execution.
  3. If #foo is a macro, then you can include a literal '#foo' in your page by escaping it thus: '\#foo'. However, if #foo is not a macro, then the escaping is not un-escaped, and '\#foo' remains in its backslashed form after the page is processed. For bonus points, spot the interesting bug when you have global macro definitions turned on, and the page containing the '#foo' macro may or may not have been loaded before the page containing 'http://www.example.com/bar#foo'

Now to be fair, these are minor niggles, and two of the three are very clearly pointed out in the Velocity documentation as places in which the language does not behave the way you'd expect it to. Given that you've been warned, any mistakes you make as a result are your fault, right?

Well, no. I tend to agree with Matz that I'm ultimately happier with a language that is... simpatico. If you have to write a special note in your documentation saying "This doesn't do what you think it would do", it's probably a better use of time to change the code so it instead does what it obviously should have been doing all along.

Previously: Jetbrains Wins. Fatality.

Next: Four Things I Have Learned About Sybase