简体   繁体   中英

Loading Velocity Templates from nested JARs

I have an application packaged inside of a onejar, which uses Velocity for templating.

In my maven project setup, I have a file in $base/src/main/resources/template.html . When the app gets packaged as a onejar, the resulting onejar contains a nested jar inside of it (under main/my-jar.jar). That jar in turn has that template.html file packaged under its root. (Apparently maven copied it from src/main/resources into the root of the package)

I'd like to load that template as a resource in Velocity. I've read I need to use a ClassPathResourceLoader to do that, so I have code that looks like this:

    VelocityEngine ve = new VelocityEngine();
    ve.setApplicationAttribute("resource.loader", "class");

    ve.setApplicationAttribute("class.resource.loader.class", 
                               org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader.class);

    ve.init();
    Template t = ve.getTemplate("template.html");

This fails every time, with an exception that none of Velocity's resource loaders can find the file.

I have two questions - first, is this even the right way to configure the use of the ClasspathResourceLoader? And second, if that were configured properly, what path would I specify so that template.html could be found inside of that inner nested jar?

I managed to find the answer after a lot of digging.

The code to use the ClasspathResourceLoader is as follows:

VelocityEngine ve = new VelocityEngine();

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

ve.init();

Secondly, many people are telling me that inside of a nested jar, the standard classpath loader shouldn't even be able to find the template.html file. I was told that some fancy third party classloader would be necessary. OneJar provides such a fancy loader. Once I got the code correct to use the ClasspathResourceLoader, things seemed to resolve.

The thing to keep in mind is that "/" is relative to the classpath root. So when $base/src/main/resources/template.html got repackaged as template.html in the root directory of the unpacked JAR, that meant that /template.html was the right resource path to load.

That path /template.html is of course relative to the nested inner JAR. How the class loader (whether standard or OneJar) didn't get confused between the / of the outer jar and the inner jar, I don't know.

specify the path where your template.html resides using / as relative path

and use setProperty like below

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

            ve.init();

            final String templatePath = "/" + template + ".html";


            Template template = ve.getTemplate(templatePath, "UTF-8");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM