Lesson 4.3: Using Freemarker with WebWork

Freemarker is a powerfull template engine that competes with Velocity. You can learn more about it in the project's homepage: http://freemarker.sourceforge.net.

First of all, to use Freemarker with Webwork, you have to place the freemarker.jar in your WEB-INF\lib folder. You can download the distribution here.

After that, just configure web.xml and start writing your templates, as explained below.

web.xml:

To use Freemarker as the view, you need to modify web.xml and add a servlet and a servlet mapping for FreemarkerServlet, as demonstrated below:

<servlet>
	<servlet-name>freemarker</servlet-name>
	<servlet-class>com.opensymphony.webwork.views.freemarker.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</param-value>
		</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>

The configuration above means that Freemarker templates can be rendered through requests to .ftl pages. That also means that you should implement security checks in your templates so an user doesn't access it directly without going through an action first (if that is required). But you can always place your Freemarker files under WEB-INF so they become unaccessible to direct requests. We will use the latter approach in our examples.

Inside a Freemarker template, you will have access to every object managed by WebWork with the following syntax:

  • $stack = OgnlValueStack;
  • $webwork = FreemarkerWebWorkUtil, a toolbox providing services like formatting url, accessing the value stack, etc;
  • $name-of-property = property retrieved from the value stack. If that fails, it looks up an attribute with that name in the HttpServletRequest, HttpSession and ServletContext, in that order;
  • $Request = HttpServletRequest;
  • $Session = HttpServletResponse;
  • $Application = OgnlValueStack.

The example below does the same thing as example 2 from lesson 3, but now, using Freemarker templates.

xwork.xml:

<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN" 
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">

<xwork>
	<!-- Include webwork defaults (from WebWork JAR). -->
	<include file="webwork-default.xml" />
	
	<!-- Configuration for the default package. -->
	<package name="default" extends="webwork-default">
		<!-- Default interceptor stack. --> 
		<default-interceptor-ref name="defaultStack" /> 
		
		<!-- Action: Lesson 4.3: HelloAction. -->
		<action name="indexFreemarker" class="com.opensymphony.xwork.ActionSupport">
			<result name="success" type="dispatcher">/WEB-INF/ftl/lesson3/index.ftl</result>
		</action>

		<action name="helloFreemarker" class="lesson03.HelloAction">
			<result name="error" type="dispatcher">/WEB-INF/ftl/lesson3/index.ftl</result>
			<result name="success" type="dispatcher">/WEB-INF/ftl/lesson3/success.ftl</result>
		</action>
	</package>
</xwork>

HelloAction.java (same as lesson 3):

package lesson03;

import com.opensymphony.xwork.ActionSupport;

public class HelloAction extends ActionSupport {
	String person;
	public String getPerson() {
		return person;
	}
	public void setPerson(String person) {
		this.person = person;
	}
	public String execute() throws Exception {
		if ((person == null) || (person.length() == 0)) return ERROR;
		else return SUCCESS;
	}
}

ex02-index.ftl

<#assign ww=JspTaglibs["/WEB-INF/lib/webwork.tld"] />

<html>
<head>
<title>WebWork Tutorial - Lesson 4.3 - Example 1</title>
</head>

<body>

<p>Click <a href="${wwUtil.buildUrl('indexFreemarker.action')}">here</a> to reload this page.</p>

<@ww.form name="'nameForm'" action="'helloFreemarker.action'" method="'POST'">
	<@ww.textfield label="'What is your name ?'" name="'person'" value="person" size="20"/>
	<@ww.submit name="'submit'" value="'Submit'"/>
</@ww.form>

</body>
</html>

If you don't want to use WebWork's UI Tags, you could do it like this:

ex02-index-notags.ftl

<html>
<head>
<title>WebWork Tutorial - Lesson 4.3 - Example 1</title>
</head>

<body>

<p>Click <a href="${wwUtil.buildUrl('indexFreemarker.action')}">here</a> to reload this page.</p>

<form name="nameForm" action="${wwUtil.buildUrl('helloFreemarker.action')}" method="POST">
	What is your name ? 
	<input type="text" name="person" value="${person}" size="20">
	<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>

However, if you choose no to use tags, it's recommended that you use Freemarker Macros to write the form elements.

ex02-success.ftl:

<#assign ww=JspTaglibs["/WEB-INF/lib/webwork.tld"] />

<html> 
<head> 
<title>WebWork Tutorial - Lesson 4.3 - Example 1</title> 
</head> 
<body> 

Come from the property WW tag (taglibs support) : <@ww.property value="person"/> <br>
Come from the Freemarker lookup in the WW stack : ${person}

</body> 
</html>

You can use either WebWork property tag or the Freemarker $person reference. Both of them return the same thing: a property from the action class.


Previous Lesson | Next Lesson