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: Java Template Engine Library - Download FreeMarker 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. --------------------------------------------------------------------------------------- That is the mailing letter with the placeholders filled with the actual values that you specified in the XML file. Closing words There is much more you can do with FreeMarker. Visit the FreeMarker web site and go through the documentation and examples to learn more about it. FreeMarker: Java Template Engine Library - Overview About the author: Denis Bredelet is a technical support engineer who likes to play with programming languages and Web technologies. |