i am trying to use FreeMarker to generate reports for different agents that work in my application. I looked online but couldn't find anywhere if it is possible to load the templates if they are not located in the resources folder of my project. As my application runs from the *.jar files i tried to use:
public ReportTemplate(final String template_path)
throws TemplateException, IOException {
CFG.setDirectoryForTemplateLoading(new File("."));
CFG.setDefaultEncoding("UTF-8");
template = CFG.getTemplate(template_path);
}
and then in my conf file where i pass the template:
parameters: {
report: /../test.ftl
}
*.jar file and the template are in the same folder, but as I understand it i first need to exit the jar file, then go and get the template. I am wondering is there an easy way to load templates for FreeMarker without putting them in the /resources/ folder of my project (that way when someone else is using the application he can design his own template and just copy it to the folder). I would also like not to use hard coded paths such as "/tmp/", thats why I am using the "." current location path.
It's possible to load templates from pretty much anywhere, and also to load templates from multiple locations. But I suspect there's a couple of misunderstandings here.
There's only a single cfg.templateLoader
property. cfg.setDirectoryForTemplateLoading(dir)
is just a convenience shorthand for cfg.setTemplateLoader(new FileTemplateLoader(dir))
, and cfg.setClassForTemplateLoading(...)
is just a convenience shorthand for cfg.setTemplateLoader(new ClassTemplateLoader(...))
. If you need to load with both mechanisms (from an arbitrary directory, and from jar-s on the Java classpath), then you need to use cfg.setTemplateLoader(new MultiTemplateLoader(new TemplateLoader[] { new FileTemplateLoader(dir), new ClassTemplateLoader(...) }))
. Now if you try to load foo/bar.ftl
, first the FileTemplateLoader
will try to load foo/bar.ftl
relative to its own base directory, and if it's not found, then the ClassTemplateLoader
will try to load foo/bar.ftl
relative to its own base package. The two TemplateLoader
-s are totally independent virtual directory trees, not aware of each other. It's just MultiTemplateLoader
that overlays the two trees over each other via the fallback mechanism I have just shown.
Also note that ClassTemplateLoader
is not aware of the location of the jars, or if there are jar-s involved at all. It just asks a Java ClassLoader
to locate and load resources.
Also note that using new File(".")
is usually a bad idea, because in most applications you have no good control over what the current working directory will be at the time the TemplateLoader
is created. Usually you have an absolute path in some configuration file instead, or it's passed in as command line argument. FreeMarker doesn't care how you do it though.