Viewing By Entry / Main
August 28, 2007
I was experimenting with onMissingMethod() last night in a Mach-II listener and created a controller/listener that lets you implement the Model-Glue style of decoupled broadcast-listener semantics within Mach-II. Let me explain...

In Mach-II, inside an event handler, you notify a specific listener to execute a specific method. In Model-Glue, inside an event handler, you simply broadcast a message and any listeners that have been declared for that message are executed automatically by the framework.

Here's the listener declaration in my mach-ii.xml file that shows the message listener:

<listener name="broadcast" type="MessageListener">
   <parameters>
      <parameter name="some.message" value="listenerA.method1,listenerB.method2" />
      <parameter name="another.message" value="listenerA.method3" />
   </parameters>
</listener>

Here's how you broadcast a message:

<notify listener="broadcast" method="some.message" />

Finally, here's the MessageListener.cfc:

<cfcomponent extends="MachII.framework.Listener" output="false">
   <cffunction name="onMissingMethod" returntype="void" access="public" output="false">
      <cfargument name="missingMethodName" />
      <cfargument name="missingMethodArguments" />

      <cfset var listenerList = getParameter(arguments.missingMethodName) />
      <cfset var listenerManager = getAppManager().getListenerManager() />
      <cfset var listener = 0 />
      <cfset var event = 0 />
      
      <cfif structKeyExists(arguments.missingMethodArguments,"event")>
         <cfset event = arguments.missingMethodArguments.event />
      <cfelse>
         <cfset event = arguments.missingMethodArguments[1] />
      </cfif>
      
      <cfloop index="listener" list="#listenerList#">
         <cfinvoke component="#listenerManager.getListener(listFirst(listener,"."))#"
                  method="#listLast(listener,'.')#"
                  returnvariable="result"
                  event="#event#" />

      </cfloop>

   </cffunction>
</cfcomponent>

Yes, it relies on ColdFusion 8's onMissingMethod() handler so that the MessageListener can respond to any message (i.e., any method call) and it uses the method name to look up the mapping to listeners and methods to be called.

Comments

One thing has that always made me leery of the ModelGlue approach is the opportunity for unintended method calls. In a small application, this should not be a issue, but in a large application, the potential for accidentally giving two methods the same name, e.g., "updateCustomerData" is much greater. Broadcasting the message could lead to hard-to-debug problems.

Perhaps the Mach-II approach is less flexible, but I know exactly which method that I'm invoking.


@Joel, there is no problem with methods having the same name in Model-Glue. The broadcast messages do not simply invoke methods of the same name - you declare a specific method in a specific controller as listening for a specific message. The key is that you can declare additional listeners without having to change the event handler (which you cannot do in Mach-II).

In Model-Glue - as in my example above - the event handler "broadcasts" a message and the framework looks up which methods in which controllers are declared to listen for that message and calls them.

I tend to recommend messages are named "needFoo", "needBar" so that it emphasizes the distinction between message names and method names (which are often "getFoo" and "getBar").


It's worth noting that Mach-II 1.6 will have publish/subscribe broadcast-style message listeners built-in. Thanx to Team Mach-II for that!


Post Your Comments
Name:
Email Address:
Comments
*** Please note that all comments require moderation so it may be some time before your comment posts to this blog! ***
Remember My Information:
 



Hosting provided by