Framework-One is a relatively simple framework created originally by Sean Corfield. The premise of FW/1 is to have a lightweight framework that leverages conventional behavior and consists of only a single CFC. So it seemed like it would naturally be fairly easy to integrate the FreeAgent sample application. In practice it turned out to be a little more of a challenge than I expected, but not so much that I was stalled for very long. After all, I got the sample app running in one evening.
The code to integrate my FreeAgent sample into FW1 turns out to be very similar to the code needed to install into ColdBox. Instead of suggesting that you call super.onApplicationStart() however, FW1 provides an empty method called setupApplication() which you can overwrite to provide any application setup you need. So instead of extending the FW1 application.cfc we simply place the FreeAgent application setup in the setupApplication() method. So in Application.cfc we extend org.corfield.framework and then we include this method:
<cfset var fa = 0 />
<cfset structDelete(application,"freeagent") />
<cfset fa = CreateObject("component","freeagent.freeagent").init() />
<cfset fa.newContainer("bookclub").init("bc.model.iocfactory") />
Using the built-in isFrameworkReloadRequest() method from FW1 allows us to reload the FreeAgent containers on any request in which the FW1 framework is reloaded.
Then I create my controller component. Several of these frameworks have their own event.cfc wrapper, but because FW1 has no event object, it's able to use the genericevent.cfc wrapper directly (which is also used by the onTap framework). It does however need an eventhandler cfc to provide the connector between the FW1 controller and the FreeAgent container's event handler. So we add /controllers/books.cfc just like we did for ColdBox, and it looks rather similar:
// set this to the name of the FreeAgent container for your application
freeagent.container = "bookclub";
Because FW1 uses conventions, the name of the component (books.cfc) determines the URL (i.e. index.cfm?event=books.authors), and the freeagent.container variable within the CFC then identifies our controller code. So in this case we use books / bookclub, but if I were converting Ray Camden's Galleon Forums application, I would name the container distinctively "galleon" and then I would name the controller.cfc "forum" to represent its role within my website.
Internally the component /freeagent/eventhandler/fw1.cfc that we're extending here is a bit different from /freeagent/eventhandler/coldbox.cfc that we use to install the application into ColdBox. The thing that gave me the biggest challenge here is that FW1 uses onMissingMethod as an alternative to the event methods, however, FW1 also goes a step beyond the PreEvent/PostEvent or PreFuseaction/PostFuseaction found in ColdBox or Fusebox. In FW1 the controller can have methods before/after which are equivalent, however, they can also have startX/endX for each individual method. So if I have a "home" method, the controller can have startHome/endHome methods that wrap the home event. The sticking point that challenged me at first is that onMissingMethod is used as an alternative for both startX/endX as well as for the individual method. So when the FW1 framework executes the event, it's going to run this sequence:
That's fine if it's just an FW1 app, you know what's going on there. But here we're using onMissingMethod to connect to a FreeAgent application, and if we send startHome and endHome to it, it's going to throw an error indicating that it doesn't have those events defined. It turns out that FW/1 stores the name of the current event in the variable request.action, so I was able to use this variable in the onMissingMethod in /freeagent/eventhandler/fw1.cfc to test for the startX/endX methods and ignore them. Then the controller sets request.view to load up the FreeAgent view template and it's pretty smooth sailing after that point.
So in the SVN repository we now have samples for standalone, ColdBox, Fusebox and FW/1. There's a sample for the onTap framework that's not tested, and there is some code for Mach-II and Model-Glue, but neither of them are completed yet. I expect both Mach-II and Model-Glue will require some code generation like the Fusebox integration needed, because both frameworks rely on XML configuration files. But that just leaves us to test onTap and to finish integration for Mach-II, Model-Glue and CF on Wheels (for now). :)