Skip to main content
Ben Nadel at the jQuery Conference 2010 (Boston, MA) with: Jeremy Kahn
Ben Nadel at the jQuery Conference 2010 (Boston, MA) with: Jeremy Kahn ( @jeremyckahn )

How To Handle NULL Values In Object Oriented Programming In ColdFusion

By on
Tags:

As you may or may not know, I am HUGELY AGAINST allowing NULL values in a database unless absolutely necessary (and yes, there are many valid cases where NULL is essential). Now, as I get more into object oriented programming (OOP) in ColdFusion, the idea of a NULL value becomes even more complicated. This has to do with how ColdFusion handles NULL values. Let's explore a little scenario in which we have a Property.cfc ColdFusion component that encapsulates one hidden variable. The Property.cfc has a Get() method and Set() method which get the private variable value and set it respectively.

This calling code on such an object, could looks like this:

<!--- Create the component. --->
<cfset objProperty = CreateObject( "component", "Property" ) />

<!---
	Set the property to be a NULL value. We are explicitly
	setting a NULL value here, but this could just as easily
	have been a NULL value coming out of a query.
--->
<cfset objProperty.Set(
	JavaCast( "null", 0 )
	) />

<!--- Get the value back out of the property. --->
<cfset strValue = objProperty.Get() />

Notice that I am explicitly setting a NULL value into the Set() method using JavaCast(). In my comments, I state that this might be value coming from the database. Now, in ColdFusion, NULL values come across as empty strings, but there are plenty of ways to get the actual NULL value from the ColdFusion query object. And, remember, this value doesn't have to come from a query - this could come from anywhere. The point is, we are modelling something that can be NULL.

Let's take a look at the Property.cfc ColdFusion component:

<cfcomponent>

	<!--- Store private varaible. --->
	<cfset VARIABLES.Value = "" />


	<cffunction
		name="Get"
		access="public"
		returntype="any"
		output="false"
		hint="Gets the property value.">

		<cfreturn VARIABLES.Value />
	</cffunction>


	<cffunction
		name="Set"
		access="public"
		returntype="void"
		output="false"
		hint="Sets the property value.">

		<!--- Define arguments. --->
		<cfargument
			name="Value"
			type="any"
			required="false"
			/>

		<cfset VARIABLES.Value = ARGUMENTS.Value />
		<cfreturn />
	</cffunction>

</cfcomponent>

Pretty basic. Now, if we run our index code with this cfc, we get the following ColdFusion error:

Element VALUE is undefined in ARGUMENTS.

The problem here is that the JavaCast() null destroys the variable into which it was placed. Therefore, the Value key is no longer available in the ARGUMENTS struct when a NULL value gets passed through.

So what can we do about this? Well, we can put logic into the Set() method that checks for an existing Value key and then sets the private property depending on the existence:

<cfcomponent>

	<!--- Store private varaible. --->
	<cfset VARIABLES.Value = "" />


	<cffunction
		name="Get"
		access="public"
		returntype="any"
		output="false"
		hint="Gets the property value.">

		<cfreturn VARIABLES.Value />
	</cffunction>


	<cffunction
		name="Set"
		access="public"
		returntype="void"
		output="false"
		hint="Sets the property value.">

		<!--- Define arguments. --->
		<cfargument
			name="Value"
			type="any"
			required="false"
			/>


		<!---
			Check to see if the value exists. Since it can be
			NULL, then the value might have been erased.
		--->
		<cfif NOT StructKeyExists( ARGUMENTS, "Value" )>

			<!--- Store NULL into property. --->
			<cfset VARIABLES.Value = JavaCast( "null", 0 ) />

		<cfelse>

			<!--- Store passed in value. --->
			<cfset VARIABLES.Value = ARGUMENTS.Value />

		</cfif>

		<cfreturn />
	</cffunction>

</cfcomponent>

A little bit wordy, but easy enough to handle. Now, if we re-run our index code, we get the following ColdFusion error:

Element VALUE is undefined in VARIABLES.

We fixed our Set() method, so the NULL handling issues moved right up to the Get() method. When we stored a NULL value into VARIABLES.Value, it destroyed the Value key. Then, when the internals of the Get() method try to access VARIABLES.Value, we get an error because that key doesn't exist.

So what we can about this? Same as before, we can put more logic in to handle the special NULL scenario:

<cfcomponent>

	<!--- Store private varaible. --->
	<cfset VARIABLES.Value = "" />


	<cffunction
		name="Get"
		access="public"
		returntype="any"
		output="false"
		hint="Gets the property value.">

		<!---
			Check to see if the value exists. Since it can be
			NULL, then the value might have been erased.
		--->
		<cfif NOT StructKeyExists( VARIABLES, "Value" )>

			<!--- Return a NULL value. --->
			<cfreturn JavaCast( "null", 0 ) />

		<cfelse>

			<!--- Return stored value. --->
			<cfreturn VARIABLES.Value />

		</cfif>
	</cffunction>


	<cffunction
		name="Set"
		access="public"
		returntype="void"
		output="false"
		hint="Sets the property value.">

		<!--- Define arguments. --->
		<cfargument
			name="Value"
			type="any"
			required="false"
			/>


		<!---
			Check to see if the value exists. Since it can be
			NULL, then the value might have been erased.
		--->
		<cfif NOT StructKeyExists( ARGUMENTS, "Value" )>

			<!--- Store NULL into property. --->
			<cfset VARIABLES.Value = JavaCast( "null", 0 ) />

		<cfelse>

			<!--- Store passed in value. --->
			<cfset VARIABLES.Value = ARGUMENTS.Value />

		</cfif>

		<cfreturn />
	</cffunction>

</cfcomponent>

Now, when we run our index code, we get no errors. Of course, our index code is very simple. If we start passing around NULL values, our calling code has to become ultra aware of the implications of the possible returned NULL value. Not a horrible thing, but not an easy thing either.

I don't know about you, but this seems like way too much work to handle null values. As such, I am sure that I will stick with treating null values as empty strings rather than true Java null value. The downside to this is that the Set() method will not know whether I am passing in a NULL value or an explicitly empty string.

But this brings us back to the whole "NULL values in the database" argument. I am saying that the Set() method won't know the difference between a NULL value and an explicitly empty string value. I am sure there are those that would say that this is OK because when you go to INSERT the value into the database, you will just replace empty strings with NULL. But here, again, we are seeing that the use of NULL (most of the time) seems very much like an arbitrary business rule that has absolutely nothing to do with "proper" database structure, which is again, why NULLs in database make no sense most of the time.... but that is whole other topic / war that I don't want to get into again.

Want to use code from this post? Check out the license.

Reader Comments

6 Comments

Hey Ben,

There's a typo in the Get method for your final example. The StructKeyExists(ARGUMNTS,"Value") should read StructKeyExists(VARIABLES,"Value").

I've had a long time struggle with the use of null in CF. I was thinking that it might be wise to create a NULL data type, but when I thought about it some more, I realized that null is not a data type. It's a value, or, more specifically, the absence of a value.

15,640 Comments

@Paul,

Thanks for the typo catch. I have fixed in the demo code. However, the result is still the same, but by coincidence it was working :)

I don't mind having NULL as empty strings in the ColdFusion language. I am comfortable with it at this point. But, part of what this entails is the ambiguity of NULL and empty string. It is this ambiguity that forces us to put in arbitrary business logic as to what becomes translates to a NULL in the database.

I don't mind the business logic at all.... but let's call it just that - business practice, NOT "best practice" database design... but again, I am off topic.

33 Comments

Some databases (Oracle in older versions, not sure about more recent ones) will treat an empty string as a null value whether you like it or not. You tell it to insert '', it inserts null :)

122 Comments

This is actually a good argument for CF to NOT handle NULL built into the language. NULL is a very complicated concept even tho' it seems like the most obvious thing in the world. As you've seen, NULL sort of permiates everything once you let it in and it makes all of your code more complicated. The best thing to do is trap it at the boundary - the database - and not let it into your code. Transfer takes that approach, BTW.

15,640 Comments

@Sean,

I certainly don't mind the way that ColdFusion treats query NULLs as empty strings. It helps to keep the code nice and simple. Trapping this stuff at the ColdFusion-Database interaction level suits me just fine.

14 Comments

Not having null seems to be fair when you create ne data base (my DBA starts looking strange at me).
But what if you have some old data base and you just really have to handle it? Lets say - in mysql you may set date to 0000-00-00 but JDBC doesn't like it and will throw the error, select stamement will throw eeception. Of course you can treat zero date values as nulls by setting it on JDBC connection string but then when you select the data from table and your CFC expects date there CF will just crash as it expects date not empty string.
Of course you can handle that in your code but why write workarounds for something that has been already invented? I mean nulls, they are already there and they are really usefull in so many languages (Java, C#, AS3). One of base programming rules is: do not reinvent the wheel.
One of the reason why I started using CF was that indirect promise: write less code. But I don't think creating workarounds is writing less code.

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel