4

I have a java socket server that sends an Animal object to the Flash client when it connects. The object is sent like this:

Amf3Output amf3Output = new Amf3Output(SerializationContext.getSerializationContext());
amf3Output.setOutputStream(userSocket.getOutputStream());
amf3Output.writeObject(animal);

And the code on flash side is:

var object:Object = socket.readObject();
trace(object);
trace(object as Animal);

However when the second trace gives me a null

I have checked that java sends out 31 bytes and Flash receives 31 bytes.

I think it might be that my Java and AS3 classes don't match some AMF requirement.

Java class:

package main;

public class Animal {

   public String name;
   public int age;
}

AS3 class:

package  
{

    [Bindable]
    [RemoteClass(alias="main.Animal")]
    public class Animal 
    {
        public var name:String;
        public var age:int;

    }

}
Rob Fox
  • 5,355
  • 7
  • 37
  • 63
  • Are you using an AMF Gateway, such as LiveCycle or BlazeDS? IF so, which one. – JeffryHouser Jul 04 '11 at 12:42
  • I'm not sure what you mean by AMF Gateway but I just took the flex-messaging-core.jar and flex-messaging-common.jar from blazeDS lib folder as they are used for the encoding/decoding process. – Rob Fox Jul 04 '11 at 12:46
  • An AMF Gateway is, basically, some program you are running on the server which will translate the server side objects into client side objects and client side objects into server side objects. It also handles the routing of your RemoteObject calls. It probably does other stuff too. It sounds like you're trying to use the BlazeDS classes manually; as opposed to setting up BlazeDS as a gateway and letting it handle that. This is an unusual approach. – JeffryHouser Jul 04 '11 at 13:32
  • I am using sockets and transfer the data using socket streams. I don't see why this wouldn't work if I use BlazeDS' encoder. I also know there are other frameworks that do this. – Rob Fox Jul 04 '11 at 13:36
  • I don't know why it isn't working either. You are taking a very unusual approach to using AMF. I'm sure in the end it will give you a solid understanding of the protocol and how it is implemented, but it's beyond my knowledge to offer an answer to your question. Best of luck! – JeffryHouser Jul 04 '11 at 14:05
  • @www.Flextras.com Must use AMF Gateway? I have tried send string or int to client, it works well. But I failed sending custom object to client – jason Dec 12 '11 at 11:31

3 Answers3

2

I'm not familiar with Java and the AMF serializers/deserializers available for it, but sending typed objects over sockets is indeed supported in flash, and works properly if you send the right data. Below is an example of a socket server in ruby communicating with a Flash application. I'm using RocketAMF to send an AMF3 object over the socket to a client after it connects.

SocketTest.as:

package {
    import flash.display.Sprite;
    import flash.net.registerClassAlias;
    import org.rackAMF.*;
    import flash.net.Socket;
    import flash.events.*;

    public class SocketTest extends Sprite {
        private var socket:Socket;

        public function SocketTest() {
            registerClassAlias('Animal', Animal);

            socket = new Socket();
            socket.addEventListener(ProgressEvent.SOCKET_DATA, onResponse);
            socket.connect("localhost", 8081);
        }

        private function onResponse(e:ProgressEvent):void {
            var animal:Animal = socket.readObject() as Animal;
            trace(Object(animal).constructor); // [trace] [class Animal]
            trace(animal.name); // [trace] Zebra
            trace(animal.age); // [trace] 5
        }
    }
}

class Animal {
    public var name:String;
    public var age:int;
}

socket_server.rb:

require 'rubygems'
require 'socket'
require 'rocketamf'

class Animal
  attr_accessor :name, :age
end

# Map "Animal" in ruby to "Animal" in flash
RocketAMF::ClassMapper.define do |m|
  m.map :as => 'Animal', :ruby => 'Animal'
end

server = TCPServer.open(8081)
loop {
  client = server.accept

  animal = Animal.new
  animal.name = "Zebra"
  animal.age = 5
  client.write RocketAMF.serialize(animal, 3)

  client.close
}
warhammerkid
  • 955
  • 5
  • 6
  • Now I'm not sure if I mapped the AS3 and Java classes wrong or var animal:Animal = socket.readObject() as Animal did the job but it works! Thanks :). – Rob Fox Jul 07 '11 at 06:34
  • @Rob Fox, I think I know why the Metadata wasn't working. I can't believe I forgot about this. It's an 'issue' with your compilation process. You probably don't have a class variable somewhere that specify 'Animal', hence the flex compiler won't compile that class in and won't know about the metadata. Keep your metadata there and within the class that's called the socket, create a `private var animal:Animal;` and it should work. – J_A_X Jul 07 '11 at 14:25
  • I didn't indeed and as I put it as an inner class now the compiler compiled it. Interesting. – Rob Fox Jul 07 '11 at 15:28
0

Have you checked that the objectEncoding is set to 3 on the ActionScript side? If you're sending AMF3 data and it's trying to read AMF0 data, it won't work.

warhammerkid
  • 955
  • 5
  • 6
0

Since you've taken parts of BlazeDS, it's hard to determine what are AMF3 requirements versus BlazeDS requirements. What I will say is that BlazeDS needs Java classes that follow the Java Beans spec and that means matching getters and setters.

I'm also assuming that more is needed on the Flex side to de-serialize the AMF3 payload: the on-the-wire format is not an Actionscript 3.0 object. I've done some BlazeDS custom serialization which is why I think you're missing something on the Flex side.

Is there a reason you're not using BlazeDS (or GraniteDS) for the communication?

SteveD
  • 5,396
  • 24
  • 33
  • I need a fast socket based high traffic connection. I was told that BlazeDS is not ideal for that. – Rob Fox Jul 05 '11 at 14:35