Injected Methods Show Up in Object Metadata in Railo but not ColdFusion

CFML , ColdFusion , Railo Add comments

I recently had a chance to listen to the latest edition of the This Week in ColdFusion Podcast wherein design patterns are discussed. One of the design patterns that Brian Carr talks about in the podcast is the Decorator Pattern. As an example, Brian describes how you can use the dynamic nature of ColdFusion to assign a function to a variable and then add that function to an object at runtime (this is also known as "method injection"). Bob Silverberg, who was a guest on the podcast then asked Brian whether the injected method would show up in the object's metadata if you called the getMetaData() function on it. Brian didn't know for sure, but he and Bob agreed that it was unlikely. This piqued my curiosity, so I set about to test this myself.

First, I built a very simple component -- person.cfc

<cfcomponent>

<cffunction name="init" access="public" returntype="any">
    <cfset variables.name = "Tony Garcia" />
    <cfreturn this />
</cffunction>

</cfcomponent>

This component only has an init() method, which sets variables.name to "Tony Garcia" and returns the instance.

Next, I wrote this template called injectiontest.cfm.

<cffunction name="testMethod" access="public" returntype="string">
    <cfreturn variables.name />
</cffunction>

<cfset tony = createObject( "component","person" ).init() />
<cfdump var="#getMetaData( tony )#" label="Before Injection" />

<cfset getName = testMethod />
<cfset tony.getName = getName /> 

<cfdump var="#getMetaData( tony )#" label="After Injection" />

The name is: 
<cfoutput>
#tony.getName()#
</cfoutput>

It's pretty clear what's going on here. First I define a function named "testMethod". Then I create an instance of person.cfc and dump out its metadata. I then assign testMethod() to a variable and inject it into my object using the name "getName" for the method (since that's what it does). I dump the metadata again after the injection and then just test the method itself by outputting its return value.

Here is the output of the dump before injection using ColdFusion 9:

Before Injection CFDump

As expected, only the init() method appears in the array of functions. This is the dump after the method injection:

After Injection Dump

The only function that appears is still the init() method. So Brian and Bob were correct in their suspicions. But then, since I work alot with Railo, I decided to run the code in Railo 3.1. Here is the dump before the method injection (now I'm just showing the functions element):

Before Injection CFDump in Railo

Again, we only see the init() function. But notice that the dump gives us some more info about the function compared to the CF9 dump. Take special note of the "owner" element, which is the path to the cfc.

Now here is the dump after the method injection:

After Injection Dump in Railo

So the Railo dump of the object's metadata does indeed include the injected method! Another interesting observation is that the name given for the method is "testMethod", not "getName", so it uses the original name of the function that was injected, not the name it was assigned to in the object. Also, note that the "owner" element is the path to the template where the injected method was defined. So if you're doing some fancy programming against metadata, the "owner" element may be used to check whether the method in question is built-in to the object or was injected.

Anyway, I thought this was pretty interesting so I thought I'd share.

13 responses to “Injected Methods Show Up in Object Metadata in Railo but not ColdFusion”

  1. Brian Carr Says:
    I'm very glad you decided to do that research Tony. I'm also thrilled to see that Railo properly describes object instance meta-data correctly. Now if it only supported full-script components and interfaces :-)
  2. Sean Corfield Says:
    Interesting! I didn't know that Railo updated the metadata dynamically!

    As for full-script - it's coming... we had argument types and defaults a long time ago and we've recently added function access and return types. Component and interface syntax, along with the new operator is planned "soon".
  3. Ben Nadel Says:
    Does Railo also have a getComponentMetaData() method? In CF, this allows the meta data to be gotten from the class definition, rather than from an instance. I ask because I wonder if Railo has any concept of meta data of the class itself?

    In CF, all instances share the same meta data object.
  4. Ben Nadel Says:
    Arrr, tabbing from comments goes to the submit button (skips subscribe + remember checkboxes). Just subscribing....
  5. Tony Garcia Says:
    @Ben,
    Yep -- I've used getComponentMetadata() in Railo with no problems.
  6. Ben Nadel Says:
    @Tony,

    Ah pretty cool then. I guess you can use getComponentMetaData() to get root class meta data and getMetaData() to get run time meta data. Seems like a sweet deal.
  7. Tony Garcia Says:
    Yeah. I guess, then, the title of the blog post is a bit misleading since I was really talking about the metadata of the object, not the component
  8. Ben Nadel Says:
    @Tony,

    I didn't mean to imply anything about the title - just curious about the differences in Railo. In CF, getMetaData() and getComponentMetaData() return the same exact thing for a CFC. So, to me, it seems cool that Railo differentiates.
  9. Tony Garcia Says:
    I went ahead and changed the title anyway. Technically, I think "object metadata" is more accurate than "component metadata".
  10. Ben Nadel Says:
    Sounds good to me :)
  11. Brian Carr Says:
    @Sean

    Full CF syntax / API support in Railo would be a dream come true :-). Needless to say (although I'll say it) I'm very happy to hear that it's close.
  12. Brad Wood Says:
    I've noticed this in Adobe CF and always considered it a bug. It's worth nothing, that structKeyExists(myObject,"injectedMethodName") WILL return true. The fact that it's not reflected in the metadata to me is just wrong.

    I can only assume the Adobe engineers chose to cache metadata and reuse it for all instances of a component for performance reasons.
  13. Tony Garcia Says:
    @Brian -- you might be interested in my latest blog post:
    http://objectivebias.com/entry/full-cfscript-component-syntax-is-now-in-latest-railo-ber

Leave a Reply

Leave this field empty

Powered by Mango Blog. Design and Icons by N.Design Studio