Broadcasts

Okay, so the notion of broadcasts as a means of requesting information from "controllers" or "listeners" is somewhat new to me. I'd heard of it, but not really read anything about it. So doing the Galleon project got me to read some about it and so here I'm going to demystify it a little (even though this information is also included in the project article I'll be publishing soon).

In Mach-II you have "event-handlers" -- and this is roughly analogous to other frameworks as a "fuseaction" (Fusebox) or a "process" (onTap - though I think I may use "event" interchangeably at times). Model-Glue on the other hand also uses "event-handler" as its nomenclature, although the way its event-handlers interact with "listeners" is different. But first you have to understand what a listener is. See we decided with MVC that we wanted to separate the model (business logic) from the view (anything a user sees) and since we did that, we needed something else between them to be sort of a traffic-cop that tells the business logic when to do what and then gives that information over to the view. (This is the way MVC is commonly explained.) So a "listener" in this context is just a component (CFC) that is part of your controller -- it doesn't know anything about your business, doesn't want to know, and it knows very little about the view. All it does is act as a messenger running up to the desk where the business objects work and saying "hey, somebody needs a list of the court cases on today's docket -- you're the clerk, give me the docket".

Now in Mach-II, the event-handler talks directly to the listener (the messenger) and says "I don't know who's in charge of the docket, but I know you can get it, so go get it for me". In Model-Glue on the other hand they actually can't talk directly. In Model-Glue there is a room full o' couriers and the only way to get anything done is to holler out into that room, "hey one of you errand boys go get me the docket! I don't care who it is, I just need it!"

That in essence is what a "broadcast" is. There's a plan to add this in the upcoming 1.6 release of Mach-II, but what I'm more interested in showing is that the same thing is equally and easily achievable with Fusebox, ColdBox or the onTap framework. The only difference really would be the syntax.

In Fusebox all you would be doing is creating a fuseaction in another circuit and calling that fuseaction to give you whatever results are going to come back. For example:

<fuseaction name="showDocket">
   <do action="broadcast.needDocket" />
   < include template="myDocketView" />
</fuseaction>

Now within the broadcast.getDocket fuseaction, you might need to set some variables in the request scope instead of locally, however, the fundamental principal of the broadcast is right there -- you don't know who's responsible for the docket, all you know is that you need it and when you ask for it via "needDocket" somebody supplies it.

ColdBox and nuveau Fusebox using CFCs as circuits works very similarly. The only difference I would make is that I wouldn't put the broadcasts in a separate circuit, but I would name them all the same and make them private methods:

<cffunction name="showDocket" access="public" output="false">
   <cfargument name="Event" type="coldbox.system.beans.requestContext">
   <cfset broadcastNeedDocket(event) />
   <cfset event.setView("myDocketView") />
</cffunction>

<cffunction name="broadcastNeedDocket" access="private" output="false">
   <cfargument name="Event" type="coldbox.system.beans.requestContext">
   <cfset var rc = event.getCollection() />
   <cfset logDocketRequest(event) />
   <cfset rc.docket = ... />
   <cfset rc.docketHelper = ... />
   ...
</cffunction>

And in the onTap framework yet again, same basic principal, slightly different syntax:

<cfinclude template="/inc/broadcast/needDocket.cfm" />

or

<cf_process netaction="broadcast/needDocket" />

Then of course in that include template you would reference whatever business objects needed to be referenced for that particular broadcast. There are only a couple of reasons why using this include would be beneficial over for example calling a nested event (similar to the Fusebox <do>) and those are that this way all the variables that will be set in the broadcast can be set locally instead of needing to be returned or set directly into the caller or request scopes, and that the include won't bootstrap the framework and execute a whole event making it more efficient. If speed is vitally important, use the include. In some circumstances however there are advantages to executing the nested event with cf_process as a method of broadcast.

And I'll make one last comment on this about Mach-II. Their wiki says that right now you can't broadcast anything, but that's really not true. The 1.5 release of Mach-II already provides a feature called a subroutine that can be used as a method of broadcast and honestly is probably already only cosmetically (syntax) different from what will be in the 1.6 release.

<event-handlers>
   <event-handler event="showDocket">
      <execute subroutine="needDocket" />
      <view-page name="showDocket" />
   </event-handler>
</event-handlers>

<subroutines>
   <subroutine name="needDocket">
      <notify listener="docketListener" method="getDocket" resultArg="docket" />
      <notify listener="docketListener" method="getDocketHelper" resultArg="docketHelper" />
      <notify listener="logger" method="logDocketRequest" />
   </subroutine>
</subroutines>

So there you have it. Broadcast. The OO equivalent of a <cfinclude>. (In this context at least -- I believe there are other contexts in which it's something else.)

Related Blog Entries

Comments
Peter J. Farrell's Gravatar Isaac, the assumption that broadcasts and subroutines are "probably already only cosmetically (syntax) different" is far from the truth.

As you elude to, subroutines are like a virtual XML "cfinclude" -- in which the subroutine is immediately executed. However in your example, you would still have to have <notify> commands inside your subroutine in order to get the data you require. Notify is a direct invocation of a listener method meaning that you have to couple the listener name and necessary method for it run. It's debatable how much coupling this introduces, but it is "some" coupling nonetheless. The new message subscriber functionality (i.e. broadcast) already in the 1.6 BER is different because you publish a message in which elsewhere in your XML you define what listener methods have a registered interest in what messages. This allows you to swap listeners or methods that have an interest in a message in one spot rather than find/replace a bunch of xml. This scenario is more common than one might expect especially during the maintenance period of an application (which is the majority of the lifespan of application lifecycle).

The message subscriber functionality also adds in multi-threading capabilities including the ability to publish a message and not wait for the subscribers to return data. It also will run subscribers in parallel if the CFML engine doesn't support threading. Also, the threading is abstracted away for you via our ThreadAdapters as threading implementations differ from CFML engine to another CFML engine.

You can read the original specification here:
http://docs.google.com/View?docid=dhjcwfn4_38gnmpf...
# Posted By Peter J. Farrell | 6/11/08 3:21 PM
ike's Gravatar Thanks Peter. I was just about to respond with "I'm still not seeing the difference" until I hit your 2nd paragraph. :P With the addition of threading, yes I see a significant difference. Up to that point however, I don't see a real significant difference in terms of coupling between declaring the message inside the listener in the XML or declaring the listener inside the "message" where the message is declared as a subroutine. In either case it seems to me like the same amount of XML and the same advantage of having just one place to change who listens to that message. But I'll certainly let people know about the threading -- I'll probably actually add a note about that in the list of features for Mach-II in my Galleon Ports project as well -- I've already got a couple of other edits to make and I'm sure I'll have lots more.
# Posted By ike | 6/11/08 6:55 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.5.006. | Protected by Akismet | Blog with WordPress