comment

Working with Transfer ORM: TQL, MSSQL and Reserved Words

2008 January 25
No Comments
I'm definitely marking this down in the "I should have known better" category. If you use MSSQL, you probably know by know that "user" is a reserved word. So, unless you use [user] as a table identifier it's imperative that you name your table something like "tbl_user" or use the plural "users". I don't like plural table names, so I opted for tbl_user. I just ran into a gotcha with my TQL for a query against tbl_user. Why? Here's a snippet from my method to check the uniqueness of a user e-mail.
// local vars struct
var local = StructNew();
// default result
local.result = false;
// tql for list
local.tql = "from user.User as user where user.Email = :Email AND user.Id != :Id";
//create a query object
local.query = getTransfer().createQuery(local.tql);
//set the named parameters
local.query.setParam("Email", getEmail(), "string");
local.query.setParam("Id", getId(), "numeric");
//run it
local.userList = getTransfer().listByQuery(local.query);
// if no records exist e-mail passes unique test
if (local.userList.recordcount eq 0)
{
	local.result = true;
}	
return local.result;

My transfer object class name is user.User, so why not alias that as "user"? That's a logical alias, right? Wrong! After pulling my hair out debugging the ever-so-descriptive error message, [Macromedia][SQLServer JDBC Driver][SQLServer]Line 1: Incorrect syntax near '.'. I finally decided to write up a unit test to try and get some meaningful debugging information. From there I pulled a query, ran that in the Query Analyzer. Scratched head a bit more, then...voila! Reserved word issue. How silly.... Of course, this is not purely a Transfer or even TQL problem, merely a cautionary tale regarding reserved words in MSSQL that I happened upon via Transfer TQL. For the record, the new TQL query reads:
local.tql = "from user.User where user.User.Email = :Email AND user.User.Id != :Id";			
The other big a-ha moment for me is that if an error occurs within a method invocation, I should debug by unit testing, not re-initializing, rinsing and repeating on the client side.

Two Utility Classes to Help Keep Your Controllers Lean

2008 January 23
No Comments
I have really enjoyed reading the perspectives on application architecture that have sprouted up on the mailing lists lately. It comes a at good time for me, since I'm beginning my first fully OO MVC project. One of the best recommendations, I feel, is to keep your controllers as dumb as possible. While this is a fine aspiration, there are plug-ins and convenience methods available to frameworks that just make life easier. In particular, the availability of "beaner" methods. I'm currently using Model-Glue, so I'll use the makeEventBean() method as an example. MakeEventBean() is really useful for populating a bean with any setter methods that match the keys in the Model-Glue event. While convenient, I think it provides a slippery slope for business logic to slide into controller methods.

read more...

Still Running ColdFusion 8 Beta? Here's How To Find Out...

2008 January 18
No Comments
When the Coldfusion 8 Beta came out, I jumped at the chance to install. The beta release had a few issues, but nothing that I ran into until I tested out multi-threading for MachII 1.6. After a bit of back and forth with the MachII team, I finally realized that I was running the beta and not the final release. If you are running into issues with any ColdFusion OSS and you think it's time to open a ticket. When you're getting the house-cleaning done (listing your OS and the version for CF, Java, etc.), double check the ColdFusion Version. ColdFusion 8 Beta: 8,0,0,171647 ColdFusion 8 Final: 8,0,0,176276 Another clue that will tip you off for running the beta is if ColdFusion will not re-start after installing either hotfix 1 or 2 for CF8.

One Giant Leap Backward - Consistency in (HTML) Email Marketing

2008 January 04
No Comments
Depending on the complexity of the design, bashing out a pixel perfect cross-browser website is somewhat less frustrating nowadays. Not so for an HTML Email campaign. Aside from the fact that image-suppression is the norm, if you want consistency across most major clients (especially HTML clients like Gmail, Yahoo!, Hotmail), you're gonna need a time machine. While doing a bit of research on whether it's still relevant to offer users a choice between plain text and html e-mail, I stumbled upon this excellent piece . The discovery was apropos, because I spent the better part of the morning cursing Gmail and it's draconian re-rendering policy for html e-mail. When I read the following bit, I was laughing so hard the crew here was wondering if I'd lost it completely.
I was talking to an email HTML developer the other day, and kept having to make this point: regress your code. It's possible to have a single template render properly in various webmail browsers. You just have to pretend it's 1995.
That gem sums up my feelings completely. Here's hoping the Email Standards Project makes life easier sometime in the future. Since I didn't find a definitive answer on the plain text vs. html e-mail subject, anyone out there with large e-mail marketing campaigns still provide both? If so, what is the primary reason for that decision?

Working with Transfer ORM: An Event Model Example

2008 January 03
No Comments
If you use Transfer ORM you may have seen Mark Mandel's Advanced Transfer ORM Techniques presentation. One of the most interesting portions of this presentation (for me) was his coverage of the Transfer Event Model. Mark demonstrates how to setup a service (in this case a CryptService) as a Transfer Event listener. There are several events that objects can register to as listeners. One event type is "AfterNew", which is fired when a new transfer object is created. In the presentation Mark demonstrates how to leverage the Event Model with an AfterNew event and a decorated transfer object to encrypt/decrypt a user password. I wanted to use this concept for a new project, but rather than copying code verbatim from the presentation, I decided to try something a little different.

read more...

Attending cf.Objective() 2008!

2008 January 02
No Comments
Okay, so it's not as sexy as announcing that I'm presenting at cf.Objective(), but I'm just as excited! This will be my first conference and I'm really looking forward to meeting a lot of folks whom I have corresponded with over the past year+. Deciding which sessions to attend will be the hard part, there are so many topics I'm interested in. If you're attending and see a wide eyed fella wandering the halls aimlessly, stop me and say, "hi". Here's my mug on ColdFusion Community.

Nominated for a CFeMmy in Best Newcomer Category!

2007 December 20
No Comments
Someone must like what I've been baking up over here at Fancy Bread. Being nominated for a CFeMmy is an honour. If you haven't cast your vote yet, vote now. Deadline is noon EST, Friday, Dec. 21. And a big thanks to whomever nominated me! :)

Blending Blueprint CSS and jQuery for Layout and Behaviour

2007 December 12
No Comments
tags: CSS · jQuery
I've always written my own CSS from scratch. Over time, I've learned the ins and outs of browser incompatibilities, but at a cost (a fraction of my sanity). For a new project I'm playing with, I decided to try out Blueprint CSS and jQuery. Blueprint took a bit of time to embrace, but when it clicked, I was able to get productive and start visualizing my layout in the language of Blueprint. Problem was, where I previously used very descriptive identifiers to provide a more semantic organization of my layout div elements, I was suddenly chaining multiple classes to achieve the same layout.

read more...

Unit Testing DAOs with CFCUnit setUp() and tearDown()

2007 November 20
No Comments
I recently starting Unit Testing with CFCUnit. Unit testing is not a new topic in the CF community, but it is new to me. I've found that there are a lot of aspects related to unit testing (like Mock objects and stubs) that you need learn about. As I continue to read and research unit testing techniques, I've seen items that go back years. One topic that I could not find a lot of information on is how to test DAOs and the SQL code in <cfquery/> tags. After rephrasing my search terms a few times, I found a great post by Robert Blackburn that also lead me to a suggestion by Paul Kenney on the old CFCDev list to wrap the test within <cftransaction/>. I liked the idea of using <cftransaction/>, but decided to try something a little different.

read more...

Making JSLint AIR: Part 2 - Porting to AIR Beta 2

2007 October 26
No Comments
Now that JSLint AIR Edition is available as an AIR Beta 2 application, I want to share my experiences working with AIR for HTML/Javascript and the process of migrating the app from Beta 1 to Beta 2. In terms of the functionality provided by AIR, my Beta 1 version allowed you to open and save a file, exit the application and open a default browser window to the original JSLint documentation page. I had originally hoped to include drag and drop of .js files and the ability to open Javascript files from a file explorer context menu, but the rush was on to submit JSLint AIR to the developer derby, so I was forced to trim features. The latter feature is available in the Beta 2 version and the former is still on the roadmap. A New Security Model With the release of Adobe AIR Beta 2, there is a new security model for HTML/Javascsript applications. This model was introduced to mitigate potential abuse of the AIR API by malicious persons by disabling eval() among other changes. Rather than rehash some specifics, I suggest reading the HTML Security FAQ. The end result of the of the new security model is that it is now incumbent upon HTML/Javascript developers to expose only the specific AIR functionality required in their application by creating a bridge between the application sandbox (where AIR API resides) and the child sandbox (where the UI resides). Here is a brief description of how the security model works and how methods are exposed between them. In the Beta1 version of JSLint, I had a single HTML file with script tags importing the Ext JS library, my application mediator and components, the JSLint engine, and AIRAliases.js. In the Beta 2 version, I now have two html files, one named root.html and another named ui.html. The names of the files are irrelevant, what matters is that AIRAliases.js is now referenced in root.html and ui.html is embedded as an iframe. <html>
<head>
<title>JSLint AIR Edition</title>
<script type="text/javascript" src="AIRAliases.js"></script>
</head>

<body style="margin: 0px; padding: 0px;">
<iframe id="UI"
src="ui.html"
sandboxRoot="http://www.fancybread.com/"
documentRoot="app-resource:/"
frameborder="0"
width="100%"
height="100%"
style="margin: 0px; padding: 0px;">

</iframe>
</body>
</html>
This setup allows you to use libraries like Ext JS or jQuery that make use of eval() to run within the child sandbox (ui.html), while keeping the AIR API within the parent sandbox (root.html). Exposing functionality between the two is a matter of creating object literals within each sandbox called 'parentSandboxBridge' and 'childSandboxBridge'. Here's a snippet from my root.html script. There are different ways to implement the parent and child sandbox bridges, I prefer to set the parentSandboxBridge for the UI iframe within window.onload() event in root.html (example below).
window.onload = function ()
{
     var UI = document.getElementById('UI').contentWindow;
      
     UI.parentSandboxBridge = {
         // provide method to exit via shell
         exitApplication : function ()
         {
             air.Shell.shell.exit();
         },
         // open the jslint docs window
         openDocsWindow : function ()
         {
             air.navigateToURL(new air.URLRequest("http://www.jslint.com/lint.html"));
         }
     };
          
     // initialize the app within the child sandbox
     UI.childSandboxBridge.initApp();
}
And in ui.html, I have the following window.onload() event.
window.onload = function() {
  // expose the init function for the application sandbox
  childSandboxBridge = {
      setSource : function (str) {   
        JSLINT_AIR.app.setSource(str);
      },
      setFileName : function (str) {   
        JSLINT_AIR.app.setFileName(str);
      },
      broadcast : function (event) {
        JSLINT_AIR.app.broadcastEvent(event);
      },
      initApp : function () {
        JSLINT_AIR.app.init();
      }
   }
}
Prior to sandboxing the application, I initialized it within the Ext.onReady(), but under the new security model, the window.onload event in ui.html runs prior to that in root.html, so in order to ensure that the AIR API is exposed prior to initializing the applciation, I provide an initApp() method in the childSandboxBridge that is called within the window.onload event in root.html. To exit the application in the beta 1 version, I called the following method in my menu component.
function exitApp()
{
    air.Shell.shell.exit();
}
As described above, direct calls to 'air' are not possible in the child sandbox under the new security model, so I moved air.Shell.shell.exit() to the application sandbox and exposed it as 'exitApllication'. Now in my menu component, I call parentSandboxBridge.exitApllication() when a user selects the 'File|Exit' menu. General Impressions HTML/Javascript developers will clearly have to consider the extra time required to develop under new security model and plan their applications carefully. Fortunately, I put a lot of effort up front to organize my code and encapsulate my AIR API calls, so that exposing them as the 'parentSandoxBridge' required a minimum amount of refactoring (especially given that my app had a limited amount of AIR functionality built in). Since I plan to maintain JSLint AIR as an HTML/Javascript app, I will likely redesign some aspects in a future release as I feel the current iteration is less cohesive than the last.