Friday, March 25, 2016

FreeMarker Template Engine With XML Data Model.

On previous post we learn how to marge object type data model with FreeMarker template. Now we learn how we can marge FreeMarker template with  XML data model. All steps are basically same as Object Data binding with FreeMarker except datamodel creation. Here we put the complete xml file into the map. We discuss in details in below

Step: 1
Download the latest stable Fremarker version from here.

Step: 2
Extract the downloaded folder and put the the jar in our project.

Step:3
Create Fremarker configuration object with version number and some recommend settings.
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setLocale(Locale.US);
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);


Step:4
Mentioning the template file location.

        cfg.setDirectoryForTemplateLoading(new File("./resources"));
        Template template = cfg.getTemplate("xml_Freemarker_Template.ftl");


Step: 5 
Creating Data model part.
         Map xmlData = new HashMap();
         xmlData.put("samples", freemarker.ext.dom.NodeModel.parse(new File("./resources/sampleXML.xml")));

Here we put key as "samples" basically we set the root of the xml document we can mention any name here but we need to put the same name in .ftl file also.   

Step: 6 
 Creating the output part.

  This is for console output:

        Writer consoleWriter = new OutputStreamWriter(System.out);
        template.process(xmlData, consoleWriter);


  This is for html output:     

        try (Writer fileWriter = new FileWriter(new File("output.html"))) {
            template.process(xmlData, fileWriter);
        }


Step: 7
Creating template file and save it with .ftl extention. Here it is a sample template file.

<#ftl strip_whitespace = true>

<#assign charset="UTF-8">
<#assign title="Example">
<#assign content>
This is content
</#assign>
<!DOCTYPE html>
<html>
    <head>
        <title>${title}</title>
        <meta charset="${charset}">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        </head>
    <body> 

        <!-- We need to use the same name of the root element which is set from code.
        Here it is "samples" and then follow the xml path so it is
sample.sampledata--> 
        <#foreach sample in samples.sample.sampledata>
            <div>
                id:${sample.id}
                name: ${sample.name}
                age:${sample.age}
                salary:${sample.salary}
                exp:${sample.exp}
                sex:${sample.sex}
                <#foreach address in sample.addresses>
                <div>
                    address1:${address.address1}
                    <#if "${address.address2}"!="">
                    address1:${address.address2}
                    </#if>
                </div>
                </#foreach>
            </div> 
        </#foreach>
        </body>
    </html>


Step: 8  

Sample XML File.

<sample>
    <sampledata>
        <id>1</id>
        <name>TestName1</name>
        <age>28</age>
        <salary>50000</salary>
        <exp>6.6</exp>
        <sex>m</sex>
        <addresses>
            <address1>My Address1</address1>
            <address2></address2>
        </addresses>
    </sampledata>


 Complete code given below :

Main Class :

package freemarker;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;

public class FreemarkerXML {

    public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException, TemplateException {
        /**
         * Create Fremarker configuration object with version number and some
         * recommend settings.
         */

        Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setLocale(Locale.US);
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

        /**
         * Mentioning the template file location.
         */

        cfg.setDirectoryForTemplateLoading(new File("./resources"));
        Template template = cfg.getTemplate("xml_Freemarker_Template.ftl");
        Map xmlData = new HashMap();
      
        /**
         * Read the XML file and process the template using FreeMarker.
         */

        xmlData.put("samples", freemarker.ext.dom.NodeModel.parse(new File("./resources/sampleXML.xml")));

        /**
         * Creating the output part.
         */

        Writer consoleWriter = new OutputStreamWriter(System.out);
        template.process(xmlData, consoleWriter);

        /**
         * For the sake of example, also write output into a file.
         */

        try (Writer fileWriter = new FileWriter(new File("output.html"))) {
            template.process(xmlData, fileWriter);
        }
    }
}


Sample XML:

<sample>
    <sampledata>
        <id>1</id>
        <name>TestName1</name>
        <age>28</age>
        <salary>50000</salary>
        <exp>6.6</exp>
        <sex>m</sex>
        <addresses>
            <address1>My Address1</address1>
            <address2></address2>
        </addresses>
    </sampledata>
    <sampledata>
        <id>2</id>
        <name>TestName2</name>
        <age>26</age>
        <salary>60000</salary>
        <exp>5</exp>
        <sex>f</sex>
        <addresses>
            <address1>My Address1</address1>
            <address2>My Address2</address2>
        </addresses>
    </sampledata>
</sample>

 

Temmplate File :

<#ftl strip_whitespace = true>

<#assign charset="UTF-8">
<#assign title="Example">
<#assign content>
This is content
</#assign>
<!DOCTYPE html>
<html>
    <head>
        <title>${title}</title>
        <meta charset="${charset}">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        </head>
    <body>  
        <#foreach sample in samples.sample.sampledata>
            <div>
                id:${sample.id}
                name: ${sample.name}
                age:${sample.age}
                salary:${sample.salary}
                exp:${sample.exp}
                sex:${sample.sex}
                <#foreach address in sample.addresses>
                <div>
                    address1:${address.address1}
                    <#if "${address.address2}"!="">
                    address1:${address.address2}
                    </#if>
                </div>
                </#foreach>
            </div> 
        </#foreach>
        </body>
    </html>

Thursday, March 24, 2016

Free Marker Template Engine With Object Data Model.

Template Engine is used when we separate our HTML coding from our source code. It is basically used when we try to follow MVC architecture in our code. Lots of  template engine available on market like Velocity,Freemarker,Rythm etc.

Here we try to focus on Freemarker template engine.

Template engines generates output with the help of template file and run time data.

 Template marker can use 2 different type of data model
  1. Object in Map model 
  2.  XML data in Map model
We need to follow the below steps to play with Freemarker template:

Step: 1
Download the latest stable Fremarker version from here.

Step: 2
Extract the downloaded folder and put the the jar in our project.

Step:3
Create Fremarker configuration object with version number and some recommend settings.
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setLocale(Locale.US);
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);


Step:4
Mentioning the template file location.
        cfg.setDirectoryForTemplateLoading(new File("./resources"));
        Template template = cfg.getTemplate("freemarker_template.ftl");


Step: 5 
Creating Data model part.

        List<SampleDataDTO> freemarkerListObjectData = new ArrayList<>();
        freemarkerListObjectData.add(new SampleDataDTO(1, "Test1", 28.2f, new BigDecimal("40000.00"), 5.2, 'm'));
        freemarkerListObjectData.add(new SampleDataDTO(2, "Test2", 29.2f, new BigDecimal("50000.00"), 6.2, 'f'));
       
        List<String> freemarkerListStringData = new ArrayList<>();
        freemarkerListStringData.add("1");
        freemarkerListStringData.add("2");
       
        Map<String, Object> freemarkerMapData = new HashMap();
        freemarkerMapData.put("mapdata1", "My First FreeMarker Page");
        freemarkerMapData.put("mapdata2", "UTF-8");
        freemarkerMapData.put("SampleDataDTO", freemarkerListObjectData);
        freemarkerMapData.put("SampleList", freemarkerListStringData);


Step: 6 
 Creating the output part.

  This is for console output:
        Writer consoleWriter = new OutputStreamWriter(System.out);
        template.process(freemarkerMapData, consoleWriter);


  This is for html output:     

        try (Writer fileWriter = new FileWriter(new File("output.html"))) {
            template.process(freemarkerMapData, fileWriter);
        }


Step: 7
Creating template file and save it with .ftl extention. Here it is a sample template file.


<#ftl strip_whitespace = true>

<#macro another_macro>
<#list SampleList as List>
    <li>${List_index + 1}. ${List}</li>
</#list>
</#macro>   


Complete code given below :

Main Class :

package freemarker;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public class FreeMarker {

    public static void main(String[] args) throws TemplateException, IOException {
         /**
         * Create Fremarker configuration object with version number and some recommend settings.
         */

        Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setLocale(Locale.US);
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);


         
          /**
         * Mentioning the template file location.
         */

        cfg.setDirectoryForTemplateLoading(new File("./resources"));
        Template template = cfg.getTemplate("freemarker_template.ftl");
        

        /**
         * Creating Data model part.
         */

        List<SampleDataDTO> freemarkerListObjectData = new ArrayList<>();
        freemarkerListObjectData.add(new SampleDataDTO(1, "Test1", 28.2f, new BigDecimal("40000.00"), 5.2, 'm'));
        freemarkerListObjectData.add(new SampleDataDTO(2, "Test2", 29.2f, new BigDecimal("50000.00"), 6.2, 'f'));

       
        List<String> freemarkerListStringData = new ArrayList<>();
        freemarkerListStringData.add("1");
        freemarkerListStringData.add("2");
       
        Map<String, Object> freemarkerMapData = new HashMap();
        freemarkerMapData.put("mapdata1", "My First FreeMarker Page");
        freemarkerMapData.put("mapdata2", "UTF-8");
        freemarkerMapData.put("SampleDataDTO", freemarkerListObjectData);
        freemarkerMapData.put("SampleList", freemarkerListStringData);
        

        /**
         * Creating the output part.
         */

        Writer consoleWriter = new OutputStreamWriter(System.out);
        template.process(freemarkerMapData, consoleWriter);

       
        /**
         * For the sake of example, also write output into a file.
         */

        try (Writer fileWriter = new FileWriter(new File("output.html"))) {
            template.process(freemarkerMapData, fileWriter);
        }
    }
}


DTO or Bean Class 

package freemarker;

import java.math.BigDecimal;


public class SampleDataDTO {
    private int id ;
    private String name;
    private float age;
    private BigDecimal salary;
    private double exp;
    private char sex;

    public SampleDataDTO() {
    }
   
    public SampleDataDTO(int id, String name, float age, BigDecimal salary, double exp, char sex) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.exp = exp;
        this.sex = sex;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public float getAge() {
        return age;
    }

    public BigDecimal getSalary() {
        return salary;
    }

    public double getExp() {
        return exp;
    }

    public char getSex() {
        return sex;
    }


.ftl files :

 Main Ftl File:

<#ftl strip_whitespace = true>
<#-- Main template file starts-->
<#-- Importing Other template file-->

<#import "sub_freemarker_template.ftl" as sub_template>
<#import "another_freemarker_template.ftl" as another_template>
<#-- Creating variable.-->
<#assign myVar>This is my variable</#assign>
<!DOCTYPE html>
<html>
    <#-- Calling Macro-->
    <@sub_template.head>
     </@sub_template.head>
    <body>
        <#-- Checking if condition and print variable.-->
        <#if myVar == "This is my variable">
            <div>${myVar}</div>
        <#elseif myVar == "">
            <div>blank</div>
        <#else>
            <div>blank</div>
        </#if>
        <#-- Using Macro.-->
        <@another_template.another_macro> 
        <#-- Showing data from  datamodel. Here it is simple key from Map-->  
        <div>${mapdata1}</div>
        <div>${mapdata2}</div>
        </@another_template.another_macro> 
            <ul>

        <#-- Showing data from  datamodel. Here it is List Object from Map-->   
                 <#list SampleDataDTO as Sample>
                    <li>${Sample_index + 1}. ${Sample.name} from ${Sample.age}</li>
                </#list>
            </ul>
        </body>
    </html>


Macro Ftl
<#ftl strip_whitespace = true>
<#macro head>
<#assign charset="UTF-8">
<#assign title="Example">
<#assign content>This is content</#assign>
    <head>
        <title>${title}</title>
        <meta charset="${charset}">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
</#macro>


Macro Ftl
 
<#ftl strip_whitespace = true>

<#macro another_macro>
<#list SampleList as List>
    <li>${List_index + 1}. ${List}</li>
</#list>
</#macro>