Freemarker è un template engine basato su Java utilizzabile sia in modalità stand-alone che in un ambiente Web, esso prevede un Template file che contiene l'output da visualizzare associato a dei place-holder riguardanti eventuali parti che vogliamo fornire dinamicamente.
<html>
<body>
<h1>${title}</h1>
</body>
</html>
Nell'esempio ${title}
indica una variabile che verrà fornita al template in maniera dinamica. Questo verrà fatto da Java, sarà infatti Freemarker che permetterà di fornire al template i valori dinamici da visualizzare. Tale modalità permette un disaccoppiamento tra la View e la parte back-end, questo perché chi realizza il template potrebbe anche non conoscere cosa rappresenta ${title}
ma, più semplicemente, aspettarsi che il valore venga fornito a runtime.
Installazione
Scarichiamo la libreria Freemarker dalla sezione download che troviamo all'indirizzo http://freemarker.org/freemarkerdownload.html e memorizziamola in una directory a parte, ci servirà successivamente:

Ora apriamo Eclipse, nel nostro caso abbiamo utilizzato Kepler, ed installiamo il plugin per Freemarker selezionando in eclipse la voce "help/Install New Software" e, inserendo l'url http://download.jboss.org/jbosstools/updates/stable/kepler/
, selezioniamo il Freemarker IDE per entrambe le checkbox come in figura:

Un primo esempio di utilizzo in Eclipse
In Eclipse creiamo un progetto Java, chiamato per esempio "FreemarkerProject", e il template mytemplate.ftl
sotto la cartella templates
:

Creiamo quindi anche il seguente Bean:
package com.freemarker; public class Developer {
private String name;
private String project;
public Developer(String name, String project) {
this.name = name;
this.project = project;
}
public String getName() {
return name;
}
public String getProject() {
return project;
}
}
Come nomi, i due campi del Bean hanno "name" e "project", vedremo successivamente come ciò non sia un caso. Creiamo ora una classe di test che dovrà caricare il template ed effettuare il binding
package com.freemarker.test;
.. imports
public class TestOutput {
public static void main(String[] args) {
// configuration object di Freemarker
Configuration cfg = new Configuration();
// definiamo la classe che carica il template
cfg.setClassForTemplateLoading(TestOutput.class, "templates");
// impostazioni raccomandate
cfg.setIncompatibleImprovements(new Version(2, 3, 20));
cfg.setDefaultEncoding("UTF-8");
cfg.setLocale(Locale.US);
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
// caricamento del template
try {
// path assoluto al template
cfg.setDirectoryForTemplateLoading(new File("C:/Users/g.astarita/Desktop/Work/WS Articoli/FreemarkerProject/templates"));
// generazione del data-model
Map data = new HashMap();
String title = "Freemaker example";
data.put("title", title);
Developer developer = new Developer("giuseppe","Progetto Telecom");
data.put("developer", developer);
Template template = cfg.getTemplate("mytemplate.ftl");
// Console output
Writer out = new OutputStreamWriter(System.out);
template.process(data, out);
out.flush();
// File output
Writer file = new FileWriter (new File("freemarkerOutput.txt"));
template.process(data, file);
file.flush();
file.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
}
}
La funzionalità di questa classe è quella di caricare il template e di effettuare il binding; nell'Hashmap data
developer.name
developer.project

Un esempio più complesso: una Web application
Ora, creiamo il Dynamic Web Project FreemarkerWebProject e, per far questo, apriamo il file Web.xml
ed aggiungiamo la parte relativa alla configurazione:
<?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"
xsi:schemaLocation="http://Java.sun.com/xml/ns/Javaee http://Java.sun.com/xml/ns/Javaee/Web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>FreemarkerWebProject</display-name>
<servlet>
<servlet-name>freemarker</servlet-name>
<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
<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>
</init-param>
<init-param>
<param-name>template_update_delay</param-name>
<param-value>0</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>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</Web-app>
In tal modo verrà caricata una servletDispatcher di Freemarker che filtrerà le richieste RL e gestirà quelle terminanti per ".ftl" interpretandole come richiesta all'engine, permettendo quindi il merging dinamico tra parametri e template. Dopo aver creato il Web project, dovremo effettuare i seguenti passaggi:

Quindi, nell'ordine, abbiamo:
- riutilizzato il bean Developer;
- aggiunto le librerie per la compilazione;
- creato il nostro template file sotto la cartella
WebContent
Ora creiamo la seguente servlet sotto il package com.myservlet
:
package com.myservlet;
import Java.io.IOException;
import Java.io.PrintWriter;
import Java.util.ArrayList;
import Java.util.HashMap;
import Javax.servlet.ServletException;
import Javax.servlet.annotation.WebServlet;
import Javax.servlet.http.HttpServlet;
import Javax.servlet.http.HttpServletRequest;
import Javax.servlet.http.HttpServletResponse;
import com.freemarker.Developer;
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public HelloServlet() {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// creiamo la lista di developers
ArrayList<Developer> developers = new ArrayList<Developer>();
developers.add(new Developer("Claudio","Html.it"));
developers.add(new Developer("Alfredo","Html.it"));
developers.add(new Developer("Giuseppe","Engineering"));
// settiamo la lista come parametro della request
request.setAttribute("developers", developers);
// binding della lista con il template
request.getRequestDispatcher("/mytemplate.ftl").forward(request, response);
}
}
Questo, infine, il nostro template mytemplate.ftl
<html>
<head><title>Freemarker Web Example</title>
<body>
<table>
<tr>
<th>Firstname</th> <th>Lastname</th>
</tr>
<#list developers as developer>
<tr>
<td>${developer.name}</td> <td>${developer.project}</td>
</tr>
</#list>
</table>
</body>
</html>
Deployamo la Web appliction su un target server e carichiamo l'URL della nostra servlet:

In questo caso lo script del template ha recuperato la lista dei beans e per ognuno ha stampato i campi a video attraverso i costrutti di Freemarker.
Un'importante considerazione è che possiamo editare il template ftl
come se fosse una pagina HTML, quindi con tutti gli strumenti che offre un moderno Web editor; ma per ottenere questo dovremo trattare il template come pagina HTML e rinominarlo con estensione ftl
:
