Here's what I said in response:
We've worked hard to make cf.Objective() 2008 a "must see" event. We have a number of firsts this year that we're very proud of:
- The public release of Open BlueDragon on May 3rd!
- The public unveiling - and Alpha - of Model-Glue 3: Gesture!
- The public unveiling of Mate, the new Flex framework from AsFusion!
- The first conference to feature the latest rising star in the frameworks world: ColdBox - with an introductory session and a two hour, hands-on advanced workshop!
- The first public information about Swiz, the new Flex framework from Chris Scott of ColdSpring fame!
- Speaking of Chris Scott, we're the first conference to feature a two-hour, hands-on workshop for ColdSpring!
- We're also the first conference to feature a two-hour, hands-on workshop on agile development for ColdFusion developers by the leading light in automated process & testing, John Paul Ashenfelter!
If you're a Mach-II user - or thinking of using Mach-II - you might also be interested in the pre-conference classes.
Brian Kotek has a great post about data vs content in the context of AJAX and frameworks. He emphasizes the benefit of having your model in CFCs as the easier way to expose data-centric functionality to AJAX and notes that for data calls, you should not be trying to go through the MVC framework. It's a good read.
Next up I covered the Fusebox 5.5 release which is currently in limited Alpha with a public Beta planned in July (as soon as we can get enough documentation together on the new features). I also announced publicly that providing a migration path for Fusebox 3 was on the roadmap (for Fusebox 5.7 probably).
Matt Woodward (and Peter Farrell) presented Mach II 1.5 which is in Beta right now, and the new website. He also talked about plans for their 2.0 release (but didn't go into specifics).
Next up was Chris Scott, who said that an official 1.2 release would appear within a few weeks and then they would be working toward a 1.5 release. This will be the last release of ColdSpring that will run on CFMX 7 - ColdSpring 2.0 will require CF8 because they want to take advantage of cfinterface and onMissingMethod() to make ColdSpring faster (and simplify the core files).
Last up was Doug Hughes who assured us that Reactor would hit an official 1.0 release as soon as the documentation was complete. Ah, the dreaded documentation...
I'll be blogging more about Model-Glue: Flex in due course - I'll be using MG:F, rather than Cairngorm, for the Flex (and AIR) development work I'll be doing over the coming months.
It's also worth noting that Model-Glue 2.0 is now an official release.
I created a test case for parent / child bean factories and aliases, I put nothing but aliases in the child factories. ColdSpring couldn't find the aliases. I deduced (wrongly) that ColdSpring did not allow aliases in child factories to redefine beans in the parent factory.
Silly me. Turns out that my test case uncovered a bug in ColdSpring: aliases only work if the factory contains at least one real bean. At least, that's what my test cases seem to show. I'm going to run this past the ColdSpring crew for confirmation.
Want to share a single instance of Transfer between multiple Model-Glue applications?
Original code / post edited out.
The definition of transferFactory is in your parent bean factory which you tell Model-Glue about by putting this line in your index.cfm:
All the Model-Glue apps share that Application.cfc and so they all have the same parent bean factory which contains the single instance of the Transfer factory object. Each Model-Glue app has its own proxy object that delegates an alias that refers to the single factory object.
Joe mentioned that he has moved the explicit Reactor ORM support declarations out of the core Configuration.xml file. In that post he said you could just declare the ormAdapter and ormService beans directly yourself.
His code base has moved on (already). If you download the very latest from SVN and you have the very latest ColdSpring from CVS, then you can take advantage of the new <alias> tag in ColdSpring!
In your Model-Glue application's ColdSpring.xml file, just add these two lines to use Transfer:
<alias name="ormAdapter.Transfer" alias="ormAdapter"/>
<alias name="ormAdapter.Reactor" alias="ormAdapter"/>
Another important change, particularly from my point of view, is full support for Transfer in the scaffolding, including parent/child relationships.
See Joe's blog for full details. Beta 2 should be available soon.
As someone who has contributed extensively to Mach II, Model-Glue, Fusebox, ColdSpring and Reactor (phew!), I would like to step up and defend Joe's decisions - he's done a sterling job, sticking to his vision for the framework and has been very clear about what should be in the framework and what should not. As a framework developer myself, I can tell you it's a rocky road. The "community" deluge you with requests for all sorts of features and you have to stand firm and defend your vision. None of the popular frameworks are "kitchen sink" efforts - there are countless feature requests that have been denied by the framework authors.
I've requested enhancements to all these frameworks. Some of those requests have been implemented but most have been denied. Even as lead developer on one of the Mach II releases, some of my suggested enhancements were turned down (and some of the changed Peter implemented in Mach II were reverted as inappropriate for the framework).
When I built Fusebox 5, I was deliberately very conservative about what went into the framework and what didn't. I implemented a few things the community really wanted that I didn't think were great ideas but I also did not implement several things that I thought were great ideas that the community weren't very interested in.
Fusebox 5.1 will be a fairly conservative enhancement release. Fusebox 6 has more scope for adding features but, even so, backward compatibility will be maintained and the addition of features will be strictly controlled but community-driven.
I don't know how community-driven Mach II is. I don't think it has a public bug tracker (Model-Glue, Fusebox, ColdSpring and Reactor all do). I get the impression that Application.cfc support was added for coolness (the other frameworks have taken great pains to remain compatible with CFMX 6.1 and equivalent competing ColdFusion engines).
Third, crack open Model-Glue and edit one of the core files - shock! horror! Edit ModelGlue/unity/config/Configuration.xml and change the definitions for ormAdapter and ormService as follows:
This defines what ORM service to use, such as Transfer.
-->
<bean id="ormAdapter" class="transfer.modelglue.TransferAdapter">
<constructor-arg name="framework">
<ref bean="ModelGlue" />
</constructor-arg>
</bean>
<!--
This defines the ORM service
-->
<bean id="ormService" class="transfer.TransferFactory">
<constructor-arg name="configuration">
<ref bean="transferConfiguration" />
</constructor-arg>
</bean>
Your Transfer configuration might look like this:
<constructor-arg name="datasourcePath">
<value>/environment/transfer/datasource.xml</value>
</constructor-arg>
<constructor-arg name="configPath">
<value>/environment/transfer/transfer.xml</value>
</constructor-arg>
<constructor-arg name="definitionPath">
<value>/environment/transferdata</value>
</constructor-arg>
</bean>
Joe and Mark and I are still looking at what it will take to support relationships with Transfer in Model-Glue. To be clear, Transfer has sophisticated support for relationships but Model-Glue's ORM support is very Reactor-centric right now which makes this level of integration somewhat more difficult!
I've talked before about the structure of our service-based system: we use ColdSpring to manage all of the model components; we have simple web service / Flash Remoting facades in front of that model; we share that configuration with our Model-Glue applications using the parent bean factory feature of ColdSpring. I've been focusing on the Model-Glue side of the things this week, so I thought I'd blog about how that's working out for us.
Model-Glue has an adapter-based architecture for ORM and ships with an implementation for Reactor. It has an ORM controller that implements the "Generic Data Messages" (e.g., ModelGlue.genericList) and relies on a Reactor-specific adapter for the actual integration with the ORM.
The ReactorORMController that ships with Model-Glue is almost entirely generic because of the adapter interface which is a testament to Joe's great design skills. Because of that, I was able to get a basic Transfer adapter up and running fairly quickly to the point that the GDMs all worked. A bit more work and I was able to get basic scaffolding working too (by creating some basic metadata and a fake dictionary object).
I haven't tackled any of the table-to-table relationship stuff but I wanted to let a broader audience know about this proof of concept to gauge interest...
So I've taken the example offline until I've figured out a simpler solution. I'll probably build a new schema that uses auto-incremenet PKs instead since I know that works with Reactor/Unity!
Joe previously presented a fairly different version of the presentation to the Portland CFUG (which I haven't watched yet - Joe himself told me there was only about 10% overlap between the two talks). I kept meaning to watch that and write it up but it may be a little superfluous now.
I downloaded Model-Glue: Unity last night and have been experimenting with it, building a version of my cat show task manager application which I'll eventually bundle into frameworks presentation code. I don't have ggcc10 working yet which was supposed to show Model-Glue 1.0 / ColdSpring / Reactor but I will fix that and add it along with the new Model-Glue 2.0 (Unity) version, ggcc11, so folks will have plenty to compare.
My initial reactions? Wow, it makes prototyping applications incredibly rapid and it's easy to take the generated scaffolding code and modify it.
His blog entry also provides links to thorough online documentation and a bug tracking system.
From the video, you'll see that Unity uses Reactor to drive the database access and ColdSpring to manage both the Model-Glue service components and the Reactor factory itself. A very powerful combination!
Ray did a great job of introducing Model-Glue, coming at this from his own experience of learning the framework and how it's helped him organize his code. Ray starts out with just a few slides to define some terms and then switches to screen sharing, showing how to build a real Model-Glue application (press release listings) from scratch with a focus on the framework itself. He makes a very clear distinction between the application model (which should be framework-independent) and the controller (which is tied to Model-Glue).
It's a great introductory piece for anyone just coming to Model-Glue or still considering which framework to use.
I'll post about Joe's presentation later, when I finally find the time to watch it all the way through.
The benefits of ColdFusion are slowing becoming apparent to my (formerly non-ColdFusion) colleagues: Java integration is fairly seamless, exposing code through web services or Flash Remoting is almost trivial, high-level tags that simplify integration tasks.
Within my overall team, I run a small group focused on core infrastructure and integration and we're getting into some prototyping work now and for that we're going to use Model-Glue to build quick HTML user interfaces and test harnesses and Reactor to simplify the data access layer, with a view to moving to custom SQL queries for performance later on. Given the ease of using ColdSpring with Model-Glue to manage the service layer, I strongly suspect we'll end up using all three frameworks together for our prototyping.
Over time we'll build out Flex 2 user interfaces, probably even for the internal administrative consoles that we might initially build using Model-Glue. The service layer we build should be directly reusable in that situation.
So far, the initial response to Model-Glue, ColdSpring and Reactor has been positive and we're looking forward to Model-Glue 2.0 a.k.a. "Unity".
I wrote a small Model-Glue / ColdSpring application that runs on her machine (which already runs the IRC bot) and lets her push files from the local financial folder tree to a specific directory on the remote website.
I figured it might be useful to someone so you can download the code from my software pod (right hand side of my blog).
Here's the code embedded in the web page on the regional website:
<cfset keys = structKeyArray(data) />
<cfset arraySort(keys,"text") />
<cfset n = arrayLen(keys) />
<cfloop from="1" to="#n#" index="i">
<cfoutput>
<p><a href="/data/#keys[i]#"><b>#keys[i]#</b></a><br />#data[keys[i]]#</p>
</cfoutput>
</cfloop>
To configure the app, edit filemanager/config/beans/beans.xml and change the local home directory and the remote server configuration.
The UI is very basic (hey, I'm an engineer not an artist!) and is modeled after the "webpush" utility Macromedia used to manage content on macromedia.com (with color-coding to indicate files that are the newer locally, the same, missing locally and missing remotely).
Anyway, if you find it useful, have fun with it. If nothing else, it's another example of using Model-Glue and ColdSpring together.
Fusebox has long had a convention to deal with this known as XFAs - eXit FuseActions. The idea is to abstract the actual fuseaction name into a variable. You specify all the exit points for a view as XFAs in the XML and refer to the variable in the view instead of hard-coding the fuseaction name. If you need to change the control flow - or the fuseaction name - you just change the XFA in the XML file and your views all pick that up. Often Fuseboxers set common XFA values in the prefuseaction for the circuit or the global preprocess fuseaction for the application, making it very simple to manage exit points.
You can do something similar in Model-Glue by using the value tag on an include:
<value name="xe.home" value="welcome"/>
</include>
If you want to set exit points globally in Model-Glue, you could make them settings in the <config> section and then have a listener for onQueueComplete which pulled all xe.* settings and added them to the event (view state).
fusebox.xml:
<classes>
<class alias="controller" classpath="fbmg.controller.Controller"
mg:needStuff="getStuff" />
</classes>
<circuits>
<circuit alias="do" path="controller/" />
</circuits>
<parameters>
<parameter name="mode" value="development-no-load" />
<parameter name="defaultFuseaction" value="do.welcome" />
</parameters>
</fusebox>
circuit.xml:
<fuseaction name="welcome">
<mg:broadcasts>
<mg:message name="needStuff" />
</mg:broadcasts>
<mg:views>
<mg:include template="main.cfm" />
</mg:views>
</fuseaction>
</circuit>
Controller.cfc:
<cffunction name="getStuff" returntype="void" access="public" output="true">
<cfargument name="attrs" type="struct" required="true" />
<cfset arguments.attrs.stuff = "1234" />
</cffunction>
</cfcomponent>
views/main.cfm:
<p>This is the main Model-Glue view.</p>
<p>This is the stuff: #viewState.getValue('stuff')#.</p>
</cfoutput>
This is using what will be the Alpha 2 codebase...
First off, while I think the tests are interesting, I've always been one to say don't worry about performance too much because "fast enough" is almost always sufficient. Very few websites get the sort of traffic to need heavy load testing and tuning, frankly, and as we know there are some very high traffic sites out there running on various frameworks. macromedia.com runs (about a quarter of its applications) on Mach II and the performance under load testing met all of our criteria.
My comments about the tests Webapper ran were meant to say:
- It's no surprise Fusebox is "faster" because it is more of a compiler than anything else (the framework doesn't really "do" anything at runtime, once your XML is compiled to CFML)
- I was pleasantly surprised that Mach II was not slower than a hand-coded CFC-based application - a lot of people complain about the "overhead" of Mach II but this shows that is not necessarily true
The point of the original (Webapper) article was that JVM tuning can have a dramatic effect on performance, as can Trusted Cache.
Those wonderful folks over at Webapper have been doing some load testing on various frameworks using the ColdFusion PetMarket application (featured in the February CFDJ). They tested Fusebox 4.1, Mach II and Simon Horwith's "no framework" versions of PetMarket. Fusebox 4.1 was the fastest which really isn't much of a surprise since it compiles everything down to straight line CFML on the first request so subsequent requests just process a single file. What surprised me was that the Mach II version outperformed Simon's version (albeit, not by very much). Overall, Simon's version was 100% slower than the Fusebox 4.1 version. Unfortunately, Webapper couldn't test the Model-Glue version because "the PetMarket Model Glue application was not fully functional". Based on my experiences, I'd expect Model-Glue to fall somewhere between Fusebox 4.1 and Mach II performance so I hope they get a chance at some point to show that.
Joe quotes around 10,000 downloads for Model-Glue which is phenomenal! Congratulations Joe!
I'm looking forward to Model-Glue 2.0, even as I work on Fusebox 5. Both new releases will provide a cleaner, more maintainable, more powerful set of core files while retaining substantial backward compatibility with the previous releases. This should be seen as a testament to the stability and maturity of those previous releases. In some ways, Fusebox 4.0 was really a "1.0" release since it a new way to write Fusebox applications, using XML and Fusebox 4.1 was therefore "1.1" - and Fusebox 5 will be "2.0". Model-Glue and Fusebox are moving forward: a brand new set of CFC-based core files that bring more expressive power, while building on the shoulders of the "1.x" applications that are out there.
It's a good time for frameworks users!
<constructor-arg name="configuration">
<value>/ggcc10/config/reactor.xml</value>
</constructor-arg>
</bean>
<bean id="taskGateway" factory-bean="reactorFactory"
factory-method="createGateway">
<constructor-arg name="objectAlias">
<value>task</value>
</constructor-arg>
</bean>
In the ModelGlue.xml file, specify the ColdSpring loader and that you want autowiring:
value="ModelGlue.Core.ColdSpringLoader" />
<setting name="autowireControllers" value="true" />
<cfargument name="gw" required="true" />
<cfset variables.taskGateway = arguments.gw />
</cffunction>
Magic!
Reactor is also getting some performance tweaks - some are already in the repository, more will be committed before cf.Objective() (do you see a pattern here?).
Check out the latest "BER" versions to try out the new abilities!
ColdSpring has recently been enhanced to support factory-bean and factory-method attributes in a bean definition so that you can declare beans that are actually created by external factories such as Reactor.
You declare the Reactor factory as a bean (managed by ColdSpring). Then you can declare DAO and gateway objects, in the ColdSpring XML file, which are created by the Reactory factory bean.
It's very slick.
However, most Reactor operations are focused on record objects which are transient (not singletons) and whilst those could be managed by ColdSpring, generally only singletons - per-application objects like services - should be managed by ColdSpring (since it adds a layer of complexity to object creation in order to leverage the power of the framework).
I was attempting to apply AOP to Reactor-generated objects so that I could simulate the security model in ggcc9 (the ninth variant of my frameworks comparison code - see the software pod on my blog). ColdSpring assumes that AOP-controlled objects are simple concrete classes and therefore it doesn't work with the nested inheritance hierarchy of the Reactor-generated DAO and gateway objects.
I did eventually make it work but it requires changes to ColdSpring and, for some of the autowiring I was doing, some changes to Model-Glue as well. I've submitted the patches to the revelant mailing lists for consideration but it means that I can't realistically release the ggcc10 variant's source code.
Despite my minor frustrations, the combination of the three frameworks is immensely powerful. If you look at the ggcc9 variant, you'll see it has several model CFCs and several bean CFCs. The ggcc10 variant has none of that. The model was really just DAOs and gateways which Reactor provides automatically and the beans become records which, again, Reactor manages automatically. About a dozen CFCs went away in the conversion. That's a lot of code I wouldn't have to write!
I added the following setting to ModelGlue.xml:
At some point I'll update this variant with the feedback I had from Chris Scott and/or Dave Ross who suggested (correctly) that the aspect should call the model and the actual check identity code should be there instead.
He also announced that Chris Scott has created an alpha pre-release of Model-Glue for Java.
As he says, if you end up using it, comment on his blog entry to let him know!
Naturally it's cat-related. I built the On Safari website last year (I am not responsible for the visual design!) using Fusebox and what little dynamic content I needed I was loading into the database from CSV files.
This year I decided to build a small content admin section to make this a more pleasant process as I add more content that people send me about past On Safari shows. For the admin, I decided to use Model-Glue, ColdSpring and Arf!
Code to fetch all the awards and sort them by year and sequence number:
<cfset var awardSelect = award.list(orderby="osyear DESC, seq ASC").getQuery() />
<cfset arguments.event.setValue("awards",awardSelect) />
Code to read in a single award record by ID:
<cfset var award = variable.rf.createRecord("admin.model.cataward") />
<cfif len(awardId)>
<cfset award.read(awardId) />
</cfif>
<cfset arguments.event.setValue("award",award) />
Code to save an award (either new or edited - Arf! knows that a blank ID means add a new record):
<cfset var award = variable.rf.createRecord("admin.model.cataward") />
<cfset var i = "" />
<cfloop list="#fields#" index="i">
<cfinvoke component="#award#" method="set#i#">
<cfinvokeargument name="#i#" value="#arguments.event.getValue(i,'')#" />
</cfinvoke>
</cfloop>
<cfset award.save() />
<cfset arguments.event.addResult("success") />
And, finally, code to delete an award:
<cfset var award = variable.rf.createRecord("admin.model.cataward") />
<cfset award.setId(awardId) />
<cfset award.delete() />
<cfset arguments.event.addResult("success") />
You can decide for yourself how much work this saves. The cataward CFC is essentially empty (just the Arf! template). It was certainly nice not having to write CRUD SQL but in an app this size there wouldn't be very much of it.
It works, it's reasonably fast - certainly fast enough for my little admin needs.
What could I do better? Well, I ought to have a separate DAO layer and isolate the use of Arf! inside that rather than just manipulating Arf! in my controller but I just wanted a quick'n'dirty content admin. I'm only using ColdSpring to create and load the Arf! Datasource and RecordFactory objects (overkill but convenient). I'm using the autowire feature (in the ColdSpring CVS version, not yet released).
That means that the Model-Glue / ColdSpring integration will be as simple as:
Specify the ColdSpring bean factory loader and location of the ColdSpring bean definition file in ModelGlue.xml:
<setting name="beanMappings" value="/ggcc9/config/beans/ggcc.xml" />
<controller name="csaw" type="coldspring.modelglue.AutoWire"/>
...other controllers...
</controllers>
In order to try it out you will need the BER of Model-Glue (which has Joe's latest ColdSpring integration), the 0.2.1 release of ColdSpring which includes both AOP and the Model-Glue adapter from Dave Ross, and you will also need this extension to ColdSpring that adds auto-wiring for Model-Glue controllers.
In this variant, ColdSpring manages all of the model (except the transient note, task and user beans - I may convert these later) and it also autowires the various beans into the controller objects at startup (so the controller objects have no internal initialization code!).
I've also modified how security is managed to use ColdSpring AOP. In the previous Model-Glue variant (#7), security was checked explicitly in various event handlers by broadcasting the checkIdentity message. Now it is handled through "before advice" on the taskDAO and taskGateway objects, using ColdSpring AOP. The advice performs the security check and throws an exception if the user is not logged in. In the exception event handler, a message is broadcast that causes event results to be set if the exception can be handled by another event (in this case the security exception can be handled by the ggcc.identify event, which challenges the user to login).
I think this shows the power of these two frameworks in combination!
The simple answer is because it doesn't know about your application framework so it doesn't know about controllers.
Dave Ross and Chris Scott are working on a plugin for Mach II that will allow ColdSpring to automatically locate the listeners, plugins and filters in your "controller" and look for setXxx(yyy) methods in them. If it can match a setter to a bean that it knows about (from the ColdSpring bean XML file), it will automatically invoke the setter for you.
I thought that was a great idea but I wanted it for Model-Glue!
So I wrote an AutoWire.cfc for Model-Glue. It relies on Joe's BER changes to Model-Glue to support the ColdSpring bean loader. I've submitted it to Joe, Dave and Chris so hopefully it will be incorporated at some point.
How it works: Model-Glue creates the bean factory, then creates the controllers. With the ColdSpring changes that Joe listed, Model-Glue creates the ColdSpring bean factory instead of its own (ChiliBeans). My AutoWire.cfc is a controller that you declare in the XML (as the first controller). At startup, when Model-Glue creates that it, AutoWire then modifies the in-memory Model-Glue object so it can intercept subsequent controller creation. Then, as Model-Glue creates the remaining controllers, AutoWire searches for setXxx(yyy) methods on each one and attempts to match them to beans declared in the ColdSpring XML file.
If anyone is desperate to try this out, I'm happy to send you the work-in-progress code...
I was able to remove the ColdSpring bean factory 'hack' from my controller (see link to Dave Ross's post in my previous entry) and just make the ModelGlue.xml changes that Joe mentions. Using ColdSpring is now so easy with Model-Glue that I expect this is how I'll be building applications moving forward!

