Rob Gonda's Blog

CFUnited 2007 Topics Online

CFUnited has posted topics for 2007 and the list looks even better than last year. They'll post about 20 more in the next couple of months, including new topics for Flex and Scorpio.

As a reminder, the 'very early registration' ends January 5th, so if you know for sure you are going, register early and save.

I'm giving a session called Embrace Factories:
Object Oriented Programming is still fairly new for ColdFusion developers. The community is learning the advantages of using objects, but once programs scale, they get out of control. Learn the best practices to organize and wire your objects together using proven design patterns such as object factories, service locators, and inversion of control. Attendees will see the evolution starting from a 20-lines simple factory, moving towards light-wire, and ending with ColdSpring.

I may also do a pre-confernce class like last year, not yet confirmed... I could do another Ajax Intensive, this time leveraging jQuery, YUI, and the new Scorpio Ajax built-in integration... I could also do one on Apollo ... which one would you rather take?

Better image manipulation quality with ASPJpeg

ColdFusion runs on top of Java and therefore can leverage of native Java classes such as BufferedImage and ImageIO. There are a few wrapper libraries that allow you to interact with them. The core relies on CreateObject("java", "java.awt.image.BufferedImage") and CreateObject("Java", "javax.imageio.ImageIO"), for the text manipulation you can use CreateObject("Java", "java.awt.Font"), and for reading and writing files you can use CreateObject("Java", "java.io.FileInputStream"). All this will be replaced with native image manipulation with the release of Scorpio (CFMX8).

However, I ran into image quality problems when resizing large images to smaller thumbnails... the resizing algorithm used by these native Java technologies is not optimal, therefore it really doesn't matter which wrapper you use, you will ultimately run into the same issues.

After much research, I chose to install a COM object used by ASP called ASPJpeg. As you probably know, ColdFusion can also leverage COM objects, and let me tell you, the quality of ASPJpeg is superb.

It really couldn't be any simpler. First initialize the COM Object:

<cfset myImage = createObject("COM","Persits.Jpeg") />


Then you may open an existing image:
<cfset myImage.Open("/path/to/original/file.ext") />


You may get the original width and height
<cfset orig_size_w = myImage.OriginalWidth() />
<cfset orig_size_h = myImage.OriginalHeight() />


Set new quality and resolution
<cfset myImage.ResolutionX(72) />
<cfset myImage.ResolutionY(72) />
<cfset myImage.Quality(80) />


Set a new width and height
<cfset myImage.Width(new_large_w) />
<cfset myImage.Height(new_large_h) />


Crop the image
<cfset myImage.Crop(crop_w, crop_h, starting_w, starting_y) />


and finally save the image to disk
<cfset myImage.Save("/path/to/original/file.ext") />


As you can see, it's extremely easy to leverage COM objects to read, resize, crop, modify quality ... ASPJpeg is capable of many other functions, but these should get you started.

Enjoy good quality!

SQL: A Case For CROSS JOIN

Sometimes we have to select data from two or more tables to make our result complete. We have to perform a join. It is usually an INNER JOIN or [LEFT | RIGHT | FULL] OUTER JOIN, but SQL also provides a CROSS JOIN ... The CROSS JOIN takes all entries of one table and combine them with all entries of a second table; because of this, it does not allow for an ON clause. There are rare occasions when you would use it, so I decided to illustrate one.

Imagine a schema where you have the following tables: contentKeys, languages, and content. This db allows you to store content in various languages. contentKeys will store the unique keys for content pieces, which after combined with languages, will return a unique piece of content in a particular language. The schema looks as follows:

The content table has a unique contraint for FK_key and FK_language (FK denotes it's a forgeign key).

Now, what if you need to know which keys exist for one language and not for others, or even which keys exist and contain content in no languages at all? We'll build a query to show this information.

The first step is to find all combinations of keys and languages. To do this we need to combine all entries in they contentKeys table with all entries in the languages table.

SELECT * FROM contentKeys CROSS JOIN languages


The next step is understanding OUTER JOINs. An outer join selects all of the records from one database table and only those records in the second table that have matching values in the joined field. In a left outer join, the selected records will include all of the records in the first database table. In a right outer join, the selected records will include all records of the second database table.

That said, if you OUTER JOIN the combination of all possible keys in all possible languages with your content table, the resulting query will let you know which keys have been translated, and which ones have not.

SELECT * from [CROSS-JOINED-QUERY] helper LEFT OUTER JOIN dbo.content
ON helper.pk_language = dbo.content.fk_language AND helper.pk_key = dbo.content.fk_key


We called the cross-joined table 'helper', and this query will return all rows there, matching them to the content table. All the exiting content/language combinations will have data in the content table, and those what do not exist will have null values. You may enter an additional where clause to filter only null values, which will indicate exactly which content keys / language combination are missing.

So for the full query, we'll take advantage of the dynamic table aliasing capabilities of sql and it looks like this:

SELECT helper.content_key, helper.code, helper.[language],
content.pk_content, helper.pk_key, helper.pk_language,
content.content
FROM (SELECT * FROM contentKeys CROSS JOIN languages) helper
    LEFT OUTER JOIN dbo.content
    ON helper.pk_language = dbo.content.fk_language AND helper.pk_key = dbo.content.fk_key
ORDER BY helper.content_key, helper.[language]

AjaxCFC for jQuery Alpha Release

I finished today the implementation of AjaxCFC for jQuery. It's the same Ajax <-> CF integration you already know, but using the jQuery Ajax engine. It supports full JSON and WDDX serialization, has improved error handling, improved log4javascript integration, still supports named and unnamed arguments, and just so you can use it right away, it's back compatible with the DWR syntax. The only incompatibility is the change of the $() function, which you can actually override if you wish, but I didn't on my release.

This is great news folks, because jQuery is extensible and allows for easily dropping plugins into your code...
I will work in documenting it for beta release, but those of you who wish to use the bleeding edge version just add a comment and I'll send you the code. I'd appreciate comments and suggestions from those who wish to check it out.

Public Beta release should come sometime next week.

This blog is running version 5.9.003. Contact Blog Owner