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.
So lets get started.
Before we starts with our Servlet FreeMarker example, we will need few tools.
JDK 1.5 or above (download)
Tomcat 5.x or above or any other container (Glassfish, JBoss, Websphere, Weblogic etc) (download)
Eclipse 3.2.x or above (download)
Freemarker JAR v2.2.8 or above(download)
Let us start with our Servlet based Freemarker application.
Open Eclipse and goto File -> New -> Project and select Dynamic Web Project in the New Project wizard screen.
After selecting Dynamic Web Project, press Next.
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.
Till this step, our basic Eclipse web project is ready. We will now add Freemarker support to this project.
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.
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.
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)
Use the Add User form to add new user into below list.
FreeMarker_Servlet_helloworld.zip (513 KB)