Skip to main content
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Francine Brady
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Francine Brady ( @darkfeather )

ColdFusion Implicit Getter Has Incorrect Type For Being Called As A Function

By on
Tags:

ColdFusion 9 overloaded the CFProperty tag (or just "property" in CFScript) to allow for the definition of implicit, or synthesized, getter and setter methods. Lately, I've been using these implicit setters as a way to provide dependency injection hooks for Sean Corfield's DI/1 Framework. The setters seems to work without fail. And, 99% of the time, the getters work as well. But, under very heavy load, it seems that the getters occasionally fail, causing the current thread to hang for several minutes.

Imagine that I have a component that has a dependency on the singleton, "userService." In order to inject this dependency, DI/1 will call:

setUserService( userService )

... then, internally to the component, in order to access that injected property, I would use something like:

getUserService().getUserByID( 4 )

Notice that internally to the component, I am using the implicit getter to locate the injected property. As I said before, 99% of the time, this works as expected. But, in very rare situations, generally under heavy load, ColdFusion will raise the following exception:

Entity has incorrect type for being called as a function. The symbol you provided getUserService is not the name of a function.

At first, I thought that this was limited to CFThread contexts, as this is where the error first started showing up. But, when we started removing the use of CFThread, the error started popping up in random places that had no relation to parallel processing.

Using Fusion Reactor, we were able to look at the stack trace of these hung requests, which looked something like this:

java.net.SocketInputStream.socketRead0
java.net.SocketInputStream.read
java.io.BufferedInputStream.fill
java.io.BufferedInputStream.read1
java.io.BufferedInputStream.read
jrun.servlet.jrpp.ProxyEndpoint.readFully
jrun.servlet.jrpp.ProxyEndpoint.readFully
jrun.servlet.jrpp.ProxyEndpoint.readInt
jrun.servlet.jrpp.ProxyEndpoint.readString
jrun.servlet.jrpp.ProxyEndpoint.getHeader
javax.servlet.http.HttpServletRequestWrapper.getHeader
javax.servlet.http.HttpServletRequestWrapper.getHeader
javax.servlet.http.HttpServletRequestWrapper.getHeader
coldfusion.runtime.CgiScope.resolve
coldfusion.runtime.CgiScope.containsName
coldfusion.runtime.CgiScope.search
coldfusion.runtime.NeoPageContext.searchScopes
coldfusion.runtime.NeoPageContext.findAttribute
coldfusion.runtime.CfJspPage._get
coldfusion.runtime.CfJspPage._get
coldfusion.runtime.CfJspPage._get
cfScreenService2ecfc850392735$funcGETUSERSERVICE.runFunction

This was completely baffling. Charlie Arehart, however, noticed that the CGI scope was being used as a look-up scope in these requests - something that would not have been expected given the code.

This discovery led Charlie to a bug that Steven Erat filed with Adobe in March, 2012.

ColdFusion 9.0.1 - Bug 3132889

In the bug log, Steven Erat points out that ColdFusion will sometimes fail to locate implicit getters and setters, causing the CGI scope to be searched - which is what we were seeing in our stack traces.

To work around this in our application, we simply stopped using the implicit getters and started referencing the injected properties directly. At this time, I don't have any better advice; I'm simply posting this here in case anyone else is having this problem.

Reader Comments

10 Comments

I've run into a similar problem. Under heavy load,one of my implict getters starts acting strangely but in a different way. I have a DocumentHeaderService Object which gets me a DocumentHeaderID via an implicit getter. I then pass that ID into a generation function which build a header from XML.

Say the DocumentHeader ID I expect is 123456. Under heavy load, the implicit function getDocumentHeaderID will not return the value "123456", it will return the value "DocumentHeader#123456".

Can't really understand why it would return [Object name]#[ID]. Odd behaviour but your post reminded me of it.

15,674 Comments

@Joe,

Hmm, that sounds really odd. I wonder if that's some sort of threading issue for concurrent code - like you're seeing a partial result that is being prepared by another thread. I've had that happen too many times when I forget to VAR-scope something; or I'm using a Java object that I didn't realize was thread-UNsafe.

@Aladdin,

No problem - hopefully more AngularJS stuff to come!

2 Comments

Just curious why you were using getters and setters by default instead of direct references to the properties? Especially when the result is the same?

It seems like it is a common stylistic choice (dogma?) to always user accessor methods, whether they are really needed or not. But I feel like it's just extra overhead.

15,674 Comments

@Eric,

It was part team decision, part something that just got slipped in there. I think I prefer the direct object reference, especially internally to a given component.

34 Comments

@Eric,

The generated accessors is generally just a stylistic thing. I like them because you have your injected dependencies "documented" at the top of your CFC (with `property` definitions), there's less characters to read/type (e.g., "getFoo()" vs. "variables.foo"), and in my IDE (IntelliJ IDEA) I get autocompletion for all get/set methods implicitly generated by a CFC's accessors=true.

But most importantly, if you're using any number of dependency injection frameworks or other libraries or tools that might populate properties for you, then they'll generally look for setters, and I'd much rather document properties up top rather than hand-coding a bunch of boilerplate setters. For example, ColdSpring and DI/1 behave this way, for autowiring dependencies.

96 Comments

@Krug ...

I submitted a ticket on you track to have javadoc style comments /** trigger method definitions ...

//youtrack.jetbrains.com/issue/IDEA-104579
\
Hopefully it will get some traction ...

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel