I wanted to share this "gotcha" that I spent an hour on the other night: I was using <cfajaxproxy> to call a CFC that I had created as a proxy to another (the proxy CFC had methods which were accessible remotely, while the other CFC, stored in session, had public methods that woudn't have been accessible via AJAX. The final CFC accessed Java functionality. The proxy was really simple; it just took the exact same arguments as did the other CFC, and passed them on to the appropriate method call:
<cffunction name="setIndicator" access="remote" output="Yes" returntype="boolean">
<cfargument name="cat" required="Yes" type="string">
<cfargument name="indicator" required="Yes" type="boolean">
<cfreturn SESSION.user.finalcfc.setIndicator(ARGUMENTS.cat, ARGUMENTS.indicator) />
</cffunction>
But every time I tried to call the proxy via AJAX, I received an error...
The setIndicator method was not found.
Either there are no methods with the specified method name and argument types, or the setIndicator method is overloaded with argument types that ColdFusion cannot decipher reliably. ColdFusion found 0 methods that matched the provided arguments. If this is a Java object and you verified that the method exists, you may need to use the javacast function to reduce ambiguity.
At first, I could only see this error by looking at the response in the Firebug pane of my browser. So to read the error more clearly, I typed the URL to the proxy into another browser tab:
http://example.com/cfcs/proxy.cfc?method=setIndicator
&cat=draft&indicator=1
And guess what happened? No error. It worked perfectly. So, I took a closer look at the URL that was being called by the AJAX proxy, and it turned out to be a little different than the one that I had typed in by hand. Besides containing a few additional URL parameters, the AJAX call had embedded the arguments ("cat" and "indicator") in JSON format, like so:
http://example.com/cfcs/proxy.cfc?method=setIndicator
&argumentCollection=%7B%22cat%22%3A%22drafts%22%C2%22indicator%22%3A1%7D
&returnFormat=json&_cf_nodebug=true&_cf_nocache=true
&_cf_clientid=3DD4269A8EDF57E48E856FA005DC90CE&_cf_rc=0
It certainly looked like the same data to me, and so I altered the proxy.cfc so that it would dump out all of the arguments that were passed to it. That test revealed that the values passed in JSON format via AJAX perfectly matched the values passed in by my hand-written (non-JSON). So why on earth would one URL blow an error and the other not?
OK, to be frank, I still don't know the answer to that question. But I do know how to resolve the problem. After playing around with adding the JavaCast function to the function calls within my proxy.cfc, I found that the issue lay with how Java accepts boolean values. For some reason, when you pass in a 1 or 0 via as a straight URL value (not in a JSON object format), Java will accept it as a boolean value. But when you pass a 1 or 0 in JSON format, Java will not interpret it as a boolean. Therefore you need to wrap your boolean arguments with JavaCast('boolean', [argument value]) if you're going to pass 1 or 0 via AJAX (or, change your JavaScript to pass 'true' and 'false').
So my final proxy.cfc needed just a simple change, and became:
<cffunction name="setIndicator" access="remote" output="Yes" returntype="boolean">
<cfargument name="cat" required="Yes" type="string">
<cfargument name="indicator" required="Yes" type="boolean">
<cfreturn SESSION.user.imap.setIndicator(ARGUMENTS.cat, JavaCast('boolean', ARGUMENTS.indicator)) />
</cffunction>

Comments (2)
March 7, 2008
17:01PM | #
When you start to play around with Java, you *quickly* realize that you can never let ColdFusion try to guess the data conversion as it tends to do this in a seemingly random way. I find that it is a best practice to use JavaCast() for every single ColdFusion-Java method call.
March 7, 2008
17:08PM | #
Thanks for the good advice, Ben. Does your experience give you any insight as to why Java would treat a 1 coming from JSON differently than a 1 coming from a URL parameter? Could the value coming from JSON somehow be more "strongly typed"? I'm really curious about it.