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