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.
I know Brian Ghidinelli also ran into this issue and had started to write his own as well. I expect he'll switch to Brian Kotek's version now.
So what does it do? Well, as you build complex domain objects by writing decorators for Transfer objects, you find you need access to services that you are managing with ColdSpring. Transfer provides an event model so you can add a listener (observer) for the afterNew event and use that to inject dependencies into your domain objects. It's a fairly manual process. What Brian's CFC does is completely automate the process. You declare the injector in your ColdSpring file and pass in Transfer to its constructor. When ColdSpring initializes the injector, the injector registers itself as an observer for that event and then it automatically injects any matching services, based on setters in the decorator. Very slick!
This is also great news for folks who feel constrained to only use official releases. The last official release of ColdSpring (1.0) was so long ago that lots of great features are only available in the BER: aliases, includes, abstract beans etc. This has been particularly troublesome for such folks trying to use Model-Glue with Transfer (or Reactor) since that has relied on aliases for quite a while. A new official release of ColdSpring (1.2) is just around the corner!
The exception from Reactor - about the database mismatch - is swallowed by ColdSpring and reported as a bean initialization exception. If that in turn is caught and dealt with by the application's initialization code, you no longer have any indication of what the problem might be.
Fortunately, we have a great tool at our disposal to dig into these buried exceptions: the ColdFusion 8 debugger!
I fired up the debugger in Eclipse and enabled break on CFML exceptions and write exceptions to the Eclipse log. As expected with ColdSpring and its exception-happy nature, I hit a few false starts but then I hit the Reactor exceptions. There are a couple of harmless exceptions as it tests for some optional plugin points but then you get the real exception, showing up in the Eclipse log. Very convenient!
Model-Glue has come on in leaps and bounds - the rearchitecture based on ColdSpring, the scaffolding infrastructure, the integrated support for Reactor and Transfer for "generic database messages". It's very impressive. And now we're got the beginnings of a Flex version, which is very promising.
Now that I'm consulting and have a number of clients, I'm encountering Mach-II quite a bit and looking at the 1.5 release. I've mentioned in the past that I think 1.5 looked quite impressive (when Peter Farrell gave the "what's new?" talk at cf.Objective(), for example). Recently, I've been making recommendations for frameworks for clients and finding myself recommending Mach-II for some clients, mostly due to the new features in 1.5. For some of the sites my clients are trying to build, the modules, includes and subroutines really do allow you to build much larger, much more modular sites than earlier versions of Mach-II.
The extended property semantics in Mach-II 1.5 are also very nice, allowing you to specify structured configuration data - including full-on CFCs - as well as allowing property values to be dynamically substituted into parameter values throughout the configuration.
I still don't really like the direct invocation model (with <notify>) compared to Model-Glue's broadcast / listener mechanism, but the other features are pretty compelling.
One thing I have seen mentioned, but cannot find, is Peter Farrell's new ColdSpringProperty CFC, to replace the old ColdSpringPlugin. Anyone know where to get a copy?
I haven't actually watched the preso but I have said publicly that I don't use the proxy generator in ColdSpring - because I don't think you can automatically generate an appropriate remote proxy for a model in the general case.
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...
Brian shows how to use the factory-bean and factory-method descriptors in your ColdSpring XML file to handle automatic injection of beans obtained from factory objects that are also managed by ColdSpring. It's a powerful technique that helps completely remove a number of dependencies from your application code.
I use the same technique with Transfer and ColdSpring:
<bean id="transfer" factory-bean="transferFactory" factory-method="getTransfer" />
For the first role, we want someone who can create crisp, clean user interfaces that are intuitive and easy to use. You'll have good graphic design skills and the ability to take a UI vision and turn it into lightweight HTML + CSS, with slick JavaScript for interactivity. If you've got ColdFusion skills, that's a bonus.
For the second role, we want someone who can build high-performance, highly scalable ColdFusion systems. You'll have a good grasp of application frameworks and object-oriented development (preferably Fusebox + ColdSpring + Transfer since that's what we use - but experience with otherwise frameworks and a willingness to learn will count).
For both roles, you will be able to work independently (and remotely, if appropriate) but with a focus on delivery and collaboration. Familiarity with source code control (e.g., SVN) and bug tracking software (e.g., Trac) is a requirement.
It's early days for Scazu so we're looking for folks who can be creative about compensation in exchange for a stake in the company. Our collective success will mean you'll be in at the ground level and able to build your own teams over time so it's a great opportunity for the right folks!
You'll learn how we built the back end that supports several functions behind Acrobat Connect and Adobe Document Center - and Kuler - as well as some of our pain points and, in particular, the problems that arise when dealing with error handling around the boundaries of systems in a Service-Oriented Architecture.
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.
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.
Big congratulations to Dave and Chris and the gang - this is an awesome piece of work!
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!
Caveat: the documentation has not yet been updated so you may find yourself asking questions on the coldspring-dev mailing list!
I'll be presenting my "Managing ColdFusion Components with Factories" talk to BACFUG on May 17th (and then my "Objects and Persistence" talk on June 21st).
Adobe San Francisco, 601 Townsend, 7pm
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.
In your fusebox.xml file, you can define a fuseaction that is executed at application startup (on the first request after the application loads):
<appinit>
<fuseaction action="m.initialize" />
</appinit>
</globalfuseactions>
<cs:initialize />
<cs:loadBeans file="/config/beans/cs.xml" />
</fuseaction>
<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.
The thread continues to be interesting so watch the responses over the next day or two. In particular, I like Chris Scott's response that explains why he prefers setter injection (over constructor injection) and then he clarifies the potentially four-step object creation / initialization process that ColdSpring uses (it's much more sophisticated than I realized).
Matt's post talks about specific benefits of ColdSpring for Mach II developers and gives a good example (data source configuration). In particular he is "already seeing a huge benefit to doing things this way" and notes that using the two frameworks in combination "reduces complexity and increases flexibility". That may seem counter to your initial perception: after all, you need to learn another framework and deal with two XML files. I think he's right tho': it helps you focus on the two very different pieces of your application independently which means fewer moving parts to consider at the same time (Mach II for the controller; ColdSpring for the model).
Scott's post is typically more expansive, expressing his initial skepticism (ColdSpring looked like people pushing ColdFusion into the Java mold again) followed by a fairly enthusiastic adoption of ColdSpring. Scott already had some familiarity with the Java Spring framework, which helped him get up to speed. He gives some slightly more involved examples and gives the "MossyBlog stamp of approval".
So there you are: two frameworks together can be simpler than one framework on its own.
It's taken me a few reads to get my head around this and, right now, I don't know how I would use it in an application but it's good to know the functionality is there. I might look at revising the Model-Glue AutoWire controller to use ApplicationContext...
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 c

