Best practices: Custom class mapping using OpenAMF and AS3 (Flash CS3 - not Flex)
Posted on September 23, 2007
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 a 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:
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 }
2) On the Flash-side you have to point the VO to its server-side "antagonist" using - that's important for class mapping on Flash-side - [RemoteClass(alias="de.websector.blog.openamf.mapping.vo.UserVO")]
and registerClassAlias("UserVO", UserVO);
to register the VO within Flash. Here an example:
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 }
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.
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:
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:
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 }
- 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
Helpful links
- [AS3] Jorge Solis: Hello World with Openamf Vishwajit: Sending custom class object thru remoting using OpenAmf
- [AS2] Ginormous Blog: Custom class mapping with openAMF Darron Schall: Some notes about using OpenAMF
- [OS X] Apple Developer Connection: Java and Tomcat on Mac OS X, Part I