FreeMarker Servlet Tutorial with Example

Welcome to Freemarker Tutorial Series. In previous post we created our first Hello World Freemarker Template example. We learned few APIs of freemarker and also how template file is loaded in Java and values are replaced. Following is the list of tutorials from Freemarker tutorial series.

Today we will create a Servlet based application that uses Freemarker FTL as view instead of default JSP. This would give you a good insight in Servlet+Freemarker integration.

The application is very simple:
1. There is a table that displays user info like firstname, lastname.
2. New user can be added via Add User form.

Below is the wireframe of our final freemarker based servlet app.

freemarker-servlet-wireframe

So lets get started.

Things We Need

Before we starts with our Servlet FreeMarker example, we will need few tools.

  1. JDK 1.5 or above (download)
  2. Tomcat 5.x or above or any other container (Glassfish, JBoss, Websphere, Weblogic etc) (download)
  3. Eclipse 3.2.x or above (download)
  4. Freemarker JAR v2.2.8 or above(download)

Let us start with our Servlet based Freemarker application.

Step 1: Getting Started

Open Eclipse and goto File -> New -> Project and select Dynamic Web Project in the New Project wizard screen.

dynamic web project in eclipse

After selecting Dynamic Web Project, press Next.

eclipse dynamic web project

Write the name of the project. For example Freemarker_Hello_World. Once this is done, select the target runtime environment (e.g. Apache Tomcat v6.0). This is to run the project inside Eclipse environment. After this press Finish.

Once the project is created, you can see its structure in Project Explorer. This is how the project structure would look like when we finish the tutorial and add all source code.

freemarker-servlet-eclipse-project-structure

Till this step, our basic Eclipse web project is ready. We will now add Freemarker support to this project.

Step 2: Add FreeMarker Support to Servlet

First copy the Freemarker JAR file in WebContent > WEB-INF > lib folder. Create this folder if it does not exists.

Once the JAR is in place, modify deployment descriptor (web.xml) file. Replace existing code with following: Don’t get scared!! :) we will dissect the code and understand whats happening here.

File: /WebContent/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" 
		xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

	id="WebApp_ID" version="2.5">

	<display-name>FreeMarker_Hello_World</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>

	<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>/</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; charset=UTF-8</param-value>
			<!-- Forces UTF-8 output encoding! -->
		</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>
			<!-- The encoding of the template files. -->
		</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>


	<servlet>
		<servlet-name>hello_servlet</servlet-name>
		<servlet-class>net.viralpatel.freemarker.HelloServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>hello_servlet</servlet-name>
		<url-pattern>/hello</url-pattern>
	</servlet-mapping>

	<!--
		Prevent the visiting of MVC Views from outside the servlet container.
		RequestDispatcher.forward/include should and will still work. Removing
		this may open security holes!
	-->
	<security-constraint>
		<web-resource-collection>
			<web-resource-name>FreeMarker MVC Views</web-resource-name>
			<url-pattern>*.ftl</url-pattern>
		</web-resource-collection>
		<auth-constraint>
			<!-- Nobody is allowed to visit these -->
		</auth-constraint>
	</security-constraint>

</web-app>

To start with first we make an entry for freemarker.ext.servlet.FreemarkerServlet servlet in web.xml. Note how we mapped this servlet with url-pattern *.ftl. Thus all the request that ends with .ftl will get processed by FreemarkerServlet servlet.

In addition to this, we also provided few parameters to FreemarkerServlet. These parameters are more or less self explanatory. Have a look at comment.

For our servlet app, we defined a new servlet net.viralpatel.freemarker.HelloServlet which we mapped to url /hello. This serves as an entry point to our app. We start with /hello page.

The FTL templates will be saved in .ftl files in our WebApp folder. To avoid any unwanted access to these files we defined security-constraint in web.xml.

Once we have setup web.xml, we add Java source code.

Step 3: Hello World FreeMarker

Create a class User.java under /src/net/viralpatel/freemarker folder. This class serves as bean class which we uses to set User data. Copy following code in User.java.

File: /src/net/viralpatel/freemarker/User.java

package net.viralpatel.freemarker;

public class User {
	private String firstname;
	private String lastname;

	public User() {
	}

	public User(String firstname, String lastname) {
		this.firstname = firstname;
		this.lastname = lastname;

	}

	//Getter and Setter methods

}

Once User bean is created, we add HelloServlet. Create HelloServlet.java under /src/viralpatel/freemarker and copy following code.

File: /src/net/viralpatel/freemarker/HelloServlet.java

package net.viralpatel.freemarker;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloServlet extends HttpServlet {
	
	private static final long serialVersionUID = 1L;
	
	private static List<User> userList = new ArrayList<User>();
	
	//Just prepare static data to display on screen
	static {
		userList.add(new User("Bill", "Gates"));
		userList.add(new User("Steve", "Jobs"));
		userList.add(new User("Larry", "Page"));
		userList.add(new User("Sergey", "Brin"));
		userList.add(new User("Larry", "Ellison"));
	}
}

We haven’t defined any doGet or doPost methods in servlet. We will add them shortly. Note how we defined a static instance of List<User>. We use it to store user list. Ideally instead of doing this, you should store user information in database. But for sake of simplicity of this example we store users in this static list.

Add following doGet() method in HelloServlet. In this method we just set User list in request via request.setAttribute("users", userList); and forwards the request to /index.ftl. We do HTTP Forward here. The request gets forwarded to index.ftl. As this URL ends with .ftl, the servlet container triggers FreemarkerServet. This servlets load the index.ftl template file and renders the output.

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//Put the user list in request and 
		//let freemarker paint it.
		request.setAttribute("users", userList);
		
		request.getRequestDispatcher("/index.ftl").forward(request, response);

	}

In our example, we also have functionality of adding a user. We have a form with two fields firstname and lastname. User can add new users through this form. We define a doPost() method which gets called when add user form is submitted. In this method we get firstname, lastname values through request and add it in our user list. Also note how we called doGet() method inside doPost(). This is because we want to render same output, the user list on adding new user.

Add doPost() method to HelloServlet.

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		String firstname = request.getParameter("firstname");
		String lastname = request.getParameter("lastname");
		
		if(null != firstname && null != lastname
				&& !firstname.isEmpty() && !lastname.isEmpty()) {
			
			synchronized (userList) {
				userList.add(new User(firstname, lastname));
			}
			
		}
		
		doGet(request, response);
	}

We are almost done. All we need is our freemarker template file. Create a file index.ftl under /WebContent/ folder. Copy following content into it.

File: /WebContent/index.ftl

<html>
<head><title>ViralPatel.net - FreeMarker Hello World</title>

<body>
  <form name="user" action="hello" method="post">
  	Firstname: <input type="text" name="firstname" />	<br/>
  	Lastname: <input type="text" name="lastname" />		<br/>
  	<input type="submit" value="Save" />
  </form>

  <table class="datatable">
  	<tr>
  		<th>Firstname</th>  <th>Lastname</th>
  	</tr>
    <#list users as user>
  	<tr>
  		<td>${user.firstname}</td> <td>${user.lastname}</td>
  	</tr>
    </#list>
  </table>
</body>
</html>

For sake of simplicity, I have removed CSS styles from the above FTL file. You can download the full source code at the end of this tutorial.

Just compare your project structure with project structure image above. See if there are any differences.

That’s All Folks

You may want to run the application see the result. I assume you have already configured Tomcat in eclipse. All you need to do:
Open Server view from Windows > Show View > Server. Right click in this view and select New > Server and add your server details.

To run the project, right click on Project name from Project Explorer and select Run as > Run on Server (Shortcut: Alt+Shift+X, R)

freemarker-servlet-example-demo

Use the Add User form to add new user into below list.

Download Source Code

FreeMarker_Servlet_helloworld.zip (513 KB)



15 Comments

  • Nigau 3 July, 2012, 7:44

    Is it possible to use your example with embedded jetty server. If yes than how will we can use css and javascript with the freemaker template files. Can you give me some pointer.

    • Ronald 23 May, 2013, 0:01

      Nigau, yes you can embed the jetty server , u can use the similar way you use the normal servlet container.

      For Example
      —————————————————-

      jetty = new Server(9090);
      
              WebAppContext theWebApp = new WebAppContext();
              theWebApp.setContextPath("/");
              theWebApp.setBaseResource(Resource.newClassPathResource("/webapp"));
              theWebApp.setDescriptor("WEB-INF/web.xml");
              theWebApp.setClassLoader(getClass().getClassLoader());
              theWebApp.addServlet(new ServletHolder(new HelloServlet(backend)), "/hello");
              
              jetty.setHandler(theWebApp);
      
      jetty.start();
      

      Please note if you Eclipse set the Jetty in your classpath and create all the required resources(javascript) in the webapp folder. Since the freemarker template is loaded by the servlet we dont need to specify any markups in the web.xml Place all the *.ftl in the webapp folder…

      Regards,
      Ronald

  • arvi 24 September, 2012, 0:53

    i am getting error “No setter found for property” templateLoaderPath. in spring servlet .i know this type of error occurs if no setter injection is declared in class..but how can i inject setter in org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer

  • Densil 9 December, 2012, 2:04

    Thanks for your tutorial. I was wondering how to add an Image in the FTl and where to store the image ?. I am bit confused with the relative /absolute path which is referenced by FTL and later by Java. Can you provide a short example based on the above project structure ?. thanks

    • Ronald 23 May, 2013, 0:20

      Hi Densil, For your query

       Thanks for your tutorial. I was wondering how to add an Image in the FTl and where to store the image ?. I am bit confused with the relative /absolute path which is referenced by FTL and later by Java. Can you provide a short example based on the above project structure ?. thanks
      

      FTL is just a template and a mere html file see the template carefully

      <html>
          <head></head>
      </html>
      

      just like this

      
               <div class="logoDiv"><img src="logo.png" class="logo"/> </div>
      

      so you can use your normal html tag to load the image,, its a relative path not the absolute path. since u r placing in a web container you would use the image in the context folder ..
      like
      —/rootContext
      +———/WEB-INF
      +———/lib
      +———freemarker.jar
      +———.jar
      +———/images [all the images]
      +———/templates [ all the templates]

      thats all, make sure your classpath entries are perfect.

      Enjoy scripting

      Regards,
      Ronald

  • bhanu 24 January, 2013, 19:18

    i am getting error
    HTTP Status 404 – /FreeMarker_Hello_World/

  • jackstyle 27 April, 2013, 15:16

    it should be http://localhost:8080/hello

  • xp 15 July, 2013, 13:12
    <welcome-file>index.html</welcome-file>

    will it be better if we set like this?

    <welcome-file>index.ftl</welcome-file>
  • ashok 31 July, 2013, 12:30

    Is there any package/bundle to use FTL on Adobe CQ

    Thanks,

  • waed 24 September, 2013, 13:59

    please when i run this code
    i get an error
    “HTTP Status 404 – /Freemarker_Hello_World/”

  • waed 25 September, 2013, 11:50

    i get
    “SEVERE: Servlet /Freemarker_Hello_World threw load() exception
    java.lang.ClassNotFoundException: javax.servlet.http.HttpServlet”
    ????????????????????

  • arx 17 October, 2013, 17:42

    Thanks for sharing the article, saved a lot of time of mine :) I am facing another issue with freemarke though. My application uses xhtml files as pdf template, my template path is web-inf/pdfTemp and I have testTemplate.xhtml there as a template file. Now whenever I try to generate a pdf, it creates something like ‘testTemplate.xhtml12300783522′ inside web-inf/pdfTemp of the server installation directory. Every time I have to manualy clean those junk files. Any idea why this files are getting generated and how to get rid of them?

  • komal 12 May, 2014, 18:08

    hi, the alignment works for chrome but except other browsers like IE, firefox, etc etc. As i’m new to this freemarker concept please let me know how to make it proper alignment for all browsers..

  • Shrikant 2 June, 2014, 15:26

    Hi, I am using ftl with spark web framework.
    My project structure is
    —/root
    +———/src[ALL THE JAVA FILES WITH SPARK]
    +———/images [all the images]
    +———/templates [ all the .FTL templates]

    I wanna put images in the .ftl file, for which i am using image tag of html.

    but the images are not shown when i run the program. I think there’s some problem with the project structure or the image path that i gave.

    Could you please help me with this?

Leave a Reply

Your email address will not be published. Required fields are marked *

Note

To post source code in comment, use [code language] [/code] tag, for example:

  • [code java] Java source code here [/code]
  • [code html] HTML here [/code]

Current day month ye@r *