Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FreeMarker can't access properties of a javabean

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?

like image 372
haydenmuhl Avatar asked Aug 04 '13 22:08

haydenmuhl


1 Answers

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.

like image 126
ddekany Avatar answered Sep 19 '22 02:09

ddekany