Log in

tipfy.ext.pyamf

So you want to integrate Flash's AMF communications with your Google App Engine deployment? Good choice! App Engine's unlimited storage is a natural fit for your next RIA application. So, how's it done? Simple. This extension implements a simple mixin object.

But first, checkout the live example of what we'll be accomplishing...

http:tipfy-pyamf.appspot.com

Setup

You'll need to add the tipfy.ext.pyamf package to your buildout.cfg file. Next, you'll want to create a handler and urls rules for your AMF handlers.

urls.py

from tipfy import Rule

def get_rules(app):
    rules = [
        # API Handlers
        Rule('/echo',
            endpoint='services/echo',
            handler='apps.services.handlers.EchoHandler',
        ),
    ]
    return rules

handlers.py

import logging

from tipfy import RequestHandler
from tipfy.ext.pyamf import AmfRequestHandlerMixin

def echo(data):
    return "GAE Response: " + data

class EchoHandler(RequestHandler, AmfRequestHandlerMixin):
    def post(self, **kwargs):
        services = {
            'myservice.echo': echo
        }
        self.set_gateway(services, logger = logging)
        return self.process_request()

Fairly straightforward, huh? Obviously, this is a ridiculously simple example. You should probably abstract out the echo service into other packages.

Testing

Well, go ahead and try opening that Handler in a web browser. It's going to fail miserably. Why? Well, AMF uses HTTP post, and a binary messaging format as the payload so the browser testing is out. So, lets crack open your trusty Flash Builder 4 and i'll show you a simple MXML based test case.

main.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.events.FlexEvent;
			import mx.rpc.events.ResultEvent;
			
			[Bindable]
			private var url_base:String = '<<<ENTER YOUR SERVICE URL HERE>>>';
			
			private var sequence:int = 0;
			
			public function handleAMFServiceResult(event:ResultEvent):void {
				trace(event.result)
				output.text += sequence + ": \""+ event.result + "\"\n";
				sequence += 1;
				setScroll();
			}
			
			protected function sendData_clickHandler(event:MouseEvent):void {
				if (input.text == ""){
					Alert.show("Enter something to send!");
				} else {
					AMFService.echo(input.text);
				}
			}
			public function setScroll():void {
				output.verticalScrollPosition = output.maxVerticalScrollPosition;
			}
		]]>
	</fx:Script>
	
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
		<s:RemoteObject id="AMFService"
						destination="myservice"
						endpoint="{url_base}"
						result="handleAMFServiceResult(event)" />
	</fx:Declarations>
	<s:layout>
		<s:VerticalLayout />
	</s:layout>
	<mx:VBox width="100%"
			 paddingBottom="20" paddingLeft="20"
			 paddingRight="20" paddingTop="20">
		<s:HGroup width="100%" height="50" verticalCenter="0">
			<s:Label text="Enter some Text to send to the server" width="270" horizontalCenter="0"/>
			<mx:Spacer width="100%" />
			<s:TextInput id="input" width="150"/>
			<s:Button id="sendData" label="Send!" click="sendData_clickHandler(event)" />
		</s:HGroup>
		<s:Label text="Server Results" />
		<mx:TextArea id="output" width="100%" height="250" editable="false"/>
	</mx:VBox>
</s:Application>

So, after pasting that into your new project, and clicking run, you should be able to enter some data into the box and click send. That string will get POST'd via HTTP to your service URL (you did enter a service url, didn't you?). App Engine will process this request using the def echo(data): entry in the handlers.py file. App Engine will then return this data all the way back to your Flash app and display it in the TextArea with id="output". It will also then auto-scroll that window.

So, that was a ridiculously simple example of AMF in python and flash. Surely you can put it to better use than I did!

Extension Reference


Powered by Moe. Yeah, the name is Moe. Powered by Google App Engine