3

I want to create a template file in java and Im using Eclipse IDE. I want to create a template file such that one program which gets the parameters from the users, it should be able to paste these parameters into the template file and then save it as a separate file. How can I do this ?

Please guide me.

Thanks N.B

N.B
  • 29
  • 1
  • 1
  • 3

4 Answers4

7

Here's how you would do this in my open-sourced template engine, Chunk.

 import com.x5.template.Theme;
 import com.x5.template.Chunk;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;

 ...

 public void writeTemplatedFile() throws IOException
 {
     Theme theme = new Theme();
     Chunk chunk = theme.makeChunk("my_template", "txt");

     // replace static values below with user input
     chunk.set("name", "Lancelot");         
     chunk.set("favorite_color", "blue");

     String outfilePath = getFilePath();
     File file = new File(outfilePath);
     FileWriter out = new FileWriter(file);

     chunk.render(out);

     out.flush();
     out.close();
 }

my_template.txt (simply place in the classpath in themes/my_template.txt)

My name is {$name}.

My favorite color is {$favorite_color}.

Output:

My name is Lancelot.

My favorite color is blue.

Your template can be made a bit smarter by adding |filters and :defaults to your tags.

my_template.txt - example 2

My name is {$name|defang:[not provided]}.

My favorite color is {$favorite_color|defang|lc:[not provided]}.

In this example, the defang filter removes any characters that might help form an XSS attack. The lc filter changes the text to lowercase. And anything after the colon will be output in case the value is null.

There is an Eclipse plugin available for editing Chunk templates directly in the Eclipse IDE. The plugin provides syntax highlighting and an outline view for template documents.

Chunk can do a lot more, take a peek at the docs for a quick tour. Full disclosure: I love Chunk in part because I created it.

Tom McClure
  • 6,699
  • 1
  • 21
  • 21
2

There are a ton of Java templating solutions.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • They best one I found easy to use was Jtwig (port of Twig from PHP symfony). It has a very good inheritance structure and scripting (also extensible) versus the other ones where you have to embedded the actual code into HTML tags and have to duplicate code because of lack of inheritance. The drawback is that jtwig has been deprecated :/ – TheRealChx101 Sep 16 '20 at 17:24
  • @TheRealChx101 The landscape is much as it was a decade ago (delta Thymeleaf, and I suppose Pebble). You're conflating "HTML templating" with "templating"; they're distinct things. There are quantifiable benefits to having "the code" in HTML tags for HTML templating, though, in that they're actual HTML and can be viewed as such (pre-data prototyping). Template inheritance suffers from the same problems as normal OOP inheritance (sometimes more) because HTML. There are a variety of ways you can implement "template inheritance" as well, depending on what you mean. – Dave Newton Sep 16 '20 at 17:32
  • When I said code I meant the template's scripting/templating language. For instance thymeleaf requires you to add attributes to HTML elements which is stupid because it's very difficult to override such behavior or add custom functions. Jtwig is just superior in every way – TheRealChx101 Sep 16 '20 at 18:35
  • @TheRealChx101 It's also *not* stupid because you can use the HTML as-is during prototyping because it's not mixed in with a different language, it's queryable via normal DOM tools (easier for tooling to deal with and introspect), etc. You may not *like* it, but it's far from "stupid". – Dave Newton Sep 16 '20 at 19:05
0

check out http://velocity.apache.org/engine/devel/

ilcavero
  • 3,012
  • 1
  • 31
  • 27
0

Let's break this into steps:

  1. Get the input parameters from the user:

    However you do this (sending a request to a servlet, using a CLI, or passing arguments to the main method) you will need to capture the input in some sort of object or data structure. To do this I would create a simple pojo class like this:

public class UserInput
{

  protected String firstName;

  protected String lastName;

    public String getFirstName()
    {
        return firstName;
    }

    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }

    public String getLastName()
    {
        return lastName;
    }

    public void setLastName(String lastName)
    {
        this.lastName = lastName;
    }

}
  1. Create a TemplateEngine Interface:

    This is handy so you can try out several template libraries. It is also best practice to use an interface so you can easily change your mind and switch to a different library. My favorite libraries are freemarker and mustache. Here is an example of an interface that demonstrates their common flows.

public interface ITemplateEngine
{
    /**
     * creates the template engines instance and sets the root path to the templates in the resources folder
     * @param templatesResouceFolder 
     */
    public void init(String templatesResouceFolder);

    /**
     * sets the current template to use in the process method
     * @param template 
     */
    public void setTemplate(String template);

    /**
     * compiles and writes the template output to a writer
     * @param writer
     * @param data 
     */
    public void process(Writer writer, Object data);

    /**
     * returns the template file extension
     * @return 
     */
    public String getTemplateExtension();

    /**
     * finishes the write process and closes the write buffer
     */
    public void flush();

} 
  1. Implement the Interface

The first is an example of a freemarker template...

/**
 * This class is a freemarker implementation of ITemplateEngine
 * Use ${obj.prop} in your template to replace a certain the token
 * Use ${obj.prop!} to replace with empty string if obj.prop is null or undefined
 * 
 * 
 */
public class FreemarkerTemplateEngine implements ITemplateEngine
{

    protected Configuration instance = null;

    protected String templatesFolder = "templates";

    protected Template templateCompiler = null;

    protected Writer writer = null;

    @Override
    public void init(String templatesResouceFolder)
    {

        if(instance == null){
            instance = new Configuration();
            instance.setClassForTemplateLoading(this.getClass(), "/");
            this.templatesFolder = templatesResouceFolder;
        }
    }

    @Override
    public void setTemplate(String template)
    {
        try
        {
            templateCompiler = instance.getTemplate(templatesFolder + File.separatorChar + template + getTemplateExtension());
        } catch (IOException ex)
        {
            Logger.getLogger(FreemarkerTemplateEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void process(Writer writer, Object data)
    {
        try
        {
            templateCompiler.process(data, writer);
            this.writer = writer;
        } catch (TemplateException | IOException ex)
        {
            Logger.getLogger(FreemarkerTemplateEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public String getTemplateExtension()
    {
        return ".ftl";
    }

    @Override
    public void flush()
    {
        try
        {
            this.writer.flush();
        } catch (IOException ex)
        {
            Logger.getLogger(FreemarkerTemplateEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}

And this is an example of a mustache template engine...

/**
 * 
 * Use {{obj.prop}} in your template to replace a certain the token
 * If obj.prop is null or undefined, it will automatically replace it with an empty string
 * If you want to exclude an entire section based on if a value is null, undefined, or false you can do this:
 *     {{#obj.prop}}
 *     Never shown
 *     {{/obj.prop}}  
 */
public class MustacheTemplateEngine implements ITemplateEngine
{

    protected MustacheFactory factory = null;

    protected Mustache instance = null;

    protected Writer writer = null;

    protected String templatesFolder = "templates";

    @Override
    public void init(String templatesResouceFolder)
    {
        if(factory == null){
            factory = new DefaultMustacheFactory();
            this.templatesFolder = templatesResouceFolder;
        }
    }

    @Override
    public void setTemplate(String template)
    {
        instance = factory.compile(templatesFolder + File.separatorChar + template + getTemplateExtension());
    }

    @Override
    public void process(Writer writer, Object data)
    {
        this.writer = instance.execute(writer, data);
    }

    @Override
    public String getTemplateExtension()
    {
        return ".mustache";
    }

    @Override
    public void flush()
    {
        try
        {
            this.writer.flush();
        } catch (IOException ex)
        {
            Logger.getLogger(MustacheTemplateEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}
  1. Create the template

Freemarker templates have a '.ftl' extension and mustache templates have a '.mustache' extension. Let's just create a mustache template called 'test.mustache', and put it in the 'resources/templates' folder.

Hello {{firstName}} {{lastName}}!
  1. Now, let's put our template engine to use.

It's always a good idea to create a JUnit test

public class JavaTemplateTest
{

    ITemplateEngine templateEngine = new MustacheTemplateEngine();

    public File outputFolder = new File(System.getProperty("user.home") + "/JavaTemplateTest");

    @Before
    public void setUp()
    {
        outputFolder.mkdirs();
    }

    @After
    public void tearDown()
    {
        for (File file : outputFolder.listFiles())
        {
            file.delete();
        }
        outputFolder.delete();
    }

    public JavaTemplateTest()
    {
    }

    @Test
    public void testTemplateEngine() throws Exception
    {

        //mock the user input
        UserInput userInput = new UserInput();
        userInput.setFirstName("Chris");
        userInput.setLastName("Osborn");

        //create the out put file
        File file = new File(outputFolder.getCanonicalPath() + File.separatorChar + "test.txt");

        //create a FileWriter 
        try (Writer fileWriter = new FileWriter(file.getPath()))
        {

            //put the templateEngine to work
            templateEngine.init("templates");
            templateEngine.setTemplate("test"); //resources/templates/test.mustache
            templateEngine.process(fileWriter, userInput); //compile template
            templateEngine.flush(); //write to file
        }

        //Read from the file and assert
        BufferedReader buffer = new BufferedReader(new FileReader(file));
        Assert.assertEquals("Hello Chris Osborn!", buffer.readLine());

    }

}

That's basically it. If you set this up using maven, the test should run and pass when running the mvn install goal.

Here is the project code that I created for this example: https://github.com/cosbor11/java-template-example

Hope it helps!

cosbor11
  • 14,709
  • 10
  • 54
  • 69