web-dev-qa-db-fra.com

Chargement du modèle de vitesse dans un fichier jar

J'ai un projet où je veux charger un modèle de vélocité pour le compléter avec des paramètres. L'ensemble de l'application est présenté sous forme de fichier jar. Au départ, j'ai pensé à faire ceci:

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();

Et cela fonctionne bien lorsque je l'exécute dans Eclipse. Cependant, une fois que j'ai empaqueté le programme et essayé de l'exécuter à l'aide de la ligne de commande, j'obtiens une erreur car le fichier est introuvable.

J'imagine que le problème est dans cette ligne:

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

Parce que dans un bocal, le fichier absolu n'existe pas, car il est à l'intérieur d'un Zip, mais je n'ai pas encore trouvé de meilleure façon de le faire.

Quelqu'un a des idées?

45
Rafael

Si vous souhaitez utiliser des ressources de classpath, vous devez utiliser le chargeur de ressources pour classpath:

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

Code final, développé en utilisant les idées présentées dans les deux réponses ci-dessus:

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();
19
Rafael

À moins que JAR ne soit éclaté, vous ne pouvez pas lire la ressource dans JAR en tant que fichier. Utilisez un flux d'entrée.

Voir les extraits de code suivants,

    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)) 
                ......
9
ZZ Coder

Peut-être que j'ai une ancienne version, c'est la seule chose qui a fonctionné pour moi

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

Pour que Velocity recherche les modèles dans classpath:

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