Mach-II 1.5 and Transfer
ColdFusionI am working on a little side project to help me dominate my fantasy football leagues. I know I am only about six weeks late in getting this thing on rails, but its for fun and I only have so much time. Before I continue this post, I should preface it by stating that I'm only going to address the integration of Mach-II and Transfer from a basic level; what you read here describes what I have found to be a clean way to access Transfer objects from within Mach-II.
At my main gig. we are using Reactor pretty heavily, and have not had any time to play around with Transfer. Truth be told, none of us are familiar enough with Transfer to really be able to swap it in for Reactor quickly (not to mention the regression testing we'd have to do). Although my little FFL project probably isn't ideally suited for Transfer (I don't expect much transactional work, mostly data mining - so lots of stored procedures and such), I decided this would be a good time for me to get Transfer into my toolbox.
I started developing my application with the Mach-II 1.5 beta, and as luck would have it the final version shipped just this past week I believe. The Mach-II guys have done a hell of a job adding new features to make the framework more powerful and easier to use.
In the past, one of the things that annoyed me about Mach-II was the inability to handle complex data types during application initialization in what I perceived to be a "clean" way. I had to stack up hokey plugins that would do this weird initialization stuff, which kind of obfuscated the application even more (for new developers, the mach-ii.xml config file alone is enough to inspire panic). I didn't notice it in the beta release (it was probably there), but there's a new feature in 1.5 that is expressly designed to make this part of life with Mach-II easier.
Before I learned about this feature, I'd been setting up my TransferFactory in onApplicationStart() and copying it into the application scope. This was okay, but it didn't help me keep all the configuration details in one place which is really my preference. I knew that my alternative was the hokey plugin method I talked about earlier, and I definitely liked that even less.
Mach-II 1.5 introduces the Property object, which is a new framework object, comparable to Plugins, Filters, and Listeners. The Property object is referenced from the section of the mach-ii.xml configuration file, and allows the inclusion of a programmable Property component that extends MachII.framework.Property. Like all Mach-II objects you can write a configure() method to do any necessary initialization, as well as write other methods to do stuff. Which, in my view is where this becomes an ideal place to integrate with Transfer, or possibly other frameworks that you'd like to shoehorn into your Mach-II app.
Because I am not getting into a lot of Transfer details here, I'd like to jump into the code that shows how to set this up (its really quite simple). I apologize for the code formatting, but CodeShare is not working right now.
First, we have a snippet from my mach-ii.xml configuration file. Most of this looks pretty familiar, with the exception of the last line, which references a custom Property component that I have written. I still don't know if I like the name of this object, but basically my intent is to use it as a gunny sack containing references to the stuff I really want, so I guess that ComponentBag will do for now .. I'm open to alternatives (actually now that I think of it, GunnySack sounds not too shabby, either). As with any other framework object you write yourself, you specify a type that names the full path to the CFC.
<properties>
...
<property name="pathToTransferDatasourceConfig" value="/stats/config/datasource.xml" />
<property name="pathToTransferConfig" value="/stats/config/transfer.xml" />
<property name="pathToTransferDefinitions" value="/stats/definitions" />
<property name="componentBag" type="stats.properties.ComponentBag" />
</properties>
Second, is my component, which is pretty small as all I'm doing right now is integrating with Transfer. I realize that coupling the component directly to the Transfer API is not the "ideal" thing to do, which is why ColdSpring integration will come later (this is a subject for another article but honestly there are tons of great ColdSpring references available already). As you can see, my configure() method simply creates and initializes the TransferFactory, using properties I defined in the mach-ii.xml configuration file. I suppose that this proves that simple properties in the configuration file are processed prior to the new Property component type.
<cfcomponent displayname="ComponentBag" extends="MachII.framework.Property">
<cffunction name="configure" access="public" output="false" returntype="void">
<cfset variables.instance = structNew() />
<!--- Instantiate the TransferFactory and cache it --->
<cfset variables.instance.transferFactory =
createObject("component", "transfer.TransferFactory").init(
datasourcePath=appManager.getPropertyManager().getProperty("pathToTransferDatasourceConfig"),
configPath=appManager.getPropertyManager().getProperty("pathToTransferConfig"),
definitionPath=appManager.getPropertyManager().getProperty("pathToTransferDefinitions") ) />
</cffunction>
<cffunction name="getTransfer" access="public" output="false" returntype="transfer.com.Transfer">
<cfreturn variables.instance.transferFactory.getTransfer() />
</cffunction>
</cfcomponent>
Finally, I'm showing you where I use the magical ComponentBag to access the Transfer object. As with all Mach-II framework objects, the PropertyManager can be accessed from within the object as you see here. From there it is a simple matter to pull out the custom component and reference methods or values pertaining to it.
<cfcomponent displayname="FileUploadListener" extends="MachII.framework.listener">
<cffunction name="uploadTeamFile" access="public" output="false" returntype="void">
<cfargument name="event" type="MachII.framework.event" required="true" />
<cfset var importer = createObject("component", "stats.model.Import").init(
appManager.getPropertyManager().getProperty("componentBag").getTransfer()) />
...
</cffunction>
</cfcomponent>
Well, that's about it. I have a few other items I need to write up sometime soon, including how to access web services secured with mutual SSL authentication from ColdFusion, as well as some topics on ColdFusion and WebSphere MQ integration. I figure by posting it here first I am holding myself more accountable for actually writing that content, in some weird way.




Loading....