Author Archive

More ColdFusion Testing Woes With Java Objects

November 24, 2008

Once again, my team is currently working on a Flex-based mapping application and I’m working on the back-end 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.

Another minor glitch I ran into while trying to test the ColdFusion method calls is with the SerializeJSON function built into ColdFusion 8. Because of the way BlazeDS works, in order to send objects from the Flex app back to ColdFusion we have to convert the object to a JSON string, send it, and then rebuild the object in ColdFusion from the JSON string. My teammate explains the process in his blog entry about the tech stack “Flex, ColdFusion, Java, and BlazeDS: with JSON?

The issue is simple. I want to test methods in the ColdFusion service we are writing in ColdFusion before I try to call them from the Flex app. It should be easier to debug that way. So I create the object and use SerializeJSON to make the string to pass to the ColdFusion service method. But I get errors saying such and such property is not found when the service method tries to rebuild the object.

Here’s a simple example that demonstrates the issue

//suppose you have a Java class like so
public class BoundingBox extends DataTransferObject
	implements Serializable
{
	static final long serialVersionUID = -4519523511904622352L;
	//Properties
	private LatLngOnly upperLeftLatLng;
	private LatLngOnly lowerRightLatLng;

	//methods
	public BoundingBox() {}

	public BoundingBox(LatLngOnly upperLeft, LatLngOnly lowerRight)
	{
		this.upperLeftLatLng = upperLeft;
		this.lowerRightLatLng = lowerRight;
	}	

	…
	//various methods including getters and setters
	…
}


<cfscript>
bnd = CreateObject("java", "com.lampo.mapping.vo.BoundingBox").init();
bnd.upperLeftLatLng =
       CreateObject("java", "com.lampo.mapping.vo.LatLngOnly").init(1.23,3.45);
bnd.lowerRightLatLng =
       CreateObject("java", "com.lampo.mapping.vo.LatLngOnly").init(5.67,7.89);
</cfscript>

<cfset str = SerializeJSON(bnd) />
<cfset objBnd =
       CreateObject("java","com.lampo.mapping.vo.BoundingBox").makeFromJSON(str) />

Annoyingly it turns out SerializeJSON is changing some of the property names so they no longer match. While it is true ColdFusion is not case-sensitive, Java is and so capitalizing the first character of the property names causes havoc. If the property is a reference to an object, errors are thrown. If the property is a primitive, the values are not set correctly.

The only solution I have is to alter the JSON string and hard code it as an argument for the method I’m testing. You can do this manually or with some regular expression magic.

<cfset str = SerializeJSON(bnd) />

<cfset pos = REFind('\"[A-Z]',str) />
<cfloop condition="pos NEQ 0">
     <cfset str = Replace(str,Mid(str,pos,2),'"#LCase(Mid(str,pos+1,1))#','all') />
     <cfset pos = REFind('\"[A-Z]',str) />
</cfloop>

<cfset objBnd =
       CreateObject("java","com.lampo.mapping.vo.BoundingBox").makeFromJSON(str) />

ColdFusion Testing Woes With Java Objects

October 7, 2008

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)#">
...

Good times with the cfhtmlhead tag

July 1, 2008

So for my first post, I’m going with something simple. For all you die hard ColdFusion gurus this is likely routine. But for anyone fairly new to ColdFusion, being aware of the cfhtmlhead tag is pretty handy. This is especially true if you are doing maintenance on a fairly substantial ColdFusion site … like me.

In most (probably very close to all) of the sections of DaveRamsey.com I help maintain, pages are generated by at least three ColdFusion templates. The header and footer templates create left and right navigation bars, a banner across the top, and a footer. An additional template(s) generate the main content for the page. The fun part is the html header is defined in the header template. The html body is opened in the header and closed in the footer. So if you want to do something ‘silly’ like write a JavaScript function to do something when the page loads or define an internal style sheet, you have something of a quandary. You don’t really want to change the header template because that would affect multiple pages, but the correct place for the JavaScript function and internal style sheet is the html header block.

Enter the cfhtmlhead tag. This tag simply takes a string for an argument and inserts the string into the page’s header block. So a solution to the problem described above would be to create a string with your JavaScriptcode and internal style sheet in it. The cfsavecontent tag is an easy way to do this. Then use the variable from the cfsavecontent in the cfhtmlhead tag to put it in the header block.

Something like so:

<cfoutput>
<cfsavecontent variable="strMyHeaderStuff">

<!--- page specific external style sheets --->
<link type="text/css" rel="stylesheet" href=" ... ">

<!--- page specific JavaScript libraries --->
<script type='text/javascript' language='javascript' src=' ... '></script>

<!--- internal style sheets --->
<style type="text/css">
...
</style>

<!--- custom JavaScipt functions for page --->
<script type="text/javascript" language="javascript">
...
</script>

</cfsavecontent>
</cfoutput>
<cfhtmlhead text="#strMyHeaderStuff#" />