I recently ran into an interesting issue involving ColdFusion, Groovy, and Lists. I thought I'd share, but before I go any further, please remember that I am still very new to Groovy. There is a good chance that I may mis-label something. So with that said, what was the problem?
The mobile version of our application is a ColdFusion web site that speaks to Groovy via ColdSpring configured beans provided to our Model-Glue application. This makes it incredibly easy for me to reuse all the Groovy services we built for the AIR application. When I need to get some content, for example, I can do:
<cfset arguments.event.setValue("task", beans.contentService.getCurrentUserContentItem(javaCast("long",id)))>
The only clue that something non-CFML is going on here is with the javaCast. Outside of that I may as well be using a 100% pure CFML application.
In general, this just plain works. Period. However, last week I ran into an odd issue with one method that took a list as an argument. I knew that a list in Groovy was an ArrayList, and that should correspond to an array in ColdFusion. I created my object, let's call it ob, and then ran code similar to this:
<cfset beans.contentService.savePublications([ob])>
Note the use of [] to shortcut the need for me actually creating an array. If that is confusing, think of it as:
<cfset var arr = arrayNew(1)>
<cfset arr[1] = ob>
<cfset beans.contentService.savePublications(arr)>
That should work, right? Unfortunately it didn't. I kept getting errors saying that my data was some odd, generic Java object as opposed to the casted object it should have been within Groovy. I tried a few things - like for example, changing my closure from:
contentItems.each { contentToSave ->
more logic here....
}
To
contentItems.each { Content contentToSave ->
more logic here...
}
I thought maybe the extra hinting there would help. All that did was move the error up to the beginning of the closure. Eventually I gave up. I wrote a new method in Groovy that took a singular object and simply called the list version. While this worked, I wasn't terribly happy with it, and shared the problem with my coworker. Sean suggested that the problem may lie in the array ColdFusion was creating. He suggested using an ArrayList in CF and then passing that to Groovy. I modified my CFML like so:
<cfset var al = createObject("java", "java.util.ArrayList")>
<cfset pub = createObject("java", "com.broadchoice.bcp.model.beans.Publication")>
<cfset pub.content = bookmark>
<cfset pub.space = space>
<cfset al.add(pub)>
<cfset beans.contentService.savePublications(al)>
This worked like a charm. It was a bit more code to work with, but at least I could use the same service methods AIR was using for the same business logic.