How to use String as Velocity Template?
Solution 1
There is some overhead parsing template. You might see some performance gain by pre-parsing the template if your template is large and you use it repeatedly. You can do something like this,
RuntimeServices runtimeServices = RuntimeSingleton.getRuntimeServices();
StringReader reader = new StringReader(bufferForYourTemplate);
Template template = new Template();
template.setRuntimeServices(runtimeServices);
/*
* The following line works for Velocity version up to 1.7
* For version 2, replace "Template name" with the variable, template
*/
template.setData(runtimeServices.parse(reader, "Template name")));
template.initDocument();
Then you can call template.merge()
over and over again without parsing it everytime.
BTW, you can pass String directly to Velocity.evaluate()
.
Solution 2
The above sample code is working for me. It uses Velocity version 1.7 and log4j.
private static void velocityWithStringTemplateExample() {
// Initialize the engine.
VelocityEngine engine = new VelocityEngine();
engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.Log4JLogChute");
engine.setProperty("runtime.log.logsystem.log4j.logger", LOGGER.getName());
engine.setProperty(Velocity.RESOURCE_LOADER, "string");
engine.addProperty("string.resource.loader.class", StringResourceLoader.class.getName());
engine.addProperty("string.resource.loader.repository.static", "false");
// engine.addProperty("string.resource.loader.modificationCheckInterval", "1");
engine.init();
// Initialize my template repository. You can replace the "Hello $w" with your String.
StringResourceRepository repo = (StringResourceRepository) engine.getApplicationAttribute(StringResourceLoader.REPOSITORY_NAME_DEFAULT);
repo.putStringResource("woogie2", "Hello $w");
// Set parameters for my template.
VelocityContext context = new VelocityContext();
context.put("w", "world!");
// Get and merge the template with my parameters.
Template template = engine.getTemplate("woogie2");
StringWriter writer = new StringWriter();
template.merge(context, writer);
// Show the result.
System.out.println(writer.toString());
}
A similar so question.
Solution 3
This works in Velocity 2.1
// Initialize the engine
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.setProperty(Velocity.RESOURCE_LOADERS, "string");
velocityEngine.setProperty("resource.loader.string.class", StringResourceLoader.class.getName());
velocityEngine.setProperty("resource.loader.string.cache", true);
velocityEngine.setProperty("resource.loader.string.modification_check_interval", 60);
velocityEngine.init();
// Add template to repository
StringResourceRepository repository = StringResourceLoader.getRepository()
repository.putStringResource("hello_world", "Hello $w");
// Set parameters
VelocityContext context = new VelocityContext();
context.put("w", "world!");
// Process the template
StringWriter writer = new StringWriter();
velocityEngine.getTemplate('hello_world').merge( context, writer );
System.out.println(writer.toString());
Solution 4
RuntimeServices rs = RuntimeSingleton.getRuntimeServices();
StringReader sr = new StringReader("Username is $username");
SimpleNode sn = rs.parse(sr, "User Information");
Template t = new Template();
t.setRuntimeServices(rs);
t.setData(sn);
t.initDocument();
VelocityContext vc = new VelocityContext();
vc.put("username", "John");
StringWriter sw = new StringWriter();
t.merge(vc, sw);
System.out.println(sw.toString());
Solution 5
Velocity 2 can be integrated into the JSR223 Java Scripting Language Framework which make another option to transform string as a template:
ScriptEngineManager manager = new ScriptEngineManager();
manager.registerEngineName("velocity", new VelocityScriptEngineFactory());
ScriptEngine engine = manager.getEngineByName("velocity");
System.setProperty(VelocityScriptEngine.VELOCITY_PROPERTIES, "path/to/velocity.properties");
String script = "Hello $world";
Writer writer = new StringWriter();
engine.getContext().setWriter(writer);
Object result = engine.eval(script);
System.out.println(writer);
tomsame
Updated on October 17, 2021Comments
-
tomsame over 2 years
What is the best way to create Velocity Template from a String?
I'm aware of Velocity.evaluate method where I can pass String or StringReader, but I'm curios is there a better way to do it (e.g. any advantage of creating an instance of Template).
-
tomsame almost 15 yearsExactly what I was looking for. Thanks. For other people's reference, runtimeServices is an instance of org.apache.velocity.runtime.RuntimeInstance
-
ZZ Coder almost 15 yearsMissed one-line. For completeness, I added it.
-
Bernhard Hofmann over 13 years+1 for the mention of Velocity.Evaluate since that's exactly what I was looking for.
-
Ben.Yan almost 7 yearsWow, this is a unique approach. how velocity engine load resource seems is internal implementation, could property "string.resource.loader.class" subject to change?
-
vektor over 4 yearsYou seem to have a typo in
Velocity.RESOURCE_LOADERS
- should probably beVelocity.RESOURCE_LOADER
. -
devatherock over 4 yearsThe
RuntimeConstants
interface which is implemented byVelocity
class has both constants -RESOURCE_LOADERS
andRESOURCE_LOADER
.RESOURCE_LOADERS
was the one I tested with -
ltlBeBoy over 3 yearsThis worked for me for some time. But then I found internal Velocity exceptions in the log file. I changed to the following solution, and everything works fine now: Velocity template as a String in Java. It uses Velocity#evaluate(context, out, logTag, instring), as mentioned in another answer here.
-
joseph about 3 yearscompilation error due to too many parens. should be
template.setData(runtimeServices.parse(reader, "Template name"));
stackoverflow complainsEdits must be at least 6 characters; is there something else to improve in this post?
.