I am integrating a FMPP transformation into our Java code base. For this, I am using the FMPP Java API. For practical reasons, I have two separate directories:
- one which contains the template:
<absolute path template>/template.ftlx - one which contains the data:
<absolute path data>/data.xml
This somehow complicates things, as I have to work with absolute paths here. Typically, the data is inside the template directory (together with a ignoredir.fmpp file). However, in our application, the data is coming from an external source (it is uploadable via a REST API), while the template is in the classpath. This also means that the data directory isn't static.
I am struggling to define all this and get the transformation happening via the Java API. Currently, I have the following:
Settings s = new Settings(new File("."));
s.set(Settings.NAME_SOURCES, new File("<absolute path template>/template.ftlx").getAbsolutePath());
s.set(Settings.NAME_OUTPUT_FILE, new File("<absolute path output>/output.xml").getAbsolutePath());
s.execute();
The code snippet above is not complete, as I have to add the data. There are the Settings.NAME_DATA and Settings.NAME_DATA_ROOT properties, but I can't get it working. I tried setting Settings.NAME_DATA_ROOT as following:
s.set(Settings.NAME_DATA_ROOT, new File("<absolute path data>").getAbsolutePath());
Then, I get the exception that FreeMarker cannot find my data:
The following has evaluated to null or missing:
==> d [in template "template.ftlx" at line 4, column 12]
In the template, I simply do:
<#list d.items>...</#list>
This makes sense that this would not work, as I did nowhere define that the data should be accessible via the d. hash (which I am doing below in config.fmpp). But I don't know how to define that properly via Settings.NAME_DATA and/or Settings.NAME_DATA_ROOT.
How can I inject my data file into all this? It should get the key d, so I can refer to d. in the template.
reference
Just as reference, if I create the following config.fmpp file in <absolute path config>, put the data.xml data file in directory <absolute path data> and call s.load(new File("<absolute path config>/config.fmpp")) before s.execute() above, everything is working fine.
data: {
d: xml(<absolute path data>/data.xml)
}
All I have to figure out is doing this in a dynamic fashion via the Java API. I cannot use config.fmpp for this, as the location of the data isn't static (and, as far as I know, config.fmpp is not parametrizable).
working solution, with doubts
After some code reading, I got it working if I do the following:
Settings s = new Settings(new File("."));
s.set(Settings.NAME_SOURCES, new File("<absolute path template>/template.ftlx").getAbsolutePath());
s.set(Settings.NAME_OUTPUT_FILE, new File("<absolute path output>/output.xml").getAbsolutePath());
s.set(Settings.NAME_DATA, "{d:xml(<absolute path output>/data.xml)}");
s.execute();
Here, we pass {configuration:xml(<absolute path output>/data.xml)} as a TDD to the NAME_DATA property. Is this the way to go? It "feels" strange to construct a textual definition in our code. Is there a way to do this in pure Java?