Reputation: 29
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
Upvotes: 3
Views: 26993
Reputation: 6729
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.
Upvotes: 7
Reputation: 16034
Let's break this into steps:
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;
}
}
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();
}
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);
}
}
}
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}}!
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!
Upvotes: 0
Reputation: 160191
There are a ton of Java templating solutions.
Upvotes: 2