Overview

Event map

Central to Mate is the Event Map. In the Event Map (or multiple event maps), you define what needs to happen when certain events are dispatched. Each event type you want to listen to will have its own Event Handlers block in the event map.

<EventMap xmlns="http://mate.asfusion.com/">
   ...event handlers blocks here...
</EventMap>

An EventMap is typically an stand-alone mxml file, and you must place it in your Application file. This requirement is due to the component creation cycle that Flex follows. If you place your event map deep inside your application, it may not be instantiated early enough to listen to all the events. Placing it in the Application file also allows you to be able to listen to early Flex events such as FlexEvent.PREINITIALIZE.

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:maps="com.yourdomain.maps.*">


   <maps:MyEventMap />

   ...other application components here...

</mx:Application>

Event Handlers

An Event Handlers block defined in the Event Map will run whenever an event of the type specified in the EventHandlers' "type" argument is dispatched. Note that in order for the handlers to be able to listen for the given event, this event must have its bubbling setting as true and be dispatched from an object that has Application as its root ancestor, or the event must be dispatched by a specific dispatcher available as "scope.dispatcher" from the Event Map.

To define a an Event Handlers block, use the EventHandlers tag.

<EventHandlers type="myEventType">
... here what you want to happen when this event is dispatched...
</EventHandlers>

As mentioned earlier, you place these Event Handler lists inside an Event Map:

<EventMap xmlns="http://mate.asfusion.com/">
      
   <EventHandlers type="myEventType">
      ... here what you want to happen when this event is dispatched...
   </EventHandlers>

   <EventHandlers type="myOtherEventType">
      ... here what you want to happen when this other event is dispatched...
   </EventHandlers>

</EventMap>

Inside the EventHandlers tag, you will place all the handlers that need to be called when the event is dispatched.

For example, if you wanted the handler list to run, you must dispatch an event of type "myEventType". Say you have a button that when clicked, the event is dispatched (note that this event has its bubble property set to true):

private function buttonClicked():void {
	var event:MyCustomEvent = new MyCustomEvent("myEventType", true);
	dispatchEvent(event);
}

This example assumes you have a custom event class called MyCustomEvent. When the button is clicked and the function buttonClicked() is executed, the first event handler list will receive the event and run each of the handlers it contains in order.

There are several handlers you can specify and each of them serves a different purpose:

Method Invoker

MethodInvoker is one of the most used tags. When placed inside an EventHandlers tag and the handlers are executed, it will create an object of the class specified in the "generator" attribute. It will then call the function specified in the "method" attribute on the newly created object. You can pass arguments to this function that come from a variety of sources, such as the event itself, a server result object, or any other value.

<MethodInvoker
   generator="ClassNameToInstantiate"
   method="methodToExecute"
   arguments="{['argument1', 'argument2']}"/>

The above example would be the same as doing the following in ActionScript code:

var myWorker:ClassNameToInstantiate = new ClassNameToInstantiate();
myWorker.methodToExecute('argument1', 'argument2');

There are other ways of specifying attributes and there are additional attributes you can use. Refer to the documentation for detailed use information.

Event Announcer

Whenever you want to trigger another event inside an event handlers block, you use the EventAnnouncer tag.

<EventAnnouncer type="myEventType" generator="EventClassNameToInstantiate" />

You can also provide properties for the newly created event:

<EventAnnouncer type="myEventType" generator="MyEventClass">
   <Properties myProperty="myValue" myProperty2="other value"/>
</EventAnnouncer>

As in the case of the MethodInvoker arguments, properties for the new event can be brought from the original event, a server result, and other sources.

The above example would be the same as doing the following in ActionScript code:

var myEvent:MyEventClass = new MyEventClass("myEventType", true);
myEvent.myProperty = "myValue";
myEvent.myProperty2 = "other value";
dispatchEvent(myEvent);

The main difference is that in the case of the EventAnnouncer, the event is dispatched whenever the container event handler list is run and in the order specified in the list.

Service Calls

You can call different service types by using the HTTPServiceInvoker tag, the WebServiceInvoker tag or the RemoteObjectInvoker tag. If you have an already created service (HTTP service, Web Service, and Remote Object), you can use the "instance" attribute so that you don't have to specify the service properties in the Event Map. In that way, you can use a separate file to create all the services you use. You can use the Service Invoker tags (WebServiceInvoker, RemoteObjectInvoker, HTTPServiceInvoker) to create your services inline in the event map.

<WebServiceInvoker instance="{myServiceInstance}" method="serverMethodToCall" arguments="{['argument1', 'argument2']}" />

When a service is called, there are two type of responses you can get: either a result with the contents of what the service returned, or a fault when there was an error when contacting the server or an error was thrown by the server. It's important to note that these possible responses are received asynchronously, so that after the request to the server was made, it is not possible to know when the response will be received.

When you use any of the Service Invoker tags inside the EventHandlers block, the server request is made and the list execution continues. Any other handlers placed after the service will execute right after the server request is made. But what if you want to wait until the server responds to the request? Inside the Service Invoker tags, you can place another list of handlers that will execute when the server replies, or throws an error.

<WebServiceInvoker instance="{myServiceInstance}" ...>

   <resultHandlers>
       ... this lsit of handlers executes when server returns results ...
   </resultHandlers>

</WebServiceInvoker>

In the same way, you can place another sequence that will execute when the request ends up in an error.

<WebServiceInvoker instance="{myServiceInstance}" ...>

   <faultHandlers>
      ... this sequence executes when server returns an error ...
   </faultHandlers>

</WebServiceInvoker>


Of course you can have both sequences inside one service tag:

<WebServiceInvoker instance="{myServiceInstance}" ...>

   <resultHandlers>
      ... this sequence executes when server returns results ...
   </resultHandlers>
   
   <faultHandlers>
      ... this sequence executes when server returns an error ...
   </faultHandlers>

</WebServiceInvoker>

WebService Invoker

The WebServiceInvoker tag is used to create a web service instance and call a method on the web service created. To use this tag, you need to specify its wsdl attribute that will determine the address of the webservice, or you use the instance attribute as specified in the previous section. You also need to specify the method to call.

<WebServiceInvoker wsdl="wsdAddress" method="methodToCall" arguments="{['argument1', 'argument2']}">

</WebServiceInvoker>

This tag will also accept all mx.rpc.soap.WebService tag attributes.

As specified in the previous section, you can have resultHandlers and faultHandlers inside the tag to handle service results and faults.

<WebServiceInvoker wsdl="wsdAddress" method="methodToCall" arguments="{['argument1', 'argument2']}">
   <resultHandlers>
      ... these handlers execute when server returns results ...
   </resultHandlers>

   <faultHandlers>
      ... these handlers execute when server returns an error ...
   </faultHandlers>
</WebServiceInvoker>

HTTPService Invoker

The HTTPServiceInvoker tag is used to create an HTTP Service instance and make a GET or POST request to that service. To use this tag, you need to specify the same attributes you would when creating an HTTP service with the <mx:HTTPService> tag, or you use the instance attribute as specified in the "Service Calls" section.

<HTTPServiceInvoker url="URLToCall" />

This tag will also accept all mx.rpc.http.HTTPService tag attributes.

You can have resultHandlers and faultHandlers inside the tag to handle service results and faults.

<HTTPServiceInvoker url="URLToCall">
   <resultHandlers>
      ... these handlers execute when server returns results ...
   </resultHandlers>
   <faultHandlers>
      ... these handlers execute when server returns an error ...
   </faultHandlers>
</HTTPServiceInvoker>

RemoteObject Invoker

The RemoteObjectInvoker tag is used to create a Remote Object instance and call a method on the object created. To use this tag, you need to specify the same attributes you would when creating a remote object with the <mx:RemoteObject> tag, or you use the instance attribute as specified in the "Service Calls" section. In addition, you need to specify what method to call.

<RemoteObjectInvoker
   destination="YourDestination"
   source="path.to.your.service"
   method="methodToCall"
   arguments="{['argument1', 'argument2']}" />

This tag will also accept all mx.rpc.remoting.RemoteObject tag attributes.

You can have resultHandlers and faultHandlers inside the tag to handle service results and faults.

<RemoteObjectInvoker destination="YourDestination" source="path.to.your.service" method="methodToCall" arguments="{['argument1', 'argument2']}">
   <resultHandlers>
      ... this sequence executes when server returns results ...
</resultHandlers>
   <faultHandlers>
      ... this sequence executes when server returns an error ...
   </faultHandlers>
</RemoteObjectInvoker>

Data Copier

The DataCopier tag is a handy tag to quickly copy values into some storage. You can use the event handler list's "data" as a temporary storage from where handlers that follow in the list can read values. You can also use some other external variable as the storage.

<DataCopier destination="data" destinationKey="someProperty" source="result" sourceKey="someProperty" />

Stop Handlers

Event Handlers run all handlers in order. If you need to stop the handlers execution before it reaches the end of the list, you can use the StopHandlers tag.

If there exists a MethodInvoker tag right before the StopHandlers tag, and the execution of the function returned a value, you can compare it to some other value and stop the handlers if it is equal.

<StopHandlers lastReturnEquals="someValue" />

A more flexible approach is to use the stopFunction attribute and handle the logic externally. The function that you implement will return true if the execution must stop or false if not.

<StopHandlers stopFunction="myStopSequenceFuntion" />

Then you implement your evaluation function:

private function myStopFunction(scope:Scope):Boolean {
	... here you do some evaluation to determine
	whether to stop the execution of the list or not...
	return false;
    //or return true;

Message Handlers

The list of EventHandlers runs when an event of the type specified is dispatched. The list of MessageHandlers, on the other hand, runs whenever a Message sent by a Flex Messaging Service is received. This message must match certain criteria similar to the criteria specified when using the <mx:Consumer> tag.

To define the handlers, use the MessageHandlers tag.

<MessageHandlers destination="YourGateway">
   ... here what you want to happen when this message is received ...
</MessageHandlers>

Just like when using the EventHandlers tag, you place this tag inside an EventMap. Between the tag block, you place the actions to perform when the message is received. You can use the same tags as you would inside the EventHandlers tag: MethodInvoker, EventAnnouncer, etc.

14 responses

  1. It would be great to see this information in an eBook, cheat sheet or similar document. Though I am green... my brain often isn't. I still like print.
  2. Hi John,
    Good suggestion.
    As a temporary solution, you can download the PDF containing the complete current documentation from the Downloads page (note: it doesn't have an index).
  3. bubbles:Boolean="true" -- a beginner such as myself might not appreciate how significant this is, until after way too many minutes of head-scratching.
  4. No, I need a diagram far earlier! Not being from a Cairngorm (or other educated) background I still need an overview of this overview with a few of your interesting diagrams to explain things. I've looked at the diagrams and it makes me want to jump in, but I'm still not sure of the direction I should be pointing. Maybe "Mate for Dummies" equivalent.

    The getting started looks like the main way of learning, I should have faith, I suppose.

    Could you compare it with the MVC of Cairngorm to show benefits that might be gained.

    Thanks
  5. That is cool solution for declarative programming in xml but I think using string indentificators for property names etc. can be a real problem in big projects (also after re-factorings).
  6. "Identificators"... lol, boy is that funny. No wonder people avoid OO programming. They must wonder if we know what we are talking about with terms like that, eh?
  7. This sounds very interesting and I will certainly look more. I too am new to Flex frameworks and have looked at others like PureMVC, Cairngorm and even EasyMVC. I would like to see some info on Mate's 'scalability' and complexity for 'project creep' and perhaps 'reusability.'

    Existing perhaps?

    TY
  8. It seems that a significant part of Mate is how it caches objects. However, unless I am missing something, there seems to be very little from an overview standpoint on how objects are cached and the limitations on accessing them. For example, are they cached with respect to a specific map or cached globally. Can you access the objects across maps. If not, are there workarounds. What are the exceptions, if any, etc.

    This would be really helpful to expound on.
  9. "...Can you access the objects across maps..."

    Yes. Use the cache="global" setting in your maps.

    Greg
  10. Is there a way to do without the XML event maps? It seems like setting up the XML event map is describing in XML what I could do in code much easier. Maybe I'm spoiled by Ruby in that you use the language for everything. Why can't it be as simple as:

    EventMap["QuoteService.GET"] = someCommandObject;

    The frameworks I've seen for Flex feel 'enterprisy'. I've done enough enterprise apps to know most of it is just theoretical infrastructure because components can possibly change instead of using the least amount of patterns to be sound and practical.
  11. i dont get a $$$$- I think this is a bad explanation.
  12. How would you use tokens with your service call tags?
  13. Hi Amy,
    It depends on what you want to do with the token. If you need it in the map, you can get it in the lastReturn object. See: http://mate.asfusion.com/page/documentation/tags/eventmap/using-smart-objects#lastReturn
  14. I can't seem to find any info on this ... If you have multiple maps, are they processed in the order they appear in the declarations or alphabetically? I'd like to have separate maps for different contexts some relating to views others relating to more global business, but if GlobalMap is processed after ApplicationMap which would process after AardvarkMap then its not much help and i may as well put it all in one map, probably AardvarkMap to be obtuse.

    Please say im doing something obvious & dumb. In a quick test project containing 3 maps in the application each with one class constructed via an object builder, i'd expect the first class in the first map to be built first, but this doesnt seem to be whats happening: I'd expect the 'CharlieClass' in 'CharlieMap' to be built first, however 'AlphaClass' from 'AlphaMap' is getting there first.

    [Application.mxml]
    ...
    <fx:Declarations>   
    <maps:CharlieMap />
    <maps:BravoMap />
    <maps:AlphaMap />
    </fx:Declarations>
    ..

    [AlphaMap.mxml]
    ...
    <mate:EventHandlers type="{FlexEvent.PREINITIALIZE}">
    <mate:ObjectBuilder generator="{AlphaClass}" constructorArguments="{scope.dispatcher}"/>
    </mate:EventHandlers>
    ...

Comments now closed