Cómo #incluir un archivo desde una plantilla Velocity usando ClasspathResourceLoader
Estoy tratando con un código Java donde Velocity 1.7 está configurado para recuperar plantillas a través de ClasspathResourceLoader. A continuación se muestra una muestra simplificada del código. Es de una aplicación web Tapestry que se ejecuta en un servidor Jetty.
La clase Java, las plantillas y el archivo a incluir están todos en la misma carpeta "testpackage", por lo que en el JAR resultante están todos en el mismo paquete "testpackage".
El problema es que si la plantilla contiene un
#include("MyInclude.vm")
directiva, Velocity no puede encontrar "MyInclude.vm" y genera una ResourceNotFoundException.
Como en el argumento de getTemplate debo anteponer el nombre del paquete al nombre de la plantilla, también intenté hacer lo mismo en el #include dentro de la plantilla:
#include("testpackage/MyInclude.vm")
pero la única diferencia es que este último funciona si ejecuto la aplicación web desde Eclipse, mientras que el primero no funciona ni siquiera desde Eclipse. Si compilo, implemento los JAR y ejecuto la aplicación web desde la implementación, ambas sintaxis fallan con la misma excepción ResourceNotFoundException.
El documento de Velocity enhttp://velocity.apache.org/engine/releases/velocity-1.7/user-guide.html#Include dice:
"Por razones de seguridad, el archivo que se incluirá solo puede estar en TEMPLATE_ROOT"
Definitivamente, esta podría ser la causa de mi problema, pero no he podido encontrar más información sobre qué es realmente TEMPLATE_ROOT.
Suena mucho a una variable de entorno, pero no sé en qué debería configurarlo, ya que estoy usando un ClasspathResourceLoader, y el archivo a incluir no es un archivo real ubicado en una carpeta, está dentro del JAR que contiene las plantillas y la clase Java (y todas en el mismo paquete).
Encontré TEMPLATE_ROOT mencionado en otra pregunta,¿Dónde debo colocar los archivos de plantilla Velocity para una utilidad de línea de comandos creada con Maven? , pero está relacionado con el uso de un FileResourceLoader. Necesito seguir usando ClasspathResourceLoader y necesito que todos los archivos estén en el JAR, no fuera de él como archivos normales en alguna carpeta.
TestVelocity.javapackage 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>