How to use FreeMarker to template nested Pojos?
freemarker, java, pojo
Solution
You have set the `TestPojo` instance itself as the data-model root, so the `user` in `user.getSub()` is the `String` "Andy", which doesn't have a `getSub` method. The correct template is `"Welcome ${user}. Sub ${getSub().user}"`. But it's nicer to write as `"Welcome ${user}. Sub ${sub.user}"`.
Problem
I'm investigating using FreeMarker to write EDI files. These are basically heavily formatted (and validated) electronic invoices. I decided to get started by writing a simple example and am stuck getting it to template a 'nested pojo'. By this I mean a POJO which contains POJOs where both of these have data I want in my output. I wrote a unit test (self contained) that is failing for an unknown reason. When I run the test I get the following exception: ``` Expression user.getSub is undefined on line 1, column 24 in simple. The problematic instruction: ---------- ==> ${user.getSub().user} [on line 1, column 22 in simple] ---------- Java backtrace for programmers: ---------- freemarker.core.InvalidReferenceException: Expression user.getSub is undefined on line 1, column 24 in simple. at freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:124) at freemarker.core.TemplateObject.invalidTypeException(TemplateObject.java:134) <snip> example.TestFreeMarkerTemplating.testSimpleTemplate(TestFreeMarkerTemplating.java:23) <snip> ``` I've tried many variations on the template, and haven't met success. This is the test: ``` package example; import java.io.*; import org.junit.Test; import freemarker.cache.StringTemplateLoader; import freemarker.ext.beans.BeansWrapper; import freemarker.template.*; import static org.junit.Assert.*; public class TestFreeMarkerTemplating { Configuration cfg = new Configuration(); StringTemplateLoader stringLoader = new StringTemplateLoader(); { cfg.setTemplateLoader(stringLoader); cfg.setObjectWrapper(new BeansWrapper()); } @Test public void testSimpleTemplate() throws TemplateException, IOException{ stringLoader.putTemplate("simple", "Welcome ${user}. Sub ${user.getSub().user}"); Template temp = cfg.getTemplate("simple"); StringWriter out = new StringWriter(); temp.process(new TestPojo(), out); assertEquals("Welcome Andy. Sub Bill", out.toString()); } public static class TestPojo { private final String user = "Andy"; private final SubPojo sub = new SubPojo(); public String getUser() { return user; } public SubPojo getSub() { return sub; } } public static class SubPojo { private final String user = "Bill"; public String getUser() { return user; } } } ``` Thanks for any help!