CFAJAXPROXY and Extended CFCs

This post is more than 2 years old.

Well here is something I didn't expect. Thanks go to a forum poster for bringing this to my attention. When you use cfajaxproxy to proxy a CFC, and that CFC extends another CFC, you don't get access to the remote methods defined in the base CFC. Consider the following example.

First, our base CFC:

<cfcomponent output="false">

<cffunction name="basemethod" access="remote" returnType="string" output="false"> <cfreturn "Hi from base!"> </cffunction>

</cfcomponent>

It has one simple method, basemethod(), defines as remote. Now for our main CFC, test.cfc:

<cfcomponent output="false" extends="base">

<cffunction name="double" access="remote" returnType="any" output="false"> <cfargument name="number" required="true" type="any"> <cfif isNumeric(arguments.number)> <cfreturn 2*arguments.number> <cfelse> <cfreturn 0> </cfif> </cffunction>

</cfcomponent>

This defines a simple method, double(), that will double a value. Ok, now for the front end code:

<cfajaxproxy cfc="test" jsclassname="myproxy"> <script> var myCFC = new myproxy()

function doDouble() { result = myCFC.double(5) console.log(result) }

function doBase() { result = myCFC.basemethod() console.log(result) } </script>

<button onclick="doDouble()">Run doDouble</button> <br/> <button onclick="doBase()">Run doBase</button>

I begin by creating the proxy with cfajaxproxy. Then I have a JavaScript block with tests for both methods, double and basemethod. Two buttons then let me run them. Running the code shows that double(5) runs just fine, but basemethod() gives:

Here's the weird thing though. I took the URL from the successful double call and modified it to run my base method:

http://localhost/test.cfc?method=basemethod&returnFormat=json&argumentCollection=more junk here...

Guess what? It worked fine. So whatever code parses the CFC to create the JavaScript proxy must not go into the base CFC. Seems odd to me as it should be trivial to walk down the CFC's functions and into the extended data.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Kevin M posted on 5/12/2009 at 7:15 AM

Can't add anything constructive as to why, but thanks for the post.

I'm using cfajaxproxy more lately especially with Coldbox. I could see this causing a lot of wasted time. Hopefully someone will have a solution or explanation

Comment 2 by Raymond Camden posted on 5/12/2009 at 7:17 AM

Well if the base CFC is under web root, you an always make another cfajaxproxy (you can have as many as you want on a page). And obviously, cfajaxproxy makes it easier to call CFC methods, but it is NOT the only way to call methods. As you can see, I had no problems calling the mehtod when I did it manually.

Comment 3 by Kevin M posted on 5/12/2009 at 7:26 AM

Yeah that is true. And granted Coldbox's proxy methods make it very easy to make it one call. but from a pure cfajaxproxy perspective who wants to have a bunch of individual objects or other gobbledy-gook. :)

Comment 4 by Azadi Saryev posted on 5/12/2009 at 9:31 AM

Thanks for blogging this, Ray!

The only other way i could come up with to work around this, is to define in test.cfc same function signatures as remote functions in base.cfc, and then call and rerurn SUPER.functionname(arguments)...

not perfect (still more code in test.cfc than there really should be when it extends base.cfc), but at least saves the need to re-define whole functions (just the arguments, if any, need to be defined), and your javascript functions can use one js proxy instead of several...

so, if you add:

<cffunction name="basemethod" access="remote" returnType="string" output="false">
<cfreturn SUPER.basemethod() />
</cffunction>

to TEST.CFC, the doBase() javascript function will return expected output.

if basemethod() of BASE.CFC required any arguments [say, NAME (string)], they would have to be defined in basemethod() function signature in TEST.CFC, and passed in the call to SUPER.basemethod():

<cffunction name="basemethod" access="remote" returnType="string" output="false">
<cfargument name="name" required="yes" type="string">
<cfreturn SUPER.basemethod(arguments.name) />
</cffunction>

Azadi

Comment 5 by marc posted on 5/12/2009 at 1:50 PM

ray, if you think this violates NDA, please remove this. But anyways: I posted this bug a while back to adobe, and I believe it will be fixed in cf9.

another fun bug I hit with cfajaxproxy completely by accident: have a CFC named "Parent" and one named "Child", and try to use them in your code with jsclassname="parent" and jsclassname="child". you get js errors. it's one of those "this would never happen in real life" kinds of things that you only hit when creating examples to prove other bugs.

Comment 6 by anthony posted on 5/12/2009 at 7:07 PM

Marc,

That's pretty crazy. Haven't tried, but couldn't you possible create JS error just by giving your CFCs names of reserved JS words?

Comment 7 by Raymond Camden posted on 5/12/2009 at 7:24 PM

FYI, I've confirmed Adobe knows this bug, AND it's fixed in CF9. Woot

Comment 8 by David McGuigan posted on 5/15/2009 at 12:22 AM

Just a random, pointless note: If you grabbed a copy of jCFC when it was public, it already handles this, even with multi-tiered inheritance.

The end.