TECH

JSP FreeMarker

JSP FreeMarker

Introduction

This example will show how to make a JSP simple layout using FreeMarker refer site of the Freemaker product which contains a very complete documentation. Anyway, I think this example doesn’t require the reader to know all the details of FreeMarker.

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

a quick view on JSP lifecycle 

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 :

 

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

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

You Might Also Like