Mixing a little Flex with my Mach-II
ColdFusion, MachII, Web Development, FlexOne of my latest projects was to create a little contact manager / sales tool to integrate with an existing system (written in Mach-II). Requirements dictated that I needed to have access to my already logged in user (must be aware of client session). "Down the road" requirements, are that we'd like to make an AIR port of this new feature as a standalone application. As a big fan of Flex, I thought it would be a great opportunity to test the efficacy of writing this new feature as a drop in Flex mini-application.
Since security is handled by the existing application, we needed to make sure the functionality of this app respected the existing security guidelines. The best way I could think of was also the easiest...just start calling events and see what happens.
Lucky for me, it all just worked. So here are a few examples that might help get you started if you are working on the same sort of project.
On creationComplete I call a method named "init()" to get that user's set of contact data:
private var myLoader:URLLoader;
public function init():void
{
var myReq:URLRequest = new URLRequest('/index.cfm/event/GetContactData);
myLoader = new URLLoader()
myLoader.addEventListener(Event.COMPLETE, dataComplete);
myLoader.load(myReq);
}Important: Notice the event listener I added to call the dataComplete method once the request was completed.
Once we have that initial set of data, all that is left is to start POSTing the create/edit/deletes the user is making to his contacts.
Here is an example of doing an HTTP POST request and passing my Contact object to a Mach-II event:
private function saveContact(Contact:ContactVO):void {
var myHTTPService:HTTPService = new HTTPService;
myHTTPService.method= "POST";
myHTTPService.url = '/index.cfm/event/SaveContact';
myHTTPService.addEventListener(ResultEvent.RESULT,function():void{init()});
myHTTPService.send(Contact);
Alert.show('Contact has been saved.');
}Note: Check out how we send the Contact object without doing anything tricky? All of the properties of my ContactVO are available as event Args in my Mach-II listener.
Here is another example of doing an HTTP POST request, but passing individual variables:
private function submitNote(htmlText:String,plainText:String,Contact:ContactVO):void
{
var myHTTPService:HTTPService = new HTTPService;
var obj:Object = new Object();
myHTTPService.method= "POST";
myHTTPService.url = '/index.cfm/event/saveNote';
obj['notetext'] = htmlText;
obj['notepreview'] = plainText;
obj['contactid'] = Contact.ContactId;
myHTTPService.addEventListener(ResultEvent.RESULT,function():void{init()});
myHTTPService.send(obj);
}Note: Notice how we create an object and define the properties we want to send, and then pass that new object in the POST.
Never use .CSS files again
MachII---AKA really really dynamic style sheets---
Recently I blogged about they new way I am serving XML data to my apps and, thinking along those same lines, I decided to serve up the .css “files” in much the same manner. The need to deliver completely separate styles to the same layout is not that uncommon if you are writing an application that will give the user a choice of “skins” (as we do on InstantSpot.com ).
Here is a basic run-down:
Let's say, we have an object “Skin” which has, as one of its attributes, Style. Style contains the actual css info that would normally be housed in your style.css (or whatever you called it) style sheet.
Now, we have a layout that needs to link to some style sheet, or we would have a pretty plain looking site. Normally there would be a link to a file under the web root like:
<link rel="stylesheet" xhref="/skins/style.css" type="text/css" />
Since, in this scenario, we don't really have anymore style.css anywhere we need to have some new way to style our site. One possibility, we could create a Mach-II event called “style.css” that pulls that data from the Skin object, and passes it on to the view.
<event-handler event=”Style.css” access=”public”>
<notify listener=”StyleListener” method=”getStyle” resultArg=”CSS” />
<view-page name=”showCSS” />
</event-handler>
ShowCSS is simple a cfcontent and a cfoutput much like my other dumb XML view.
<cfcontent type=”text/css”>
<cfoutput>#event.getArg(“CSS”)#</cfoutput>
And finally, we can now link in that new style sheet via our Mach-II event.
<link rel="stylesheet" xhref="/index.cfm/event/style.css" type="text/css" />
voila...no more style.css files.
I have used other methods for using dynamic data in a stylesheet before but there is something beautiful to me about using the Mach-II event. Also, the .css extension on the event name might appease the validators out there.
PS. There is more to this story, stay tuned for the real reason we needed “really really dynamic style sheets”
Secure your XML
MachIISecond...the issue at hand.
I'm using a few XML 'documents' to feed SPRY ds's in secured areas of my app, all of which containing sensitive data.
I don't want to a) actually write any of the content to a file, or b) allow unauthorized users to ever get to or see that data.
As it turns out its fairly simple to do.
Instead of defining the location of an XML file for my Spry ds like
new Spry.Data.XMLDataSet("UserAccounts.xml", "useraccounts/useraccount")
I merely supply that DataSet call with the link to a Mach-II event like so... (I named the event with a '.xml' extension just because I thought it was cool, it is not required)
new Spry.Data.XMLDataSet("/index.cfm/event/UserAccounts.xml", "useraccounts/useraccount")
warning...pseudo-code ahead:
Then, my event-handler only needs to a)check authentication, b) generate the content, c) pass it to a dumb view.
<event-handler event="UserAccounts.xml" access="public">
<filter name="CheckAdminLogin" />
<notify listener="CustomerAdminListener" method="generateUserAccountsXML" resultArg="XML"/>
<view-page name="showXml" />
</event-handler>
(I won't get in to actually creating valid XML since that isn't really relevant to this post.)
Once that listener has created the eventArg and passed it to the view, all the view does is something like this:
<cfcontent type="text/xml" reset="yes">
<cfoutput>#event.getArg("XML")#</cfoutput>
The end...
Mach-II, Event Chains, And You
MachII(Let me preface this by saying the general concept is successful, but the actual reason I created this plugin has yet to be addressed...so it may or may not be the best solution for the problem at hand.)
We have decided that we want to assemble some user interface sections out of a few different events (Mach-II Events) but, throughout the process we may or may not want to do some event mapping to dynamically call events in that process.
Example:
We want to have an event that sets specific args (title, dimensions, data, whatever) that gets passed to another event that will assemble that info into a 'dumb' form layout, or form widget, etc. Now, the big deal here is that these dumb widgets are going to be used by any number of other events so they must be able to accept info from previous events, and decide whether or not to continue announcing other events to complete the request.
The hour long drive home yesterday got me thinking of a way to gracefully dictate that event flow, while still being very clear in the controller (the machii config xml) what was going to happen on that request. The EventChain plugin was born out of that brainstorming session.
The EventChainPlugin simply has a postEvent() process that looks for the existence of an event-arg named “EventChain” which is a comma delimited list of event names you would like to have run in that request. In the very first event that is run on the request, you build your chain and let the plugin do the rest.
<event-handler name=”Event1”>
<event-arg name=”EventChain” value=”event2,event3,event4,event5” />
<!--
do event stuff here
--->
</event-handler>
<event-handler name=”Event2”>
<!--
do event stuff here
--->
</event-handler>
and so on...
(notice: only assign the arg in that initial event if you want to be able to use your other events wherever you want)
If you don't supply the EventChain arg, or it finishes its list of events, it just rests peacefully waiting for the next chain.





Loading....