Re: Custom directive's body not being read properly when the body has directives
Daniel Dekany <[email protected]> Wed, 29 May 2013 15:11:02 +0200
| Newsgroups | gmane.comp.web.freemarker.user |
|---|---|
| Message-ID | <[email protected]> |
Hello,
The problem is that your Writer implementation is incorrect
(regardless of if it's used with FreeMarker or not). The write(char[]
cbuf, int off, int len) method of a Writer might be called for
multiple times before the Writer is closed, but in your case, each
invocation of it will re-start the output file.
Anyway, I don't think you need your own Writer implementation for
this. Unless there's something that you don't show here, you could
just use a FileOutputStream wrapped into an OutputStreamWriter (and
maybe the whole wrapped into a BufferedWriter too), and then after the
body has returned, close the top-most writer so it's surely flushed
into the file.
BTW:
<@file name="newFile.html" path="${outputDirectoryPath}">
is better written as:
<@file name="newFile.html" path=outputDirectoryPath>
You don't need the ${...}, unless you want to insert something that's
not a string into a string literal (because that's what it does).
--
Thanks,
Daniel Dekany
Wednesday, May 29, 2013, 1:50:36 PM, srihari_ravi wrote:
> Hi, my requirement is to create an output HTML file using a freemarker
> template such that the file name, content are specified in the template
> itself. The code I am using is shown at the end. What my code does:
> 1. freemarker template: uses a new @file directive, wraps some HTML tags
> 2. FileDirective.java (implementation for @file): gets parameters filename
> and filepath, simply gets directive's body (everything between <@file> and
> </@file>) and writes to the file mentioned in parameters
>
> *Current behavior:* When I include freemarker directives (example: #assign,
> #list) in the directive body, the HTML output does not contain the whole
> content. The content after the directive is only included. Without a
> directive inside it (if body has only plain HTML tags), the output file
> contains the complete body. I need the # directives inside the body to
> dynamically create some content from the input datamodel.
> *Current output:* (source of newFile.html)
>
> Test heading...
>
> Paragraph 1...
> <P>
> Paragraph 2...
> </BODY>
> </HTML>
>
> *Expected behavior:* Everything inside the tags <@file> is the directive's
> body, so it should be included in the output post resolution of freemarker
> specific tags. Expected output is as shown below:
> <HTML>
> <HEAD>
> <TITLE>My Page</TITLE>
> </HEAD>
>
> Test heading...
>
> Paragraph 1...
> <P>
> Paragraph 2...
> </BODY>
> </HTML>
>
> If in the template below, I move the <#assign> line after "Paragraph 2...",
> what I get is this:
> </BODY>
> </HTML>
>
>
> *CODE:
> Template:*
> <#include "ErrorDoc_Directives.ftl">
>
> <@file name="newFile.html" path="${outputDirectoryPath}">
> <HTML>
> <HEAD>
> <TITLE>My Page</TITLE>
> </HEAD>
> <#assign name="test">
>
> Test heading...
>
> Paragraph 1...
> <P>
> Paragraph 2...
> </BODY>
> </HTML>
> </@file>
>
> *Directive:*
> public class FileDirective implements TemplateDirectiveModel {
> private static final String PARAM_NAME_NAME = "name";
> private static final String PARAM_NAME_PATH = "path";
>
> @Override
> public void execute(Environment environment, Map params, TemplateModel[]
> templateModels,
> TemplateDirectiveBody templateDirectiveBody) {
> // Process parameters
> Iterator paramIter = params.entrySet().iterator();
> String fileName = null;
> String filePath = null;
>
> while (paramIter.hasNext()) {
> Map.Entry ent = (Map.Entry)paramIter.next();
> String paramName = (String)ent.getKey();
> TemplateModel paramValue = (TemplateModel)ent.getValue();
>
> switch (paramName) {
> case PARAM_NAME_NAME:
> fileName = ((SimpleScalar)paramValue).getAsString();
> break;
> case PARAM_NAME_PATH:
> filePath = ((SimpleScalar)paramValue).getAsString();
> break;
> }
> }
>
> Writer fileWriter;
> try {
> fileWriter = new FileWriter(new File(fileName));
> templateDirectiveBody.render(new OutputFileWriter(fileName,
> filePath)); // use a custom writer to write to an external file defined by
> fileName & filePath
> } catch (Exception e) {
> System.out.println("EXCEPTION RENDERING THE OUTPUT");
> }
> }
>
> private static class OutputFileWriter extends Writer {
> private final String fileName;
> private final String filePath;
>
> OutputFileWriter(String fileName, String filePath) {
> this.fileName = fileName;
> this.filePath = filePath;
> }
>
> @Override
> public void write(char[] cbuf, int off, int len) {
> File file = new File(filePath + "/" + fileName);
> FileWriter fw;
> BufferedWriter bw = null;
> try {
> fw = new FileWriter(file.getAbsoluteFile());
> bw = new BufferedWriter(fw);
> bw.write(cbuf);
> bw.close();
> } catch (IOException e) {
> System.out.println("Exception caught while working with the
> buffer writer...\n");
> e.printStackTrace();
> if (bw != null) {
> try {
> bw.close();
> } catch (IOException f) {
> System.out.println("Exception caught while closing
> the buffer writer...");
> }
> }
> }
> }
> }
> }
>
> PS: I apologize for the post being so long! :)
>
>
>
> --
> View this message in context:
> http://freemarker.624813.n4.nabble.com/Custom-directive-s-body-not-being-read-properly-when-the-body-has-directives-tp4654561.html
> Sent from the freemarker-user mailing list archive at Nabble.com.
>
> ------------------------------------------------------------------------------
> Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
> Get 100% visibility into your production application - at no cost.
> Code-level diagnostics for performance bottlenecks with <2% overhead
> Download for free and get started troubleshooting in minutes.
> http://p.sf.net/sfu/appdyn_d2d_ap1
> _______________________________________________
> FreeMarker-user mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/freemarker-user
>
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1