Monday, July 13, 2009

Moving my blog to a new address

With the release of ColdFusion 9 beta, I am also moving my blog from blogger to a new address (http://www.rupeshk.org). I have moved all the content including comments from blogger to the new site. The new blog is still in beta as I still need to do lot of cleanup.

I will keep posting the entries to both the blogs for some time till I feel that the traffic has moved to the new blog. So please put all your comments on the new blog so that its all at one place :-)

If you are subscribing to my feed or if you have linked to this blog, you can change that to use the new feed. See you over at http://www.rupeshk.org

Sunday, July 12, 2009

ColdFusion 9 and ColdFusion builder beta available

I am sure by the time you will be reading this, the blogosphere will be buzzing with this news :-). We just (13th July 12:01 AM EST) went live with the beta of ColdFusion 9 and ColdFusion builder. All of us in the team had been working really hard for last one and half years to put in features, that will take RAD to the next level, features that will make your life easy, features that you are going to love. ColdFusion has always been known for "making hard things easy" and I am sure this release will make even harder things easy :-)

Ben talked about the new features in ColdFusion 9 and ColdFusion beta here :

http://www.adobe.com/devnet/coldfusion/articles/coldfusion9_whatsnew.html

http://www.adobe.com/devnet/coldfusion/articles/cfbuilder_whatsnew.html

Here are the links for public beta

ColdFusion 9 : http://labs.adobe.com/technologies/coldfusion9/

ColdFusion Builder : http://labs.adobe.com/technologies/coldfusionbuilder/

I also wanted to highlight an excellent devnet article written by Mark Mandel introducing ColdFusion ORM. I am sure ColdFusion ORM is going to completely change the way ColdFusion applications are built and is going to make you much more productive. Hey, I am not boasting because its my baby, but I genuinely feel this :-)

Saturday, June 13, 2009

Devnet Article on ColdFusion Performance tuning

In case you haven't seen it yet, there is a new devnet atricle that was published this week on "Performance tuning for ColdFusion Application". Its an excellent article written by Kunal from the ColdFusion team. It gives a great insight into how to go about tuning your JVM, how to tune the VM's Garbage collector settings and how to tune different settings in ColdFusion server. It also gives some tips on best practices for writing ColdFusion application from a performance perspective. Overall an excellent article.

However, there is one mistake in the fourth page where it suggests to use File functions instead of File tag which I would like to correct. Actually it should have suggested to use new File functions that were introduced in ColdFusion 8 instead of older File functions or cfile tag.

Tuesday, July 01, 2008

ColdFusion Livedocs on AIR

I was doing a code review for Vinu today (dont ask me which feature it was :-)) and we needed to check the reference doc for a tag. And instead of opening the local doc page, he opened this cool application that had livedocs and it was blazing fast (I know Livedocs sucks ! and yes I work for Adobe ;-)).

I was like 'whoa!! thats a cool app.. Did you write it? Why dont you release it for public??' And then he told me that some one from the community had written it and its already available for everyone. It has been developed by Brian Love and it is available here. It has very small size application, very lightweight and extremely fast.

So in case you haven't downloaded it, download it now!! I am sure you would love it.

Monday, June 30, 2008

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" >
<cfloop from=1 to=10 index="i">
<cfdocumentsection>
<cfdocumentitem type="header" evalAtPrint="true" no = #i#>
<cfoutput>Chapter #attributes.no#</cfoutput>

<cfif (CFDocument.currentPageNumber % 2 eq 0)>
<cfoutput> Page is even</cfoutput>
<cfelse>
<cfoutput> Page is odd</cfoutput>
</cfif>
</cfdocumentitem >
Document Body.
</cfdocumentsection>
</cfloop>
</cfdocument>

CFUnited Presentation - All about CFThread

I did a presentation on "All about CFThread" at CFUnited this year and I think it went fairly well. It was a repeat session - once on friday 21st June and another on Saturday 22nd June and both the sessions had pretty good number of people attending it. Thanks a lot to all those attended. As promised, I have uploaded my presentation and the sample code up here.

Please feel free to ask me questions if you have any.

Friday, June 27, 2008

Back from hiatus

I took a long long break from blogosphere and now that I am rejuvenated after CFUnited, I am back. :-) Thinking about it, it was a really long break - my last post was on Feb 18th which makes it 4 months. So what did I do in those last 4 months? Well lot of things ;-)

  • I GOT MARRIED :-) So thats the biggest thing that happened. I took a one month long vacation to get married, went to Mauritius for my honeymoon and we had a really great time. Here is one of our pics. In case you want to see more of these, you can head over to Flickr. :D

 

  • There was a more than one month long Cricket series called "Indian Premier League" and I watched each and every match ;-)
  • All of us in the ColdFusion team were quite busy (and still are) in research, planning and implentation for the Centaur. In other words, I was working for you guys.

Now that I am back, you should see some regular posts from me. The next one goes in a while.

Monday, February 18, 2008

Reading MP3 meta-data from ColdFusion

On friday I posted about how to read the meta-data for Swf (flash) file from ColdFusion and on the same note, I think it will be cool to read the meta-data for MP3 file as well. Here is the specification for MP3 header and it is fairly straight forward to read the header using the spec.

ColdFusion 8 knows how to read MP3 file and it can provide a set of meta-data for it. Though this functionality is not exposed via any tag or function, you can still use it. The meta-data it provides are

  • Bit Rate : in kbps
  • Frequency : in Hz
  • Play duration : in second
  • Version : integer
      • 0 - MPEG version 2.5
      • 1 - MPEG version 2
      • 3 - MPEG version 1
  • Copy Right : true/false
  • Channel mode : integer
      • 0 - Stereo
      • 1 - Joint Stereo
      • 2 - Dual Channel
      • 3 - Mono or Single Channel

Here is an example code.

<cfset mp3File = createObject("java", "coldfusion.util.MP3File").init("C:\music.mp3")>
<cfoutput>mp3File.getBitRate() : #mp3File.getBitRate()# kbps</cfoutput><br>
<cfoutput>mp3File.getFrequency() : #mp3File.getFrequency()# Hz</cfoutput><br>
<cfoutput>mp3File.getVersion() : #mp3File.getVersion()#</cfoutput><br>
<cfoutput>mp3File.getDuration() : #mp3File.getDuration()# Sec</cfoutput><br>
<cfoutput>mp3File.isCopyRighted() : #mp3File.isCopyRighted()#</cfoutput><br>
<cfoutput>mp3File.getChannelMode() : #mp3File.getChannelMode()#</cfoutput><br>

Though you can use the above mentioned class (coldfusion.util.MP3File) without any problem, you must keep it in mind that it is unsupported and *might* change in future. Just a disclaimer !!! :-)

This class does not get you the ID3V1 or ID3V2 meta-data, but it should be easy for you to do it. For ID3V1, all you need to do is to read the last 128 bytes of the mp3 file and you have all the information required. Reading ID3V2 tag is little more involved and there are a number of open source java libraries available (common one being jidlib and jaudiotagger) which can be used.

Friday, February 15, 2008

Reading Flash (Swf) metadata from ColdFusion

Wouldn't it be cool if you could read the meta-data of Swf file in ColdFusion? The most common use case I can think of is to find the dimension of swf movie so that you can set the dimension for the same in object tag while you are embedding the flash movie in your page. And the good news is that you can do that currently in ColdFusion with just 2-3 lines of code!! All you need to do is to create a TagDecoder and decoder the header with it. Here is the complete code.

<cfscript>
fis = createObject("java", "java.io.FileInputStream").init("C:\test.swf"); // Create the FileInputStream
decoder = createObject("java", "macromedia.swf.TagDecoder").init(fis); // create TagDecoder
header = decoder.decodeHeader(); // Decode the header.
fis.close();
rect = header.size;
WriteOutput("
Is Compressed : #header.compressed#<br>
Frame Count : #header.framecount#<br>
Frame rate : #header.rate#<br>
Version : #header.version#<br>
Height : #rect.getHeight()#<br>
Width : #rect.getWidth()#");
</cfscript>

The height and width value that you see here would be in twips which is defined as 1/20 of a point or 1/1440 inch. This means, for a 72 dpi screeen, you will have to divide it by 20 to get the height and width in pixels.

Monday, January 14, 2008

Adobe ColdFusion Survey

As promised earlier, here they come. As part of the research for Centaur (next major version of ColdFusion aka ColdFusion 9), we need your feedback on ColdFusion 8 features, what enhancements do you need in them, what new features you want in the new release etc etc.

Adobe ColdFusion Survey

We would also like your inputs on platform and vendor support for upcoming ColdFusion release.

Platform and Vendor Support

Please do take some time to take this survey as this would really help us shape the new features in the upcoming version. THIS is YOUR chance to get your favorite features in !

Thursday, January 10, 2008

DNS lookup Caching in ColdFusion/Java

Two days back, I got an interesting question from our support team. The Customer in this case was using CFLdap which connected to a particular LDAP server and things were working fine. The problem came when they replaced this LDAP server with another LDAP server and assigned the same dns name to the new ldap server. Ideally any connection made henceforth should have worked with the new ldap server but actually that did not happen. ColdFusion started throwing error and it did not work until the ColdFusion server is restarted. Ever seen something similar?

It is obvious that it happend because the IP address was being cached for the host name as a result of which ColdFusion was still trying to connect to the old IP address even though the host name now pointed to a different IP address. This caching also applies for all other network protocol tags such as CFHTTP, CFFTP, CFFEED etc and is not limited to CFLDAP. It is actually the JVM that does this caching. When JVM is requested to resolve a host name, it does the host name to IP address resolution and caches the result. This result will be used for all subsequent lookups. It also caches the negative results. By that I mean, if the dns reolution fails, it caches the failed result for a certain period so that any lookup for that hostname in that period will not result into another resolution on network and will immediately return the failed result.

For more detail on this caching, check out the Javadoc for InetAddress class.

As per this doc, there are two parameters that control this caching

networkaddress.cache.ttl (default: -1)
Indicates the caching policy for successful name lookups from the name service. The value is specified as as integer to indicate the number of seconds to cache the successful lookup.

A value of -1 indicates "cache forever".

networkaddress.cache.negative.ttl (default: 10)
Indicates the caching policy for un-successful name lookups from the name service. The value is specified as as integer to indicate the number of seconds to cache the failure for un-successful lookups.

A value of 0 indicates "never cache". A value of -1 indicates "cache forever".


Now where do you specify this settying? You can specify this setting in <Java_home>/jre/lib/security/java.security file. For standalone ColdFusion server it will be in <ColdFusion _dir>/runtime/jre/lib/security/java.security file.

As you see, by default networkaddress.cache.ttl caches the result for ever and hence it is configured for best performance. Any change to this mean drop in performance. If you don't want to cache the resolved IP address for ever, as is the case here, you would need to change networkaddress.cache.ttl value to 60 seconds or 300 seconds or any value you feel suitable. You would not want to set it to 0 as that would mean "never cache" the result which might affect the performance significantly.

In which case you would want to change the value for networkaddress.cache.negative.ttl? That would be mostly in case when you want to cache the negative result for a longer time and in turn improving the performance. For example, if you are trying to connect to a hostname which can not be resolved to any ip address, and that happens very frequently, each of the call (as long as they are not in the same 10 sec window) would become very slow. Increasing this value would increase the performance but again you would not want to cache the negative result for ever.

After you change this setting, you will have to restart the ColdFusion server for this change to take effect.

Monday, January 07, 2008

ColdFusion 8 finalist among Dr. Dobb's Jolt Product Excellence Awards

Good to see ColdFusion 8 as a finalist in Web Development tools category among Dr. Dobb's 18th Annual Jolt Product Excellence Awards. Here is the entire story and here is the list of finalists.

Adobe ColdFusion IDE Survey

As part of our research on CF9 (Centaur), the ColdFusion team has come up with a survey to find out what features do you use and would like to have in an IDE for Coldfusion. Please take few minutes to take this quick survey.

http://www.surveymonkey.com/s.aspx?sm=321RrO9_2fWaP_2bdYMnmF9CuQ_3d_3d

Check out this space in few days for another survey to tell us what you would want to see in CF 9 !

Wednesday, January 02, 2008

Encrypted CFML Templates

Coming back from the 10 days shutdown period that we had at Adobe, I am catching up with the blogs and I read this interesting post by Ray where he mentioned that some one got his cfml templates encrypted and then lost the originals. Hmmm.. that is a situation, I would never want to be in. In case you have not figured it out yet, it is not possible to get back the original source. Let me explain.

Why do we need to encrypt cfml templates? To protect the cfml code and your intellectual properties (IP) in case you want to distribute your CF application. Right? In pre-CFMX7 era, ColdFusion used to have "cfencode" utility which used to encrypt the template which you can then distribute to anyone. ColdFusion used to know how to decrypt that and then how to execute that. However, this was not a good solution as people came up with utility to decode this encrypted file. And THAT means that  your code and IP was not protected at all. This had another disadvantage - template execution was slower as it meant decrypting the template first and then compiling/executing it.

With CFMX7, this changed. ColdFusion came up with sourceless deployment to make it nearly impossible to decode it back to the original source. When you use 'cfcompile' with deploy option, your cfml template is compiled to java byte code (class) but the file in which this byte code is written still retains the same template name. To give an example, if you run cfcompile on "hello.cfm", the output would still be "hello.cfm" but it will actually be java class file. To confirm this, just open one of such encrypted file in a hex editor and you would see the first 8 bytes will be CAFEBABE - the magic number for java class files. This file can then be distributed to your customers. For execution, ColdFusion works smart - when request comes for this template, it sees that it is not a cfml template but a class file, skips parsing and compiling the template, and directly proceeds with the execution.

As you see, there is no encryption and no key involved here. The encrypted file is simply a java class file and I have not heard of any utility that can decompile this class file back to cfm source. Though there are many Java decompilers available which can convert the class file to approximate java source file, it will be a huge huge task to write a decompiler which can generate cfm code for class file. One needs to know how CF does the code generation, know a great deal about bytecode instructions and apply lots and lots of heuristic to get the approximate cfm source. This is definitely not an easy thing to do even if some one breaks open the CF engine to see how it generates the java code from cfm code.

The bottom line is - in case you use sourceless deployment, ALWAYS backup your original source.

Wednesday, December 19, 2007

Friday, December 14, 2007

Firefox (Adblock plus) blocks even Google adsense

I have been using my new laptop at work (my old one crashed at MAX) for two weeks and its been pretty good. Not because the laptop is something extraordinary, its because I installed the latest versions of all the softwares and plugins I use. And the most pleasant part of it is - it has been completely ads free. I did not notice it earlier but once I landed up on sys-con's site to read some article and I was pleasantly surprised to find no irritating video ad there. For a moment, I thought that may be sys-con has grown up but that was just for a moment :-). The snapshot shows it all.

IE

cfdj_ie_1

Firefox

cfdj_firefox_1

Its actually a firefox plugin adblock plus that does it automatically. The most interesting thing was that it even removed google text ads. Its interesting because we have always seen Google promoting firefox and firefox as a browser closer to Google. So now a firefox plugin that blocks google adsense and in turn hurts Google revenue is certainly not going to go well with Google. It will be interesting to see how Google plays it.

So how exactly does adblock plus block the ads? Gecko engine - the engine underneath Firefox, uses a content policy which decides which content should be loaded and which should not. Adblock defines its own policy which gets added to the browser's policy. It comes with a predefined huge collection of filters and if the url to be loaded matches any of that, it does not let the browser make a request for it. For google adsense, the url contains 'pagead2' which you can see in the adblock preference below.

adp

Its also going to hurt many bloggers as lot of them earn substantially from ads and mainly adsense.  Even my blog page contains adsense but I dont mind adblock plus as I haven't yet earned anything from it anyway. I'm loving it. :-)

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.

Wednesday, December 12, 2007

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>

Wednesday, November 21, 2007

64 bit Support on ColdFusion 8 (Windows, Linux and Leopard)

ColdFusion team is working to get ColdFusion 8 working on 64 Bit platforms(Windows, Linux and Leopard). If you are interested and want to participate in the testing of early releases of 64 Bit support on ColdFusion 8 on these platforms, please enroll yourself for prerelease program here.

JRun updater 7 released

JRun 4 updater 7 got released last week and is publicly available for download. It now supports a host of new platforms, includes upgrades to existing software components and fixes for many critical bugs.

Some of the important platform support include

  • JDK 1.6 support
  • Support for Windows Vista.
  • Mac OS X 10.4 on Intel
  • 64-bit Support on Solaris-SPARC.
  • IIS7 support.
  • Apache 2.2.x support
  • SunOne Webserver 7
  • IBM JDK 1.5

Another important reason why you might want this is - a very significant performance improvement in web clustering. Check out the detailed release notes here.