Sometimes you just need to add some bit of Java to the page and you don't want, or can't involve java developers. You know the classname, the class is available to your application (through system libraries or being added to the WEB-INF directories) and all you want to do is reference it. This is the function of the $javabeans objects.
The BeanFactory $javabeans object provides a simplified equivalent to the <jsp:useBean> and <jsp:setProperty> features in JSP, allowing page designers to add arbitrary Java objects to their templates without requiring updates to the Java webapp libraries or any other java programmer intervention.
To support Java beans, SportPage adds two context utility objects, $params and $javabeans:
this is a class borrowed from Turbine. This is a java Map object populated with GET/POST or PATH_INFO parameters. Access methods provide ways to get at java primitive types (getBoolean, getBigInteger...)
This utility object is often used in conjunction with JavaBeans to set bean properties with one call just as you would normally do in JSP:
$params.setProperties( $mybean )
this is a BeanFactory which addresses performance issues with trying to instance new objects on every Velocity template call; unlike JSP, the BeanFactory leaves the scope of the object to the bean itself.
The bean is created according to the following method search sequence:
getInstance(ExtendedProperties) method which has access to the server configuration.
getInstance(Context) method that can be used to detect the HttpSession, the $path or whatever other clue is useful in the page context to decide how to and when to create a new bean.
If the context method fails, it will then try getInstance(). This allows beans to be implemented as singletons (ie only one bean per JVM)
if the singleton method fails, it will then try for a null constructor, the standard constructor for java beans. In this way, any class that can be included in JSP using the usebean tag can be included under a request scope in a Velocity page; if the need arises (and it probably will) this will be expanded to allow constructors to instance a bean with page and/or webapp scope.[3]
Inside a Velocity template, we can use constructs like
#set ($now = $javabean.getBean("java.util.Date"))
or, if the bean supports it, have a form handler selecting weather cities and use
#set ($weather = $javabean.getBean($context, "cbc.utilities.weather" )) $params.setProperties( $weather )
Any configuration file dot-variables ending in “.bean” will be interpreted as a fully-qualified Java classname and instanced as a Java bean; like any dot-property, you can specify these per-topic and inherit bean variables from a parent topic
default.weather.bean=cbc.utilities.weather
will define a global $weather variable using the specified class
sports.luge.history.weather.bean=cbc.utilities.weather_history
would mean that, in sports/luge/history only, the $weather refers to a different class of object.
Caution | |
---|---|
Because dot-variable and BeanFactor constructors are evaluated as each template is accessed, they are expensive to invoke; the beans should cache themselves or be singleton objects where ever practical, and constructors should be lightening quick. |
[3] Java beans can also be created under an applications scope by attaching bean instances to the $global application configuration Map object. Because Velocity templates are all, to Java, the same servlet, there is no equivalent to a page scope without extra programming to cache the object based on the $path; examples of such caching can be found in the JDOMFile source code.