(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>
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).
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