Richard’s Weblog

March 19, 2009

FreeMarker, a brief example

Introduction

This example will show how to make a simple layout using FreeMarker ( I used version 2.3.15 ) as the template engine. In previous posts, I used almost the same example with Tiles 2 and StringTemplate. This is not an introduction to FreeMarker, since the site of the product contains a very complete documentation. Anyway, I think this example doesn’t require the reader to know all the details of FreeMarker.

For those who didn’t read the aforementioned Tiles 2 and StringTemplate examples, basically I wan’t all pages of a web application to share the same layout, without having to re-code this layout in all pages of the application. The layout is a typical one : a header part, a menu part, a footer part and a body part. Only the body should be coded for each pages.

Configuration

dependencies

  • freemarker.jar

The only required library can be found under the lib directory of the downloaded FreeMarker release. It will be in the /WEB-INF/lib directory of my sample application.

Servlet

FreeMarker comes with a servlet ready to use in a J2EE application. I’ll just use it in my web.xml file :

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
  
  <servlet>
    <servlet-name>freemarker</servlet-name>
    <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
      
    <!-- FreemarkerServlet settings: -->
    <init-param>
      <param-name>TemplatePath</param-name>
      <param-value>/WEB-INF</param-value>
    </init-param>
    <init-param>
      <param-name>NoCache</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>ContentType</param-name>
      <param-value>text/html</param-value>
    </init-param>
      
    <!-- FreeMarker settings: -->
    <init-param>
      <param-name>template_update_delay</param-name>
      <param-value>0</param-value> <!-- 0 is for development only! Use higher value otherwise. -->
    </init-param>
    <init-param>
      <param-name>default_encoding</param-name>
      <param-value>ISO-8859-1</param-value>
    </init-param>
    <init-param>
      <param-name>number_format</param-name>
      <param-value>0.##########</param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>freemarker</servlet-name>
    <url-pattern>*.ftl</url-pattern>
  </servlet-mapping>  

</web-app>

For simplicity, I just used the example found in the FreeMarker documentation. So I have a servlet that can process template files.

Implementation

I start by the layout, since I think this is the central part of the example. My layout will be a FreeMarker template file named “defaultLayout” and located in /WEB-INF/layout directory :

defaultLayout.ftl

<#macro myLayout>
  <html>
    <body style="width:100%;height:100%">
      <table border="1" cellspacing="0" cellpadding="0" style="width:100%;height:100%">
        <tr>
          <td colspan="2">
            <#include "header.ftl"/>
          </td>
        </tr>
        <tr>
          <td>
            <#include "menu.ftl"/>
          </td>
          <td>
            <#nested/>
          </td>
        </tr>
        <tr>
          <td colspan="2">
            <#include "footer.ftl"/>
          </td>
        </tr>
      </table>
    </body>
  </html>
</#macro>

This template is written as a “User-defined directive“. This directive will be used by pages to announce the use of my template, and inject the body that must be displayed. You’ll see how this injection of the body into the layout is done in the home page implementation. It makes use of the include directive, which tells FreeMarker to find and inject the result of processing the specified template file. The path for the included templates is relative to the defaultLayout.ftl location directory ( /WEB-INF/layout ).

Here follows the code of the header, footer and menu, just for fun, since in this example they contains only pure html code.

header ( /WEB-INF/layout/header.ftl )

<div><h1>this is the header</h1></div>

footer ( /WEB-INF/layout/footer.ftl )

<div><h1>this is the footer</h1></div>

menu ( /WEB-INF/layout/menu.ftl )

  <div>
    <h1>
       <ul>  
         <li>Menu item 1</li>  
         <li>Menu item 2</li>  
         <li>Menu item 3</li>  
         <li>Menu item 4</li>  
         <li>Menu item 5</li>  
         <li>Menu item 6</li>
       </ul>
    </h1>
  </div>  

All these files will never be called directly as pages to be rendered, they are just part of the layout. So now I need a page that will use this layout to display itself. For my fisrt page I implement a home page simply saying hello to the user :

home page ( /WEB-INF/home.ftl )

<#import "layout/defaultLayout.ftl" as layout>
<@layout.myLayout>
  <div><h1>Hello Dude</h1></div>
</@layout.myLayout>

The first line will import my layout template file, making the defined macro usable by my page, under the “layout” namespace. The rest of the code defines the template’s body. Recall the “<#nested/>” directive used in the defaultLayout.ftl file ? This “<#nested/>” tag will be replaced by the content of the directive.

From now my directory tree looks like this :

.
`-- WEB-INF
    |-- home.ftl
    |-- layout
    |   |-- defaultLayout.ftl
    |   |-- footer.ftl
    |   |-- header.ftl
    |   `-- menu.ftl
    |-- lib
    |   `-- freemarker.jar
    `-- web.xml

Note that all is under WEB-INF, preventing users to see the template files code.

After installing the application under tomcat and launching the home page url (http://localhost:8080/freemarker/home.ftl), I see that my layout have been successfully applied to my home page :

layout-using-freemarker

Customizing the title of pages

Now I wan’t my template to have it’s title injected by the page that uses it. To make this, I must modify the layout directive to tells FreeMarker it can receive a title. If no title is provided, the default value “FreeMarker example” will be used. Here is the modified layout :

the layout ( /WEB-INF/layout/defaultLayout.ftl )

<#macro myLayout title="FreeMarker example">
  <html>
    <head>
      <title>
        ${title}
      </title>
    </head>
    <body style="width:100%;height:100%">
      <table border="1" cellspacing="0" cellpadding="0" style="width:100%;height:100%">
        <tr>
          <td colspan="2">
            <#include "header.ftl"/>
          </td>
        </tr>
        <tr>
          <td>
            <#include "menu.ftl"/>
          </td>
          <td>
            <#nested/>
          </td>
        </tr>
        <tr>
          <td colspan="2">
            <#include "footer.ftl"/>
          </td>
        </tr>
      </table>
    </body>
  </html>
</#macro>

Now all my pages by default will put “FreeMarker example” in their browser’s window title bar. Let’s tell my home page to specify its own title :

home page ( /WEB-INF/home.ftl )

<#import "layout/defaultLayout.ftl" as layout>
<@layout.myLayout "Home page">
  <div><h1>Hello Dude</h1></div>
</@layout.myLayout>

Now all pages using this layout can define theyr own title.

Auto-importing namespace into pages

My application use only one layout. I can avoid having to import it in every pages. To make this, I must tell the FreeMarkerServlet to “auto_import” my defaultLayout.ftl file using the “layout” namespace. Auto-import is a configuration setting of FreeMarker.

<servlet>
 ...
<init-param>
      <param-name>auto_import</param-name>
      <param-value>layout/defaultLayout.ftl as layout</param-value>
</init-param>
 ...
</servlet>

This way, we could change the layout for the entire application without having to edit every pages. So now my home page can use the layout namespace without having to import it :

home page ( /WEB-INF/home.ftl )

<@layout.myLayout "Home page">
  <div><h1>Hello Dude</h1></div>
</@layout.myLayout>

Conclusion

FreeMarker makes it a great candidate for replacing JSP in applications that must ensure the separation of the business logic from the display logic. I didn’t show it in this example, because the focus was only to apply a layout to pages, but this separation is forced since no template can modify the data-model that the page will use to display itself.

About these ads

24 Comments »

  1. After reading this article, I feel that I need more information on the topic. Can you share some more resources please?

    Comment by Heartburn Home Remedy — April 15, 2009 @ 8:05 am | Reply

    • Oh, I’m not sure what you mean by “some more resources”. If you have a more precise question maybe I could help, otherwise, the freemarker manual is very complete I think.

      Comment by Richard — April 15, 2009 @ 9:15 am | Reply

  2. Thanks for great article, Richard.
    Brief, concrete and very useful.

    Best,
    Taras

    Comment by Taras Matyashovsky — June 1, 2009 @ 11:00 am | Reply

  3. Hi Just wanted to know how I can run this on WAS. I am not using tomecat and trying to run this on RSA

    Comment by bas.r — June 30, 2009 @ 9:57 am | Reply

  4. Hi I want to run this on WAS in RSA. I am not able to run this in RSA.Can you please tell me how I can run this in RSA

    Comment by bas.r — June 30, 2009 @ 10:09 am | Reply

  5. its working on WAS also thanks

    Comment by bas.r — June 30, 2009 @ 10:36 am | Reply

  6. Can you please post some example on Spring+Freemarker

    Comment by bas.r — June 30, 2009 @ 10:46 am | Reply

  7. Hey for the awesome article , it was helpful .Appritiatable

    Comment by Neloy — July 21, 2009 @ 12:25 am | Reply

  8. Glad to hear about someone else using Freemarker. I agree, the documentation on the Freemarker site is very thorough.

    Comment by Jeff Smith — July 30, 2009 @ 9:15 am | Reply

  9. Thanks Richards, for providing important information in freemarker. I read freemarker but i didnt know that how to use that. But after reading this article i got to know that i should go more further in this. Can you provide some more information regarding freemarker if u have?

    With My Best Regards,

    Comment by Hardik Thakkar — August 26, 2009 @ 8:26 am | Reply

  10. it is very nice but i need some ex,Can you please post some example on Spring+Freemarker

    Comment by srichandra — September 7, 2009 @ 1:38 am | Reply

  11. OMG, is that tables for layouts or something? If the goal was just to show how cool Freemarker is, then laying out pages with tables is probably the worst way of doing it. Please take your time and rewrite the article.

    Comment by inca — September 26, 2009 @ 6:54 am | Reply

  12. It is a very good material for the people who started learning FTL.

    Thank a lot Richards.

    Comment by sucharitha — December 14, 2009 @ 4:07 am | Reply

  13. Great article! Bonus points for a spring, sitemesh integration example ;-)

    Keep up the the great work!
    -Ruby

    Comment by Matt Ruby — March 17, 2010 @ 9:50 am | Reply

  14. I agree, great article!

    Comment by frisörutbildning i göteborg — October 18, 2010 @ 11:31 am | Reply

  15. very useful article for the freemarker learners

    Comment by sivaram — September 6, 2011 @ 4:55 am | Reply

  16. Hi, This is cool and exactly what I was looking for, but in my case, the menu part itself is served by another servlet, the reason is that the menu is dynamic(based on user’s uthorization and url). So is there anyway I can draw the menu by the servlet and the rest being exactly the same?

    Comment by Jarus Singh — September 25, 2011 @ 1:55 am | Reply

  17. WHat if title section needs to contain markup? Although you example looks short, maybe Facelets alternative for having multiple named sections like #nested tag is more powerful? Or can we have multiple #nested section and give name to them in FreeMarker also?

    Comment by zhang ye — October 15, 2011 @ 11:18 am | Reply

  18. Thanks, Nice Explanation !

    Comment by janakadalugama — October 31, 2011 @ 7:54 am | Reply

  19. how to set image in freemarker templates?
    i use intelij -idea ide.

    this code not working Freemarker Tamplates
    please give small Example to how to display image in webpages??

    Comment by Paresh Radadiya — September 5, 2012 @ 12:35 am | Reply

  20. What if in some circumstances, i wanted to provide the content not only of the body section, but also of the menu section ? It’s like ‘overriding’ the menu section of the layout with something defined in the page. Just like apache tiles where we can override the any tiles in the layout. Is it possible with freemarker that only has one in the layout ? I have also asked this in the user group without any replies so far.

    Comment by moonbladewolf — March 7, 2013 @ 8:44 am | Reply

  21. Heya i am for the primary time here. I found this board and I
    to find It really helpful & it helped me out a lot. I am hoping to present something again and help others such as you aided me.

    Comment by Lina — October 18, 2013 @ 12:38 am | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Rubric Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: