OpenAMF is a free open-source alternative to Adobe’s (formely Macromedia’s) Java Flash Remoting. It’s difficult to find any tutorials or posts about OpenAMF using AS3, because it seems that the OpenAMF project has stopped since 2006.

Anyway, at my current project we are using OpenAMF with AS3 (Flash CS3) and it works like a charm. But there are some important differences between AS2 and AS3 Flash Remoting using Flash CS3. To avoid running into any issues – particulary mapping custom classes – follow the following tips. But first of all thanks to Marc Schachtel for his great support on server-side ;-) .

Best practices

  1. Create on the server- and Flash-side identical simple objects using the Value Object pattern to send and receive custom objects over the wire. Assuming a UserVO would be created on server-side as follows:

    UserVO.java ( Download code )

    1. package de.websector.blog.openamf.mapping.vo;
    2.  
    3. import java.util.Date;
    4.  
    5. public class UserVO
    6. {
    7.     private String userName;
    8.     private Date registerDate;
    9.    
    10.     public UserVO() {}
    11.  
    12.     public String getUserName()
    13.     {
    14.         return this.userName;
    15.     }
    16.  
    17.     public void setUserName(String value)
    18.     {
    19.         this.userName = value;
    20.     }
    21.    
    22.     public Date getRegisterDate()
    23.     {
    24.         return this.registerDate;
    25.     }
    26.  
    27.     public void setRegisterDate(Date value)
    28.     {
    29.         this.registerDate = value;
    30.     }
    31.  
    32. }
    33.  
  2. On the Flash-side you have to point the VO to its server-side “antagonist”using [RemoteClass(alias="de.websector.blog.openamf.mapping.vo.UserVO")] and – that’s important for class mapping on Flash-side – registerClassAlias("UserVO", UserVO); to register the VO within Flash. Here an example:

    UserVO.as ( Download code )

    1. package
    2. {
    3.  
    4.     [RemoteClass(alias="de.websector.blog.openamf.mapping.vo.UserVO")]
    5.  
    6.     import flash.net.registerClassAlias;
    7.        
    8.     public class UserVO
    9.     {
    10.         private var _userName: String;
    11.         private var _registerDate: Date;
    12.        
    13.         public function UserVO():void {}
    14.    
    15.         public function get userName(): String
    16.         {
    17.             return this._userName;
    18.         }
    19.    
    20.         public function set userName(value: String): void
    21.         {
    22.             this._userName = value;
    23.         }
    24.        
    25.         public function get registerDate(): Date
    26.         {
    27.             return this._registerDate;
    28.         }
    29.    
    30.         public function set registerDate(value: Date): void
    31.         {
    32.             this._registerDate = value;
    33.         }
    34.  
    35.         static public function register():void
    36.         {      
    37.             registerClassAlias("UserVO", UserVO);      
    38.         }
    39.     }
    40. }
    41.  
  3. Within the OpenAMF config file named openamf-config.xml you have to configure the behavior of outgoing AMF messages setting the forceLowerCaseKeys-tag to false to avoid converting all keys to lower case.

    snippet1.xml

    1. <amf-serializer>
    2.         <force-lower-case-keys>false</force-lower-case-keys>
    3. </amf-serializer>
  4. Map within the same openamf-config.xml file all Value Objects located on the server- and Flash-side as follows:

    snippet2.xml

    1. <custom-class-mapping>
    2.     <java-class>de.websector.blog.openamf.mapping.vo.UserVO</java-class>
    3.     <custom-class>UserVO</custom-class>
    4. </custom-class-mapping>
  5. To connect the OpenAMF gateway within Flash you have to create an instance of flash.net.NetConnection; calling myNetConnectionInst.connect("http://mysite/openamf/gateway");. To listen to results or faults create a flash.net.Responder; instance and use it for calling server-side services using myNetConnectionInst.call("com.yoursite.YourService.serviceMethod", youResponder, parameters);.

    OpenAMF use the AMF0 protocol so you have to point it using myNetConnectionInst.objectEncoding = ObjectEncoding.AMF0;.

    Don’t forget to register the VO with its static register() method.

    Here is an example:

    OpenAMFMapping.as ( Download code )

    1. package {
    2.    
    3.     import flash.net.Responder;
    4.     import flash.net.NetConnection;
    5.     import flash.net.ObjectEncoding;
    6.    
    7.     import flash.display.Sprite;
    8.    
    9.     public class OpenAMFMapping extends Sprite {
    10.        
    11.         private var _nc: NetConnection;
    12.        
    13.         public function OpenAMFMapping() {
    14.  
    15.             UserVO.register();
    16.            
    17.             _nc = new NetConnection();
    18.          _nc.objectEncoding = ObjectEncoding.AMF0;
    19.        
    20.             _nc.connect("http://localhost:8080/mappingExample/gateway");
    21.            
    22.             var responder:Responder = new Responder(onResult, onFault);
    23.  
    24.             _nc.call("de.websector.blog.openamf.mapping.services.UserServices.getUserByName", responder, "Luke Skywalker");   
    25.         }
    26.  
    27.        
    28.         private function onFault(result:Object):void {
    29.             trace("onFault: " + result.toString());
    30.         }
    31.        
    32.         private function onResult(result:Object):void {
    33.  
    34.             trace("onResult: " +  result);
    35.            
    36.            
    37.             try {         
    38.                 var user: UserVO = result as UserVO;               
    39.                 trace("userName: " + user.userName);   
    40.                 trace("userRegisterDate: " + user.registerDate);   
    41.             }
    42.             catch(error: Error) {
    43.                 trace ("onResult ERROR " + error.message);       
    44.             }
    45.         }
    46.        
    47.     }
    48.    
    49. }
  6. Tip: For better remoting calls check out Danny Pattersons “AS3 Lightweight Remoting Framework[UPDATE 10/17/07] or Aaron Smith’s SSR: Super Simple Remoting[/UPDATE] as well.

Screen shot

Mapped results within Flash CS3 debugger calling server-side service getUserByName(String userName):


Download example files

OpenAMFMappingExampleFiles.zip
(Downloads: 839)

Helpful links

14 Responses to “Best practices: Custom class mapping using OpenAMF and AS3 (Flash CS3 – not Flex)”

  1. anatole tartakovsky Says:

    Clear DataBuilder plugin does automatic configuration of OpenAM/LCDS/FDS and generates both client and server side code for communication. We also added hot deployment and configuration and generalized RemoteObject that can be used for Adobe RPC or openAmf. It is also very simple to add additional protocols. In addition, recognised standard ones like WebServices are automatically proxied over RPC as long as destination has wsdl suffix and proxy is configured.

    Regards,
    Anatole

  2. sectore Says:

    Anatole,

    thanks for your hint. One question: Does Clear DataBuilder work with “pure” Flash apps (without the Flex framework)?

    -sectore

  3. Aaron Smith Says:

    There is a really nice remoting package called SSR (ssr.riaforge.org) It’s much simpler than as3lrf.

  4. Aaron Smith Says:

    actually the ssr project moved to osflash.org/projects/ssr

  5. sectore Says:

    Aaron,

    thanks for your hint! I’ve added a link to yours SSR: Super Simple Remoting, too ;)

    -sectore

  6. Manan Says:

    I am new to AS3. I have one question about the statement in this article which says “On the Flash-side you have to point the VO to its server-side “antagonist” using [RemoteClass(alias="de.websector.blog.openamf.mapping.vo.UserVO")]”

    I was playing around with this example and I removed this line from my code and still everything works fine for me. I can send and receive object from server even without this line.

    Can anyone explain me why do we need to put this line in our code and what exactly it does ?

    Any help is appreciated.

    Thanks,
    Manan

  7. sectore Says:

    Manam,

    you’re right – it seems that the meta tag named RemoteClass is needed for Flex only instead using
    registerClassAlias(“com.mydomain.vo.MyServerSideVO”, MyFlashVO);

    Using Flash you have to use the registerClassAlias method mentioned above without the metag [RemoteClass(alias="com.mydomain.vo.MyServerSideVO")]. The Flash IDE compiler ignores this metatag.

    Thanks for your hint!

    -sectore

  8. WS-Blog » AsUnit (AS3): RemoteTestCase for testing asynchronous data using Flash Remoting Says:

    [...] The following test example based on my Flash Remoting example using OpenAMF described at the previous article called “Best practices: Custom class mapping using OpenAMF and AS3 (Flash CS3 – not Flex)” [...]

  9. Marcio Says:

    I create the following function

    ———————————

    package com.cerebrum.utils {

    import mx.rpc.events.ResultEvent
    import mx.controls.Alert;

    public class Result {

    [Embed("/assets/images/dialog-information.png")]
    public var IconDialogInformation:Class;

    public function Result(event:ResultEvent,MyObject:Object):void {
    Alert.show(“teste”, “teste”, 4, null, null, IconDialogInformation);
    }

    }

    }

    ———————————

    I as follows

    import Result;

    Result(event, meuobjeto);

    ———————————

    Is presented in the following error flex builder

    1137: Incorrect number of arguments. Expected no more than 1.

    ———————————

    How should I inform the function that actually has 2 parameters?

  10. Rogelio Says:

    It’s not working for me! Can anyone send me a zipped file with the files that need to be in the Tomkat webapps folder?

    For some reason the flash side is not reaching the java class, the UserVO object is never filled…

    Please help!!!

  11. sectore Says:

    Rogelio (or Adrain ;) ),

    I’ve already sended all files to you using your email adress hosted at advanceme.com

    Anyway, you can ping me an email again.

    -Jens

  12. zornic Says:

    I have some AS3 problem at CS4 (1137: Incorrect number of arguments. Expected no more than 0.)

    var currentColumn:int = i -(currentRow * numColumns);
    “”aSpinners[i]= new Spinner(i);”"
    gameScreen.addChild(aSpinners[i]);
    aSpinners[i].x=currentColumn*hSpace;
    aSpinners[i].y=currentRow*vSpace;

  13. openamf_java Says:

    OpenAMF is a good library for AMF communications, I write a simple tutorial to get in communication servlet with as3 client side.

    http://programmaremobile.blogspot.com/2009/10/java-and-amf-by-as3-in-flash.html

    The problem is that OpenAMF supports only the AMF0 format, that is old. I don’t like to use older version of a tecnologies

  14. henry Says:

    Hi Sector,

    According to Manan question.. why then do most ppl insert the
    [RemoteClass()] in their code if it is not really necessary? or when is it necessary and when is it not needed?

Leave a Reply

Follow sectore on Twitter