Posts Tagged cfdocument

New ‘EvalAtPrint’ attribute in CFDocumentItem

A new evalAtPrint attribute has been added to cfdocumentitem tag in ColdFusion 801 which is applicable when the item type is header or footer. The default value of this attribute is false.

Note: The cfdocumentitem behavior with the default evalAtPrint value is identical to the behavior in ColdFusion MX 7, but differs from the behavior of the ColdFusion 8 release.

When the evalAtPrint attribute value is false, the default value, ColdFusion evaluates the cfdocumentitem tag body at the same time when it is processing the cfdocument tag. This is the behavior identical to CFMX7. In this case you can use CFDocument variables (TotalPageCount, CurrentPageNumber, TotalSectionpageCount and CurrentSectionpageNumber) only inside cfoutput and not in any expression because the page numbers are not known unless the cfdocument body content is evaluated and layed out.

In order to use CFDocument variables in expression inside CFDocumentItem tagbody, you should set evalAtPrint to true as shown in the following example.

<cfdocument format="pdf">
<cfdocumentitem type="header" evalAtPrint="true">
       <cfif (CFDocument.currentPageNumber % 2 eq 0)>
           <cfoutput> Page is even</cfoutput>
       <cfelse>
           <cfoutput> Page is odd</cfoutput>
       </cfif>
   </cfdocumentitem >
   Document body…
</cfdocument>

In this case, ColdFusion evaluates the cfdocumentitem tag body when it prints the header or footer, not when it evaluates the cfdocument tag body. This ensures that the cfdocument tag body is already evaluated and layed out and page number information is available when cfdocumentitem tag is being evaluated

A side effect of this is, if a variable is used inside both cfdocument and cfdocumentitem, cfdocumentitem tag will only see the final value of that variable. In the following example, cfdocumentitem will always get 11 as value of ‘I’ and hence all the headers will print ‘Chapter 11’.

<cfdocument format="pdf" >
<cfloop from=1 to=10 index="i">
   <cfdocumentsection>
   <cfdocumentitem type="header" >
       <cfoutput>Chapter #i#</cfoutput>
   </cfdocumentitem >
DocumentSection body
   </cfdocumentsection>
</cfloop>
</cfdocument>

To handle this, you can now pass the variable into the cfdocumentitem tag as a custom attribute, as shown in the following example:

<cfdocument format="pdf" >
   <strong><cfloop from=1 to=10 index="i"></strong>
       <cfdocumentsection>
           <strong><cfdocumentitem type="header" evalAtPrint="true" no = #i#>
               <cfoutput>Chapter #attributes.no#</cfoutput> </strong>
               <cfif (CFDocument.currentPageNumber % 2 eq 0)>
                   <cfoutput> Page is even</cfoutput>
               <cfelse>
                   <cfoutput> Page is odd</cfoutput>
               </cfif>
           </cfdocumentitem >
           Document Body.
       </cfdocumentsection>
   </cfloop>
</cfdocument>

Tags: ,

Images and CFDocument performance

Sometime back one of our customer reported that using png images in cfdocument makes it very very slow. I could not replicate it with any png image but it did happen with his png image.

Today, Andy reported a similar issue but this time it was for jpeg images. In both the cases, performance hit is huge and it does not happen with all the images.

I spent a significant amount of time debugging it today and it turns out that the reason for both the issues are same – there is something special about these images and that is colorspace. All these images actually had a different colorspace than what java imaging uses. Because of this, when we need the pixel values of image to print it on pdf (by calling BufferedImage.getRGB()), it tries to convert this colorspace to RGB colorspace and that is very very costly. That is where the entire time goes. So how do you fix it? I opened all the images in an image editor and saved it again. This time it got saved in standard RGB colorspace and the time taken to create the pdf got reduced from 110 sec to 1.5 seconds. That is huge!!! Isn’t it? But can you control all the images over the web? NO.. right? Read on.. there is more to this story.

A little bit of looking up on web pointed me to this Sun bug which is the exact same bug which we were hitting. Thankfully it got fixed in mustang i.e JDK1.6 which ColdFusion8 uses by default. But hey wait a second.. Didn’t Andy say that he is seeing it on ColdFusion 8? why do we still see this happening when it is fixed in JDK1.6? It appears that this bug was fixed only in core JDK api but not in JAI (Java advanced imaging) codecLib that ColdFusion 8 uses. So what do we do now? You can do either of these two

  1. Remove clibwrapper_jiio.jar from “lib” folder.
  2. Or, set this system property to the JVM. -Dcom.sun.media.imageio.disableCodecLib=true . You can set this in [cf-install_dir]/runtime/bin/jvm.config if you are using standalone coldfusion server.

You should keep in mind that codecLib libraries are native libraries which are meant to increase the java imaging performance. So disabling it might degrade the performance of CFImage somewhere. Also keep in mind that removing this jar or disabling codecLib will not result into any loss of functionality – it just means that all image operations will be pure java.

There is another related Sun’s bug which I thought might be useful to you. Image loading might get very slow if the server is running in debug mode. Your server is running in debug mode if you see something like this in your jvm.config or VM startup option.

-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005

This bug got introduced in JDK1.6 and does not exist on 1.5. So make sure that you are not running the server in debug mode.

To summarise, you can do following to increase the performance of image loading in cfdocument.

  1. If you are on JDK1.5, there is not much you can do. The only option is to change the colorspace of images. I will try to see if we can address this in ColdFusion code.
  2. If you are on JDK1.6,
    • Disable codecLib as mentioned above.
    • Disable debug mode by removing the complete debug string mentioned above
  3. In addition to this, you might want to use ‘localurl’ attribute for cfdocument tag. See this for more details.

Tags: , ,

Missing text in pdf created by CFDocument

I had heard about people not getting images in the generated pdf but this one was something new and spooky. Yesterday Andy Matthews posted it on cf-talk where he says that for his content, though a pdf containing 15 pages gets created but only the first page has some content and rest of the pages are blank. I ran his code on my machine and sure enough it was happening. All the content including text and image on all the pages except the first page was gone. So what was wrong? I simplified his code and here is a simple example which you can try.

<cfdocument format="pdf">
Text Outside div
<div style="width:300px;overflow:auto;">
 This is text inside the div. Will it show up?
</div><br>
</cfdocument>

In the generated pdf you will see only “Text Outside div”. Spooky.. isn’t it? The reason it happened was because of css style ‘overflow:auto’. The rendering engine used by CFDocument underneath does not handle overflow:auto and it simply ignores the content in the div. The weird part is – it considers that content for all rendering calculations including page number and page break calculation.

Something you should watch out for if you use css styles in cfdocument. A workaround for the time being is not to use overflow:auto style. So modifying the above code like this will make it work.

<cfdocument format="pdf">
Text Outside div
<div style="width:300px;">
 This is text inside the div. Will it show up?</div><br>
</cfdocument>

Tags:

CFDocument hotfix for ColdFusion 8 released

We have released a cumulative hotfix for CFDocument related issues in ColdFusion 8. Bugs being addressed in this hotfix are

  • PDF/Flashpaper document generated in CF8 are nearly 70% scaled down than CFMX 7. This was making document appear smaller in CF8 as compared to CF7.
  • Using cfdocumentitem in a loop inside cfdocument causes the error, “routines cannot be declared more than once”.
  • StackOverFlowError when a large document with table is created. A simple report with over 1500 table row causes this problem. More complex, but shorter documents have also resulted in this error. This was a pretty nasty one and it deserves a separate blog entry :-) .

You can download the hotfix directly from here. You would need to extract the hotfix jar from the downloaded zip file and apply that jar.

Tags: ,

Missing images in CFDocument

I have seen huge no of postings on CF forum where CFDocument users have complained about seeing red-cross (or red-x ) for images . In this post, I would like to list the reasons why they happen and how they could be resolved .

Before we proceed with different cases of red-x, lets see in brief, how images are rendered in CFDocument.

During the processing of cfdocument tag, CF engine interprets/executes the content inside the cfdocument tag, creates html content out of it and renders it in the memory. While rendering this html content, if any image tag is found, a separate HTTP request is made to retrieve this image content. A separate HTTP request is necessary because image in the generated html can be local as well as remote. For Java geeks out there, we use URLConnection.getContent() to retrieve the image data. A red-x means that CFDocument was not able to retrieve the image.

Now lets see different scenarios one by one

  1. Image name has space in it. In CFMX 7.0, you can get red-x for images if the image file name has any space in it. For example if the image file name is “my picture.jpg”, only a red-x will appear in the pdf/flashpaper. It happens because the url created for the image is not encoded. A workaround for this is to either use encoded url for the images i.e replace ’space’ in the name with ‘%20‘ OR dont have spaces in the file name at all :) . This bug has been fixed in Merrimack (Coldfusion 7.0.1). So if you are still on 7.0, upgrade :)

  2. If your server is behind firewall. As we mentioned earlier, CF server needs to send an HTTP request for the images. If the firewall prevents any outgoing connection from the server, CF will not be able to retrieve them and will show a red-x in place of them. You will need to setup your firewall in such a way that server can send an HTTP request to itself.
  3. If your server is behind a proxy. If Coldfusion server is connected to the external world using a proxy, then also CFDocument will not be able to load the images. This is because currently there is no way you can specify proxy configuration for CFDocument tag.
    Current solution to solve this is to define the following system properties for the JVM. You can specify these in “runtime/bin/jvm.config” if you are using standlone or on JRun server.

    -DproxySet=true -DproxyHost=[hostname] -DproxyPort=[port] -Dhttp.proxyHost=[hostname] -Dhttp.proxyPort=[port]

  4. If you are using HTTPS and your images do not appear in the pdf/flashpaper, you must ensure the following
    • CF server’s certificate is trusted. In other words, certificate of the CA who issued the certificate for you, must be present in the trusted certificate store (runtime/lib/trustStore). You can use keytool to list/view/import/.. certificate in the certificate store.
      If CF is using a self signed certificate, CF’s certificate must be present in the trustStore.
    • The certificate is valid and has not expired.
    • Host name of the server must match the host name to which the certificate was issued.

  5. If the resources on your webserver are protected using some kind of authentication like basic authentication or digest authentication, cfdocument can not retrieve those resources. That is because you can not provide any authentication information to cfdocument tag currently. This means that cfdocument can not retrieve images if it is protected using authentication and you will see a red-x. One solution for this is to replace all image urls with “file” urls.
    See this entry
    for more details on this workaround. The other solution is to write little java code to set a ‘java.net.Authenticator‘. I will post a separate entry for this.
  6. You get red-x for images and you have verified that its none of the above mentioned cases. Time to check the web server now. We have seen some cases where the web server is configured to allow requests only from a certain set of browsers (User agents to be precise) perhaps to prevent spiders and bots from overloading the server. When CFDocument creates a URLConnection for the image, it sends a “User-Agent” header, that looks like “User-Agent:Java/1.4.2_07“, in the HTTP request. If the web server does not recognize “Java” user-agent, it returns a status code of 404 (resource not found) and hence the images can not be displayed. Solution for this case is to either change the configration for the web server or set your own user agent using the following system property on the JVM.
        -Dhttp.useragent="ColdFusion"

    You can give any name here as userAgent in place of “ColdFusion”.

Hope this helps people in resolving isues related to missing images in CFDocument. In case you are getting a red-x even after verifying all the cases mentioned above, please let me know.

Related Entry :

Tags: , ,