Posts in Category "ActionScript"

Making HTTP calls in ActionScript 3

The lingua franca of the web is HTTP, and no programming language can claim to be a web-oriented language if it doesn’t fully support it. Custom APIs and modern protocols are increasingly being built on top of HTTP. Just as it’s rarely a good idea to invent a new XML language, it’s increasingly apparent that HTTP, and more broadly REST, is almost always the most appropriate foundation upon which to build new web APIs.

So how does ActionScript 3 stack up in the area of HTTP support? I’ll (arbitrarily) give a score to AS3’s support for the core elements of a minimal HTTP implementation.

Methods

AS3’s HTTPService class supports the basic HTTP methods (GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE), but doesn’t allow custom methods. The WebDAV protocol uses a handful of custom HTTP methods (PROPFIND, PROPPATCH, MKCOL, etc.) which HTTPService would be unable to invoke, so it may be a while before we see an AS3-based WebDAV implementation.

Score: 4/5 (Support for custom methods is missing, but few APIs use them anyhow)

Request headers

HTTPService has a headers property which can hold an arbitrary Array of name-value pairs.

Score: 5/5

Response headers

Unfortunately, there’s no way to extract the headers from an HTTP response. (If you’re interested in verifying this, just make an HTTPService call to a bogus page and set a breakpoint in the fault handler. When execution stops there, examine the FaultEvent in Flex Builder’s Variables window — there’s no evidence anywhere that the error is indeed a 404.) I had a conversation with Matt Chotin of the Flex team about this some months ago, and he indicated that not all browsers expose the headers.

This is a pretty significant limitation, especially since REST principles are motivating the designers of more recent protocols and APIs to leverage the HTTP status code vocabulary to define the semantics of method results, rather than invent new vocabularies in the form of custom responses.

Score: 1/5 (I’ll give it one point, since at least it’s possible to distinguish between successful calls and unsuccessful calls.)

Authentication

HTTPService supports authentication against a remote endpoint via the setRemoteCredentials method. Alternatively, the user’s credentials can be specified in Flex Data Server’s proxy-service.xml file.

Score: 5/5

Overall: 15/20

With the glaring exception of support for response headers, AS3’s support for HTTP is full-featured enough to implement just about any REST-style protocol or API. Let’s hope the Flex and Apollo teams can fill this one remaining hole in a future release.

An Asynchronous Cookbook (Part Two)

In the previous post, I outlined a few different solutions to the problem of how to structure your asynchronous ActionScript code. The concept of an asynchronous method chain, in which a series of methods that make asynchronous calls to external services are executed sequentially, is an important one for Flex developers who want their apps to pull in data from multiple web services. NoteTag is a prime example: it publishes notes to Blogger and/or TypePad, and stores references to notes and tasks on del.icio.us.

But suppose that one method in the asynchronous chain needs some piece of data generated by an earlier method in the chain. How can you make state available to more than one method in the chain?

Problem #4: One or more methods in an asynchronous method chain need access to data generated somewhere else in the chain. For example, imagine that our getFirstFeed method needs to return the first feed in an Atom service document and the Atom service document.

Solution #4a: Stash the data onto the call object and pass it down the chain (per Sho’s suggestion). This approach works fine in the simple case, but suppose you have a really long chain of methods – you might end up passing data through a bunch of methods that don’t need it, just so that the last method can use the data.

Solution #4b: Stash the data on the enclosing object as a private data member. This is perhaps the simplest solution, as it makes the data available to any method in the chain. But if the client method is called a second time before it has finished its first series of asynchronous calls, then the stashed data could be overwritten! What we really want is a way to ensure that any state we generate during the execution of the asynchronous method chain is scoped on a per-method-invocation basis…

Solution #4c: Achieve per-method-invocation variable-scoping by putting the logic for the chained calls into an internally-scoped delegate class which is instantiated when the client method is called. Because a new delegate is instantiated each time the method is called, the data can be stored on the delegate without any risk of its being overwritten. This approach can be done by convention (by forcing your clients to use a factory class that creates a new object for each operation) or explicitly (by having the method literally create a delegate object, as below).

public class FeedRetriever extends EventDispatcher
{
private var protocol:AtomPublishingProtocol; // initialized elsewhere

// Dispatches a GetFeedEvent after retrieving the first feed listed
// in the service document.
public function getFirstFeed(serviceURI:URI):void
{
var delegate:FeedRetrieverDelegate =
new FeedRetrieverDelegate(this,protocol);
delegate.getFirstFeed(serviceURI);
}
}

// Internally-scoped delegate which is instantiated on every call to
// FeedRetriever.getFirstFeed (and which can therefore safely store state).
internal class FeedRetrieverDelegate
{
private var target:IEventDispatcher;
private var protocol:AtomPublishingProtocol;

// State that needs to be tracked (the service document).
private var service:IService;

public function FeedRetrieverDelegate(target:IEventDispatcher,
protocol:AtomPublishingProtocol):void
{
this.target = target;
this.protocol = protocol;
}

public function getFirstFeed(serviceURI:URI):void
{
// Use a utility class to handle registration and unregistration
// of event listeners.
var responder:AsyncResponder = new AsyncResponder();
responder.setNextEventHandler(protocol,
onGetService, // result handler
“getService”, // result event
onFault,      // fault handler
“atomFault”); // fault event

// Make the asynchronous call to retrieve the service document.
protocol.getService(serviceURI);
}

private function onGetService(event:GetServiceEvent):void
{
// Store the service document since the next method needs
// access to it.
this.service = event.service;

// Get the collection that represents the first feed.
var collection:ICollection = service.workspaces[0].collections[0];

// Use a utility class to handle registration and unregistration
// of event listeners.
var responder:AsyncResponder = new AsyncResponder();
responder.setNextEventHandler(protocol,
onGetFeed,    // result handler
“getFeed”);   // result event
onFault,      // fault handler
“atomFault”); // fault event

// Make the asynchronous call to retrieve the first feed.
protocol.getFeed(collection);
}

private function onGetFeed(event:GetFeedEvent):void
{
// Dispatch a result event to the caller, using
// the passed-in target object.
var newEvent:GetFeedEvent = new GetFeedEvent();
newEvent.feed = event.feed;
newEvent.service = this.service;
target.dispatchEvent(newEvent);
}

private function onFault(event:AtomFaultEvent):void
{
// Do fault processing...
}

// ...
}

But it’s not always ideal from an object-orientation perspective to separate this logic into two classes. Is there a way that we can attain per-method-invocation variable-scoping without using multiple classes? Our final solution accomplishes just that.

Solution #4d: Put your responder code in one or more closures. (A closure is a function that exists within the body of another function and which when executed has its own set of local variables.) Within a closure, you can access variables in the outer scope – a nice benefit. The drawback? Because the closure needs to be declared prior to the asynchronous method call, the flow of control within the code can be a bit confusing.

public class FeedRetriever extends EventDispatcher
{
private var protocol:AtomPublishingProtocol; // initialized elsewhere

// Dispatches a GetFeedEvent that contains the first feed and
// the service document.
public function getFirstFeed(serviceURI:URI):void
{
// #1: The flow of control starts here...

// Declare a function closure that will be called later.
var onGetService:Function = function(event1:GetServiceEvent):void
{
// #3: After protocol.getService completes, control jumps
// to here...

// We set the service document into a local variable,
// which is accessible even from within the subsequent
// closure.
var serviceLocalVar:IService = event1.service;

// Get the first feed in the service document.
var collection:ICollection = serviceLocalVar.workspaces[0].collections[0];

// Declare another function closure to be called later.
var onGetFeed:Function = function(event2:GetFeedEvent):void
{
// #5: After protocol.getFeed completes, control
// jumps to here, and finishes by dispatching
// the client event.

// Dispatch a result event to the caller.
var newEvent:GetFeedEvent = new GetFeedEvent();
newEvent.feed = event2.feed

// Notice how we can access serviceLocalVar -
// this is one nice benefit of closures.
newEvent.service = serviceLocalVar;
dispatchEvent(newEvent);
}

// #4: ... and continues down to here...

// Use a utility class to handle registration and
// unregistration of event listeners.
var responder2:AsyncResponder = new AsyncResponder();
responder2.setNextEventHandler(protocol,
onGetFeed, // result handler
GetFeedEvent.GET_FEED, // result event
onFault, // fault handler
AtomFaultEvent.ATOM_FAULT); // fault event

// Make the asynchronous call to retrieve the first feed.
protocol.getFeed(collection);
}

// #2: ... and continues down to here...

// Use a utility class to handle registration and unregistration
// of event listeners.
var responder1:AsyncResponder = new AsyncResponder();
responder1.setNextEventHandler(protocol,
onGetService, // result handler
“getService”, // result event
onFault,      // fault handler
“atomFault”); // fault event

// Make the asynchronous call.
protocol.getService();
}

private function onFault(event:AtomFaultEvent):void
{
// Do fault processing...
}
}

Following the flow of control in the previous example is a bit like watching a yoyo in action. Sho has some ideas
on how to improve the readability of closure-heavy code.

Summary: When it comes to implementing asynchronous methods in ActionScript, there are a number of approaches that you can take. In many cases you’ll be able to stick with the simplest approach (create an event listener to respond to the event), but there are certain situations where the more complicated approaches are called for. For each such situation, ask yourself the following questions:

  • Do I need to process the result of an asynchronous call?
  • Will the object that makes the asynchronous call be used again after I’m done with it?
  • Do I need to make multiple sequential asynchronous calls?
  • In the chain of sequential asynchronous calls, does a method need access to data that is generated by a different method in the chain?

If the answer to any of these questions is “yes”, then consider using one or more of the following:

  • A helper class that can manage event registration (a la AsyncResponder)
  • Stateful objects
  • Delegates that achieve per-method-invocation variable scoping
  • Closures

An Asynchronous Cookbook (Part One)

If you haven’t read Sho Kuwamoto’s series of blog posts on dealing with asynchronous events, I highly recommend them. Any Flex developer that builds applications that make remote calls is eventually going to run into the problem of how best to structure their code. In the course of developing NoteTag, we tried dozens of solutions to “the asynchronous problem”. The bad news: there is no one-size-fits-all solution. The good news: there are a few key rules-of-thumb which can guide you towards choosing the solution that’s right for the situation.

I’ll walk through the specific problems we’re trying to solve, using the example of a class which provides support for retrieving an Atom service document. (In Atom Publishing Protocol parlance, a service document is an index of blogs that are available from a particular account on a blog server.)

Problem #1: Asynchronous calls don’t return right away, but you often need to process the result.

Solution #1: Create a result handler method, and add it as an event listener to the object which is making the asynchronous call.

public class AtomPublishingProtocol extends EventDispatcher
{
// Dispatches a GetServiceEvent after retrieving the service document.
public function getService(serviceURI:URI):void
{
var service:HTTPService = new HTTPService();
service.url = serviceURI.toString();
service.method = "GET";
service.resultFormat="e4x";
service.addEventListener("result",onGetServiceResult);
service.send();
}

private function onGetServiceResult(event:ResultEvent):void
{
var xml:XML = new XML(event.result);
var atomEvent:GetServiceEvent = new GetServiceEvent();

// Convert the XML to a domain object.
atomEvent.service = ModelFactory.createServiceFromXML(xml));

dispatchEvent(atomEvent);
}

// ...
}

This is the simplest problem, with a correspondingly simple solution. (I’ve left out the fault listener to keep this simplest of examples as simple as possible.) One thing to point out: we didn’t need to unregister the HTTPService event listener because we created a new instance and “threw it away”. But that won’t always be the case…

Problem #2: Asynchronous calls are made using an object that can be called from multiple places in the application. (Imagine that our app reuses one instance of HTTPService for all remote calls.)

Solution #2: For every event registration, there must be a corresponding “unregistration”. Failure to unregister an event listener could lead to it being called again if the event-generating object (HTTPService, in the following example) is called from somewhere else.

public class AtomPublishingProtocol extends EventDispatcher
{
private var service:HTTPService; // initialized elsewhere

// Dispatches a GetServiceEvent after retrieving the service document.
public function getService(serviceURI:URI):void
{
service.url = serviceURI.toString();
service.method = "GET";
service.resultFormat="e4x";
service.addEventListener("result",onGetServiceResult);
service.addEventListener(”fault”,onFault);
service.send();
}

private function onGetServiceResult(event:ResultEvent):void
{
// Manually unregister the listeners in case service
// is used from somewhere else.
service.removeEventListener(“result”,onGetServiceResult);
service.removeEventListener(“fault”,onFault);

var xml:XML = new XML(event.result);
var atomEvent:GetServiceEvent = new GetServiceEvent();

// Convert the XML to a domain object.
atomEvent.service = ModelFactory.createServiceFromXML(xml));

dispatchEvent(atomEvent);
}

private function onFault(event:FaultEvent):void
{
// Manually unregister the listeners here too!
service.removeEventListener(“result”,onGetServiceResult);
service.removeEventListener(“fault”,onFault);

// Do fault processing...
}

// ...
}

Problem #3: A method needs to perform multiple asynchronous calls before returning. Let’s make the use case a bit more complicated: we now use our AtomPublishingProtocol implementation to return the first feed listed in the service document.

Solution #3a: Chain the calls together manually.

public class FeedRetriever extends EventDispatcher
{
private var protocol:AtomPublishingProtocol; // initialized elsewhere

// Dispatches a GetFeedEvent after retrieving the first feed listed
// in the service document.
public function getFirstFeed(serviceURI:URI):void
{
// Manually set up the event listeners.
protocol.addEventListener(“getService”,onGetService);
protocol.addEventListener(“atomFault”,onGetServiceFault);

// Make the asynchronous call to retrieve the service document.
protocol.getService(serviceURI);
}

private function onGetService(event:GetServiceEvent):void
{
// Manually unregister the event listeners.
protocol.removeEventListener(”getService”,onGetService);
protocol.removeEventListener(”atomFault”,onGetServiceFault);

// Get the collection that represents the first feed.
var collection:ICollection = event.service.workspaces[0].collections[0];

// Manually set up the next set of event listeners.
protocol.addEventListener(“getFeed”,onGetFeed);
protocol.addEventListener(“atomFault”,onGetFeedFault);

// Make the asynchronous call to retrieve the first feed.
protocol.getFeed(collection);
}

private function onGetServiceFault(event:AtomFaultEvent):void
{
// Manually unregister the event listeners.
protocol.removeEventListener(”getService”,onGetService);
protocol.removeEventListener(”atomFault”,onGetServiceFault);

// Do fault processing...
}

private function onGetFeed(event:GetFeedEvent):void
{
// Ugh!  How many times do we have to manually
// add and remove event listeners?!?!?
protocol.removeEventListener(”getFeed”,onGetFeed);
protocol.removeEventListener(“atomFault”,onGetFeedFault);

// Dispatch a result event to the caller.
var newEvent:GetFeedEvent = new GetFeedEvent();
newEvent.feed = event.feed;
dispatchEvent(newEvent);
}

private function onGetFeedFault(event:AtomFaultEvent):void
{
// Manually unregister the event listeners.
protocol.removeEventListener(”getFeed”,onGetFeed);
protocol.removeEventListener(”atomFault”,onGetFeedFault);

// Do fault processing...
}

// ...
}

As you can see, it’s a real pain to manually handle registration and unregistration of event listeners. A helper class which can take care of the event registration for us will simplify our code.

Solution #3b: Use a helper class (e.g. AsyncResponder to manage event registration. (For reasons of space, I don’t include the source for the helper class, but you can find it in the Connections library, or in the NoteTag download.)

public class FeedRetriever extends EventDispatcher
{
private var protocol:AtomPublishingProtocol; // initialized elsewhere

// Dispatches a GetFeedEvent after retrieving the first feed listed
// in the service document.
public function getFirstFeed(serviceURI:URI):void
{
// Use a utility class to handle registration and unregistration
// of event listeners.
var responder:AsyncResponder = new AsyncResponder();
responder.setNextEventHandler(protocol,
onGetService, // result handler
“getService”, // result event
onFault,      // fault handler
“atomFault”); // fault event

// Make the asynchronous call to retrieve the service document.
protocol.getService(serviceURI);
}

private function onGetService(event:GetServiceEvent):void
{
// Get the collection that represents the first feed.
var collection:ICollection = event.service.workspaces[0].collections[0];

// Use a utility class to handle registration and unregistration
// of event listeners.
var responder:AsyncResponder = new AsyncResponder();
responder.setNextEventHandler(protocol,
onGetFeed,    // result handler
“getFeed”);   // result event
onFault,      // fault handler
“atomFault”); // fault event

// Make the asynchronous call to retrieve the first feed.
protocol.getFeed(collection);
}

private function onGetFeed(event:GetFeedEvent):void
{
// Dispatch a result event to the caller.
var newEvent:GetFeedEvent = new GetFeedEvent();
newEvent.feed = event.feed;
dispatchEvent(newEvent);
}

private function onFault(event:AtomFaultEvent):void
{
// Do fault processing...
}

// ...
}

This chaining of methods works quite well, and is reasonably easy for a reader to follow. (NoteTag uses this approach in a number of places, both explicitly with AsyncResponder and indirectly via the ChainedCommand class, which uses AsyncResponder to chain asynchronous method calls within Cairngorm Commands.)

In the next post, I’ll add another wrinkle to this problem: what if one method in the asynchronous method chain needs access to data that was generated earlier in the chain?

AS3 programming 101 for C/C++ coders

In my previous article, I covered ActionScript 3 languange syntax and constructs that may be of interest to C/C++ coders starting out on ActionScript 3. This article covers areas of AS3 that are different from C/C++ in regards to functional issues that may be interesting to people with C/C++ experience. ActionScript 3 is a powerful language with some very nice features. However, as a long time C/C++ coder I found ActionScript lacking things I was used to having.

Continue reading…

AS3 language 101 for C/C++ coders

This article covers aspects of ActionScript 3 that would be helpful to C/C++ application engineers transitioning to application development in Flex and Flash.

I’ve used C/C++ through most of my educational and professional career. I’ve also done a respectable share of Javascript and Perl. ActionScript 3 could be viewed as an interesting blend of features from all of these languages. Actionscript 3 conforms to the ECMAscript 4 spec. So, it is a standard languange. In addition to the standard language syntax, AS3 contains a custom class framework for working with Flex/Flash.

The following are areas in the AS3 language that I personally found interesting.

Continue reading…