Solved

ResultEvents not firing on multiple Flex3 WebService calls

Posted on 2009-04-08
8
847 Views
Last Modified: 2013-11-11
I have a user form in Flex that has three drop-downs that need to be initialized. I have created a class that wraps the web service methods:

            public function GetShipments( custId:int ):void {
                  ws.addEventListener( ResultEvent.RESULT, WebService_Results );
                  var callToken:AsyncToken = ws.getShipmentsForCustomer( custId );
                  callToken.marker = "shipments";
            }
            public function GetRoutes( custId:int ):void {
                  ws.addEventListener( ResultEvent.RESULT, WebService_Results );
                  var callToken:AsyncToken = ws.getRoutesForCustomer( custId );
                  callToken.marker = "routes";
            }
            public function GetDevices( custId:int ):void {
                  ws.addEventListener( ResultEvent.RESULT, WebService_Results );
                  var callToken:AsyncToken = ws.getDevicesForCustomer( custId );
                  callToken.marker = "devices";
            }
            private function WebService_Results( e:ResultEvent ):void {
                  var results:ArrayCollection;

                  switch ( e.token.marker ) {
                        case "shipments":
                              trace( "got shipment results" );
                              results = Route.ArrayToTypedArray( e.result as ArrayCollection );
                              dispatchEvent( new ShipmentsEvent( ShipmentsEvent.LOAD, results ) );
                              break;
                              
                        case "routes":
                              trace( "got route results" );
                              results = Route.ArrayToTypedArray( e.result as ArrayCollection );
                              dispatchEvent( new RoutesEvent( RoutesEvent.LOAD, results ) );
                              break;
                              
                        case "devices":
                              trace( "got device results" );
                              results = Device.ArrayToTypedArray( e.result as ArrayCollection );
                              dispatchEvent( new DeviceEvent( DeviceEvent.LOAD, results ) );
                              break;
                  }
            }

On my user form, I call the init() function on creationComplete:

private function init():void {
      mySvc.getInstance().addEventListener( ShipmentsEvent.LOAD, GetShipments_Result );
      mySvc.getInstance().addEventListener( RoutesEvent.LOAD, GetRoutes_Result );
      mySvc.getInstance().addEventListener( DeviceEvent.LOAD, GetDevices_Result );

      mySvc.getInstance().getShipments( 2 );
      mySvc.getInstance().getRoutes( 2 );
      mySvc.getInstance().getDevices( 2 );
}

In Service Capture, as expected I see 4 requests to the web service and the correct results returned:
      GET WSDL
      getShipments
      getRoutes
      getDevices

However, only one trace gets fired...
"got shipment results"

If I sequence them by calling getRoutes in the result handler of getShipments, and getDevices in the result handler of getRoutes, all three events are received fine.

However, this seems horribly clumsy and hard to manage over a large enterprise application.

What might I be doing wrong, or is sequencing the only way to go?
0
Comment
Question by:FredMBarrett
  • 5
  • 3
8 Comments
 
LVL 20

Expert Comment

by:ChristoferDutz
ID: 24098827
Hi

Could you try to add a trace-statement outside the switch statement? I would guess that the there are problems with the token, but it's just an assumption, as I was having similar problems.

Also I would try to change the callback signature to Event for debugging, because when using the different types of registering callbacks I had different types of events fired.

I would recomend adding the event listener to the token, that you are recieving or to the method. You are currently registering to events fired by the webservice itself.

Try:
var _getShipmentsToken:AsyncToken;

public function GetShipments( custId:int ):void {
    getShipmentsToken = ws.getShipmentsForCustomer( custId );
    getShipmentsToken.addEventListener( "result", WebService_Results );
    getShipmentsToken.marker = "shipments";
}

Notice the token is defined outside the function scope because I had problems otherwise. I guess as soon as flex leaves the function, the local variables are destroyed and so is the token.

Or (I am using the Flex Builder Webservice Adapters):

public function GetShipments( custId:int ):void {
    ws.addgetShipmentsForCustomerEventListener(WebService_Results);
    var callToken:AsyncToken = ws.getShipmentsForCustomer( custId );
    callToken.marker = "shipments";
}

Hope this helps,
    Chris
 
0
 

Author Comment

by:FredMBarrett
ID: 24099340
Hi ChristoferDutz:

Thanks for your reply. I made the updates you suggested and still no love. The traces all show that, basically whichever event happens first, that one wins and all others are lost.

I moved the token definitions outside of the function and created a token for each method call.
I also added the event listener to the token itself.

            public function GetShipments( custId:int ):void {
                  ws.addEventListener( ResultEvent.RESULT, WebService_Results );
                  _getShipmentsToken = ws.getShipmentsForCustomer( custId );
                  _getShipmentsToken.addEventListener( ResultEvent.RESULT, WebService_Results );
                  _getShipmentsToken.marker = ShipmentsEvent.LOAD;
            }

Again, Service Capture shows the results coming in, and they all do come in correctly, but whichever result appears first is the only one that bubbles back and none of the other events get fired.

Very frustrating as you can imagine.
0
 
LVL 20

Expert Comment

by:ChristoferDutz
ID: 24100822
Have you turned on the logging capabilities of flex?
When im in my office again tomorrow, I could send you a code fragment to initialize the Flex log-framework. It helped me quite a lot when having similar problems.

Are you using the flexBuilder generated Webservice-client?

Whatever you are using, I would suggest setting a breakpoint in your event handler (The one that is called), step up one layer and have a look at the code there. When figguring out my problems regarding Flex + CXF + Aegis integration I had to do quite a lot of debugging in the Flex sources :-(

Chris
0
 
LVL 20

Assisted Solution

by:ChristoferDutz
ChristoferDutz earned 250 total points
ID: 24106093
I call the following code to get a lot of debug information on my console (When debugging flex using the Flex Builder and Eclipse):
	    	private function initLogging():void 

	    	{

	            // Create a target.

	            var logTarget:TraceTarget = new TraceTarget();

	

	            // Log only messages for the classes in the mx.rpc.* and 

	            // mx.messaging packages.

	            //logTarget.filters=["mx.rpc.*","mx.messaging.*"];

	            logTarget.filters=["*"];

	

	            // Log all log levels.

	            logTarget.level = LogEventLevel.ALL;

	

	            // Add date, time, category, and log level to the output.

	            logTarget.includeDate = true;

	            logTarget.includeTime = true;

	            logTarget.includeCategory = true;

	            logTarget.includeLevel = true;

	

	            // Begin logging.

	            Log.addTarget(logTarget);

	        }

			

Open in new window

0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:FredMBarrett
ID: 24109144
Thank you, Christofer...
Where does this log file get generated?
0
 
LVL 20

Expert Comment

by:ChristoferDutz
ID: 24138481
Well the way it is configured in the sample I posted, it is generated in the Eclipse console of my Flex Builder. You can however let the debug version of the Flash player debug to a local file:
http://joelhooks.com/2008/08/12/super-automatic-trace-for-flex/

Here the link for the Debug version of the flash player:
http://www.adobe.com/support/flashplayer/downloads.html
0
 

Accepted Solution

by:
FredMBarrett earned 0 total points
ID: 24150123
Well, I found the problem through experimentation, and I am chalking it up to "not all good examples extend to enterprise-level solutions."

As you can see from the first example in the list, each function added its own listener to the event. The correct solution is to add a single listener at the module scope.

Each caller function would .addEventListener and the handler would .removeEventListener, and with many of these going on throughout the processing, events would get lost.

By adding a single event listener in the creationComplete() function, and then not removing it as part of the handler functions, I haven't lost any events since, and I can call multiple web service methods in a row and get all the results I expect.

Now it seems obvious, but without Service Capture and help from ChrisoferDutz, it was quite maddening!

Thanks, Chris.
private function MyService_Init():void {

   ws = new WebService();

   ws.addEventListener( ResultEvent.RESULT, MyService_Results );

   ... //other init stuff

}

public function GetShipments( custId:int ):void {

   showBusyCursor();

   var token:AsyncToken = ws.getShipmentsForCustomer( custId );

   token.marker = ShipmentsEvent.LOAD;

}

private function MyService_Results( event:ResultEvent ):void {

   var token:AsyncToken = event.token;

   var resultsArray:ArrayCollection;

   var resultsXML:XML;

			

   if ( token != null ) {

      trace( token.marker );

      switch ( token.marker ) {

      case UserLoginEvent.GET_USER:

         resultsArray = UserProfile.ArrayToTypedArray( 

            event.result as ArrayCollection );

         dispatchEvent( new UserLoginEvent( resultsArray ) );

         break;

      case ShipmentsEvent.LOAD:

         resultsArray = Shipment.ArrayToTypedArray( 

            event.result as ArrayCollection );

         dispatchEvent( new ShipmentsEvent( ShipmentsEvent.LOAD, resultsArray ) );

         break;
 

//etc

}

Open in new window

0
 
LVL 20

Expert Comment

by:ChristoferDutz
ID: 24155561
Ok ... the detail with the removeListener wasn't visible in your example ... Seems that this indeed seems to be the cause of your problems :-)

I'd suggest you close the question and don't add it to the knowledge-base.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
playing flash video on kiosk at startup 6 402
Flash player plugin 13 7 323
Adobe Presenter not Publishing Slide Theme 17 120
Download Adobe Flash Player 6 58
This article describes a solution to a problem of subloading one movie into another when they have different SWF versions. Sometime back, I was working on an ActionScript project while I came across an interesting fact which I would like to share…
While working over numerous projects I often had the requirement for doing a screen capture in AS3.0. Unfortunately I found no "ready made" solutions in google search that suited my requirements. But I did come across some great resources which help…
In this tutorial viewers will learn how to create a basic motion tween animation in Flash Open a new document in Flash: Draw/import an image: Press CTRL + F8 to convert it into a graphic symbol: Select a frame (how long you want the tween to last): …
The goal of the tutorial is to teach the user how to select which audio input to use. Once you have an audio input plugged into the laptop or computer, you will go into the audio input settings and choose which audio input you want to use.

948 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now