MethodInvoker

(This tag must be placed inside an <EventHandlers> tag or a <MessageHandlers> tag)

MethodInvoker is one of the most used tags. When placed inside a EventHandlers tag and the list of handlers is 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. Unless you specify cache="false", this object instance will be "cached" and not instantiated again.

Example:

<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');

The main difference is that in the case of the MethodInvoker, the object is created and the function executed whenever the list of handlers is run and in the order specified in the list.

Note: To call static methods, methods on a singleton object, or on an object that has been created elsewhere, use the InlineInvoker tag instead.

Attributes

generator

required

The generator attribute specifies what class should be instantiated and run.

Suppose you have a class called "MyWorker" in the package com.yourdomain.business. You can specify a complete path to com.yourdomain.business.MyWorker:

<MethodInvoker
   generator="com.yourdomain.business.MyWorker"
   method="methodToExecute"
   arguments="{['argument1', 'argument2']}"/>

Generally you may want to use a binding to specify the class name. Assuming you have an import statement like this in your Event Map:

import com.yourdomain.business.MyWorker;

or simply:

import com.yourdomain.business.*;

You can then instantiate your object using bindings:

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

The advantage of using this syntax is that if you are using Flex Builder, you can press the command key (Mac) or the Ctrl key (Windows) and click on the generator class (MyWorker in the example) and it will take you to the class definition.

method

The method attribute specifies what function to call on the created object. If your class MyWorker contains a function called doWork(), you would then write:

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
/>

arguments

If the function in your class has arguments, you can pass them via the "arguments" attribute. Suppose your doWork function has the following signature:

public function doWork(name:String, value:Number)

then you can pass those arguments as follows:

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{['Tom', 36]}"/>

Note that the arguments attribute expects an array. Besides passing literal values, you can pass values coming from the event that triggered the execution of the list of handlers:

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{[event.userName, event.age]}"/>

This assumes that the event contained a userName property and an age property.

If this method invoker tag is inside an <resultHandlers> tag that originated from a <WebServiceInvoker>, <HTTPServiceInvoker> or <RemoteObjectInvoker> tag, you can also pass values coming from the server result:

<RemoteObjectInvoker .....service attributes....>

   <resultHandlers>
   
      <MethodInvoker
         generator="{MyWorker}"
         method="doWork"
         arguments="{[resultObject.userName, resultObject.age]}"/>


   </resultHandlers>
   
</RemoteObjectInvoker>

Again, this assumes the server returned an object that contained a userName property and an age property.

If this MethodInvoker tag is inside an <faultHandlers> tag that originated from one of the service invoker tags, you can also pass values coming from the server fault. This comes in handy when you want to handle possible server errors.

<RemoteObjectInvoker .....service attributes....>

   <faultHandlers>
   
      <MethodInvoker
         generator="{MyWorker}"
         method="doWork"
         arguments="{[fault.faultDetail, fault.errorID]}"/>


   </faultHandlers>
   
</RemoteObjectInvoker>

You can also pass the complete event, resultObject, fault, data or lastReturn as an argument depending on what your function expects.

For example, if the function has the following signature:

public function doWork(event:MyCustomEvent):void

you would be able to send the event as an argument of the method:

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{[event]}"/>

If you wanted to send a service result, you would pass the resultObject as an argument.

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{[resultObject]}"/>

Your worker function signature would depend on what you are expecting to receive from the server. If you are using Flash Remoting, you might be getting a mapped class, such as a Customer.

public function doWork(customer:Customer)

If you are using HTTPService, you might be getting an XML object:

public function doWork(xmlDoc:XML)

You can also use the service fault, the sequence data or a lastReturn.

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{[fault]}"/>

The data is always an object, so your function must accept an object:

public function doWork(data:Object)

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{[data]}"/>

Receiving the value returned by a previous MethodInvoker execution:

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{[lastReturn]}"/>

Of course you can use any combination of arguments:

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{[event.age, resultObject, 'Tom']}"/>

Specifying only one argument

Although the arguments attribute expects an array, it is also possible to supply an object when there is only one argument that the worker function expects. See these examples:

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="A string"/>

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{event}"/>

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{event.userName}"/>

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{resulObject}"/>

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{resulObject.userId}"/>

<MethodInvoker
   generator="{MyWorker}"
   method="doWork"
   arguments="{lastReturn}"/>

Specifying the arguments in verbose mode

Finally, arguments can also be passed by using SmartObjects.

For example, if you want to pass event.userName and event.age, you can pass them as follows:

<MethodInvoker generator="{MyWorker}" method="doWork">
   <arguments>
      <SmartObject source="event" key="userName" />
      <SmartObject source="event" key="age" />
   </arguments>
</MethodInvoker>

cache

Boolean

The cache attribute lets you specify whether this newly created object should be kept live so that the next time an instance of this class is requested, this already created object is returned instead.

For example, say you have two sequences that want to use the same instance of an object. Since the default value for this attribute is "true", it will do that by default. On the other hand, if you wanted to have two different instances, then you must set this attribute to "false".

<EventHandlers type="myEventType">

   <MethodInvoker
      generator="{MyWorker}" method="doWork"
      cache="false" />

      
</EventHandlers>

<EventHandlers type="myOtherEventType">

   <MethodInvoker
   generator="{MyWorker}" method="doDifferentWork"
   cache="false" />

   
</EventHandlers>

Inner tags

Properties

You can add properties to your object by using the Properties tag inside the MethodInvoker tag. These properties will be set before calling the function specified in the "method" attribute, so you can be sure that those properties will be available when the function is executed. These properties must be public.

Suppose you are creating an instance of a ShippingCalculator class. This class has a property called weightFactor and flatFee. In order to set those two properties, you can use the <Properties> inner tag. As attributes of the Properties tag, you can specify the names of your properties and set the values of those properties by setting the value of those attributes as follows:

<MethodInvoker
   generator="{ShippingCalculator}"
   method="calculateShipping" .... >


      <Properties weightFactor="0.5" flatFee="3" />

</MethodInvoker>

Besides specifying literal values, you can assign values coming from the event that triggered the handlers:

<MethodInvoker
   generator="{ShippingCalculator}"
   method="calculateShipping" .... >


      <Properties weightFactor="{event.factor}" flatFee="{event.fee}" />

</MethodInvoker>

This assumes that the original event contained a factor property and a fee property.

If this MethodInvoker tag is inside a <resultHandlers> tag that originated from one of the service invoker tags, you can also pass values coming from the server result:

<RemoteObjectInvoker .....service attributes....>

   <resultHandlers>
   
      <MethodInvoker
         generator="{ShippingCalculator}"
         method="calculateShipping" .... >

      
            <Properties weightFactor="{resultObject.factor}" flatFee="{resultObject.fee}" />
      
      </MethodInvoker>
      
   </resultHandlers>

</RemoteObjectInvoker>

This assumes the server returned an object that contained a factor property and a fee property.

If this MethodInvoker tag is inside an <faultHandlers> tag that originated from one of the service builder tags, you can also pass values coming from the server fault. This comes in handy when you want to handle possible server errors.

<RemoteObjectInvoker .....service attributes....>

   <resultHandlers>
   
      <MethodInvoker
         generator="{MyErrorHandler}"
         method="handleShippingError" .... >

      
            <Properties myErrorProperty="{fault.faultDetail}" />
      
      </MethodInvoker>
      
   </resultHandlers>

</RemoteObjectInvoker>

You can also use the complete resultObject, fault or data as a property depending on what your event properties are.

For example, if the server returned a number with the value of the flat fee, you would be able to set the property "flatFee" with the server result:

<MethodInvoker
   generator="{ShippingCalculator}"
   method="calculateShipping" .... >


      <Properties flatFee="{resultObject}" />

</MethodInvoker>

You can use the service fault:

<MethodInvoker
   generator="{MyErrorHandler}"
   method="handleShippingError" .... >


      <Properties error="{fault}" />

</MethodInvoker>

You can also use the sequence data. The data property must be of type Object.

<MethodInvoker
   generator="{ShippingCalculator}"
   method="calculateShipping" .... >


      <Properties myProperty="{data}" />

</MethodInvoker>

Finally, you can use the lastReturn

<MethodInvoker
   generator="{ShippingCalculator}"
   method="calculateShipping" .... >


      <Properties myProperty="{lastReturn}" />

</MethodInvoker>

Read more

3 responses so far

  1. I think the MethodInvoker tag should have an instance attribute so that you can handle the caching for yourself. It just seems like that would be a more flexible solution. Say you have several EventMaps how are they going to share a model? What if you need multiple instances of the same model? Say you have an interface like firefox where each tab you want a new Document model. You want that tab to bind to a specific instance of a model.
  2. Charlie,
    We actually had that in previous versions. In the current version, that functionality has been transferred to the InlineInvoker tag.

    If you have several event maps, they would all share the same model if you specify cache="true", which is the default value.

    The example that you give about a Multiple Document Interface would require more work, but it is possible to achieve. Most likely, there would be a "Tab Manager" that would take care of passing/storing the corresponding document to the tabs (instead of trying to access the specific model from the event map).
  3. Hi,

    Let's presume, I've a class and it's constructor needs a parameter, how can I use the methodinvoker in this case?

    i.e.

    var repo:IRepo = new DjangoRepo("http://localhost:8000";);
    repo.getMedia( ... )

    do I have set a setter for the host parameter?

    regards,
    Viktor

Leave a response

If you need help or want to comment on something not related to this page, please post in the forums. Thanks!