1. JSP versus FreeMarker?
  2. Why is FreeMarker so picky about null-s and missing variables, and what to do with it?
  3. Why does FreeMarker print the numbers with strange formatting (as 1,000,000 or 1 000 000 instead of 1000000)?
  4. Why does FreeMarker print bad decimal and/or grouping separator symbol (as 3.14 instead of 3,14)?
  5. Why does FreeMarker give an error when I try to print a boolean like ${aBoolean}, and how to fix it?
  6. FreeMarker can't find my templates (TemplateNotFoundException or FileNotFoundException, "Template not found" error message)
  7. The documentation writes about feature X, but it seems that FreeMarker doesn't know that, or it behaves in a different way as documented, or a bug that was supposedly fixed is still present.
  8. The < and > of FreeMarker tags confuses my editor or the XML parser. What to do?
  9. What are the legal variable names?
  10. How can I use variable names (macro name, parameter name) that contain minus sign (-), colon (:), dot (.), or or other special characters?
  11. Why do I get "java.lang.IllegalArgumentException: argument type mismatch" when I try to use X JSP custom tag?
  12. How to include other resources in a way as jsp:include does it?
  13. How can I get the parameters to my plain-Java-method/TemplateMethodModelEx/TemplateTransformModel/TemplateDirectiveModel implementation as plain java.lang.*/java.util.* objects?
  14. Why I can't use non-string key in the myMap[myKey] expression? And what to do now?
  15. When I list the contents of a map (a hash) with ?keys/?values, I get the java.util.Map methods mixed with the real map entries. Of course, I only want to get the map entries.
  16. How can I modify sequences (lists) and hashes (maps) in FreeMarker templates?
  17. What about null and the FreeMarker template language?
  18. How can I use the output of a directive (macro) in expressions (as a parameter to another directive)?
  19. Why do I have ``?''-s in the output instead of character X?
  20. How to retrieve values calculated in templates after template execution done?
  21. How to assign to (or #import into) a dynamically constructed variable name (like to name that's stored in another variable)?
  22. Can I allow users to upload templates and what are the security implications?
  23. How to implement a function or macro in Java Language instead of in the template language?
  24. In my Servlet based application, how do I show a nice error page instead of a stack trace when error occurs during template processing?
  25. I'm using a visual HTML editor that mangles template tags. Will you change the template language syntax to accommodate my editor?
1.  JSP versus FreeMarker?

We compare FreeMarker with the JSP 2.0 + JSTL combo here.

FreeMarker Pros:

  • FreeMarker is not tied to Servlets or networking/Web; it is just a class library to generate text output by merging a template with Java objects (the data-model). You can execute templates anywhere and anytime; no HTTP request forwarding or similar tricks needed, no Servlet environment needed at all. Because of this you can easily integrate it into any system.

  • Terser syntax. Consider this JSP (assuming <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>):

    <c:if test="${t}">
      True
    </c:if>
    
    <c:choose>
      <c:when test="${n == 123}">
          Do this
      </c:when>
      <c:otherwise>
          Do that
      </c:otherwise>
    </c:choose>
    
    <c:forEach var="i" items="${ls}">
    - ${i}
    </c:forEach>

    and the equivalent FTL:

    <#if t>
      True
    </#if>
    
    <#if n == 123>
      Do this
    <#else>
      Do that
    </#if>
    
    <#list ls as i>
    - ${i}
    </#list>
  • No servlet specific scopes and other highly technical things in templates (unless, of course, you expose them into the data-model deliberately). It was made for MVC from the beginning, it focuses only on the presentation.

  • You can load the templates from anywhere; from the class path, from a data-base, etc.

  • Locale-sensitive number and date formatting by default. When you output for a human audience, all you need to do is just write ${x} rather than <fmt:formatNumber value="${x}" />.

  • Easier to define ad-hoc macros and functions.

  • No sweeping errors under the carpet. Missing variables and null-s will not silently default to 0/false/empty-string, but cause error. See more about this here...

  • ``Object wrapping''. This lets you show the objects to templates in a customized, presentation oriented way (e.g. see here how a W3C DOM nodes can be seen by templates using this technology.)

  • Macros and functions are just variables, so they can be easily passed around as parameter values, put into the data-model, etc., just like any other values.

  • Virtually unnoticeable delay when visiting a page for the first time (or after it was changed), because no expensive compilation happens.

FreeMarker Cons:

  • Not a ``standard''. There are fewer tools and IDE integrations, fewer developers knows it and there's much less industry support in general. (However, most JSP tag libraries can work in FreeMarker templates with the proper setup, unless they are base on .tag files.)

  • Its syntax doesn't follow the HTML/XML rules apart from some visual similarity, which is confusing for new users (it's the price of the terseness). JSP doesn't follow it either, but it's closer to it.

  • Since macros and functions are just variables, incorrect directive and parameter names and missing required parameters can be detected only on runtime.

  • Doesn't work with JSF. (It could work technically, but nobody has implemented that yet.)

You may read this if you are considering replacing JSP with FreeMarker in an existing application or in a legacy framework that only supports JSP: Programmer's Guide/Miscellaneous/Using FreeMarker with servlets/Using FreeMarker for ``Model 2''

2.  Why is FreeMarker so picky about null-s and missing variables, and what to do with it?

To recapitulate what's this entry is about: FreeMarker by default treats an attempt to access a non-existent variable or a null value (this two is the same for FreeMarker) as error, which aborts the template execution.

First of all, you should understand the reason of being picky. Most scripting languages and template languages are rather forgiving with missing variables (and with null-s), and they usually treat them as empty string and/or 0 and/or logical false. This behavior has several problems:

  • It potentially hides accidental mistakes, like a typo in a variable name, or when the template author refers to a variable that the programmer doesn't put into the data-model for that template, or for which the programmer uses a different name. Humans are prone to do such mistakes, while computers are not, so missing this opportunity that the template engine can show these errors is a bad business. Even if you very carefully check the output of the templates during development, it is easy to look over mistakes like <#if hasWarnigs>print warnings here...</#if>, which would then silently never print the warnings, since you have mistyped the variable name (have you noticed it?). Also think about maintenance, when you later modify your application; probably you will not re-check templates (many applications has hundreds of them) that carefully each time, for all possible scenarios. Unit tests typically doesn't cover web page content very good either (if you have them at all...); they mostly only check certain manually set patterns in the web page, so they will often gloss though changes that are actually bugs. But if the page fails with exception, that's something human testers will notice and unit test will notice (as the whole page will fail), and in production the maintainers will notice (assuming somebody check error logs).

  • Makes dangerous assumptions. The script language or template engine knows nothing about the application domain, so when it decides the value of something that it doesn't know to be 0/false, it is a quite irresponsible and arbitrary thing. Just because it's not know what's your current balance at your bank, can we just say it's $0? Just because it is not known if a patient has penicillin allergy, can we just say he/she doesn't have it? Just consider the implications of such mistakes. Showing an error page is often better than showing incorrect information that looks good, leading to bad decisions on the user side.

Being not picky is mostly sweeping under the carpet in this case (not facing the problems), which of course most people feels more convenient, but still, we believe that in most cases being strict will save your time and increase your software quality on the long run.

On the other hand, we recognize that there are cases where you don't want FreeMarker to be that picky for good reason, and there is solution for them:

  • It's often normal that your data-model contains null-s or have optional variables. In such cases use these operators. If you use them too often, try to rethink your data-model, because depending on them too much won't just make the templates too verbose, but increases the probability of hiding errors and printing arbitrary incorrect output (for the reasons described earlier).

  • In some application you may rather want to show an incomplete/damaged page than an error page. In this case you can use another error handler than the default one. A custom error handler can skip the problematic part, or show an error indicator there, instead of aborting the whole page rendering. Note, however, that although the error handlers don't give arbitrary default values to variables, for pages that show critical information it's maybe still better to show an error page.

  • If the pages contain parts that aren't critically important (like some side bars), another feature you may interested in is the attempt/recover directives.

3.  Why does FreeMarker print the numbers with strange formatting (as 1,000,000 or 1 000 000 instead of 1000000)?

FreeMarker uses the locale-sensitive number formatting capability of the Java platform. The default number format for your locale may uses grouping or other formatting. If you don't want that, you have to override the number format suggested by the Java platform with the number_format FreeMarker setting. For example:

cfg.setNumberFormat("0.######");  // now it will print 1000000
// where cfg is a freemarker.template.Configuration object

Note however than humans often find it hard to read big numbers without grouping separator. So in general it is recommended to keep them, and in cases where the numbers are for ''computer audience'' (which is confused on the grouping separators), use the c built-in. For example:

<a href="/shop/productdetails?id=${product.id?c}">Details...</a>

For computer audience you need ?c anyway, as the decimal separators can also warry depending on the locale.

4.  Why does FreeMarker print bad decimal and/or grouping separator symbol (as 3.14 instead of 3,14)?

Different countries use different decimal/grouping separator symbols. If you see incorrect symbols, then probably your locale is not set properly. Set the default locale of the JVM or override the default locale with the locale FreeMarker setting. For example:

cfg.setLocale(java.util.Locale.ITALY);
// where cfg is a freemarker.template.Configuration object

However, sometimes you want to output a number not for human audience, but for ``computer audience'' (like you want to print a size in CSS), in which case you must use dot as decimal separator, regardless of the locale (language) of the page. For that use the c built-in, for example:

font-size: ${fontSize?c}pt;
5.  Why does FreeMarker give an error when I try to print a boolean like ${aBoolean}, and how to fix it?

Unlike numbers, booleans has no commonly accepted format, not even a common format within the same page. Like when you show on a HTML page if a product is washable, you will hardly want to show for the visitor "Washable: true", but rather "Washable: yes". So we force the template author (by ${washable} causing error) to find out with his human knowledge how the boolean value should be shown at the given place. The common way of formatting a boolean is like ${washable?string("yes", "no")}, ${caching?string("Enabled", "Disabled")}, ${heating?string("on", "off")}, etc.

However, there are two cases where this gets impractical:

  • When printing boolean to generate computer language output, and hence you want true/false, use ${someBoolean?c}. (This requires at least FreeMarker 2.3.20. Before that, the common practice was writing ${someBoolean?string}, however that's dangerous because its output depends on the current boolean format setting, whose default is "true"/"false".)

  • When you have format most of the booleans on the same way. In this case you can set the boolean_format setting (Configuration.setBooleanFormat) to reflect that, and then since FreeMarker 2.3.20 you can just write ${someBoolean}. (Note that this doesn't work for true/false though - you have to use ?c there.)

6.  FreeMarker can't find my templates (TemplateNotFoundException or FileNotFoundException, "Template not found" error message)

Firs of all, you should know that FreeMarker doesn't load templates from file system paths directly. Instead, it uses a simple virtual file system that might reads non-filesystem resources (templates from inside jar-s, from inside a database table, etc.). What that virtual file is decided by a configuration setting, Configuration.setTemplateLoader(TemplateLoader). Even if the TemplateLoader your are using maps to the file system, it will have a base directory that contains all the templates, and that will be the root of your virtual file system that you can't reach out from (i.e., absolute paths will be still relative to the virtual file system root).

Tips to solve the problem:

  • If you are the one who configure FreeMarker, be sure that you set a proper TemplateLoader.

  • Otherwise see if the template-not-found error's message contains the description of the TemplateLoader used. If it doesn't, you are using an old FreeMarker version, so update it. Getting FileNotFoundException instead of TemplateNotFoundException is also a sign of that, and so you will get less helpful error messages. (If the TemplateLoader in the error message is like foo.SomeTemplateLoader@64f6106c and so doesn't show some relevant parameters, you may should ask the author to define a nicer toString().)

  • A frequent mistake is using a FileTemplateLoader for a Servlet-based web application, instead of a WebappTemplateLoader. It may works in one environment, but not in another, as the Servlet specification makes no promises about your resources being accessible as plain files, not even when the war file is extracted.

  • Know that when you are including/importing a template from another template, if you don't start the template name with /, it will be interpreted relatively to the directory of the including template. The error message contains the full (resolved) name, so you should notice this there.

  • Check that you aren't using \ (backslash) instead of / (slash). (FreeMarker 2.3.22 and later will warn you about that in the error message.)

  • As a last resort, turn on debug level logging (in the logging framework that you are using) for the category freemarker.cache, to see more of what's going on.

7.  The documentation writes about feature X, but it seems that FreeMarker doesn't know that, or it behaves in a different way as documented, or a bug that was supposedly fixed is still present.

Are you sure that you are using the documentation written for the same version of FreeMarker that you actually use? Especially, note that our online documentation is for the latest stable FreeMarker release. You may use an older release; update it.

Are you sure that the Java class loader finds the same freemarker.jar that you expect to use? Maybe there is an older version of freemarker.jar around, which shadows the never. To check this, try to print the version number in a template with ${.version}. (If it dies with ``Unknown built-in variable: version'' error message, then you use a very, very old release.).

If you suspect that the problem is that you have multiple freemarker.jar-s, the typical culprit is that some module has a Maven or Ivy dependency with the old freemarker group ID, as opposed to the more modern org.freemarker group ID. Because of the different group ID-s these aren't seen as conflicting artifacts by Maven or Ivy, and so both version gets in. In this case you have to exclude the freemarker dependency.

If you think that the documentation or FreeMarker is wrong, please report it using the bug tracker, or the mailing list. Thank you!

8.  The < and > of FreeMarker tags confuses my editor or the XML parser. What to do?

Starting from FreeMarker 2.3.4 you can use [ and ] instead of < and >. For more details read this...

FreeMarker has no limitations regarding the characters used in variable names, nor regarding the length of the variable names, but for your convenience try to chose variable names that can be used with the simple variable reference expressions (see it here). If you have to choose a more extreme variable name, that's not a big problem either: see here.

10.  How can I use variable names (macro name, parameter name) that contain minus sign (-), colon (:), dot (.), or or other special characters?

If you have a variable with strange name like "foo-bar", FreeMarker will misunderstand what you mean if you just use it like in ${foo-bar}. In this case, it will believe that you want to subtract the value of bar from foo. This FAQ entry explains how to handle situations like this.

First of all it should be clear that these are just syntactical problems, as otherwise FreeMarker has no limitations regarding the characters used in variable names, nor regarding the length of them.

If the special character is one of minus sign (-, UCS 0x2D) or dot (., UCS 0x2E) or colon (:, UCS 0x3A), then all you have to do is putting a backslash (\) before these characters, like in foo\-bar (since FreeMarker 2.3.22). Then FreeMarker will know that you didn't mean the operator with the same symbol. This works everywhere where you specify unquoted identifiers, like for macro and function names, parameter names, and all kind of variable references in general. (Note that these escapes only work in identifiers, not in string literals.)

When the special character is not one of minus sign, dot, or colon, then it gets trickier. Let's say the problematic variable name is "a+b". Then:

  • If you want to read the variable: If it's a subvariable of something, you can write something["a+b"] (remember, something.x is equivalent to something["x"]). If it's a top-level variable, those are accessible through the special hash variable ,.vars, so you can write .vars["a+b"]. Naturally, this trick works with macro and function invocations too: <@.vars["a+b"]/>, .vars["a+b"](1, 2).

  • If you want to create or modify the variable: All directives that let you create or modify a variable (such as assign, local, global, macro, function, etc.) allows the quotation of the destination variable name. For example, <#assign foo = 1> is the same as <#assign "foo" = 1>. So you can write things like <#assign "a+b" = 1> and <#macro "a+b">.

  • Unfortunately, you can't use such a variable name (that contains special characters other than -, . and :) as macro parameter name.

11.  Why do I get "java.lang.IllegalArgumentException: argument type mismatch" when I try to use X JSP custom tag?

Fist of all, update FreeMarker, because 2.3.22 and later gives a much more helpful error message, that pretty much answers the question. Anyway, the reason is as follows. On JSP pages you quote all parameter (attribute) values, it does not mater if the type of the parameter is string or boolean or number. But since custom tags are accessible in FTL templates as plain user-defined FTL directives, you have to use the FTL syntax rules inside the custom tags, not the JSP rules. Thus, according to FTL rules, you must not quote boolean and numerical parameter values, or they are interpreted as string values, and this will cause a type mismatch error when FreeMarker tries to pass the value to the custom tag that expects non-string value.

For example, the flush parameter to Struts Tiles insert tag is boolean. In JSP the correct syntax was:

<tiles:insert page="/layout.jsp" flush="true"/>
...

but in FTL you should write:

<@tiles.insert page="/layout.ftl" flush=true/>
...

Also, for similar reasons, this is wrong:

<tiles:insert page="/layout.jsp" flush="${needFlushing}"/>
...

and you should write:

<tiles:insert page="/layout.jsp" flush=needFlushing/>
...

(Not flush=${needFlushing}!)

12.  How to include other resources in a way as jsp:include does it?

Not with <#include ...>, as that just includes another FreeMarker template without involving the Servlet container.

Since the inclusion method you look for is Servlet-related, and pure FreeMarker is unaware of Servlets or even HTTP, it's the Web Application Framework that decides if you can do this and if so how. For example, in Struts 2 you can do this like this:

<@s.include value="/WEB-INF/just-an-example.jspf" />

If the FreeMarker support of the Web Application Framework is based on freemarker.ext.servlet.FreemarkerServlet, then you can also do this (since FreeMarker 2.3.15):

<@include_page path="/WEB-INF/just-an-example.jspf" />

but if the Web Application Framework provides its own solution, then you may prefer that, after all it may does something special.

For more information about include_page read this...

13.  How can I get the parameters to my plain-Java-method/TemplateMethodModelEx/TemplateTransformModel/TemplateDirectiveModel implementation as plain java.lang.*/java.util.* objects?

Unfortunately, there is no simple general-purpose solution for this problem. The problem is that FreeMarker object wrapping is very flexible, which is good when you access variables from templates, but makes unwrapping on the Java side a tricky question. For example, it is possible to wrap a non-java.util.Map object as TemplateHashModel (FTL hash variable). But then, it can't be unwrapped to java.util.Map, since there is no wrapped java.util.Map around at all.

So what to do then? Basically there are two cases:

  • Directives and methods that are written for presentation purposes (like kind of ``tools'' for helping FreeMarker templates) should declare their arguments as TemplateModel-s and the more specific sub interfaces of that. After all, the object wrapping is about transforming the data-model to something that serves the purpose of the presentation layer, and these methods are part of the presentation layer. If you still need a plain Java type there, you may turn to the ObjectWrapperAndUnwrapper interface of the current ObjectWrapper (can be get with Environment.getObjectWrapper()).

  • Methods that are not for presentation related tasks (but for business logic and like) should be implemented as plain Java methods, and should not use any FreeMarker specific classes at all, since according the MVC paradigm they must be independent of the presentation technology (FreeMarker). If such a method is called from a template, then it is the responsibility of the object wrapper to ensure the conversion of the arguments to the proper type. If you use the DefaultObjectWrapper or the BeansWrapper then this will happen automatically. For DefaultObjectWrapper, this mechanism works much better, if you set its incompatibleImprovements to 2.3.22.

14.  Why I can't use non-string key in the myMap[myKey] expression? And what to do now?

The "hash" type of the FreeMarker Template Language (FTL) is not the same as Java's Map. FTL's hash is an associative array too, but it uses string keys exclusively. This is because it was introduced for sub variables (as password in user.password, which is the same as user["password"]), and variable names are strings.

So until FTL has a type that supports non-string keys, you will have to turn to the Java API of the Map. You can do it like this: myMap?api.get(nonStringKey). However, for ?api to work, you may need to configure FreeMarker a bit; see more here...

Note that as Java's Map is particular about the exact class of the key, at least for numerical keys calculated inside the templates you will have to cast them to the proper Java type, otherwise the item will not be found. For example if you use Integer keys in a Map, then you should write ${myMap.get(numKey?int)}. This is because of FTL's deliberately simplified type system has only a single numerical type, while Java distinguishes a lot of numerical types. Note that the casting is not needed when the key value comes directly from the data-model (i.e. you didn't modified its value with arithmetical calculations in the template), including the case when it's the return value of a method, and it was of the proper class before wrapping, because then the result of the unwrapping will be of the original type.

15.  When I list the contents of a map (a hash) with ?keys/?values, I get the java.util.Map methods mixed with the real map entries. Of course, I only want to get the map entries.

Certainly you are using BeansWrapper as your object wrapper, or a custom subclass of it, and the simpleMapWrapper property of that is left to false. Unfortunately, it's the default (for backward compatibility), so you have to explicitly set it to true where you create the object wrapper. Also, at least since 2.3.22, applications should just use DefaultObjectWrapper (with its incompatibleImprovements set to 2.3.22 - that's important), which never had this problem.

16.  How can I modify sequences (lists) and hashes (maps) in FreeMarker templates?

First of all, you may don't want to modify the sequence/hash, just concatenate (add) two or more of them, which results in a new sequence/hash, rather than modifying an existing one. In this case use the sequence concatenation and hash concatenation operators. Also, you may use the subsequence operator instead of removing sequence items. However, be aware of the performance implications: these operations are fast, but the hashes/sequences that are the result of many subsequent applications of these operations (i.e., when you use the result of the operation as the input of yet another operation, and so on) will be slow to read.

Now if you still want to modify sequences/hashes, then read on...

The FreeMarkes Template Language doesn't support the modification of sequences/hashes. It's for displaying already calculated things, not for calculating data. Keep templates simple. But don't give it up, you will see some advices and tricks bellow.

The best is if you can divide the work between the data-model builder program and the template so that the template doesn't need to modify sequences/hashes. Maybe if you rethink your data-model, you will realize this is possible. But, seldom there are cases where you need to modify sequences/hashes for some complex but purely presentation related algorithms. It seldom happens, so think twice whether that calculation (or parts of it) rather belongs to the data-model domain than to the presentation domain. Let's assume you are sure it belongs to the presentation domain. For example, you want to display a keyword index on some very smart way, whose algorithm need you to create and write some sequence variables. Then you should do something like this (ugly situations has ugly solutions...):

<#assign caculatedResults =
    'com.example.foo.SmartKeywordIndexHelper'?new().calculate(keywords)>
<#-- some simple algorithms comes here, like: -->
<ul>
  <#list caculatedResults as kw>
    <li><a href="${kw.link}">${kw.word}</a>
  </#list>
</ul>

That is, you move out the complex part of the presentation task from the template into Java code. Note that it doesn't affect the data-model, so the presentation is still kept separated from other the other application logic. Of course the drawback is that for this the template author will need the help of a Java programmer, but for complex algorithms that's probably needed anyway.

Now, if you still say you need to modify sequences/hashes directly with the FreeMarker template, here are two solutions, but please read the warning after them:

  • You can write a TemplateMethodModelEx and TemplateDirectiveModel implementation that can modify certain types of sequences/hashes. Just certain types, because TemplateSequenceModel and TemplateHashModel doesn't have methods for modification, so you will need the sequence or hash to implement some additional methods. An example of this solution can be seen in FMPP. It allows you to do things like this (pp stores the services provided by FMPP for templates):

    <#assign a = pp.newWritableSequence()>
    <@pp.add seq=a value="red" />

    The pp.add directive works only with sequences that were created with pp.newWritableSequence(). So for example the template author can't modify a sequence that comes from the data-model with this.

  • A sequence can have some methods/directives if you use a customized wrapper (so you can <@myList.append foo />). (Also, if you use BeansWrapper and configure it so it exposes the public methods, you can use the Java API for variables that are for java.util.Map-s and java.util.List-s. Just like with Apache Velocity.)

But beware, these solutions have a problem: The sequence concatenation, sequence slice operator (like seq[5..10]) and ?reverse do not copy the original sequence, just wraps it (for efficiency), so the resulting sequence will change if the original sequence is changed later (an abnormal aliasing effect). The same problem exists with the result of hash concatenation; it just wraps the two hashes, so the resulting hash will magically change if you modify the hashes you have added earlier. As a work-around, after you did the above problematic operations, either be sure you will not modify the objects that were used as input, or create a copy of the result with a method provided by the solution described in above two points (e.g. in FMPP you could do <#assign b = pp.newWritableSequence(a[5..10])> and <#assign c = pp.newWritableHash(hashA + hashB)>). Of course this is easy to miss... so again, rather try to build the data-model so you will not need to modify collections, or use a presentation task helper class as was shown earlier.

17.  What about null and the FreeMarker template language?

The FreeMarker template language doesn't know the Java language null at all. It doesn't have null keyword, and it can't test if something is null or not. When it technically faces with a null, it treats it exactly as a missing variable. For example, both if x is null in the data-model and if it's not present at all, ${x!'missing'} will print ``missing'', you can't tell the difference. Also, if for example you want to test if a Java method has returned null, just write something like <#if foo.bar()??>.

You may interested in the rationale behind this. From the viewpoint of the presentation layer a null and non-existent thing is almost always the same. The difference between this two is usually just a technical detail, which is rather the result of implementation details than of the application logic. That you can't compare something to null (unlike in Java); it doesn't make sense to compare something with null in a template, since the template language doesn't do identity comparison (like the Java == operator when you compare two objects) but the more common sense value comparison (like Java's Object.equals(Object); that doesn't work with null either). And how could FreeMarker tell if something concrete equals with something that is missing and thus unknown? Or if two missing (unknown) things are equal? Of course these questions can't be answered.

There is at least one problem with this null-unaware approach. When you call a Java method from a template, you may want to pass a null value as argument (since the method was designed to be used in Java language, where the concept of null is known). In this case you can exploit a bug of FreeMarker (that we will not fix until we provide a correct solution for passing null values to a method): if you specify a missing variable as the argument, then it will not cause an error, but a null will be passed to the method instead. Like foo.bar(nullArg) will call the bar method with null as argument, assuming that there is no varaible exists with ``nullArg'' name.

18.  How can I use the output of a directive (macro) in expressions (as a parameter to another directive)?

Capture the output into a variable with the assign or local directive. For example:

<#assign capturedOutput><@outputSomething /></#assign>
<@otherDirective someParam=capturedOutput />
19.  Why do I have ``?''-s in the output instead of character X?

This is because the character that you want to print can't be represented with the charset (encoding) used for the output stream, so the Java platform (not FreeMarker) substitutes the problematic character with question mark. In general you should use the same charset for the output as for the template (use the getEncoding() method of the template object), or which is even safer, you should always use UTF-8 charset for the output. The charset used for the output stream is not decided by FreeMarker, but by you, when you create the Writer that you pass to the process method of the template.

Example: Here I use UTF-8 charset in a servlet:

...        
resp.setContentType("text/html; charset=utf-8");
Writer out = resp.getWriter();
...
t.process(root, out);
...

Note that the question marks (or other substitution characters) may be produced outside FreeMarker, in which case the above obviously will not help. For example a bad/missconfigured database connection or JDBC driver may bring the text already with substitution characters in it. HTML forms are another potential source of encoding problems. It's a good idea to print the numerical code of the characters of the string on various places, to see where the problem occurs first.

You can read more about charsets and FreeMarker here...

20.  How to retrieve values calculated in templates after template execution done?

First of all, be sure your application is designed well: templates should display data, and almost never calculate data. If you are still sure you want to do it, read on...

When you use <#assign x = "foo">, then you do not actually modify the data-model (since that is read-only, see: Programmer's Guide/Miscellaneous/Multithreading), but create the x variable in the runtime environment of the processing (see Programmer's Guide/Miscellaneous/Variables, scopes). The problem is that this runtime environment will be discarded when Template.process returns, as it was created for a single Template.process call:

// internally an Environment will be created, and then discarded
myTemplate.process(root, out);

To prevent this, you can do the below, which is equivalent with the above, except that you have chance to return the variables created in the template:

Environment env = myTemplate.createProcessingEnvironment(root, out);
env.process();  // process the template
TemplateModel x = env.getVariable("x");  // get variable x
21.  How to assign to (or #import into) a dynamically constructed variable name (like to name that's stored in another variable)?

If you really can't avoid doing that (you should, as it's confusing), you can solve that with constructing the appropriate FTL source code dynamically in a string, then using the interpret built-in. For example, if you want to assign to the variable whose name is stored in the varName variable:

<@"<#assign ${varName}='example'>"?interpret />
22.  Can I allow users to upload templates and what are the security implications?

In general you shouldn't allow that, unless those users are system administrators or other trusted personnel. Consider templates as part of the source code just like *.java files are. If you still want to allow users to upload templates, here are what to consider:

  • Denial-of-Service (DoS) attacks: It's trivial to create templates that run practically forever (with a loop), or exhaust memory (by concatenating to a string in a loop). FreeMarker can't enforce CPU or memory usage limits, so this is something that has no solution on the FreeMarker-level.

  • Data-model and wrapping (Configuration.setObjectWrapper): The data-model might gives access to the public Java API of some objects that you have put into the data-model. By default, for objects that aren't instances of a the bunch of specially handler types (String, Number, Boolean, Date, Map, List, array, and a few others), their public Java API will be exposed. To avoid that, you have to construct the data-model so that it only exposes the things that are really necessary for the template. For that, you may want to use SimpleObjectWrapper (via Configuration.setObjectWrapper or the object_wrapper setting) and then create the data-model purely from Map-s, List-s, Array-s, String-s, Number-s, Boolean-s and Date-s. Or, you can implement your own extremely restrictive ObjectWrapper, which for example could expose your POJO-s safely.

  • Template-loader (Configuration.setTemplateLoader): Templates may load other templates by name (by path), like <#include "../secret.txt">. To avoid loading sensitive data, you have to use a TemplateLoader that double-checks that the file to load is something that should be exposed. FreeMarker tries to prevent the loading of files outside the template root directory regardless of template loader, but depending on the underlying storage mechanism, exploits may exist that FreeMarker can't consider (like, just as an example, ~ jumps to the current user's home directory). Note that freemarker.cache.FileTemplateLoader checks the canonical paths, so that's maybe a good candidate for this task, yet, adding a file extension check (file must be *.ftl) is maybe a good idea.

  • The new built-in (Configuration.setNewBuiltinClassResolver, Environment.setNewBuiltinClassResolver): It's used in templates like "com.example.SomeClass"?new(), and is important for FTL libraries that are partially implemented in Java, but shouldn't be needed in normal templates. While new will not instantiate classes that are not TemplateModel-s, FreeMarker contains a TemplateModel class that can be used to create arbitrary Java objects. Other "dangerous" TemplateModel-s can exist in you class-path. Plus, even if a class doesn't implement TemplateModel, its static initialization will be run. To avoid these, you should use a TemplateClassResolver that restricts the accessible classes (possibly based on which template asks for them), such as TemplateClassResolver.ALLOWS_NOTHING_RESOLVER.

23.  How to implement a function or macro in Java Language instead of in the template language?

It's not possible (yet), but something very similar is possible if you write a class that implements freemarker.template.TemplateMethodModelEx or freemarker.template.TemplateDirectiveModel respectively, and then where you were write <#function my ...>...</#function> or <#macro my ...>...</#macro> you write <#assign my = "your.package.YourClass "?new()> instead. Note that using the assign directive for this works because functions (and methods) and macros are just plain variables in FreeMarker. (For the same reason you could also put TemplateMethodModelEx or TemplateDirectiveModel instances into the data-model before calling the template, or into the shared variable map (see: freemarker.template.Configuration.setSharedVariable(String, TemplateModel)) when you initialize the application.)

24.  In my Servlet based application, how do I show a nice error page instead of a stack trace when error occurs during template processing?

First of all, use RETHROW_HANDLER instead of the default DEBUG_HANDLER (for more information about template exception handlers read this...). Now FreeMarker will not print anything to the output when an error occurs, so the control is in your hands. After you have caught the exception of Template.process(...) basically you can follow two strategies:

  • Call httpResp.isCommitted(), and if that returns false, then you call httpResp.reset() and print a ``nice error page'' for the visitor. If the return value was true, then try to finish the page be printing something that makes clear for the visitor that the page generation was abruptly interrupted because of an error on the Web server. You may have to print a lot of redundant HTML end-tags and set colors and font size to ensure that the error message will be actually readable in the browser window (check the source code of the HTML_DEBUG_HANDLER in src\freemarker\template\TemplateException.java to see an example).

  • Use full page buffering. This means that the Writer doesn't send the output to the client progressively, but buffers the whole page in the memory. Since you provide the Writer instance for the Template.process(...) method, this is your responsibility, FreeMarker has nothing to do with it. For example, you may use a StringWriter, and if Template.process(...) returns by throwing an exception, then ignore the content accumulated by the StringWriter, and send an error page instead, otherwise you print the content of StringWriter to the output. With this method you surely don't have to deal with partially sent pages, but it can have negative performance implications depending on the characteristic of the pages (for example, the user will experience more response delay for a long page that is generated slowly, also the server will consume more RAM). Note that using a StringWriter is surely not the most efficient solution, as it often reallocates its buffer as the accumulated content grows.

25.  I'm using a visual HTML editor that mangles template tags. Will you change the template language syntax to accommodate my editor?

We won't change the standard version, because a lot of templates depend on it.

Our view is that the editors that break template code are themselves broken. A good editor should ignore, not mangle, what it doesn't understand.

You maybe interested in that starting from FreeMarker 2.3.4 you can use [ and ] instead of < and >. For more details read this...