user446882
user446882

Reputation: 427

Coldfusion CreateObject() Returns Instance of Wrong Object

I'm running into an issue that only seems to affect our production server and without any apparent rhyme or reason. Essentially, we're getting the following error (I'm going to use dummy names to illustrate the point):

Message: Neither the method someFunction was found in component Components.services.SomeComponent nor was there any default method with this name present in any of the implementing interface.

This happens at a few different lines in the codebase but once it's been thrown, it will never get past that point again until clearing the Component Cache in CFADMIN. Here's the kicker: the offending line in the code looks like this:

<cfset var a = createObject("Components.services.app.ComponentA").someFunction() >

It seems like the createObject call to create ComponentA is instead returning an instance of SomeComponent. I've tried the following:

Nothing seems to help -- none of this is reproducible in our UAT or anyone's dev environments and it's intermittent in production, but, again, once it's been thrown that server is done. Clearing Component Cache in CFADMIN temporarily fixes it until someone will randomly throw it again hours later.

Some additional caveats:

Next steps (none of these are ideal):

Is there some way to granularly exclude certain CFC's from being retrieved from the Component Cache and force them to be re-evaluated when calling createObject()?

Upvotes: 7

Views: 252

Answers (2)

BKBK
BKBK

Reputation: 484

Your definition of the object,

createObject("Components.services.app.ComponentA"),

misses an attribute. The definition should be

createObject("component", "Components.services.app.ComponentA").

Upvotes: 0

dswitzer2
dswitzer2

Reputation: 111

I've seen this behavior before when the component is using a path that has an Application mapping. I've seen this happen in a few different scenarios, but the most common scenario was like this:

In your Application.cfc, there's a mapping to your components that uses a relative path. Something like:

this.mappings["/Components"] = expandPath("../some/relative/path/com");

As long as the application is always initialized from the same folder as the Application.cfc then this works fine. However, if the application is initialized from a subfolder, then the Components mapping no longer points to the expected folder.

If you need to use a relative path for a mapping, you can avoid this by doing something like:

variables.rootFolder = getDirectoryFromPath(getCurrentTemplatePath());
this.mappings["/Components"] = variables.rootFolder & "../some/relative/path/com";

That should force the mapping to always use the same physical path folder, even when called from a subfolder.

Another scenario in which I've seen this happen is in a shared environment where there are multiple Applications with the same name.

If you have multiple instances of a website running that are using the same Application name in your Application.cfc, then the first website that is initialized ends up sharing it's mappings with the other application. If the applications are different, this can lead to components not being found.

Hopefully one of these two scenarios gets you on the right track to resolving your issue!

Upvotes: 5

Related Questions