Re: Mapping objects
Todd Hivnor <[email protected]> Tue, 04 Jul 2006 13:32:03 -0700
| Newsgroups | gmane.comp.java.openamf.user |
|---|---|
| Message-ID | <[email protected]> |
You are on the right path, generally.
SmackletType is defined in
public class HelloWorld, which seems wrong. I would define SmackletType
in SmackletType.as. SmackletType is also defined in the
com.flashdb.services package, but this package isn't included in your
call to Object.registerClass.
I keep the same class hierarchy in Flash and Java, so if SmackletType is
defined in the com.flashdb.services package in Java, then I create that
exact same package in Flash. It just keeps things clear, and makes the
class mappings simple:
<custom-class-mapping>
<java-class>com.flashdb.services.SmackletType</java-class>
<custom-class>com.flashdb.services.SmackletType</custom-class>
</custom-class-mapping>
Object.registerClass("com.flashdb.services.SmackletType",
com.flashdb.services.SmackletType);
You seem to have a couple of packages in play, com.flashdb.services and
com.flashdb.domain. This might be part of the problem.
I personally don't use the underscore in front of variable names. I use
function names like getSmackletName() and receive values in Flash like
smackletName. The underscore may work, but if you might experiment with
dropping it if you can't get things to work, after getting the packages
in line.
I recommend using local HTTP proxy server to inspect the Remoting
traffic. I personally use ServiceCapture, but there is apparently
something else called Charles which might work. But generally these let
you see the data flows between Java and Flash, which is really handy.
You do need to implement Serializable in your Java class, as I
understand it.
OpenAMF will use introspection to dig into your Java object, and call
all of its getters. This is convenient, but can be a hassle if you have
getters which access data you don't want serialized. I use methods like
fetchSmackletName(), as opposed to getSmackletName(), if I don't want
smackletName sent to Flash.
If you want to learn about the serialization process, it is helpful to
understand that OpenAMF uses CarbonFive's ASTranslator. The ASTranslator
documentation is pretty good.
You can do a lot of great things with Java and Flash Remoting, they work
really well together. You can serialize very complex nested objects. I
personally define my whole application interface in Java, and then have
Flash just render it. So can change my user interface from Java, without
recompiling the .swf. When I first started using Remoting, I didn't take
the time to understand how powerful the object mapping stuff is. I later
rewrote the app using object mapping, and the code is much simpler &
cleaner. So I would encourage you to take the time to fully experiment
with the object mapping stuff, before writing any real application code.
One thing to understand is that the Java-->Flash serialization is more
powerful than the Flash->Java serialization. If you have Object A which
references Object B, and Object B references Object A, then you have a
circular reference loop. When serializing from Java to Flash this is
fine. Java will send one copy of each object, and not get confused. If
you sent this back, from Flash to Java, then Flash will lock up. It
can't resolve the circular reference, and gets hopelessly confused. So,
watch out for that. You can do a recursion check in Flash, to detect this.
Here is my code, which has a couple of references to things you don't
have. It can easily be adapted. The code will recursively walk through
an object, building up an array of the all the objects encountered thus
far. If it finds a duplicate, then there is a recursive loop, so it
reports the problem and bails out.
class LearnerService {
/** Return true of the object is Ok.
* Also return true if we are not currently checking for recursion.
* If there is a problem trace it, and set the problematicObject
variable
*/
private static var problematicObject;
public static function recursionCheck(currObject : Object) : Boolean {
if (DebugConfig.checkRecursionInEvents()) {
trace(Log.L_INFO+ "Performing Recursion Check ...");
var result : Boolean =
LearnerService.recursionCheckHelper(currObject, new Array());
if (result) {
trace(Log.L_INFO+ "Recursion Check Passed! ");
}
return result;
} else {
return true;
}
}
private static function recursionCheckHelper(currObject : Object,
objectsFound : Array) : Boolean {
var childObject : Object;
var i : Number;
var hasError : Boolean = false;
for (var key : String in currObject) {
childObject = currObject[key];
if ( (typeof(childObject) == "object") ||
(typeof(childObject) == "movieclip")) {
for (i=0; i<objectsFound.length; i++) {
if (childObject == objectsFound[i]) {
trace(Log.L_ERROR+ "Found recursive child
object=" + childObject + " with key=" + key +
" in object=" + currObject + " inside
runEvent.");
LearnerService.problematicObject =childObject;
return false;
}
}
objectsFound.push(childObject);
// recursively check
if (recursionCheckHelper(childObject, objectsFound) ==
false) {
hasError = true;
break;
}
} else if (childObject == null) {
// no need to check null's
} else if (
(typeof(childObject) == "string") ||
(typeof(childObject) == "boolean") ||
(typeof(childObject) == "number") ||
(typeof(childObject) == "function")
) {
// no need to check these things
} else {
trace(Log.L_ERROR+ "Not an object: child object=" +
childObject + " is " + typeof(childObject) + " with key=" + key +
" in object=" + currObject + " inside runEvent.");
}
}
return ! hasError;
}
}
Luke DeWitt wrote:
> Hey Guys,
>
> I finally got OpenAMF up and working (had to use the last release
> though) and I am am so sorry to ask this question again, but I have
> read through a bunch of the mail list archives and I am getting nowhere!
>
> I used this tutorial here:
> http://www.flash-db.com/Tutorials/helloOpenamf/hello2.php?page=4 to
> get started in the wonderful world that is java to flash remoting.
> This was a simple little tutorial, but I am looking to do more than
> just echo a String. At this moment I am trying to send a custom java
> object (SmackletType) to Flash. I figure that if I can get this
> working I will have no problem doing the next couple of steps which
> are just extenstions of this.
>
> Here is some code to help people visualize what I am doing:
>
> Java Code for Smacklet Type:
>
> package com.flashdb.domain;
>
> import java.io.Serializable;
>
> public class SmackletType implements Serializable { // does this
> need to be serializable?
>
> // class properties
> private String _smackletName;
> private String _smackletTeaseLink;
> private String _smackletLink;
> private String _smackletThumbnail;
>
> // constructor
>
> public SmackletType(String smackletName, String smackletLink, String
> smackletTeaseLink, String smackletThumbnail) {
>
> _smackletThumbnail = smackletThumbnail;
> _smackletTeaseLink = smackletTeaseLink;
> _smackletLink = smackletLink;
> _smackletName = smackletName;
>
> } // SmackletType constructor
>
> // getters and setters
>
> public String get_smackletLink() {
> return _smackletLink;
> }
>
> public void set_smackletLink(String link) {
> _smackletLink = link;
> }
>
> public String get_smackletName() {
> return _smackletName;
> }
>
> public void set_smackletName(String name) {
> _smackletName = name;
> }
>
> public String get_smackletTeaseLink() {
> return _smackletTeaseLink;
> }
>
> public void set_smackletTeaseLink(String teaseLink) {
> _smackletTeaseLink = teaseLink;
> }
>
> public String get_smackletThumbnail() {
> return _smackletThumbnail;
> }
>
> public void set_smackletThumbnail(String thumbnail) {
> _smackletThumbnail = thumbnail;
> }
>
> } // SmackletType class
>
>
> ActionScript Code for SmackletType:
>
> class SmackletType {
>
> // class properties
> private var _smackletName:String;
> private var _smackletTeaseLink:String;
> private var _smackletLink:String;
> private var _smackletThumbnail:String;
>
> // constructor
>
> public function SmackletType(smackletName:String,
> smackletLink:String, smackletTeaseLink:String, smackletThumb:String) {
>
> _smackletThumbnail = smackletThumb;
> _smackletTeaseLink = smackletTeaseLink;
> _smackletLink = smackletLink;
> _smackletName = smackletName;
>
> } // SmackletType constructor
>
> // getters and setters
> public function get smackletName():String {
> return _smackletName;
> }
>
> public function set smackletName(sSmackletName:String):Void {
> _smackletName = sSmackletName;
> }
>
> public function get smackletLink():String {
> return _smackletLink;
> }
>
> public function set smackletLink(sSmackletLink:String):Void {
> _smackletLink = sSmackletLink;
> }
>
> public function set smackletTeaseLink(sSmackletTeaseLink:String):Void {
> _smackletTeaseLink = sSmackletTeaseLink;
> }
>
> public function get smackletTeaseLink():String {
> return _smackletTeaseLink;
> }
>
> public function get smackletThumbnail():String {
> return _smackletThumbnail;
> }
>
> public function set smackletThumbnail(sSmackletThumbnail:String):Void {
> _smackletThumbnail = sSmackletThumbnail;
> }
>
> } // SmackletType class
>
> I have added the following into my openamf-config.xml file:
>
> <custom-class-mapping>
> <java-class>com.flashdb.domain.SmackletType</java-class>
> <custom-class>SmackletType</custom-class>
> </custom-class-mapping>
>
> This is the simple piece of java code I have edited to send my object:
>
> package com.flashdb.services;
>
> import com.flashdb.domain.*;
>
> public class HelloWorld {
>
> SmackletType testSmackletType = new SmackletType("Slots",
> "http://www.google.com", "http://www.google.ca", "00.gif");
>
> public SmackletType makeEcho(){
> return testSmackletType;
> }
>
> }
>
> And Finally, the ActionScript code to actually call for the object:
>
> //Import needed classes
> import mx.remoting.Service;
> import mx.services.Log;
> import mx.rpc.RelayResponder;
> import mx.rpc.FaultEvent;
> import mx.rpc.ResultEvent;
> import mx.remoting.PendingCall;
> import mx.remoting.debug.NetDebug
> NetDebug.initialize()
> // initialize the Logger
> var myLogger : Log = new Log (Log.DEBUG, "logger1" );
> // override the default log handler
> myLogger.onLog = function (message : String ) : Void {
> trace ("myLogger-->>>" + message );
> }
>
> //Create the service
> myService = new Service ("http://localhost/helloworld/gateway",
> myLogger, "com.flashdb.services.HelloWorld", null, null);
> Object.registerClass("com.flashdb.domain.SmackletType", SmackletType);
> //on Data handler
> //function onEchoData (msg : ResultEvent){
> function onEchoData (msg : SmackletType){
> mx.remoting.debug.NetDebug.trace ({level : "Debug", message :
> "onCategoryData" });
> // show.text = msg.result;
> //var temp:SmackletType = msg;
> var temp:SmackletType = msg;
> trace(temp.smackletName() + " HOOGEY BOOGEY!");
> }
> //on Error handler
> function onEchoFault (rs : ResultEvent){
> mx.remoting.debug.NetDebug.trace ({level : "None", message : "There
> was a problem: " + fault.fault.faultstring });
> }
> //Buttons callbacks
> callButton.onPress = function () {
> //create the remoting call
> var pc : PendingCall = myService.makeEcho();
> pc.responder = new RelayResponder (this._parent, "onEchoData",
> "onEchoFault" );
> }
> //just clear the textfield
> clearButton.onPress = function (){
> show.text = "";
> }
> stop();
>
>
> When I run my program and hit the "callbutton", I get this...
>
> myLogger-->>>7/4 15:15:2 [INFO] logger1: Creating Service for
> com.flashdb.services.HelloWorld
> myLogger-->>>7/4 15:15:2 [INFO] logger1: Creating gateway connection
> for http://localhost/helloworld/gateway
> myLogger-->>>7/4 15:15:2 [INFO] logger1: Successfully created Service
> myLogger-->>>7/4 15:15:3 [INFO] logger1: Invoking makeEcho on
> com.flashdb.services.HelloWorld
> undefined HOOGEY BOOGEY!
> myLogger-->>>7/4 15:15:3 [INFO] logger1:
> com.flashdb.services.HelloWorld.makeEcho() returned {_smackletLink:
> "http://www.google.com",
> _smackletName: "Slots",
> _smackletTeaseLink: "http://www.google.ca",
> _smackletThumbnail: "00.gif"}
>
>
> I just want to be able to get that info that is being passed into
> Flash to become my SmackletType object. Can anyone give me a hand?
> This stuff is making my life so much easier right now over web
> services, and any help I could get would be greatly appreciated.
>
> Thank you!
>
> --LD
>
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642