This following examples guide us how to use FreeMarker template for sending
an email in real time Applications.
In this example we take a scenorio in which a Sales Rep sending an email to customer after placing the Order.
import java.io.File;
import java.io.IOException;
import freemarker.template.Configuration;
import freemarker.template.Template;
public class FreeMarkerConfig {
private static FreeMarkerConfig freeMarkerConfig = null;
private static Configuration cfg = null;
private FreeMarkerConfig(ServletContext context){
cfg = new Configuration();
cfg.setTemplateLoader(TEMPLATE_PATH,context.getRealPath("/templates/SalesOrderEmailTemplate")));
}
public static FreeMarkerConfig getInstance(){
if(freeMarkerConfig == null){
freeMarkerConfig = new FreeMarkerConfig(null);
return freeMarkerConfig;
}
return freeMarkerConfig;
}
public static Template getTemplateByName(String fileName){
try{
return cfg.getTemplate(fileName);
}catch(IOException e){
throw new RuntimeException("Error in loading ftl template: "+e.getMessage());
}
}
}
---Template Invoker - which fills the data in Email template
public class EmailTemplateReader () {
public static String getMailBodyBySalesOrderEvent(Opportunity opp, WebUser webuser) throws Exception{
Template template =FreeMarkerConfig.getTemplateByName("SalesOrder.ftl");
Contact contact = LeadServices.getPrimaryContact(opp.getObjid());
Site site = LeadServices.getPrimarySite(opp.getObjid());
Address address = site.getAddressByCustPrimaddr2address();
/* Create a data model */
Map root = new HashMap();
root.put("contact", getContactData(orderId));
root.put("webuser", getUserData(orderId));
StringWriter strOut = new StringWriter();
/* Merge data model with template */
return getProcessedTemplate(root, template);
}
public static String getProcessedTemplate(Map root, Template template){
try{
StringWriter textWriter = new StringWriter();
template.process(root, textWriter);
return textWriter.toString();
}catch(Exception e){
throw new RuntimeException("Exception in processing template:"+e.getMessage());
}
}
}
SalesOrder.ftl (Template) :
${contact},
Thank you for contacting me about Java Book. Per our discussion I have attached
a sales order for ${contact.address1} ${contact.address2} ${contact.city} ${contact.state} ${contact.zip}.
Please sign where indicated on the last page and fax the entire sales order to me at ${faxNumber}.
Once I have the signed sales order, I will place your order and get your stuff shipped.
Thank you for choosing YYYYOrg.
Regards,
${user.userFirstName} ${user.userLastName}
${user.userOffice}
${user.userPhone}
${user.userEmail}
/// New Examples
/// New Examples
First steps with FreeMarker
About FreeMarker
FreeMarker is a Java template engine. It is mostly used to make web pages. Using a template engine you can design a document containing placeholders, which is processed by the engine to "fill the blanks". Depending on the power and flexibility of the template engine you can do more or less with it. FreeMarker ranks high on both accounts.
To get started, download the latest FreeMarker from the official download page:
FreeMarker comes in a .tar.gz format, which is understood by most archive tools (you can use 7-Zip).
Next we will write a few examples that will introduce you to FreeMarker. You will need Java installed on your computer to run them. For the examples copy freemarker.jar located in the lib directory of FreeMarker to the Java extension folder, which is under lib/ext in the Java home folder. This document can help you locate it:
On Mac OS X it is /Library/Java/Home/lib/ext.
Example 1: Web page
Open your favourite Web editor and enter the following text in the page:
${pet} does ${number} little hops :)
For the title of the page enter:
Page for ${pet}!
Save the document as example1.html. Then open a text editor and enter the following Java program:
import freemarker.template.Template;
import freemarker.template.Configuration;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;
public class Example1
{
public static void main(String[] args)
{
// Add the values in the datamodel
Map datamodel = new HashMap();
datamodel.put("pet", "Bunny");
datamodel.put("number", new Integer(6));
// Process the template using FreeMarker
try {
freemarkerDo(datamodel, "example1.html");
}
catch(Exception e) {
System.out.println(e.getLocalizedMessage());
}
}
// Process a template using FreeMarker and print the results
static void freemarkerDo(Map datamodel, String template) throws Exception
{
Configuration cfg = new Configuration();
Template tpl = cfg.getTemplate(template);
OutputStreamWriter output = new OutputStreamWriter(System.out);
tpl.process(datamodel, output);
}
}
In FreeMarker lingo, the datamodel is a Java variable that contains all the values used to fill in the blanks. The program builds the datamodel, then calls a helper function to process the template with the FreeMarker engine. This helper function initialises the engine by creating a new configuration. Then it reads the template file (example1.html) into a Template variable. Finally it processes the template using the datamodel.
Save the Java program as "Example1.java" and compile it in a command window:
javac Example1.java
You will need to navigate to the directory containing Example1.java and Example1.html before running the compiler. When the file compiles successfully (ignore the "unchecked" warnings) run the program with the command:
java Example1
You should get a result like:
<html>
<head>
<title>Page for Bunny!</title>
</head>
<body>
Bunny does 6 little hops :)
</body>
</html>
That is the code of the processed Web page. You can save the output in a file to see what the actual generated Web page looks like:
java Example1 > example1out.html
Open example1out.html in a Web browser to view the results. You will see the placeholders filled with the actual values that you entered in the Java program. Experiment with different values and different variable names to see what you can do.
Example 2: Mail merge
For this example we will make a file which contains the person's data. Open a plain text editor and enter:
recipient=John Smith
address=3033 Long Drive, Houston, TX
Save the file as "example2.dat". Next create a letter template with the following:
To: ${recipient}
${address}
Dear ${recipient},
Thank you for your interest in our products. We will be sending you a catalog shortly.
To take advantage of our free gift offer, please fill in the survey attached to this
letter and return it to the address on the reverse. Only one participant is allowed for
each household.
Sincere salutations,
D. H.
Save the file as "example2.txt". Finally write a Java program that will merge the two files together using FreeMarker:
import freemarker.template.Template;
import freemarker.template.Configuration;
import java.io.OutputStreamWriter;
import java.io.FileInputStream;
import java.util.Properties;
import java.util.Map;
public class Example2
{
public static void main(String[] args)
{
Properties data = new Properties();
// Read the data file and process the template using FreeMarker
try {
data.load(new FileInputStream("example2.dat"));
freemarkerDo(data, "example2.txt");
}
catch(Exception e) {
System.out.println(e.getLocalizedMessage());
}
}
// Process a template using FreeMarker and print the results
static void freemarkerDo(Map datamodel, String template) throws Exception
{
Configuration cfg = new Configuration();
Template tpl = cfg.getTemplate(template);
OutputStreamWriter output = new OutputStreamWriter(System.out);
tpl.process(datamodel, output);
}
}
This program uses the predefined Java class Properties to read the values from the data file. Then it proceeds as in the previous example.
Save the Java program as "Example2.java" and compile it in a command window:
javac Example2.java
Then run the program with the command:
java Example2
You should get a result like:
To: John Smith
3033 Long Drive, Houston, TX
Dear John Smith,
Thank you for your interest in our products. We will be sending you a catalog shortly.
To take advantage of our free gift offer, please fill in the survey attached to this
letter and return it to the address on the reverse. Only one participant is allowed for
each household.
Sincere salutations,
D. H.
That is the mailing letter with the placeholders filled with the actual values that you specified in the data file.
Note that to use this example, you will need a separate data file for each person you are writing to. In the next example we will see a way to use a single file which contains all the recipients details.
Example 3: XML data source
FreeMarker includes powerful XML processing features. Here we will use only the simplest one to read a list of names and addresses from a XML file and insert them in the template.
Open a plain text editor and enter:
<recipients>
<person>
<name>John Smith</name>
<address>3033 Long Drive, Houston, TX</address>
</person>
<person>
<name>Janet Mason</name>
<address>11c Poplar Drive, Knoxville, TN</address>
</person>
</recipients>
Save the file as "example3.xml". Next create a new file with:
[#ftl]
[#foreach recipient in doc.recipients.person]
To: ${recipient.name}
${recipient.address}
Dear ${recipient.name},
Thank you for your interest in our products. We will be sending you a catalog shortly.
To take advantage of our free gift offer, please fill in the survey attached to this
letter and return it to the address on the reverse. Only one participant is allowed for
each household.
Sincere salutations,
D. H.
---------------------------------------------------------------------------------------
[/#foreach]
Save the file as "example3.ftl". This template uses more features of FreeMarker than previous examples. The first line contains [#ftl] to mark a FreeMarker file. Then it contains the directive [#foreach ... in ...] to repeat the enclosed template with each item in the list. The dots in doc.recipients.person denote a path, ie. we want "person" inside "recipients" itself inside "doc". Similarly recipient.name means the value of "name" in "recipient".
The following program will process the template:
import freemarker.template.Template;
import freemarker.template.Configuration;
import java.io.OutputStreamWriter;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class Example3
{
public static void main(String[] args)
{
Map tree = new HashMap();
File document = new File("example3.xml");
// Read the XML file and process the template using FreeMarker
try {
tree.put("doc", freemarker.ext.dom.NodeModel.parse(document));
freemarkerDo(tree, "example3.ftl");
}
catch(Exception e) {
System.out.println(e.getLocalizedMessage());
}
}
// Process a template using FreeMarker and print the results
static void freemarkerDo(Map datamodel, String template) throws Exception
{
Configuration cfg = new Configuration();
Template tpl = cfg.getTemplate(template);
OutputStreamWriter output = new OutputStreamWriter(System.out);
tpl.process(datamodel, output);
}
}
This program uses class freemarker.ext.dom.NodeModel which comes with FreeMarker to read the XML document. The resulting tree is added to the datamodel.
Save the Java program as "Example3.java" and compile it in a command window:
javac Example3.java
Then run the program with the command:
java Example3
You should get a result like:
To: John Smith
3033 Long Drive, Houston, TX
Dear John Smith,
Thank you for your interest in our products. We will be sending you a catalog shortly.
To take advantage of our free gift offer, please fill in the survey attached to this
letter and return it to the address on the reverse. Only one participant is allowed for
each household.
Sincere salutations,
D. H.
---------------------------------------------------------------------------------------
To: Janet Mason
11c Poplar Drive, Knoxville, TN
Dear Janet Mason,
Thank you for your interest in our products. We will be sending you a catalog shortly.
To take advantage of our free gift offer, please fill in the survey attached to this
letter and return it to the address on the reverse. Only one participant is allowed for
each household.
Sincere salutations,
D. H.
---------------------------------------------------------------------------------------