Re: Custom directive's body not being read properly when the body has directives

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Re: Custom directive's body not being read properly when the body has directives

Daniel Dekany
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
> [hidden email]
> 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
_______________________________________________
FreeMarker-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/freemarker-user