Debugging With CFLOG

Debugging in ColdFusion has always meant, for me, liberal use of the cfdump and cfabort tags. However, this tried and true technique does not always work.

I came across one such situation the other day while working with a Java applet for viewing Crystal Reports. When I attempted to view a report, I received a blank viewer window. The problem was, my report was not loading. Just looking at the code didn't help, I needed to step through the code and see where the problem lay.

One of the applet parameters is the path to the template that interacts with a COM object that makes up the backend reporting engine. Without going into too much detail, the parameter looks something like:

view plain print about
1<param name="ReportName" value="reportServer.cfm" />

Since the template is called by the applet, the output from a cfdump tag will not appear on the screen.

Enter cflog. I placed a cflog tag in various places throughout the reportServer.cfm template to try to figure out where the error that caused the report not to load was thrown. I started with log messages to trace the flow of the request through the various code methods. For example:

view plain print about
1<cflog file="reportviewer" text="Entering parseQueryString()">

helped me figure out if the query string was being parsed to retrieve configuration data. I also placed one at the end of the parseQueryString() method.

I ran the page, then checked the ColdFusion log files (%cfusion%\logs) to see if a log file named reportviewer.log existed and what sort of information it contained. Sure enough, the program was entering, but not exiting parseQueryString(). I had incorrectly initialized several variables.

The above method works great for simple values. However, one of the most useful aspects of cfdump is how easy it is to view complex values. cflog, however, cannot simply write an array to a log file. Instead, the complex value needs to be translated into a string. WDDX helps with that task:

view plain print about
1<!--- FAILS: cflog cannot directly write complex values to a log --->
2<cfset myArray = arrayNew(1)>
4<cflog file="reportserver" text="#myArray#>
6<!--- SUCCESS: Serialize the array, then write the WDDX packet to a log --->
7<cfset myArray = arrayNew(1)>

9<cfwddx action="
cfml2wddx" input="#myArray#" output="wddxPacket">
10<cflog file="
reportserver" text="#wddxPacket#">

Unless you are very good a reading XML (and who isn't) you will need to take the WDDX string out of the log and manipulate it to view its contents. Hint: cfdump :)

It's A Mac

I do a lot of my personal development work on a notebook computer. Except for some graphic and publication design work a few jobs ago, I have always used a PC running Windows. However, I have (mostly) fond memories of using OS 9 and OS X, so I decided to take the plunge and replace my aging Sony Vaio, running Windows XP Pro, with a MacBook Pro running Leopard, OS 10.5.

The experience in the Apple Store in Tysons Corner was certainly not what I expected. Since it was midday on a Saturday, it was rather busy. Regardless, I was approached at least three times while I was checking out the Macbooks. My questions were answered, I checked out right at the display table, and walked out with a 2.4GHz MacBook Pro. Very relaxed, very easy.

Adding the notebook to my wireless network was a snap. Soon I was downloading and installing everything I need to develop on the Mac: Firefox, Eclipse, CFEclipse, etc. I hit a major snag with ColdFusion 8, which does not come with a connector for Apache 2. After much Googling and several installation attempts, I finally had success following along with Matthew Wallace's video guide. Thanks, Matthew, for a great resource.

CFStack Part 2 - Push, Peek, Pop

Continuing from my last post about stacks, let's take a look at what needs to be done to add, look at, and remove an item from a stack.


Adding an item is done through the push method:

view plain print about
1<cffunction name="push" displayname="push" hint="I push an item to the top of the stack." access="public" output="false" returntype="Any">
2    <cfargument name="item" type="Any" required="true" />
3    <cfset var local = structNew() />
5    <cfset arrayPrepend(getStackData(), arguments.item) />
7    <cfreturn arguments.item />

A quick note. The getStackData method is a simple helper method that returns the current stack array.

Since the stack is an array, the built-in arrayPrepend function in ColdFusion makes it easy to add an item to the top of the stack. ArrayPrepend adds an element to the first position in an array, and pushes any other array elements down one position.


Now that the stack has data, we can use the peek method to take a look at the top item:

view plain print about
1<cffunction name="peek" displayname="peek" hint="I look at and return the object at the top of the stack." access="public" output="false" returntype="Any">
2    <cfset var local = structNew() />
3    <cfset local.result = "" />
4    <cfset local.stack = getStackData()>
6    <cfif NOT empty()>
7        <cfset local.result = local.stack[1] />
8    </cfif>
10    <cfreturn local.result />

This method uses another helper methods, empty(), which returns true if the stack array is empty.

Since we are looking for the first item on the stack, ColdFusion again makes it simple to grab the first element of the stack array. Remember, ColdFusion is not zero-based, so the array element at position 1 is the top element.


Removing the item at the top of the stack is accomplished with the pop method:

view plain print about
1<cffunction name="pop" displayname="pop" hint="I remove and return the object at the top of the stack." access="public" output="false" returntype="Any">
2    <cfset var local = structNew() />
3    <cfset local.result = peek() />
5    <cfset arrayDeleteAt(getStackData(), 1) />
7    <cfreturn local.result />

The pop method both removes the the top element from the stack array, done here with the ColdFusion arrayDeleteAt function, and returns that element to the calling code.

The push, peek, and pop methods are the most often used methods when working with a stack. Since a stack, by definition, only exposes its top item, these three methods add, examine, and remove this element.

A Stack of CF - What is a Stack?

I was rereading Java for ColdFusion Developers (by Eben Hewitt) the other day and came across the concept of a stack. So, in the spirit of "well, why not do it in CF too," I decided to create a small utility CFC that contains the basic functionality found in the java.util.Stack class.

The Wikipedia article defines a stack as "a temporary abstract data type and data structure based on the principle of Last In First Out (LIFO)." One real-world example of a stack is a roll of coins. Closed on one end, you can only add or subtract coins from the top of the stack.

After looking at the Sun Java API for the Stack class, I decided on the following basic structure for my Stack CFC:

view plain print about
1<cfcomponent displayname="Stack" output="false">
3    <cfset instance = structNew() />
5    <!--- Constructor --->
6    <cffunction name="init" displayname="init" hint="I am the constructor. I create an empty stack." access="public" output="false" returntype="Stack">
7        <cfset instance.stack_data = arrayNew(1) />
8        <cfreturn this />
9    </cffunction>
11    <!--- Public Methods --->
12    <cffunction name="empty" displayname="empty" hint="I test to see if the stack is empty. I return true if the stack is empty." access="public" output="false" returntype="boolean">
13        ...
14    </cffunction>
16    <cffunction name="peek" displayname="peek" hint="I look at and return the object at the top of the stack." access="public" output="false" returntype="Any">
17        ...
18    </cffunction>
20    <cffunction name="pop" displayname="pop" hint="I remove and return the object at the top of the stack." access="public" output="false" returntype="Any">
21        ...
22    </cffunction>
24    <cffunction name="push" displayname="push" hint="I push an item to the top of the stack." access="public" output="false" returntype="Any">
25        <cfargument name="item" type="Any" required="true" />
26        ...
27    </cffunction>
29    <cffunction name="search" displayname="search" hint="I return the stack position for an object." access="public" output="false" returntype="numeric">
30        <cfargument name="item" type="Any" required="true" />
31        ...
32    </cffunction>
34    <cffunction name="getElementCount" displayname="getElementCount" hint="I return the number of elements in the stack." access="public" output="false" returntype="numeric">
35        ...
36    </cffunction>
38    <!--- Private Methods --->
39    <cffunction name="getStackData" displayname="getStackName" hint="I return the stack array." access="private" output="false" returntype="array">
40        ...
41    </cffunction>

An array makes the most sense to me for storing the contents of a stack, so the init method creates an empty array instance variable to initialize the stack. I prefer to create a structure called "instance" within my CFCs to handle instance data. Fully scoped, the stucture's name is variables.instance.

I'll walk through the remainder of the CFC in future posts.

CFDirectory and IP Addresses

While working with cfdirectory today, a colleague asked me why the list action returned no results, even though there were thousands of files in the directory being browsed. She was reading a directory on a file server inside the network.

After first going down the permissions path, we found out that the culprit was the path being used in the name attribute of the cfdirectory tag. She was referencing the server with its IP address. Changing the path to use the server name returned the expected resultset.

A little research later revealed that you can use IP addresses if you elevate the permissions for the ColdFusion service.

It is always good to learn something new about ColdFusion.

CFUnited - Ajax and Frameworks

Frameworks make life easier when coding an application. They provide structure and hide many of the tedious, repetitive details of setting up an application. I have used Fusebox 3 heavily in the past, and played with Fusebox 4.1 and 5. I am currently working on rewriting an application I wrote using a homegrown framework in Model-Glue.

Joe Rinehart's talk on Ajax and ColdFusion frameworks, appropriately titled "Ajax Development with ColdFusion Frameworks," provided an introduction to using Ajax frameworks with ColdFusion frameworks, specifically Prototype and with Model-Glue. Prototype is a javascript library that makes Ajax calls easier to write, while is all about effects, DOM manipulation, and other "Web 2.0" user interface magic.

Joe's presentation walked through Ajaxifying a basic to-do list application written with the Model-Glue framework. Adding an Ajaxed delete function involved six lines of code within a javascript function - one line for the delete Ajax call and one line to fade out the deleted task from the to-do list. Too easy.

CFUnited - ColdSpring

Rob Gonda's talk about object factories, Embracing Factories, really convinced me that ColdSpring is worth more than a casual look.

CFUnited - OO Architecture

Matt Woodward's talk on object-oriented architecture, OO Architecture Back to Front, covered the basics and reasons you should separate business logic from your controller and UI layers. Working "back to front" helps keep your code scalable and reusable. Using a simple Mach-ii app in his examples, he provided a clear overview of a business, data, service, controller, and presentation layer.

The most important concept, I think, is that the UI should never talk to the database - CF templates should not have embedded queries in them. I can remember doing exactly that when first learning CF. Aside from the crazy whitespace at the top of the source, I have fond memories of the time I spent updating hundreds of templates just to implement a simple database change.

Using a service layer to handle requests between the controller and the data layer has helped me keep the number of queries I write under control, and is much easier to maintain.

CFUnited - OO in CF

Object-oriented programming is fairly new to ColdFusion development. The addition of CFCs in CFMX really make it happen. Nick Tunney's CFUnited talk on object-oriented programming and CF started with a quick introduction to OO, then moved to how it can be applied to CF.

His example of putting all of your CRUD methods inside the entity CFC is different from how I normally work with data access methods, but makes sense. I normally write an entity CFC, a data persistence CFC, and often a gateway CFC. Perhaps this is an example of "over engineering" Nick mentioned. After all, my applications to this point do not go outside CF.

Another tip that stuck with me is to have a commit() method for persisting the object's data. Instead of calling individual CRUD methods, I can call the commit() method, which then determines if an insert or update needs to be run. Cool idea.

Previous Entries