Watch out for Inherited Meta Data

I've been working on a project that makes heavy use of metadata over
the past few weeks and just got bit hard by a little quirk with
metadata.  Metadata is created on the first call to getMetaData()
for a given CFC type, and then cached for quicker subsequent
recall.  That's a good thing.  However, you can run into
issues with inheritance, because the metadata is only updated for the
specific CFC it was generated for.  In other words, if you update
a superclass of a CFC, the CFC's metadata won't change, even though
it's behaviour might.  If you're on *nix, running touch `find .
-name "*.cfc"`
will take care of the problem by forcing CF to recompile
all your CFCs (and consequently regenerate their meta data).

However,
that's not the really insidious quirk.  You would think that since
a superclass's metadata doesn't refresh when you change the superclass,
that the metadata originally from the superclass would be separate from
the superclass's meta data.  However, that's not the case, and you
can actually modify the superclass's metadata by updating a copy of the
subclass's metadata.

Couple
caveats.  First, this was demonstrated (repeatedly) on CFMX 6.1; I
have
no idea if the same gotcha exists on CF7.   Second, I can't make a
simple repeatable test case out of it.  It happens every time in
my app, but when I make a standalone example things works
consistently.  I suspect it has something to do with the specific
order that the getMetaData calls, the copying of the metadata
structures, and the updating of the fields, but I haven't been able to
pin-point it.

Solution?  Don't ever maintain a reference to any part of a
CFC's metadata.  If you need to keep a registry of metadata
snippets, always use duplicate().  Adding that fixes the problem,
because duplication ensures no lingering cross-object references
persist.

One response to “Watch out for Inherited Meta Data”

  1. John Farrar

    I found that the only sure method of managing caches is to go into CFAdministrator and manually clear the cache.