FreeMarker: Frequently asked questions
FreeMarker is the template framework used for user interface.
What are some good FreeMarker resources?
- Apache FreeMarker Manual at https://freemarker.apache.org/docs/index.html
What's some good stuff in the FreeMarker tutorial?
- Assignment: Defining variables in the template at https://freemarker.apache.org/docs/dgui_misc_var.html
- Builtins for strings, dates, hashesetc: Built-in Reference at https://freemarker.apache.org/docs/ref_builtins.html
- How to access statics: Bean wrapper at https://freemarker.apache.org/docs/pgui_misc_beanwrapper.html
- Directives (the FM equivalent to JSP tags): Directive Reference at https://freemarker.apache.org/docs/ref_directives.html
- lists: list, else, items, sep, break, continue at https://freemarker.apache.org/docs/ref_directive_list.html
- if / else: if, else, elseif at https://freemarker.apache.org/docs/ref_directive_if.html
- include: include at https://freemarker.apache.org/docs/ref_directive_include.html
Where is the Eclipse FreeMarker plugin / syntax highlighter?
You can try to look here: Editor and IDE plugins at https://freemarker.apache.org/editors.html.
What is the difference between FreeMarker functions, macros, and includes?
- macro, nested, return at https://freemarker.apache.org/docs/ref_directive_macro.html
- function, return at https://freemarker.apache.org/docs/ref_directive_function.html
- include at https://freemarker.apache.org/docs/ref_directive_include.html
Why do we use ?c on numbers?
For details, see FAQ at https://freemarker.apache.org/docs/app_faq.html#faq_number_grouping.
How do you debug FreeMarker code?
To tell FreeMarker to log error messages instead of rendering them to HTML, you set a Jive
system property: jive.freemarker.logError
to true
.
You won't always get feedback pointing to the line number of the FreeMarker error. On
occasion if the syntax is mangled enough you get a FileNotFoundException
from FreeMarker, and the application gives you a SystemError
. In that case,
you need to back your changes out to the point where you're getting clear feedback.
If you're overriding a template from a plugin, on occasion when there is a failure it defaults back to the original FreeMarker template.
How do you access statics and enums?
You can give the template authors complete freedom over which class static methods they use by placing the static models hash into your template root model with the following:
root.put("statics", BeansWrapper.getDefaultInstance().getStaticModels());
This object exposes just about any class static methods if it's used as a hash with class name as the key. You can then use expression like this in your template:
${statics["java.lang.System"].currentTimeMillis()}
You can give the template authors complete freedom over which enum classes they use by placing the enum models hash into your template root model like this:
root.put("enums", BeansWrapper.getDefaultInstance().getEnumModels());
This object exposes any enum class if it's used as a hash with class name as the key. You can then use an expression like this in your template:
${enums["java.math.RoundingMode"].UP}
Why do we have a custom FreeMarker manager?
We override the standard FreeMarker manager with our custom manager to provide access to application resources from the UI templates. Some example resources are: JiveGlobals, JiveConstants, LocaleUtils, and StringUtils.
Explain FreeMarker Caching
There's an update delay in FreeMarker manager set to cache each FreeMarker file in memory forever. However, you can change the delay by setting the system property to a number, the value is in seconds that must elapse before checking if there's a newer version of the template file.
jive.freemarker.templateUpdateDelay = 123
On JiveFreemarkerManager, there is a method to flush the cache:
JiveFreemarkerManager.flushTemplateCache()
As part of the performance tuning done for CS 2.0, we increased the template caching behaviors to allow for caching all FTLs in the application (previously only about 3/4 of the templates could be cached in a stressed system). Additionally, the interval at which CS would check for new template files was quite low — 5 seconds. This meant that the FTL engine would hit the file system for each accessed FTL every five seconds. This number has been set to an indefinite value to improve production performance for 2.0.
As a consequence of these changes, developers may not see changes to FTLs when running in a
standard CS configuration. To restore this desired behavior, we've added checks to the FTL
manager that, if jive.devMode
is enabled, FTL caching and change checks
will be entirely turned off. To enable this behavior, do one of the following:
- Set a java system property
-Djive.devMode=true
- Set a jive property (jive_startup.xml or in
jiveProperty
) with the same name and valuetrue
Additionally, these values can be individually tuned when not in devMode
with the following Jive Properties:
jive.freemarker.templateUpdateDelay |
The interval after which FreeMarker checks for changes to an FTL file |
jive.freemarker.strongTemplateCacheSize |
The number of hard references FTL keeps in the cache |
jive.freemarker.weakTemplateCacheSize |
The number of weak references FTL keeps in the cache when hard references are exhausted |
The conditions when the Jive properties would need to be changed are few and far between, change with caution.
How do I deal with null checks?
Here's how to handle missing values: Handling missing values at https://freemarker.apache.org/docs/dgui_template_exp.html#dgui_template_exp_missing. And additional explanation at https://freemarker.apache.org/docs/app_faq.html#faq_picky_about_missing_vars.
You need to "sanitize" your output to prevent various XSS security hacks and exploits, involving hijacking HTML. This prevents people working in array blocks, end of string declarations, and so on, creating new HTML tags like script tags, closing tags to deface the page, and so on.
Sanitize your output by using the ?html
and
?javascript
FreeMarker directives; for example,
${community.name?html}
.
communityName = "${community.name?javascript}";
How can I address security concerns with FreeMarker? How can I prevent XSS attacks?
- URL encoded, which translates non-alphanumeric characters into their equivalent hexadecimal values, preventing the browser from interpreting it.
- HTML entity encoded, which translates special characters into their equivalent HTML entity values.
- Escape characters which can be used to break out of JavaScript statements such as
' + https://yourcommunity.com/ ;
In FreeMarker, this can be done respectively with foo?url
, or or if the
character encoding is not specified by you application with
foo?url('ISO-8859-1')
, or or whatever your encoding is.
foo?html
when using a FreeMarker variable inside of a JavaScript
statement foo?js_string
.
What are some gotchas with FreeMarker and JavaScript?
Prototype syntax and FreeMarker syntax are very similar and easy to mix up; for example, Prototype is like this:
$('somediv').close();
${user.name}
What are some things you shouldn't do?
Avoid using method calls through the statics mechanism. All data should be passed in to you through an Action method. If you need something from some other manager class or object in the system, proxy the call through the action method. This better insulates you from changes in the API during upgrades, because the call will be caught at compile time, not at run time.
When you create a variable assignment use a variable unlikely to collide with other
variables, because FreeMarker doesn't complain when you reassign a variable. For example if
you <#assign user = 'Nate'>
you may be reassigning the variable user
that was assigned in a superclass of your action, for example, in
JiveActionSupport
.
What are these tags with the jive prefix?
For example:
<@jive.userAvatar>
These are specific Jive macros added via the JiveFreemarkerManager.
What Jive macros are available to me?
Here are some examples of Jive macros:
<#macro displayUserDisplayName user=''>
<#macro userDisplayNameLink user='' rel=''>
<#macro userAvatar user='' size=16 class='' useLinks=true>
<#macro userStatusLevel user='' container='' showPoints=false>
<#macro jiveContentList content=content showContainer=false limit=-1>
<#macro importJavascript scripts>
How do I add a macro to the Jive macros?
The only way to do that right now is to overlay
template/global/include/jive-macros.ftl
. We recommend avoiding this if
possible.
How do I add something to the global FreeMarker context?
JiveFreemarkerManager is specified as a spring bean — freemarkerManager. You could modify the bean to point to your custom FreeMarker manager, which extends the method and adds in any classes you want to the static model:
public static void populateStatics(Map<String, Object> model) {
What should be in FTLs versus in actions?
Generally you should follow the model-view-controller (MVC) pattern, making the FTL only responsible for display. Examples of FTL logic would be looping over a collection to generate items in a list or rows in a table.
If you have to manipulate data in any way for display you should put that logic in an action.
What's the relationship between OGNL and FreeMarker?
OGNL is the way FreeMarker resolves object and method references. Struts depends on OGNL. For more information, see Struts OGNL Documentation at https://struts.apache.org/tag-developers/ognl.html.
What are some best practices with HTML and FreeMarker?
When mixing HTML and FreeMarker markup where the FreeMarker notation is nested inside an HTML attribute or other value that is in quotes, please toggle the use of double or single quotes. To clarify:
<a href="></a>">bad</a>
<a href='></a>'>bad</a>
<a href='></a>'>good</a>
<a href="></a>">most preferred</a>
Here are the benefits of doing so:
- Better syntax highlighting depending on IDE/editor of choice.
- Better fallback failure if FreeMarker notation fails. This happened recently in a case where the rendered HTML was broken because a title attribute on a link didn't parse correctly. After changing the quotes to toggle, the HTML was fine (the title tag was still wrong, but it no longer broke the page).