AMFPHP on AIR Tutorial with MAMP

I had a look at my 3 year old AMFPHP tutorial and thought about what all changed. ActionScript 2 was replaced by AS3, I moved from Flash to Flex and changed my OS from Windows to OS X. I have developed desktop apps in the past with SWF Studio and now Adobe AIR is the solution for cross platform desktop applications. Summary:

  • AS2 -> AS3
  • Flash -> Flex
  • Windows -> OS X
  • SWF Studio -> Adobe AIR

Due to these huge changes I wanted to see how AMFPHP fits into this environment and write a new tutorial.

First the setup up the local server. Instead of WAMP (Windows, Apache, MySQL, PHP) I am now using MAMP (M for Mac) which is the pendent on OS X:

  • Download and install MAMP an Mac+Apache+MySQL+PHP bundle
  • Start the MAMP server: /Applications/MAMP/MAMP.app (Your browser should come up with a MAMP page saying your installation was successfully)
  • Download the latest AMFPHP and put it into /Applications/MAMP/htdocs/amfphp (I used 1.9 beta 20080120)
  • Download the MyService.php.txt, rename it to MyService.php and place it into /Applications/MAMP/htdocs/amfphp/services

As a client we could choose Flex in the browser but I wanted to demonstrate AIR:

  • Open Flex Builder and create a new AIR project called AMFPHPonAIR
  • The AMFPHPonAIR.mxml opens where you put this code (download):
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
	creationComplete="init()">
 
	<mx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.messaging.channels.AMFChannel;
			import mx.messaging.ChannelSet;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;
 
			[Bindable]
			private var lastResult:String;
 
			private function init():void
			{
				var cs:ChannelSet = new ChannelSet();
				var channel:AMFChannel = new AMFChannel("my-amf", "http://localhost:8888/amfphp/gateway.php");
				cs.addChannel(channel);
				myService.channelSet = cs;
				myService.hello("You");
			}
 
			private function onResult(re:ResultEvent):void
			{
				var s:String = re.result as String;
				Alert.show(s, "Remote Result");
				lastResult = s;
			}
			private function onFault(fe:FaultEvent):void
			{
				Alert.show(fe.message.toString(), "Remote Error");
			}
		]]>
	</mx:Script>
 
	<mx:TraceTarget fieldSeparator="->" includeLevel="true" includeCategory="true" includeTime="true" />
 
	<mx:RemoteObject id="myService" result="onResult(event)" fault="onFault(event)"
        showBusyCursor="true" destination="AMFPHP" source="MyService">
        <mx:method name="hello" />
    </mx:RemoteObject>
 
    <mx:HBox>
		<mx:TextInput id="message" text="Yourself" />
		<mx:Button label="say hello" click="myService.hello(message.text)" />
	</mx:HBox>
 
	<mx:Label text="Last Result: {lastResult}" />
 
</mx:WindowedApplication>

The most important part is in the init function where the remoting endpoint is set via ActionScript.
Right-click the src/AMFPHPonAIR.mxml and choose Debug As-> Adobe AIR Application

If all works right you should see something like this:

AMFPHP on AIR

You can change the text in the TextInput control and click the button to send it to your server and the result is shown below the TextInput. Now that was easy I think! About 50 lines of code for a full AIR application which uses AMFPHP on the server side.

This example works but has no seperation of model,view and controller so I changed it to use the Cairngorm micro-architecture. Download this example AIR application (sourceview) and overwrite it into the src folder

The Cairngorm.swc should be in placed in the libs directory of your AIR project. Now let’s dive a bit in the code to understand the Cairngorm structure and how the RemoteObject configuration with the AMFPHP remoting gateway.

The AMFPHPonAIR.mxml is the main application MXML and you can right-click it to Run or Debug your AIR application. If you are not familiar with Cairngorm at all I recommend checking the docs as this is not a Cairngorm tutorial. If you have questions feel free to post a comment.

The main MXML is pretty short and instantiates only a TraceTarget, the FrontController, the Services (ServiceLocator) and the main view.

The creationComplete event goes into the init-function which dispatches a StartupEvent. Open the airamfphp/ctrl/FrontController.as on you see two events mapped to their commands. When the StartupEvent is dispatched the CairngormEventDispatcher calls the StartupCommand’s execute method with the event as the parameter.

Open the airamfphp/StartupCommand.as. The execute method gets called when the StartupEvent is dispatched. The ServiceLocator singleton maps to our business/Services.mxml because we instantiated it in out main MXML. The Services.mxml defines the RemoteObject which maps to the MyTestservice.php in the AMFPHP services directory. I added the method setServer to the ServiceLocator to set the remoting endpoint. This is pretty straight forward and is a replacement for the services-config.xml which can be compiled into the application (compiler flag -services service-config.xml). In real life the server settings should come out of an external configuration so you can switch from local dev to staging, production etc.

Going on in the StartupCommand you see that MyDelegate get’s instantiated and we call hello “You”. The delegate expects an IResponder as parameter and the command implements the IResponder interface meaning the methods result and fault. The delegate is standard Cairngorm so let’s finalize the command. For result and fault an Alert comes up which shows the server result of the call of MyService.hello(“You”).

The view/MainView.mxml shows a TextInput, Button and Label and when the button is pressed a HelloEvent with the text of the TextInput as parameter. The HelloEvent is mapped to the HelloCommand in the FrontController so open the HelloCommand to see what happens. We use the same delegate and fault-method and the result-method is changed to set the result within a bindable variable in the model/MyModelLocator singleton. This variable is bound to the Label’s text property so it shows up there after you pressed the button and the result is received from the server. That’s it!

If you want to use Flex in the browser instead of AIR simply create a new Flex project and change the root node from WindowedApplication to Application. The rest of the source should stay the same as we did not use any AIR API specific features.
A big thanks to the guys who have taken over the AMFPHP project and to Patrick Mineault of course for this great peace of software!
I would appreciate feedback if the detail level is to low or if your miss explanations on any parts so I can extend these parts.

13 comments to AMFPHP on AIR Tutorial with MAMP