I'm dealing with some Java code where Velocity 1.7 is set to retrieve templates through the ClasspathResourceLoader. Below is a stripped down sample of the code. It's from a Tapestry web application running on a Jetty server.
The Java class, the templates and the file to be included are all are in the same folder "testpackage", so in the resulting JAR they are all in the same package "testpackage".
The problem is that if the template contains an
#include("MyInclude.vm")
directive, Velocity cannot find "MyInclude.vm", and it throws a ResourceNotFoundException.
Since in the argument of getTemplate I must prepend the package name to the template name, I also tried to do the same in the #include inside the template:
#include("testpackage/MyInclude.vm")
but the only difference is that the latter works if I run the web app from Eclipse, while the former doesn't work not even from Eclipse. If I build, deploy the JARs and run the web app from the deployment, both syntaxes fail with the same ResourceNotFoundException.
The Velocity doc at http://velocity.apache.org/engine/releases/velocity-1.7/user-guide.html#Include says:
"For security reasons, the file to be included may only be under TEMPLATE_ROOT"
This definitely could be the cause of my problem, but I haven't been able to find any further information about what TEMPLATE_ROOT actually is.
It sounds a lot like an environment variable, but I don't know what I should set it to, since I'm using a ClasspathResourceLoader, and the file to be included is not an actual file located in a folder, it's inside the JAR containing the templates and the Java class (and all in the same package).
I found TEMPLATE_ROOT mentioned in another question, Where should I put Velocity template files for a command line utility built with Maven? , but it's related to using a FileResourceLoader. I need to keep using the ClasspathResourceLoader and I need all the files to be in the JAR, not outside it as normal files in some folder.
TestVelocity.java
package testpackage;
import java.io.StringWriter;
import java.util.Properties;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
public class TestVelocity
{
public static String getText()
{
String text = "";
Properties properties = new Properties();
properties.setProperty("resource.loader", "class");
properties.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
VelocityEngine engine = new VelocityEngine();
VelocityContext context = new VelocityContext();
StringWriter writer = new StringWriter();
try
{
engine.init(properties);
// This works because the template doesn't contain any #include
Template template = engine.getTemplate("testpackage/TemplateWithoutInclude.vm");
// This causes ResourceNotFoundException: Unable to find resource 'TemplateWithInclude.vm'
// Template template = engine.getTemplate("testpackage/TemplateWithInclude.vm");
template.merge(context, writer);
text = writer.toString();
}
catch (Exception e)
{
e.printStackTrace();
}
return text;
}
}
TemplateWithoutInclude.vm
<!DOCTYPE html>
<html>
<head></head>
<body>
<p>Hello</p>
</body>
</html>
TemplateWithInclude.vm
<!DOCTYPE html>
<html>
<head></head>
<body>
#include("MyInclude.vm")
</body>
</html>
MyInclude.vm
<p>
Hello
</p>