This is an odd issue that I’ve run into with ColdFusion 8 and the CFAJAXProxy.
Here’s my calling page which runs the same method, once within the page execution and once as the onclick event handler for the link implemented via CFAJAXProxy:
[cf]
<html><head>
<script type="text/javascript">
function doStuff() {
//setup our proxy object
var testJsObj = new proxyTest();
//plain return mode
testJsObj.setReturnFormat(‘plain’);
// use the setter of the argument to set a value
setReturn = testJsObj.setPassedVal(‘Test’);
alert(setReturn);
//call the method which *should* return
myJsVal = testJsObj.doStuff();
//attempt to alert the value = which will fail
alert(myJsVal);
//return false to kill the link event bubble
return false;
}
</script>
</head><body>
<!— set up our ajaxproxy obj – 9/25/2009 0:16:37 PM – RCWD —>
<cfajaxproxy cfc="proxyTest" jsclassname="proxyTest" />
<!— Dummy link to call the CFC via CFAJAXProxy – 9/25/2009 0:15:15 PM – RCWD —>
<a href="#" onclick="doStuff()"> Click Me</a>
<!— Execution run instatiation of the method – 9/25/2009 0:15:43 PM – RCWD —>
<cfset testObj = createObject(‘component’,'proxyTest’).init() />
<!— Invoke the setter – 9/25/2009 0:16:00 PM – RCWD —>
<cfset testObj.setPassedVal(‘Test’) />
<!— Invoke the stub function – 9/25/2009 0:16:05 PM – RCWD —>
<cfset myVal = testObj.doStuff() />
<br />
<!— output the return value of the stub function – 9/25/2009 0:16:18 PM – RCWD —>
<cfoutput>#myVal#</cfoutput>
</body>
</html>
[/cf]
And this is the CFC being called:
[cf]
<cfcomponent output="true">
<cfproperty name="passedVal" hint="passedVal" type="string" />
<cffunction name="init" access="remote" output="true" returntype="proxyTest">
<!— Constructor – 9/25/2009 0:07:26 PM – RCWD —>
<cfreturn this />
</cffunction>
<cffunction name="getPassedVal" access="remote" output="false" returntype="string">
<!— passedVal Getter – 9/25/2009 0:07:35 PM – RCWD —>
<cfreturn variables.passedVal>
</cffunction>
<cffunction name="setPassedVal" access="remote" output="false" returntype="string">
<!— passedVal Setter
Obv this would normally return void but for the purposes of validation we’ll return a string – 9/25/2009 0:08:14 PM – RCWD —>
<cfargument name="argPassedVal" type="string" required="true">
<!— set our variable – 9/25/2009 0:07:50 PM – RCWD —>
<cfset variables.passedVal=arguments.argPassedVal/>
<!— Test to see if the variable has been set properly – 9/25/2009 0:06:42 PM – RCWD —>
<cfif arguments.argPassedVal eq getPassedVal()>
<cfreturn "Set" />
<cfelse>
<cfreturn "Not Set" />
</cfif>
</cffunction>
<cffunction name="doStuff" hint="Does stuff" access="remote" output="true" returnFormat="plain" returntype="any">
<!— Stub function that simply gets the value of our variable and returns it – 9/25/2009 0:07:03 PM – RCWD —>
<cfreturn this.getPassedVal() />
</cffunction>
</cfcomponent>
[/cf]
For testing purposes both are in the same directory on the server.
As you can see if you run the code, the normally executed invoke of the setter works properly and the method calls are all fine. Once you drop it into CFAJAXProxy I get an “uncaught exception: Error: Element PASSEDVAL is undefined in VARIABLES.”
(Note: The full error can be found on this Pastebin)
I’ll admit this is only the third time I’ve used CFAJAXProxy in anger but this behaviour is puzzling to say the least.
Any thoughts?
Update: I’ve fixed the syntax of the JS Object creation as per Andrew Scott’s comment but it’s still throwing the undefined error.
var testJsObj = new proxyTest;
should be
var testJsObj = new proxyTest();
Andrew, thanks but I don’t think that was it. The object was working ok as it can return the setter return value so the obj instantiation is ok.
I copied and pasted your code into an app here. Ran it in firefox with firebug installed and found that you have an error in your ColdFusion code.
Element PASSEDVAL is undefined in VARIABLES.
The reason for the error is that the object is reinstantiated for every request back to the server, Ajax works this way and is why it works in normal code.
The only way around this is to turn the CFC into a singleton and persist it into the application scope.
Does that make sense?
Hi Andrew, that makes perfect sense. I’d hoped that somewhere in the ColdFusion OO JS layer there was some very clever code that maintained the object based on session (or similar) but can appreciate why the object is instantiated for each call.
The singleton approach could prove very useful in certain projects but in this instance the whole reason the issue came to light is due to a problem with application scoping caused by the architecture of the application.