ActiveApi - Wrapping a RESTful API in AS3

ActiveApi is my AS3 wrapper for a RESTful api, I just came up with ActiveApi right now so if I'm stepping on someones toes just let me know.  In my last post I kind of went over how I came up with these classes so I'm just going to dive into some code. 

To get started you need to define a controller class that extends from activeapi.base.Controller.  This class should be a singleton, you can do that however you like.  Controller defines a getter base\_url that just throws an error so you'll want to override that so it returns your base url.  This is what you'll get:

package activeapi.example
{
    import activeapi.base.Controller;
   
    public class ExampleController extends Controller
    {
        public const BASE\_URL:String = "http://localhost:3001/";
       
        private static var ExampleController = new ExampleController(true);
       
        public function TrackerController(only\_one\_allowed:Boolean) {
        }
       
        public static function get inst(): ExampleController {
            return \_instance;
        }

        public override function get base\_url():String {
            return BASE\_URL;
        }
    }
}


Controller extends from EventDispatcher so you get all the event listening and dispatching methods from that.  This is the class that you will add listeners to for CREATE and DELETE of your objects, like this:

ExampleController.inst.addEventListener("session"+ActiveEvent.CREATE, auth);


Point to note, I'm prefixing the type of object I am creating to the event string, this isn't the ideal design but it was the best I could come up with.

Next is defining the class that is going to be doing the RESTful operations, the Session class in this example.  For now I haven't found a reason to create a base class to extend from, instead you instantiate an object that will be used to delegate the work to.  This is what the basic Session class would look like:

package activeapi.example
{
    import mx.rpc.events.ResultEvent;
    import activeapi.example.base.ActiveEvent;
    import activeapi.example.base.ResourceHandler;
   
    public class Session
    {
        //Static resource handler, passing in the name of the model and the controller instance.
        private static var resource:ResourceHandler = new ResourceHandler("session", ExampleController.inst);
       
        public var id:String;
       
        public function Session(identifier:String)
        {
            id = identifier;
        }   

        public static function create(args:Object):void {
            //let the resource handler make the call
            resource.create(args, create\_complete\_callback);
        }
        // static create method Session.create
        private static function create\_complete\_callback(event:ResultEvent):void {
            //delegate to the resource handler to handle the basic result and fire the events.
            resource.handle\_and\_dispatch(ActiveEvent.CREATE, Session.parse(event.result), event);
        }
       
        public function destroy():void {
            resource.destroy({id:id}, delete\_complete\_callback);
        }
       
        private function delete\_complete\_callback(event:ResultEvent):void {
            resource.handle\_and\_dispatch(ActiveEvent.DELETE, null, event);
        }
       
        public static function parse(data:Object):Session {
            //return a new session from the data
        }
    }
}


This class has a bit more going on.  First off is the ResourceHandler, it takes the name of the object type you want to create and a Controller as it's parameters.  I made mine static so that I could use it in both my static create method and instance method destroy.  Under the covers the ResourceHandler sets up some HTTPService objects pointing to the urls for creating and destroying the session object and setting op the correct mehod and response type (XML).  These objects aren't accessible but are used by calling the create and destroy methods on the ResourceHandler.  In the callback I use another method on the, handle\_and\_dispatch, to do some basic parsing of the response and then dispatching the events on the controller.  The second parameter of handle\_and\_dispatch is an object and is added to the final event that is dispatched.  The auth method that was added to listen for session CREATE before might look something like this:

private function auth(event:ActiveEvent):void {
    if(Session(event.object).id!=null)
        Application.application.currentState = "logged\_in"
    else
        Alert.show(event.message.toString());
}


And that's basically it.  The ExampleController kind of acts like a central messaging system and the major work is delegated to the ResourceHandler.  I still need to pull this out from the project I'm using it for, which shouldn't take long, so if you're interested in the code let me know in the comments.  I'd also really appreciate some feedback on the design choices and improvement suggestions.  Personally I'm still left feeling like there's a better way but trying to figure something out has been sucking up way too much time.

Posted October 22, 2008

Comments

comments powered by Disqus