Category Archives: ColdFusion

Managing ColdFusion code formatting


Hi all!

Since I use eclipse as ColdFusion editor, I have installed cfeclipse plug-in for ColdFusion.

I got two issues which makes me writing this blog post. One is slowing down editing of large file in cfeclipse and proper code formatting which improves readability.

Since cfelipse is now providing more features, eclipse is now taking more time and gives a slow response in typing. My project has some files with more that 1200 lines to 10k lines! So eclipse becomes time-consuming if we try to edit those files.

cfmodule and cfinclude are two options that can be used to reduce the file size by splitting main file by your functionality. But if you are still stick and you don’t want to use them, then you can use notepad++ for those files.

Most of the ColdFusion guys aware of Notepad++’s plugin for ColdFusion. It is simply great! But Notepadd++ and its plug-ins are not yet compared with eclipse with efclipse.

I reviewed my files and those files are also having leading spaces in code indentation. I think tab is the best way to have white spaces for code indentation, because if you can move cursor with your keyboard’s arrow keys faster than if we have spaces. It can also reduce number of characters of your file.

Recently cfeclipse’s update provides color formatting for variable scopes and color formatting within cfscript tag.
They are now also providing css, JavaScript and SQL code formatting as well as. But the main issue is we do not need newline for each ColdFusion tag. For example:

<input type="checkbox" name="mycheckbox" <cfif form.mycheckbox EQ 1>checked</cfif>/>

So auto code formatting with Ctrl+Shift+F will not give you nice and intelligent output.

So I decided to remove leading spaces with tab characters, without using auto code formatter.

To see the tab and space characters, just enable the “Show symbols” option.

notepad-optionWhat my logic is to find all leading spaces and replace 4 spaces with one tab character.

space-issueRun this code with providing your large file which has mix of spaces and tab in code indentation and see the output!

<cfif FileExists("#ExpandPath('/codeformatter_out.cfm')#")>
	<cffile action="delete" file="#ExpandPath('/codeformatter_out.cfm')#"/>
</cfif>
<cfloop file= "#ExpandPath('/codeformatter_source.cfm')#" index="theLine">
	<cfset ret = ReFind("^[ \t]+",theLine, 1, true) > <!--- RegEx to file leading spaces (tab+spaces) --->
	<cfif ret.len[1] GT 0>
		<!--- Find space count --->
		<cfset totalspace = len(rereplace(left(theLine,ret.len[1]),'[^ ]+',"","all"))>
		<!--- Find tab count --->
		<cfset totaltab = len(rereplace(left(theLine,ret.len[1]),'[^\t]+',"","all"))>
		<!--- 4 space should be converted to 1 tab --->
		<cfset totalnewtab = ceiling(totalspace / 4)>
		<!--- Calculate total tab to set --->
		<cfset finaltab = totaltab + totalnewtab>
		<!--- Create tab string to replace --->
		<cfset tabStr = "">
		<cfloop from="1" to="#finaltab#" index="i">
			<cfset tabStr = tabStr & "	">
		</cfloop>
		<!--- Replace leading spaces with our tab string --->
		<cfset theLine = ReReplace(theLine,"^[ \t]+",tabStr)>
		<!--- Remove trailing spaces --->
		<cfset theLine = ReReplace(theLine,"[ \t]+$",'')>
	</cfif>
     <cffile action="append" file="#ExpandPath('/codeformatter_out.cfm')#" output="#theLine#"/>
</cfloop>

Bug – count() function in ColdFusion query of query


Hi,

It has been a great time since I started working on ColdFusion. I must say that it is the easiest language in the world and yet it is a powerful and can be compared to any major programming language.

In last few days, I was using ColdBox and MockBox framework in our current project. I was using query of query which is very similar to SQL query, and we can use it over query object in ColdFusion.

Count() is a math function, but if we use it with select statement like count(*), it returns a number of rows fetched in select query. I used it query of query, and it was giving me the correct count if my select statement is returning some rows, but if it is not returning any row then ideally it should give 0 as output, but it gives [empty string].

I must need to come out of this issue, and I used a recordCount property of returning object, but you can also use CodlFusion function val() to convert the empty string to 0.

I can state that it is a bug base on the answer I get from the community. See my question on Stack Overflow Community. Still I will wait for some time if it is appropriate I’ll report it to ColdFusion bug tracking system.

Binding ColdFusion query to DataGrid in Flex


Hi,
In this post I’ll explain you how to bind ColdFusion data into Flex grid.
First, get ready with your cfc.
Your cfc function may look like:

<cffunction name="getCategoryList" access="remote" output="false" returntype="query">
<cfset var qCategoryList = "" />
	<cfquery name="qCategoryList" datasource="#application.dsn#" username="#application.dbuid#" password="#application.dbpwd#">
		SELECT
			categoryId,
			categoryName, 
			Description
		FROM	tblCategory
	</cfquery>
	<cfreturn qCategoryList />
</cffunction>

Please note here that we are returning a ColdFusion query.

Now I’m setting up mxml page to show the grid and fetch the ColdFusion data with RemoteObject.

<?xml version="1.0" encoding="utf-8"?>
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009" 
		 xmlns:s="library://ns.adobe.com/flex/spark" 
		 xmlns:mx="library://ns.adobe.com/flex/mx" 
		 creationComplete="categoryGateway.getAllForGrid();">
	<fx:Declarations>
		<s:RemoteObject destination="ColdFusion" source="cfc.categoryGateway" id="categoryGateway">
			<mx:method name="getAllForGrid" result="returnHandler(event)"
					   fault="mx.controls.Alert.show(event.fault.faultString)"/>
		</s:RemoteObject>
	</fx:Declarations>
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.rpc.events.ResultEvent;
			private function returnHandler(e:ResultEvent):void 
			{
				dgCategory.dataProvider = e.result;
			}
		]]>
	</fx:Script>
	<s:VGroup>
		<mx:DataGrid id="dgCategory">
			<mx:columns>
				<mx:DataGridColumn headerText="Category ID" dataField="categoryId"/>
				<mx:DataGridColumn headerText="Category Name" dataField="categoryName"/>
				<mx:DataGridColumn headerText="Description" dataField="Description"/>
			</mx:columns>
		</mx:DataGrid>
	</s:VGroup>
</s:Panel>

Easy enough?

Now let me point out important notes:

Remember one thing that ActionScript 2.0 and 3.0 are now case sensitive!

So if you write “description” instead of “Description” in DataGridColumn, it wouldn’t bind!

Also If your cfc method returns a ColdFusion structure, then you can get the value of structure elements by typing element name in capital later.

For e.g.

Your cfc method:

<CFSET var myStruct = structNew()>
<CFSET myStruct.query = qGetAllRecord>
<CFSET myStruct.RowCount = qGetAllRecord.recordCount>
<CFRETURN myStruct>

And your ActionScript code would be:

dgCategory.dataProvider = e.result.QUERY;
Alert.show(e.result.ROWCOUNT);

Automated tests using Ant integration of testing frameworks – cfunit, cfcunit and mxunit


If you have seen my previous post, Then you might want to automate testing. You can automate all three popular testing frameworks (cfunit, cfcunit and mxunit) with ant.

I’ve tested in eclipse 3.6 version, but it will also work in Adobe ColdFusion Builder.

Step 1: Create build.xml file and put it in your project.

Step 2: Copy and paste the following code in build.xml file.

For mxunit :

<?xml version="1.0"?>

<project name="mxunit_example" default="main" basedir=".">
	<taskdef name="mxUnit" classname="org.mxunit.ant.MXUnitAntTask" />

	<property name="domain" value="localhost"/>
	<property name="webroot" value="c:\inetpub\wwwroot"/>

	<target name="main">
		<mxUnit server="${domain}"
			defaultrunner="/mxunit/runner/HttpAntRunner.cfc"
			verbose="true">
			<!-- componentPath is not required, but it results in a much faster test run -->
			<directory remoteMethod="run" path="${webroot}\mxunit_example" packageName="mxunit_example" componentPath="mxunit_example" recurse="true" includes="*.cfc"/>
		</mxUnit>
	</target>
</project>

For cfunit :

<?xml version="1.0"?>
<project name="CFUnitExample" default="main" basedir=".">
	<taskdef name="CFUnit" classname="net.sourceforge.cfunit.ant.CFUnit"/>

	<property name="domain" value="http://localhost/"/>

	<target name="main">
		<CFUnit testcase="${domain}CFUnitExample/test/MyCFCTest.cfc"
			verbose="true"/>
	</target>
</project>

For cfcunit :

<?xml version="1.0"?>

<project name="CFCUnit_example" default="main" basedir=".">
	<taskdef name="CFCUnit" classname="org.cfcunit.ant.CFCUnitTask" />

	<property name="domain" value="localhost"/>

	<target name="main">
		<CFCUnit hostname="${domain}"
			testcase="CFCUnit_example.CalculatorTest"
			verbose="true"
			haltonfailure="true"
			haltonerror="true"
			showstacktrace="true"/>
	</target>
</project>

Explanation :

1) Project name should match with you project name.

2) Class name of the taskdef: You should have put class file on the correct location. For e.g. org.mxunit.ant.MXUnitAntTask

I have the MXUnitAntTask.class file in c:\inetpub\wwwroot\org\mxunit\ant\ location.

If you don’t have that class file then download the mxunit, extract it, extract the jar file located in mxunit\ant\lib\mxunit-ant.jar. You will find the class files in that.

Step 3: Configure Ant for you project

1) Right click on your project and go to properties -> Builders. Click on new button.

2) Select Ant builder. Press ok and it will open a dialog (edit configuration). Type a new build name.

3) Select your build.xml file for build file by browse the workspace.

4) Select class path tab and click on “add external jars” button. Link your mxunit-ant.jar file.

5) Select Build option tab and click the check box for “Specify working set of relevant resources”.

6) Click on “Specify Resources” button and select your project or you can also select single directory. Click on ok button.

If you find the difficulties in above steps then please visit fusion authority website.

Cheers! Now write test cases. Each time when you hit save, eclipse will automatically build you files and you will see outputs in console.

Useful links :

http://blog.stannard.net.au/2006/09/23/cfcunit-and-ant/

http://corfield.org/blog/post.cfm/Automated_Testing_with_cfcUnit

http://www.fusionauthority.com/techniques/4568-test-driven-development-with-coldfusion-part-ii.htm

Testing frameworks – cfunit, cfcunit and mxunit


Hi folks,

There are lots of testing frameworks available for Test-driven development (TDD).
Most of them are of xUnit family. Recently I had gone through three most popular
testing frameworks for ColdFusion.

CFUnit

CFCUnit

MXUnit

After using all three, I decided to post a comparison of them. Information may be inaccurate, Corrections are always acceptable.

Features CFUnit CFCUnit MXUnit
Based on XUnit & JUnit Yes Yes Yes
Eclipse Plug-in Removed in final cfeclipse release No Yes
Eclipse Ant integration using jar Yes Yes Yes
Supported Output format HTML HTML, XML HTML,XML,JUnit Report XML, CF query, CF Array
HTML UI No Yes Yes
Easy to see your data with cfoutput, cfdump, and debug(), also cfcatch to view data No No Yes
Directory runner No No Yes
Testing private methods Yes Yes
Support for setUp() and tearDown() functions Yes Yes Yes
beforeTests() and afterTests() functions No No Yes
Help and tutorials availability Few Few Enough
Assertion Only Standard Assertions More than 30 Built-in assertion There are around 10 built-in assertions

I personally like MXUnit for its eclipse
Plug-in and better UI.

Little bit about coldfusion sessions and general logout code


Hello friends,

I just started working on ColdFusion, and I have some interesting stuffs, that I’d like to share with you.

For any web application, we normally use session for maintaining client’s login/logout activity. Sessions are created on server side, and each session will have some unique id (in ColdFusion, we have ‘sessionid’). It will alive for some time duration, so if successfully logged-in user requests another page during that time, then server will skip checking of authentication.

We’ll see how session and cookie plays roll in that duration. Server sends two variables to client’s browser. Normally it creates cookies, but if cookies are disabled in client’s browser, then it uses URL. Those two variables are CFID and CFTOKEN.

Now let’s do something interesting. Create one login page and one welcome page. Welcome page will only viewable if user successfully logged in. Now you login from one browser and see the cookies. Pass the same cookies in URL for welcome page from another browser or computer (e.g. welcome.cfm?CFID=35473&CFTOKEN=12004479). You’ll be able see welcome page without asking for login!

So those two variables were just a reference to identify your browser! But two most important thing that you shouldn’t forget ever!
1. If you are using any website that provides login (e.g. facebook, gmail) for your activity, then don’t forget to systematically logout from the website.
2. If you are developer then you should handle the sessions carefully.

In ColdFusion there are four standard cookies that are used for session management. More information is here.
So when we code for logout page, we normally remove the user’s session from server. There is an easy way to do this, and it is to use structDelete(session) function.
But it’ll remove the mapping of client’s browser and server. So in future it will not allow you or another user to login from the same browser.

So you should remove all the session items. You can delete all session items except the standard items (CFID, CFToken, URLToken, SessionID).

Here is the code that you might want to have in your logout.cfm page:

<cfsilent>
 <cflock scope=”Session” type=”Readonly” timeout=”20?>
 <cfset variables.sessionItems = “#StructKeyList(Session)#”>
 </cflock>
 <cfloop index=”ListElement” list=”#variables.sessionItems#”>
 <cfif listFindNoCase(“CFID,CFToken,URLToken,SessionID”, “#ListElement#”) is 0 >
 <cflock scope=”Session” type=”Exclusive” timeout=”20?>
 <cfset StructDelete(Session, “#ListElement#”)>
 </cflock>
 </cfif>
 </cfloop>
 <cflocation url=”login.cfm” addtoken=”false”>
</cfsilent>