FreeMarker: Frequently Asked Questions

Version 13

    FreeMarker is the template framework used for user interface.

    What are some good FreeMarker resources?

     

    What's some good stuff in the FreeMarker tutorial?

     

    Where is the Eclipse FreeMarker plugin / syntax highlighter?

     

    What is the difference between FreeMarker functions, macros, and includes?

     

    Why do we use ?c on numbers?

    See here

     

    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 nice feedback pointing to the line number of the FreeMarker error. On occasion if the syntax is mangled enough you will get a FileNotFoundException from FreeMarker, and the application will give 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 will default back to the original FreeMarker template.

     

    How do you access statics / enums?

    You can give the template authors complete freedom over which classes' static methods they use by placing the static models hash into your template root model with

    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

    ${statics["java.lang.System"].currentTimeMillis()}

    in your template. 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 with

    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's 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:

     

    Set a java system property "-Djive.devMode=true"

    or

    Set a jive property (jive_startup.xml or in jiveProperty) with the same name and value true

     

    Additionally, these values can be individually tuned when not in devMode with the following Jive Properties:

     

     

    jive.freemarker.templateUpdateDelayThe interval after which FreeMarker will check for changes to an FTL file
    jive.freemarker.strongTemplateCacheSizeThe number of hard references FTL will keep in the cache
    jive.freemarker.weakTemplateCacheSizeThe number of weak references FTL will keep 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:  http://freemarker.sourceforge.net/docs/dgui_template_exp.html#dgui_template_exp_missing
    Some explanation:  http://freemarker.sourceforge.net/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, etc., creating new HTML tags like script tags, closing tags to deface the page, etc.

    Sanitize your output 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?

    Under almost every circumstance, user input which is rendered should be either:

    • 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://brewspace.jiveland.com/ ;
    • In FreeMarker, this can be done respectively with:
    foo?url

    or if the character encoding is not specified by you application

    foo?url('ISO-8859-1')

    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 simply modify the bean to point to your custom FreeMarker manager, which extends the method:

        public static void populateStatics(Map<String, Object> model) {

     

    and adds in any classes you want to the static 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. Struts OGNL Documentation:  http://struts.apache.org/2.0.11.2/docs/ognl.html  [TODO: Explain needed of how FreeMarker resolves what it needs, and why we need to know that.]

     

    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).