Velocity jumpstart
Sitevision modules often uses the Apache Velocity template engine when rendering output. Velocity is a markup language that has a small footprint, a simple syntax and good performance.
This page briefly shows you the basics of Velocity.
Accessing objects
When you write code in a Velocity template, you have access to all objects available in the Velocity context. Each object is registered with a name and you use the name (prefixed with a dollar-sign) to access the object.
For example: if an instance of a java.util.ArrayList
is registered as "myList
" in the context, you access it as follows in your Velocity template:
$myList
Invoking methods
You invoke methods as you would in Java.
For example: if an instance of a java.util.ArrayList
is registered as "myList
" in the context, you invoke the size()
method as follows in your Velocity template:
$myList.size()
Invoking no-args get methods
If you invoke a get-method that has no arguments, you can use the short-name notation Velocity provides.
For example: if you want to call the getThing()
method of an object that is registered as "aObject
" in the Velocity context you can do so in three ways:
$aObject.getThing()
$aObject.Thing
$aObject.thing
The first one is obvious since it uses the full method signature. The two below is using the short-name notation to execute the getThing()
method.
Comments
All lines that starts with two ## are considered as single line comments. For example:
## This is a single line comment
Comments that span multiple lines are demarcated with #* and *#. For example:
#*
This is a multiple
line comment!
*#
Selections
Selections in Velocity is done using the familiar if/elseif/else
idiom. For example:
#if ($something == 1)
...
#elseif ($somethingIsTrue)
...
#else
...
#end
Note that #elseif
is one word (i.e. no space between else and if). Also note that the end of a selection statement is demarcated with an #end
Iterations
Iterations in Velocity is done with the foreach construct. Hence, to iterate in Velocity you must have some kind of collection/iterator.
An example of how to iterate the items in a java.util.ArrayList
registered as "myList
" in the context:
#foreach ($aItem in $myList)
$aItem.doSomething()
...
#end
Note that you specify the name of the item (i.e. $aItem
above) variable as you like (a variable name can only contain characters ['a'..'z', 'A'..'Z', '0'..'9', '-', '_']). Also note that the end of the foreach construct is demarcated with an #end
Predefined variables in foreach loops
Velocity provides special predefined variables that is available during execution of the foreach construct
#foreach ($item in $someIterableThing)
$foreach.count ## 1-based counter
$foreach.index ## 0-based counter
$foreach.first ## boolean - whether or not this is the first entry
$foreach.last ## boolean - whether or not this is the last entry
#end
Note! Legacy 1-based counter variable $velocityCount
is deprecated. Use $foreach.count
instead
You can break out of a foreach loop with the #break
directive
#foreach ($item in $someIterableThing)
...
## Break out of the loop when 3 items has been processed
#if ($foreach.count == 3)
#break
#end
#end
Assigning objects and values
Variables is assigned using the set construct. For example:
#set ($myThing = 1)
You can use actual values in assignments and concatinate them when the variable is set
#set ($name = 'Stina')
#set ($age = 30)
#set ($sentence = $name + ' is ' + $age + ' years old')
You can also do simple mathematical operations when the variable is set (or re-set). For example:
#set ($count = 0)
#foreach ($aItem in $myList)
#set ($count = $count + 1)
...
#end
$count should be equal to $myList.size()
Caveats
No null assignments
You can not assign a null value to a Velocity object. If you try to assign or use a null
value, the previous value will be used instead!
For example, the result of:
#set ($myVariable = "Hello")
My variable: $myVariable <br>
#set ($myVariable = $aObject.thisMethodReturnsNull())
My variable: $myVariable
will be:
My variable: Hello <br>
My variable: Hello
No parsing of assignments enclosed in single quotes
If you assign something enclosed in single quotes, it will not be parsed.
For example, the result of:
#set ($myVariable = '$aObject.Thing')
Hello $myVariable
will be:
Hello $aObject.Thing
Tips & Trix
Check for null values
You can do a simple if-statement to check if a value exist. For example:
#if ($aObject)
$aObject.xxx
#end
Ensure no null value
You can use the ! operator to ensure nothing will be printed if it is null
.
$!aObject.doSomething()
An example: If you have a link object (named "link
" on the context) and it has no title (i.e. getTitle()
method returns null
). If your Velocity template look like this:
<a href="..." title="$link.Title">A link</a><br>
<a href="..." title="$!link.Title">A link again</a>
Then the rendered result will be this:
<a href="..." title="$link.Title">A link</a><br>
<a href="..." title="">A link again</a>
E.g. When Velocity doesn't find what you specify, your statement will be printed 'as-is'!
Explicit statement
Sometimes you have to explicitly tell Velocity where your statement really ends. This is done with curly brackets.
For example if you want to call the getThing()
method on aObject and some text is directly after your statement:
${aObject.Thing}text
(Without brackets Velocity would look for a method or variable named "Thingtext
" and fail)
Null check/assignment workaround
As stated above - Velocity ignores null assignments. A common strategy to work around this is to use the "Check for null value" strategy stated above. You sometimes end up with code like this:
## Ensure doStuff() returns non-null value
#if ($myObject.doStuff())
#set ($thing = $myObject.doStuff())
$thing.doThis()
$thing.doThat()
...
#end
The downside with this strategy is that it requires two subsequent method invocations. That is of course a really bad thing if the method does costly things.
Tip! The ScriptUtil interface of the Sitevision Public API allows you to do it more efficiently using the getNonNullValue()
method. The code above can be better utilized as:
## Assign thing - Boolean.FALSE if result is null
#set ($thing = $scriptUtil.getNonNull($myObject.doStuff()))
#if ($thing)
$thing.doThis()
$thing.doThat()
...
#end
Velocity and (X)HTML
Ensure that string demarcation characters in method arguments does not collide with characters in HTML. A simple solution for this problem is to use single quotes instead of quotes. For example:
<a href="$aObject.doThingWithString('A String')" title="">A link</a>