Notification Service: Simple Velocity service
28 October 2008One of the fundamental components of my envisioned Notification Service is the merging of dynamic data with predefined message templates. There may be other ways of accomplishing this, but for my money, nothing beats Velocity when it comes to template resolution in a Java environment. Velocity has quite a number of capabilities, though, and I just wanted a simple interface to a specific process, so I created the SimpleVelocityService:
package org.restafarian.core.utils;
import java.io.StringWriter;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
/**
* <p>This class is a simple wrapper for Velocity.</p>
*/
public class SimpleVelocityService {
private static final Log log = LogFactory.getLog(SimpleVelocityService.class);
private static SimpleVelocityService STATIC_SERVICE = null;
/**
* <p>Constructs a new SimpleVelocityService.</p>
*/
private SimpleVelocityService() {
try {
Velocity.init();
} catch (Exception e) {
log.error("Exception initializing SimpleVelocityService: Velocity runtime engine
initialization failure: " + e, e);
}
}
/**
* <p>Uses Velocity to evaluate the template using the source data for the
* Velocity context.</p>
*
* @param template the velocity template
* @param sourceData the source data used for the Velocity context
* @return the resolved template
*/
public static String evaluate(String template, Object sourceData) {
return getService().evaluateTemplate(template, sourceData);
}
/**
* <p>Uses Velocity to evaluate the template using the source data for the
* Velocity context.</p>
*
* @param template the velocity template
* @param sourceData the source data used for the Velocity context
* @return the resolved template
*/
private String evaluateTemplate(String template, Object sourceData) {
StringWriter writer = new StringWriter();
VelocityContext context = null;
if (sourceData.getClass().isAssignableFrom(VelocityContext.class)) {
context = (VelocityContext) sourceData;
} else {
try {
Map values = (Map) sourceData;
context = new VelocityContext(values);
} catch (ClassCastException e) {
context = new VelocityContext();
}
}
try {
Velocity.evaluate(context, writer, getClass().getName(), template);
} catch (Exception e) {
log.error("Exception caught on SimpleVelocityService.evaluate(): " + e, e);
}
return writer.toString();
}
/**
* <p>Returns the currently active service object.</p>
*
* @return the currently active service object
*/
public static SimpleVelocityService getService() {
if (STATIC_SERVICE == null) {
STATIC_SERVICE = new SimpleVelocityService();
}
return STATIC_SERVICE;
}
}
Basically, this module provides a single method that takes two arguments (the boilerplate message template and the data to be used to resolve variables in the template) that can be invoked with a one-line static call:
String resolvedMessage = SimpleVelocityService.evaluate(template, sourceData);
Two objects go in, and one comes back out. As I say, Velocity can do many more things, but this is sufficient for the current needs of the Notification Service, so this is good enough for now. For a typical e-mail notification, I might invoke this process twice, once for the body of the e-mail and once for the subject. Having variable data in both the subject and the body is something that I think would be a nice, standard feature for a Notification Service, and a little utility such as this one makes it easy to invoke the process as many times as needed.
Next time we’ll talk a little bit about the overall design at somewhat of a higher level, and then maybe we’ll start building some pieces.
Leave a reply
You must be logged in to post a comment.





