My team is currently working on a Flex-based mapping application. I’m working on the backend using ColdFusion to grab the data from our SQL server, package it in a Java based data transfer object (DTO), and send it to the requesting Flex app. My teammate wrote a great blog entry about the tech stack entitled “Flex, ColdFusion, Java, and BlazeDS: with JSON?“.
One minor glitch showed up while trying to test the ColdFusion method calls. I wrote a simple ColdFusion template to call the methods in the ColdFusion service component. All I wanted to do was simply check the methods were working before I tried calling them from the Flex application. I called the function and used the <cfdump> tag to see what was in the object:
... <cfset obj = CreateObject("component", "components.lampo.mapping.service.MapToolWebServiceImpl") /> <cfset myobj = obj.getPostalCodePolygon(objUser, "37128") /> <cfdump var="#myobj#"> ...
Sadly all the <cfdump> tag showed was the names of the methods and properties of the object. I.e. it did not show the property values!
I did a little bit of research and was unable to locate an elegant solution. One possibility would be to simply add a method to each DTO that dumps the current state of the object. But we have over a dozen DTOs and I didn’t really want to pollute them with a debugging method. So I wrote a simple function to display the property values of any object:
<cffunction name="dumpJObj" output="false" returntype="struct" access="public"> <cfargument name="obj" type="any" required="yes" /> <cfargument name="depth" type="numeric" required="no" default="1" /> <cfset var stcRet = StructNew() /> <cfset var ary = StructKeyArray(obj) /> <cfloop index="i" from="1" to="#ArrayLen(ary)#"> <cfif IsDefined("obj.#ary[i]#")> <cfset value = Evaluate("obj.#ary[i]#") /> <cfif IsObject(value) AND depth GT 0> <cfset stcRet[ary[i]] = dumpJObj(value, depth - 1) /> <cfelseif IsObject(value)> <cfset stcRet[ary[i]] = "depth limit reached" /> <cfelse> <cfset stcRet[ary[i]] = Evaluate("obj.#ary[i]#") /> </cfif> <cfelse> <cfset stcRet[ary[i]] = "" /> </cfif> </cfloop> <cfreturn stcRet /> </cffunction>
I wrote the function specifically for the Java based DTOs we are passing. My first thought was to write it using Java reflection but I was able to write it completely in ColdFusion. So I guess it should work for ColdFusion objects as well.
My first version did not handle nested objects so in the next version I added in some recursion. This opened the possibility of an infinite loop if the class has itself as a nested object. I simply added a depth count to prevent this from happening. The depth defaults to 1 so the function will display the values of the top level object and the values of the objects it contains.
To make the function available where I needed it, I made it a part of the service class.
... <cfset obj = CreateObject("component", "components.lampo.mapping.service.MapToolWebServiceImpl") /> <cfset myobj = obj.getPostalCodePolygon(objUser, "37128") /> <cfdump var="#dumpJObj(myobj)#"> ...