2011-05-18 15 views
5

Actualmente estoy tratando de comunicarme entre java y flex usando sockets y objetos serializados AMF.Leer un objeto AMF con conector flexible

En el lado java, uso Amf3Input y Amf3Output de BlazeDS (flex-messaging-common.jar y flex-messaging-core.jar).

La conexión se establece correctamente, y si trato de enviar un objeto a partir de la flexión de Java, que puede leer fácilmente los objetos:

lado FLEX:

protected function button2_clickHandler(event:MouseEvent):void 
{ 
    var tmp:FlexAck = new FlexAck; 
    tmp.id="123456789123456789123456789"; 
    tmp.name="A"; 
    tmp.source="Aaaaaa"; 
    tmp.ackGroup=false; 
    s.writeObject(tmp); 
    s.flush(); 
} 

lado de Java:

ServerSocket servSoc = new ServerSocket(8888); 
Socket s = servSoc.accept(); 
Amf3Output amf3Output = new Amf3Output(SerializationContext.getSerializationContext()); 
amf3Output.setOutputStream(s.getOutputStream()); 
Amf3Input amf3Input = new Amf3Input(SerializationContext.getSerializationContext()); 
amf3Input.setInputStream(s.getInputStream()); 
while(true) 
{ 
    try 
    { 
     Object obj = amf3Input.readObject(); 
     if(obj!=null){ 
      if (obj instanceof AckOrder){ 
      System.out.println(((AckOrder)obj).getId()); 
     } 
     }     
} 
catch (Exception e) 
{ 
     e.printStackTrace(); 
    break; 
} 
    } 
    amf3Output.close(); 
    amf3Input.close(); 
    servSoc.close(); 

De esta manera funciona perfectamente, pero el problema es leer objetos enviados desde el lado de java.

El código que utilizo en Java es:

for(int i=0;i<10;i++){ 
    ack = new AckOrder(i,"A","B", true); 
    amf3Output.writeObject(ack); 
    amf3Output.writeObjectEnd(); 
    amf3Output.flush(); 
} 

tengo un controlador on ProgressEvent.SOCKET_DATA:

trace ((s.readObject() como FlexAck) .ID);

Pero tengo errores tales como: Error # 2030: Fin del archivo detectado Error # 2006: Índice fuera de límite

si añado manipulaciones en ByteArrays, me las arreglo para leer el primer objeto, pero no el seguimiento.

s.readBytes(tmp,tmp.length); 
content = clone(tmp); 
(content.readObject()); 
trace("########################## OK OBJECT RECEIVED"); 
var ack:FlexAck = (tmp.readObject() as FlexAck); 
trace("**********************> id = "+ack.id); 

He pasado muchos de nuestros tratando de encontrar algo en varios foros, etc., pero nada ayudó.

Así que si alguien me puede ayudar, sería genial.

Gracias

Sylvain

EDIT:

Aquí es un ejemplo que pensé que debería funcionar, pero no espero que es mejor ilustrar lo que me propongo hacer (conexión permanente con el zócalo y un intercambio de mensajes).

clase

Java:

import java.net.ServerSocket; 
import java.net.Socket; 
import awl.oscare.protocol.AckOrder; 
import flex.messaging.io.SerializationContext; 
import flex.messaging.io.amf.Amf3Input; 
import flex.messaging.io.amf.Amf3Output; 


public class Main { 
public static void main(String[] args) { 
     while(true) 
     { 
     try { 
     ServerSocket servSoc = new ServerSocket(8888); 
     Socket s = servSoc.accept(); 
     System.out.println("connection accepted"); 
     Amf3Output amf3Output = new Amf3Output(SerializationContext.getSerializationContext()); 
     amf3Output.setOutputStream(s.getOutputStream()); 
     Amf3Input amf3Input = new Amf3Input(SerializationContext.getSerializationContext()); 
     amf3Input.setInputStream(s.getInputStream()); 
     while(true) 
     { 
      try 
      { 
       System.out.println("Reading object"); 
       Object obj = amf3Input.readObject(); 
       if(obj!=null) 
       { 
        System.out.println(obj.getClass()); 
        if (obj instanceof AckOrder) 
        { 
         AckOrder order = new AckOrder(); 
          order.setId(((AckOrder)obj).getId()); 
order.setName(((AckOrder)obj).getName()); 
          order.setSource(((AckOrder)obj).getSource()); 
         order.setAckGroup(((AckOrder)obj).isAckGroup()); 
          System.out.println(((AckOrder)obj).getId()); 
         amf3Output.writeObject(order); 
         amf3Output.writeObjectEnd(); 
         amf3Output.flush(); 
        } 
       } 
      } 
      catch (Exception e) 
      { 
       e.printStackTrace(); 
       break; 
      } 
     } 
     amf3Output.close(); 
     amf3Input.close(); 
     servSoc.close(); 
    } catch (Exception e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    } 

} 
} 

Java objeto Serializable:

package protocol; 

import java.io.Serializable; 

public class AckOrder implements Serializable { 
    private static final long serialVersionUID = 5106528318894546695L; 
    private String id; 
private String name; 
private String source; 
private boolean ackGroup = false; 

public String getId() { 
    return this.id; 
} 

public void setId(String id) { 
    this.id = id; 
} 

public String getName() { 
    return this.name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public void setSource(String source) { 
    this.source = source; 
} 

public String getSource() { 
    return this.source; 
} 

public void setAckGroup(boolean ackGroup) { 
    this.ackGroup = ackGroup; 
} 

public boolean isAckGroup() { 
    return this.ackGroup; 
} 

public AckOrder() 
{ 
    super(); 
} 
} 

Flex Side:

principal código de flexión:

<fx:Script> 
    <![CDATA[ 
     import mx.collections.ArrayCollection; 
     import mx.controls.Alert; 
     import mx.events.FlexEvent; 
     import mx.utils.object_proxy; 


     private var _socket:Socket = new Socket();; 

     private function onCreationComplete():void 
     { 
      this._socket.connect("localhost",8888); 
      this._socket.addEventListener(ProgressEvent.SOCKET_DATA, onData); 
     } 

     private function onData(e:ProgressEvent):void 
     { 

      if(this._socket.bytesAvailable) 
      { 
       this._socket.endian = Endian.LITTLE_ENDIAN; 
       var objects:Array = []; 
       try{ 
        while(this._socket.bytesAvailable > 0) 
        { 
         objects.push(this._socket.readObject()); 
        } 
       }catch(e:Error){trace(e.message);} 
        trace("|"+(objects)+"|"); 
      } 

     } 

     protected function sendButton_clickHandler(event:MouseEvent):void 
     { 
      var tmp:FlexAck = new FlexAck; 
      tmp.id="1"; 
      tmp.name="A"; 
      tmp.source="B"; 
      tmp.ackGroup=false; 
      this._socket.writeObject(tmp); 
      this._socket.flush(); 
     } 


    ]]> 
</fx:Script> 
<s:Button x="0" y="0" name="send" label="Send" click="sendButton_clickHandler(event)"/> 

Flex objeto serializable:

package 
{ 

[Bindable] 
[RemoteClass(alias="protocol.AckOrder")] 
public class FlexAck 
{ 
    public function FlexAck() 
    { 
    } 

    public var id:String; 
    public var name:String; 
    public var source:String; 
    public var ackGroup:Boolean; 

} 
} 

Edición 25/05/2011:

he añadido los oyentes en mi código flex:

this._socket.addEventListener(Event.ACTIVATE,onActivate); 
       this._socket.addEventListener(Event.CLOSE,onClose); 
       this._socket.addEventListener(Event.CONNECT,onConnect); 
       this._socket.addEventListener(Event.DEACTIVATE,onDeactivate); 
       this._socket.addEventListener(IOErrorEvent.IO_ERROR,onIOerror); 
      this._socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError); 

pero hay no hay errores y todavía no logro recibir objetos correctamente.

+0

¿Por qué leerlo dos veces si solo se envía un objeto? –

+0

De hecho, el código de Java que envía el objeto está en un bucle que intenta enviar 10 objetos. – Sylvain

+0

Entonces ese código no se muestra. Lo que mostró fue que se creó un objeto, se agregó la línea final y se encendió. –

Respuesta

0

Después looking at the code, creo que lo que quiere hacer en el extremo de Java es la siguiente:

for(int i=0;i<10;i++){ 
    ack = new AckOrder(i,"A","B", true); 
    amf3Output.writeObject(ack); 
} 
amf3Output.flush(); 

Al hacer 'ras', que está enviando información a través de la toma por lo que sólo había de ser un objeto enviado a la vez. En el extremo Flex, siempre debes intentar ver cuál es la longitud del objeto y asegurarte de que no lo pases, lo que provocaría este error.

EDIT:

private var _socket:Socket = new Socket(); 

private function onCreationComplete():void 
{ 
    // Add connection socket info here 
    this._socket.addEventListener(ProgressEvent.SOCKET_DATA, onData); 
} 

// This gets called every time we get new info, as in after the server flushes 
private function onData(e:ProgressEvent):void 
{ 
    if(this._socket.bytesAvailable) 
    { 
     this._socket.endian = Endian.LITTLE_ENDIAN; // Might not be needed, but often is 
     // Try to get objects 
     var objects:Array = []; 
     try{ 
      while(this._socket.bytesAvailable > 0) 
      { 
       objects.push(this._socket.readObject()); 
      } 
     }catch(e:Error){} 
     // Do something with objects array 
    } 
} 

La función onData se llama continuamente (cada vez que el servidor envía información) ya que todo es asíncrona.

+0

Lo siento, pensé que mi descripción era clara, pero puedo ver que no es el caso. De hecho, me gustaría leer un objeto a la vez. Creé este ciclo para simular un proceso que se comunicará con mi código flexible mediante el envío de objetos. Por lo tanto, podría ser un objeto enviado y otro varios segundos después (con una conexión persistente a través de sockets). Intenté usar el código que publicaste, pero todavía tengo problemas para leer más de un objeto. – Sylvain

+0

Si solo envía un objeto, el extremo Flex solo obtendrá un objeto ... No estoy seguro de lo que no entiende sobre este concepto ... Básicamente está tratando de leer un objeto que su cliente no tiene. t recibido todavía –

+0

Lo que intento es abrir el socket => send 1 object => leer el objeto, y mantener la conexión abierta, luego, enviar un nuevo objeto y leer este nuevo objeto. Todo está bien hasta que intento leer el segundo objeto. – Sylvain

1

Usted tiene que enviar los datos AMF como ByteArray en el servidor:

final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
amf3Output.setOutputStream(baos); 
amf3Output.writeObject(order); 
amf3Output.flush(); 
amf3Output.close(); 
s.getOutputStream().write(baos.toByteArray()); 

Entonces

this._socket.readObject() 

funciona como se esperaba!

1

Hola el problema es causado por el siguiente texto:

  1. Una corriente AMF es con estado. Cuando serializa los objetos, los comprime en relación con los objetos que ya se escribieron.

  2. La compresión se realiza al hacer referencia a descripciones de clase, valores de cadena y objetos previamente enviados usando índices (por ejemplo, si la primera cadena que envió fue "heloWorld", cuando envíe esa cadena, la secuencia AMF enviará cadena índice 0).

  3. Desafortunadamente, ByteArray y Socket no mantienen tablas de referencia entre las llamadas a readObject.Por lo tanto, incluso si continúa agregando sus objetos recién leídos al final del mismo objeto ByteArray, cada llamada a readObject creará nuevas tablas de referencia, descartando las creadas previamente (esto significa que debería funcionar para referencias repetidas a la misma cadena dentro de un árbol de objetos))

  4. En su ejemplo, siempre escribe los mismos valores de cadena en las propiedades. Por lo tanto, cuando envía el segundo objeto, sus propiedades de cadena no se serializan como cadenas, sino como referencias a las cadenas en el objeto escrito anteriormente.

La solución, es la creación de una nueva fuente de AMF para cada objeto que envíe.

Esto es una basura completa, por supuesto (!) Significa que realmente no podemos utilizar la compresión en protocolos personalizados. Sería mucho mejor si nuestros protocolos pudieran decidir cuándo restablecer estas tablas de referencia, quizás cuando se volvieron demasiado grandes.

Por ejemplo, si usted tiene un protocolo RPC, sería bueno tener un flujo de AMF pasar los nombres de los métodos remotos como referencias en lugar de cadenas para la velocidad ...

No he comprobado pero creo este tipo de cosas lo hace RTMP. La razón por la que probablemente no estaría disponible en objetos de desarrollador como ByteArray y Socket (suspiro, espero que esto no sea cierto) es porque Adobe quiere impulsarnos hacia LCDS ...

Adición/edición: solo encontró esto, que proporciona una solución http://code.google.com/p/cvlib/

Cuestiones relacionadas