views:

2987

answers:

5

I have a couple of remote object methods that I want to respond to in different ways depending on the context, but I'd rather not set up a bunch of different RemoteObject aliases. Any advice on doing that? Some background:

Let's say I have an admin application that displays sales stats in different ways. The remote method looks like:

<mx:RemoteObject id="rpt" destination="AMFServer">
  <mx:method name="getSalesStats" fault="getSalesStatsFault(event)" 
   result = "getSalesStatsSuccess(event)" />
</mx:RemoteObject>

The getSalesStats method takes an employee ID and a sales type as its arguments. You'd call it like:

rpt.getSalesStats(120, "peanuts");

public function getSalesStatsSuccess(e:ResultEvent):void {
   salesdata:ArrayCollection = e.result.rows as ArrayCollection; 
   salesGraph.dataProvider = salesdata; 
   salesGraphPanel.title = "Peanut Sales, 1990";
}

I want to be able to call this method in different contexts, sometimes sending the result to a chart and sometimes to a datagrid; I want to be able to change the title and type of chart depending on what the user wants. Some of what I want can be achieved by evaluating the data returned from the server; the object contains the report name, so I can evaluate that value. But some things need to change based on more than just what I get back from the server. If this was a synchronous call, it would be easy; I'd do something like:

function buttonOneClick():void {
   myData1:ArrayCollection = getSalesStats(120, "peanuts");
   myChart.dataProvider = myData1;
}

function buttonTwoClick():void {
   myData2:ArrayCollection = getSalesStats(120, "cashews");
   myDataGrid.dataProvider = myData2; 
}

I'd like to pass something through the remote method to the responding function, like:

rpt.getSalesStats(120, "peanuts", "clicked button one");

but that of course throws an error because the server doesn't want that last argument. Any thoughts? I'll clarify if this is confusing..

A: 

You can have multiple methods to a remoteObject.

<mx:RemoteObject id="rpt" destination="AMFServer">
    <mx:method name="getSalesStatsToChart" fault="getSalesStatsFault(event)" 
        result = "getSalesStatsToChartSuccess(event)" />
    <mx:method name="getSalesStatsToDataGrid" fault="getSalesStatsFault(event)" 
        result = "getSalesStatsToDataGridSuccess(event)" />
</mx:RemoteObject>

Is there any reason why you can't use something like this?

CookieOfFortune
I was going to reply that I don't have much control over the server-side Java code, but of course those methods are just the AMF gateway aliases, so I could create a bunch of those. for simplicity I could send them all to the same result function and evaluate event.target.name to see which method was called. That might keep things manageable since there are going to be a lot of user interaction combinations, so a lot of these methods..
SkippyFlipjack
A: 

Flex supports the Asynchronous Completion Token design pattern for handling multiple requests to the same service. See the BlazeDS documentation.

Martin Harrigan
+2  A: 

Here is a great example of using AsyncToken with RemoteObject method calls to do precisely what you need.

Something to keep in mind when you are using AsyncToken is that it is a dynamic object and you can add any property you'd like to it. The event in your responder method will carry a reference to the AsyncToken and you can access your dynamic properties to easily identify the context of the response.

Joel Hooks
A: 

I think there are only two ways to do this:

  • Have a separate remote object for each call context. The effect on performance is neglectable IMO.
  • Set concurrency for the remoteobject to single (or first, not sure about the name, but not multiple or last) and have some sort of flag that you can use to tell which was the last method called. This will, of course, limit server calls to one at a time on this remote object. calls will fail immediately if the previous call didn't return a result yet.

That's the only way I see it if you have no access to the server. If I were in your situation, i will even create the remote object every time I do the remote call. I don't think it affects performance (please correct me if I'm wrong). Good luck!

Ammar
+1  A: 

In Flex 4 and 3.4, use the CallResponder class:

<mx:RemoteObject id="rpt" destination="AMFServer"/>
<s:CallResponder id="toChartResponder" fault="getSalesStatsFault(event)" 
        result = "getSalesStatsToChartSuccess(event)" />
<s:CallResponder id="toDataGridResponder"fault="getSalesStatsFault(event)" 
        result = "getSalesStatsToDataGridSuccess(event)"/>

To make the call, assign the returned AsyncToken from the method call to the token property of the responder:

toDataGridResponder.token = rpt.getSalesStats();

This separates the response definition from the method call, and you can then wrap it in whatever logic you need.

David Gassner