2010-05-28 12 views
41

Tengo un proyecto donde quiero cargar una plantilla de velocidad para completarla con los parámetros. Toda la aplicación está empaquetada como un archivo jar. Lo que inicialmente pensé hacer fue esto:Cargando la plantilla de velocidad dentro de un archivo jar

VelocityEngine ve = new VelocityEngine(); 

    URL url = this.getClass().getResource("/templates/"); 

    File file = new File(url.getFile()); 

    ve = new VelocityEngine(); 
    ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "file"); 
    ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, file.getAbsolutePath()); 
    ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, "true"); 

    ve.init(); 

    VelocityContext context = new VelocityContext(); 

    if (properties != null) { 
    stringfyNulls(properties); 
    for (Map.Entry<String, Object> property : properties.entrySet()) { 
    context.put(property.getKey(), property.getValue()); 
    } 
    } 

    final String templatePath = templateName + ".vm"; 
    Template template = ve.getTemplate(templatePath, "UTF-8"); 
    String outFileName = File.createTempFile("report", ".html").getAbsolutePath(); 
    BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outFileName))); 

    template.merge(context, writer); 

    writer.flush(); 
    writer.close(); 

Y esto funciona bien cuando lo ejecuto en eclipse. Sin embargo, una vez que empaqueté el programa e intenté ejecutarlo usando la línea de comando, recibí un error porque no se pudo encontrar el archivo.

Me imagino que el problema es en esta línea:

ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, file.getAbsolutePath()); 

Debido a que en un frasco no existe el archivo absoluta, ya que es el interior de una postal, pero todavía no podía encontrar una mejor manera de hacerlo .

¿Alguien tiene alguna idea?

+2

por el amor de dios, resalte el código en su publicación y haga clic en el botón de código para que esté formateado correctamente. :) – vicatcu

+0

¿Está seguro de que el directorio/templates/se está exportando a su jar? Debes marcarlo como parte de tu configuración de compilación y demás. – vicatcu

+0

desconocía el botón de código, gracias. Sí, el directorio de plantillas se está metiendo en el archivo jar. – Rafael

Respuesta

67

Si desea utilizar los recursos de la ruta de clases, se debe utilizar cargador de recursos para la ruta de clases:

ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); 
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); 
+0

Lo probaré! ¿Sabes dónde puedo encontrar documentación para cada RuntimeContants y sus posibles valores? – Rafael

+0

No se pudo hacer que funcione, no encuentra el archivo ni en eclipse ni en el contenedor. – Rafael

+0

@Rafael: Solucionado. 'ClasspathResourceLoader' no está registrado por defecto. – axtavt

7

A menos que se explotó JAR, no se puede leer el recurso en el JAR como archivo. Use una secuencia de entrada.

Ver siguientes fragmentos de código,

InputStream input = classLoader.getResourceAsStream(fileName); 
    if (input == null) { 
     throw new ConfigurationException("Template file " + 
       fileName + " doesn't exist");   
    } 

    InputStreamReader reader = new InputStreamReader(input);    
     Writer writer = null; 

     try { 
      writer = new OutputStreamWriter(output);   

      // Merge template 
      if (!engine.evaluate(context, writer, fileName, reader)) 
       ...... 
17

código final, desarrollaron usando las ideas presentadas en las dos respuestas anteriores:

VelocityEngine ve = new VelocityEngine(); 
      ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); 
      ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); 

      ve.init(); 

      final String templatePath = "templates/" + templateName + ".vm"; 
      InputStream input = this.getClass().getClassLoader().getResourceAsStream(templatePath); 
      if (input == null) { 
       throw new IOException("Template file doesn't exist"); 
      } 

      InputStreamReader reader = new InputStreamReader(input); 

      VelocityContext context = new VelocityContext(); 

      if (properties != null) { 
       stringfyNulls(properties); 
       for (Map.Entry<String, Object> property : properties.entrySet()) { 
        context.put(property.getKey(), property.getValue()); 
       } 
      } 

      Template template = ve.getTemplate(templatePath, "UTF-8"); 
      String outFileName = File.createTempFile("report", ".html").getAbsolutePath(); 
      BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outFileName))); 

      if (!ve.evaluate(context, writer, templatePath, reader)) { 
       throw new Exception("Failed to convert the template into html."); 
      } 

      template.merge(context, writer); 

      writer.flush(); 
      writer.close(); 
+0

¡Gracias, esto me ayudó mucho! Puede ser que mi adaptación funcione solo un poco diferente, pero al usar VelocityEngine # evaluate (...), podría dejar de lado la creación de instancias de la plantilla y la llamada a Template # merge (...) – Argelbargel

+0

funciona como un amuleto. RuntimeInstance resolvió mi problema y me permitió cargar la plantilla en mi paquete.La mejor solución para OSGI – iberbeu

1

Para hacer mirada de velocidad para las plantillas en la ruta de clase:

VelocityEngine ve = new VelocityEngine(); 
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); 
ve.setProperty("classpath.resource.loader.class",ClasspathResourceLoader.class.getName()); 
ve.init(); 
+0

Eso se ve exactamente como la respuesta aceptada. – JKirchartz

+7

Creo que llegaste un poco tarde a la fiesta. –

Cuestiones relacionadas