Thursday, August 28, 2014

Flex UIComponent CallLater Exception Handling

I recently ran into an issue with Flex that took me a while to track down related to callLater() execution and the UIComponent.setFocus() method.

In my case I was executing some functions using callLater() for various reasons, but I also had some event listeners set up that were listening for focus change and also testing to see if components were in focus.  It was a perfect storm for trouble it turns out.

After lots of debugging and scratching my head I started to get an idea of what was going wrong.  If you take a look at the UIComponent.callLaterDispatcher() method you can see the first line of code increments the UIComponentGlobals.callLaterDispatcherCount variable and the same variable is decremented at the end of the method.  I also found reference to this variable in the UIComponent.setFocus() method, where it will postpone setting the focus on the current component if the value of callLaterDispatcherCount is not zero.  If you look at the ASDoc for the callLaterDispatcherCount it states that in order to fix a problem with the ActiveX player the focus is deferred until enterFrame.  So that explains why my focus handler wasn't being notified, because for some reason that counter wasn't zero.

Now back in the UIComponent.callLaterDispatcher() there is an import if statement that tests the UIComponentGlobals.catchCallLaterExceptions variable.  Basically if this is set to false, which it is by default, any errors will not be caught by the callLaterDispatcher() method and the callLaterDispatcherCount will never be decremented.  So as soon as your callLater function throws one error the setFocus will stop working correctly.  Conversely if you have the "catchCallLaterExceptions" set to true any Error in the function being called later will be caught and wrapped inside a dynamic event and dispatched via the SystemManager.

For the short term I fixed the error that was being thrown, which allowed the "callLaterDispatcherCount" to be decremented back to zero.  The other option I am looking at in the long term is setting the UIComponentGlobals.catchCallLaterExceptions variable to true on application initialization so the counter will always get decremented and handling any callLater exceptions at the application level, as laid out in this blog post, Summa - Global Error Handling in Flex  Hopefully this will help people out if they run into a similar problem.

Additional Resources:
Liquid Night - Global Exception Handling in Flex
Doug McCune - How are you doing global exception handling in Flex/Flash/AS3?