First, using ${...}
is a way of helping the Velocity parser know exactly what you consider to be Velocity code. Normally, when velocity sees $something.somethingElse.somethingMore
, it tries to parse as much as it can until it sees a word breaking character, such as a space or comma. When it sees ${something.somethingElse}.somethingMore
, it only reads until the matching }
as actual code, the rest is plain text. This means that ${pro.test}.sort(...)
considers .sort(...)
as plain text that should be printed, so it wouldn't call it as a method. That's why the first example fails with an error. You only need to use the formal syntax outside directives, though, you can just remove all the {
and }
from the call when inside #foreach(...)
.
Second, #foreach
is very lax, it doesn't complain when you try to pass something invalid in the iterated scope; if it doesn't resolve to a valid list, then it simply ignores it and considers that there's nothing to iterate over. When something doesn't work as expected, print the values you're working with:
$pro.test $pro.test.class $pro.test.sortOrder $pro.test.sortOrder.class
#foreach ($it in ${pro.test.sort(${pro.test.sortOrder})})
...
#end
What does that print? Is $pro.test
really a set? Is $pro.test.sortOrder
a valid sort order specification, as expected by SortTool
?
If $pro.test
is a standard implementation of the Set
interface, then there's no sort
or sortOrder
method. Assuming that the Velocity SortTool
is available under the $sorter
variable, you could try, for starters:
#foreach ($it in $sorter.sort($pro.test))
...
#end
Now, what exactly is $pro.test.sortOrder
supposed to be? If it's a property, then note that for security reasons Velocity doesn't allow access directly to properties, it can only call methods. As a means of simplifying the syntax, $pro.test.sortOrder
will actually try to call one of these: getsortOrder()
, getSortOrder()
, get("sortOrder")
, issortOrder()
, isSortOrder()
.