I'm not sure if there is a way to do this in Velocity or not:
I have a User POJO which a property named Status, which looks like an enum (but it is not, since I am stuck on Java 1.4), the definition looks something like this:
public class User {
// default status to User
private Status status = Status.USER;
public void setStatus(Status status) {
this.status = status;
}
public Status getStatus() {
return status;
}
And Status is a static inner class:
public static final class Status {
private String statusString;
private Status(String statusString) {
this.statusString = statusString;
}
public final static Status USER = new Status("user");
public final static Status ADMIN = new Status("admin");
public final static Status STATUS_X = new Status("blah");
//.equals() and .hashCode() implemented as well
}
With this pattern, a user status can easily be tested in a conditional such as
if(User.Status.ADMIN.equals(user.getStatus())) ...
... without having to reference any constants for the status ID, any magic numbers, etc.
However, I can't figure out how to test these conditionals in my Velocity template with VTL. I'd like to just print a simple string based upon the user's status, such as:
Welcome <b>${user.name}</b>!
<br/>
<br/>
#if($user.status == com.company.blah.User.Status.USER)
You are a regular user
#elseif($user.status == com.company.blah.User.Status.ADMIN)
You are an administrator
#etc...
#end
But this throws an Exception that looks like org.apache.velocity.exception.ParseErrorException: Encountered "User" at webpages/include/dashboard.inc[line 10, column 21] Was expecting one of: "[" ...
From the VTL User Guide, there is no mention of accessing a Java class/static member directly in VTL, it appears that the right hand side (RHS) of a conditional can only be a number literal, string literal, property reference, or method reference.
So is there any way that I can access static Java properties/references in a Velocity template? I'm aware that as a workaround, I could embed the status ID or some other identifier as a reference in my controller (this is a web MVC application using Velocity as the View technology), but I strongly do not want to embed any magic numbers or constants in the view layer.
Members of static classes can be accessed directly using the class name followed by a (.) and class member name. Class Members can be methods, fields, properties, or events. A static class can contain only the static members while a non-static class can contain static members.
To use, either add this pair of macros to your template, or better yet, to your VM_Global_library. vm file. Then from the template you want to debug, you can simply add #showDebugPopup() to the bottom of the template you want to debug, and it will pop up a window with debugging information.
Since static variables belong to a class, we can access them directly using the class name. So, we don't need any object reference. We can only declare static variables at the class level. We can access static fields without object initialization.
In the static method, the method can only access only static data members and static methods of another class or same class but cannot access non-static methods and variables. Non-static method: Any method whose definition doesn't contain the static keyword is a non-static method.
I figured out a workaround that allows me to add each User.Status
object to the Velocity context, which avoids any sort of references to constants or magic numbers in the template.
On the controller/Java side:
// put the statuses directly into the model
Map statusMap = new HashMap();
statusMap.put("user", User.Status.USER);
statusMap.put("groupOperator", User.Status.ADMIN);
...
modelAndView.addObject("statusmap", statusMap);
And then in the template these values can be referenced like so:
#if($user.status == $statusmap.user)
You are a regular user
#elseif($user.status == $statusmap.admin)
You are an administrator
##etc...
#end
Yeah, Velocity doesn't natively grok classes and packages. You could do what you did, or use the FieldMethodizer class to automate that. Another option would be the FieldTool in VelocityTools 2.0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With