Reputation: 427
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:
Components.services.app.ComponentA
, Components.services.app.ComponentB
, etc... are all hard-codednew
syntax instead of createObject
./Components/services/app
called (for instance) "app" so that I could create the objects like new app.ComponentA()
instead of new Components.services.app.ComponentA
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:
new ComponentC()
is instead creating someComponent
... new ComponentA()
is instead creating someOtherComponent
someComponent
, someOtherComponent
) are CFC's that live outside this directoryNext 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
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
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