FreeMarker can't access properties of a javabean
freemarker, javabeans, templates
Solution
`Model` must be a public class for this to work.
Some other notes unrelated to the question: Use `setServletContextForTemplateLoading` instead `setDirectoryForTemplateLoading`, or else your app won't work if it's run from an unpacked `.war`. Also, of course you must not re-create the `Configuration` for each request, but I assume that's like that only for the sake of this example.
Problem
According to the documentation, you should be able to pass a javabean to a FreeMarker template, and it will be able to access the getters of the bean. I've been trying to do this, but have not had any luck. Here's my code where I pass the bean to the template. ``` public class Hello extends HttpServlet { public static final Logger LOGGER = Logger.getLogger(Hello.class.getName()); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { Configuration cfg = new Configuration(); cfg.setDirectoryForTemplateLoading(new File(this.getServletContext().getRealPath("/templates"))); cfg.setObjectWrapper(new DefaultObjectWrapper()); cfg.setDefaultEncoding("UTF-8"); cfg.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER); cfg.setIncompatibleImprovements(new Version(2, 3, 20)); // FreeMarker 2.3.20 final String name = req.getParameter("name"); // This works when model is a Map, but not when it is a bean Model model = new Model(); model.setUsername(name); Template template = cfg.getTemplate("hello.ftl"); template.process(model, resp.getWriter()); } catch (TemplateException ex) { LOGGER.log(Level.SEVERE, "Unexpected template exception", ex); resp.sendError(500); } } private static class Model { private String username; public void setUsername(String username) { this.username = username; } public String getUsername() { return username; } } } ``` When I try to access `${username}` in a template, I get the following error. ``` The following has evaluated to null or missing: ==> username [in template "hello.ftl" at line 8, column 10] Tip: If the failing expression is known to be legally null/missing... (snip) The failing instruction (FTL stack trace): ---------- ==> ${username} [in template "hello.ftl" at line 8, column 8] ---------- ``` I can get the template to work correctly when I use a Map. I've tried explicitly wrapping the Model object with various TemplateModel wrappers, but nothing I try seems to work. Any hints?