How can you load data dynamically with the FMPP Java API?

214 Views Asked by At

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?

0

There are 0 best solutions below