Neat Trick!
Looking forward to the possibility of newer versions of the various frameworks, when I started porting Galleon I decided to include full copies of the frameworks in my distribution. Granted that means my distribution is going to be large. Currently it's about 12MB. I don't expect it to grow much beyond that, because the frameworks are already in it, along with a complete copy of Galleon, much of which has already been copied 4 times.
In spite of the size I felt it was important to include full copies of the current versions of each framework because I know they work with the "application skeletons" I've used to create the ports. (My own framework is the only one that doesn't have an "application skeleton" because the context of the framework is different.) And I decided to use the new application-specific mappings feature (this.mappings) in ColdFusion 8 to ensure that each port will use the copy of its framework that's been included with the distribution.
That's when I hit my first snag. Fusebox, MachII and ColdBox all want the Application.cfc to extend a component in the framework's core files. So for example, in the application skeleton for the Mach-II framework, Application.cfc looks like this:
...
</cfcomponent>
Personally I think this is a poor convention. You'd think, because the soft-constructor in the Application.cfc has to finish executing before the mappings take effect, that you wouldn't be able to use a mapping in the application skeleton cfc to tell it where to find MachII. For example:
<cfset this.mappings["/MachII"] = ExpandPath("../MachII") />
<cffunction name="onApplicationStart" ...>
...
</cffunction>
</cfcomponent>
The cfset tag is in the soft constructor, so unless you already had MachII installed at the web root (or a mapping), this will fail... and even if it doesn't fail, it still won't use the version of MachII you want it to use (which was important in my case). That would mean that even with the new CF8 mappings feature, you'd still be stuck with just one copy of MachII on a given server.
It turns out that's hapilly untrue.
I was able to make these work by slightly modifying the application skeletons' Application.cfc templates. Here's the code:
<cfcomponent extends="mach-ii" ...>
<cfset this.mappings["/MachII"] = ExpandPath("../MachII") />
<cffunction name="onApplicationStart" ...>
...
</cffunction>
</cfcomponent>
mach-ii.cfc
<cfinclude template="../MachII/mach-ii.cfc">
Viola! The cfinclude actually works ... and not only does it work, but the server instantiates an object and everything. There did seem to be a couple of peculiarities... I ended up having to copy the fusebox5 directory and modify some of its core files because it wasn't finding certain variables in the "variables" scope... but even there, it required very few changes.
I suspect this also resolves a personal issue I had before with wanting to have components in a subdirectory extend other components in a parent directory. So for example if I had /cfc/myproject/myfactory.cfc and I wanted it to extend /cfc/myfactory.cfc then I could simply place a dummy cfc in the /myproject/ directory, include ../myfactory.cfc and extend the dummy cfc.
In any event, it solved my immediate problem, which made me really happy.
UPDATE 6/11/2008: I just found this article on Peter Farrell's blog where he talks about having the same issue and his solution. Small world. :)
UPDATE 6/14/2008: Peter responded the other day on another blog to say that my solution doesn't work and that I must be confused and the server is merely finding the MachII directory in my web-root and using that, making me think it's working when it's not... I've got a lot of things in my htdocs directory, but a MachII directory is not one of them.
And then today when I came home from work what did I find? A big long thread on the cf-talk list where a guy is trying to dynamically extend a CFC. So I figured what the heck, can't hurt to try it right? So I modified my original solution slightly and I put a CFIF around the include. And wouldn't you know it -- you actually CAN dynamically extend... So what I've got now is Application.cfc extending proxy.cfc which has this code in it:
<cfif val(url.fish)>
<cfinclude template="baluga.cfc" />
<cfelse>
<cfinclude template="helloworld.cfc" />
</cfif>
And if I visit index.cfm I see "hello world" and if I visit index.cfm?fish=1 I see "hello baluga".
This proof that the extends attribute of the cfcomponent tag could have been a run-time attribute, in spite of what Sean Corfield and everyone else has said about it being necessarily a compile-time attribute.
I went ahead and zipped it up and uploaded the code for everyone's enjoyment. :)

There are no comments for this entry.
[Add Comment]