0

As title, is there any way to iterate or display Apache velocity template attributes?

for example, I have following code :

<code>
${ctx.messages.headerMessage}
</code>

And I want to know how many other attributes the variable ${ctx} has

f_puras
  • 2,521
  • 4
  • 33
  • 38
vincent zhang
  • 444
  • 5
  • 20
  • Did you check [this](https://stackoverflow.com/questions/5683690/how-to-use-for-loop-in-velocity-template) – soorapadman Apr 12 '19 at 10:55
  • @soorapadman thank you for your comment, this is for iterate the collection or array, not iterate the variable attributes – vincent zhang Apr 12 '19 at 13:01
  • @vincentzhang It's hard to answer your question without knowing the class of `$ctx`. What does `$ctx.class.name` display? – Claude Brisson Apr 13 '19 at 18:24
  • hi @ClaudeBrisson , thank you for your comment. the $ctx.class.name you could consider it is Person.java, if, there are only two attributes, for example, String firstName, String lastName. then how to iterate these two attributes on Velocity template? – vincent zhang Apr 14 '19 at 23:06

1 Answers1

1

It's only possible to discover and to loop on an object properties (that is, the ones with getters and/or setters) if you can add a new tool to your Velocity context. If you can't, you're rather stuck.

There are several ways to do this, I illustrate below how to do this with commons-beanutils.

First, add Apache commons-beanutils in your class path, and add it to your Velocity context from Java:

import org.apache.commons.beanutils.PropertyUtils;
...
    context.put("beans", new PropertyUtils());
...

One remark: if you do not have access to the Java part, but if by chance commons-beanutils is already in the classpath, there is one hakish way of having access to it: #set($beans = $foo.class.forName('org.apache.commons.beanutils.PropertyUtils').newInstance()).

Then, let's say that I have the following object:

class Foo
{
    public boolean isSomething() { return true; }
    public String getName() { return "Nestor"; }
}

which is present in my context under $foo. Using your newly $beans properties introspector, you can do:

#set ($properties = $beans.getPropertyDescriptors($foo.class))
#foreach ($property in $properties)
  $property.name ($property.propertyType) = $property.readMethod.invoke($foo)
#end

This will produce:

  bar (boolean) = true
  class (class java.lang.Class) = class Foo
  name (class java.lang.String) = Robert

(you'll need to filter out the class property, of course)

One last remark, though. Templates are for coding the View layer of an MVC application, and doing such a generic introspection of objects in them is rather inadequate in the view layer. You're far better of moving all this introspection code on the Java side.

Claude Brisson
  • 4,085
  • 1
  • 22
  • 30