Skip to content

Using Event Mappings

thofrey edited this page Apr 1, 2014 · 4 revisions

Table of Contents

  1. What are event mappings?
  2. Application Flow Visibility
  3. Portability
  4. Readability
  5. Common Questions
  6. In Closing

What are event mappings?

Mach-II offers an event-mapping xml command available for use within your mach-ii configuration file. The purpose of the event mapping command is to allow the developer to create generic event names, thereby allowing the abstraction of literal event names from application listeners. This approach offers at least two key advantages outlined below.

Application Flow Visibility

First, let's take a look at some sample code that does not take advantage of event-mappings:

    <!-- without event mappings -->
    <event-handler event="processLoginAttempt" access="public">
        <notify listener="SecurityListener" method="attemptLogin" />
        <execute subroutine="buildLayout" />
    </event-handler>
    <!--- in SecurityListener --->
    <cffunction name="attemptLogin">
        ... arguments, logic ...

        <cfif qLogin.recordCount gt 0>
            <cfset exitEvent = "showWelcomeScreen" />
        <cfelse>
            <cfset exitEvent = "showLoginForm" />
        </cfif>

        <cfset announceEvent(exitEvent, arguments.event.getArgs()) />

    </cffunction>

You will notice above that without using event-mappings, the event names showWelcomeScreen and showLoginForm are hardcoded within the listener's code. This makes debugging more difficult as the developer can not simply glance at the event-handler's .xml and determine the possible outcomes easily. In this example, the developer needs to open the SecurityListener and read its code to determine the possible outcomes.

As a point of contrast, let's see how the same code might look if the developer had taken advantage of Mach-II event-mappings:

    <!-- with event mappings -->
    <event-handler event="processLoginAttempt" access="public">

        <event-mapping event="pass" mapping="showWelcomeScreen" />
        <event-mapping event="fail" mapping="showLoginForm" />
        <notify listener="SecurityListener" method="attemptLogin" />

        <execute subroutine="buildLayout" />
    </event-handler>

As illustrated in the xml block above, note that event-mappings must be declared before they can be referenced in any listener methods. If you were to set the event-mappings after the notify command, the listener would not have access to the mappings and an exception would occur. Remember that event-handlers process commands in the order they are defined and therefore the event-mappings need to be declared first. As a result, the usual convention is to always define mappings at the top of event-handlers if they are used in that event-handler.

Let's now take a look at how including event-mappings has improved the code in our Mach-II listener.

    <!--- in SecurityListener --->
    <cffunction name="attemptLogin">
        ... arguments, logic ...

        <cfif qLogin.recordCount gt 0>
        <cfset exitEvent = "pass" />
        <cfelse>
        <cfset exitEvent = "fail" />
        </cfif>

        <cfset announceEvent(exitEvent, arguments.event.getArgs()) />

    </cffunction>

In this example, the developer has not hardcoded any event names within the listener file, and instead has clearly defined them in the .xml configuration file.

Portability

Another key advantage to using event-mappings is the issue of portability. If the developer hardcodes literal event names within his/her listeners, he will have trouble reusing those listeners without modification in another application. This is due to the fact that each application has its own needs, and therefore has its own unique set of event-handlers. For this reason, using generic event-mappings, such as "pass" or "fail" within the listener is often a better solution as it can allow the listener to be reused in another application without modification.

Readability

The biggest advantage of using event-mappings is that the flow of your application can be completely seen from your XML configuration files without having to open up listeners or filters to find out the next event name. Other than providing a way to "generic-ify" your listener's event announcing to make them more reusable, readability is the primary reason event-mappings should be used.

Common Questions

Can I use event-mappings in conjunction with the redirectEvent() method ?

Yes, both announceEvent() and redirectEvent() respect event-mappings made for the current event-handler.

Example event handler:

    <event-handler event="something" access="public">
        <event-mapping event="pass" mapping="somethingGood" />
        <event-mapping event="fail" mapping="somethingBad" />
        <notify listener="widget" method="makeDecision" />
    </event-handler>

In makeDecision():

    <cffunction name="makeDecision" access="public" returntype="void" output="false">
        <cfargument name="event" type="MachII.framework.Event" required="true" />

        <cfset var result = false />

        <!--- ... stuff that decides the value of the "result" variable ... --->

        <cfif result>
            <cfset redirectEvent("pass") />
        <cfelse
            <cfset redirectEvent("fail") />
        </cfif>
    </cffunction>

I have an event-mapping defined in my event handler. Why is it when I call announceEvent() or redirectEvent() my mapping is ignored or not found?

Check where in your event-handler your event-mapping is defined. You must defined your event-mapping in the XML before you call announceEvent(), redirectEvent(), <announce> or <redirect>. The commands in the event-handler are processed in the order they are defined (like a stack).

Where should I define my event-mappings?

It's common practice to define all of your event-mappings at the top or near the top of your event-handler before any application flow control logic is done via filter or listeners.

Can I set event-mapping and use the generic mapping inside a filter?

Yes, all API methods and commands in Mach-II will look for event-mappings first. It does not matter if they are used in XML or in you CFML code in filters or listeners.

In Closing

Team Mach-II recommends that hard coding of event names should be avoided in listeners and filters. This can be accomplished by using event-mappings within the Mach-II XML config file and announcing "generic" events inside your listeners and filters.

Clone this wiki locally