2017-06-27 1 views
1

J'ai besoin d'aide pour sérialiser une Entité pour l'envoyer par Akka Remote.akka Sérialisation ByteBuffer - java.lang.UnsupportedOperationException

C'est la classe sérialiseur:

@Override 
public void toBinary(Object o, ByteBuffer buf) { 

    byte[] bytes = null; 
    ByteArrayOutputStream bos = null; 
    ObjectOutputStream oos = null; 
    try { 
     bos = new ByteArrayOutputStream(); 
     oos = new ObjectOutputStream(bos); 
     oos.writeObject(o); 
     oos.flush(); 
     bytes = bos.toByteArray(); 
    } 
    catch(Exception e){ 
     //System.out.println(e.getStackTrace()); 
     e.printStackTrace(); 
    } 
    buf.put(bytes); 
} 

@Override 
    public Object fromBinary(ByteBuffer buf, String manifest) { 
     Object obj = null; 
     ByteArrayInputStream bis = null; 
     ObjectInputStream ois = null; 

     try { 
      bis = new ByteArrayInputStream(buf.array()); 
      ois = new ObjectInputStream(bis); 
      obj = ois.readObject(); 
     } 
     catch(Exception e){ 
      //System.out.println(e.getStackTrace()); 
      e.printStackTrace(); 
     } 
     return obj; 
    } 

Im obtenir l'exception suivante dans la ligne 5

java.lang.UnsupportedOperationException 
    at java.nio.ByteBuffer.array(ByteBuffer.java:994) 
    at serializers.ExampleByteBufSerializer.fromBinary(ExampleByteBufSerializer.java:67) 
    at akka.serialization.Serialization.deserializeByteBuffer(Serialization.scala:190) 
    at akka.remote.MessageSerializer$.deserializeForArtery(MessageSerializer.scala:91) 
    at akka.remote.artery.Deserializer$$anon$3.onPush(Codecs.scala:620) 
    at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:499) 
    at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:401) 
    at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:571) 
    at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:457) 
    at akka.stream.impl.fusing.GraphInterpreterShell.processEvent(ActorGraphInterpreter.scala:546) 
    at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processEvent(ActorGraphInterpreter.scala:725) 
    at akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:740) 
    at akka.actor.Actor$class.aroundReceive(Actor.scala:513) 
    at akka.stream.impl.fusing.ActorGraphInterpreter.aroundReceive(ActorGraphInterpreter.scala:650) 
    at akka.actor.ActorCell.receiveMessage(ActorCell.scala:527) 
    at akka.actor.ActorCell.invoke(ActorCell.scala:496) 
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257) 
    at akka.dispatch.Mailbox.run(Mailbox.scala:224) 
    at akka.dispatch.Mailbox.exec(Mailbox.scala:234) 
    at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) 
    at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) 
    at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) 
    at akka.dispatch.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) 

Voici le message Im envoyer à l'acteur à distance:

public class Message2Serialize implements Serializable { 

    String nombre; 

    public Message2Serialize(String nombre) { 
     this.nombre = nombre; 
    } 

    public Message2Serialize() { 
    } 

    public String getNombre() { 
     return nombre; 
    } 


    public void setNombre(String nombre) { 
     this.nombre = nombre; 
    } 
} 

La chose étrange est que cela fonctionne d'une manière, si nous envoyons le message en utilisant cela, il fonctionne bien dans la rec eptor:

ActorSelection selection = getContext().system().actorSelection("akka://[email protected]:25521/user/actors.MessageReceiverActor"); 
selection.tell(message2Serialize, getSelf()); 

Mais quand on rejoue à l'acteur de l'expéditeur en utilisant getSender().tell(m, getSelf()); alors nous avons eu l'exception.

Nous utilisons Java 1.8 et akka-remote_2.11: 2.5.3

Merci à l'avance! Rodri

+0

Avez-vous essayé de le faire sans définir un sérialiseur personnalisé? – thwiegan

+0

Oui, cela fonctionne parfaitement avec le sérialiseur Java par défaut –

+0

Quelle que soit la raison pour laquelle vous utilisez le personnalisable? Afaik le par défaut fait la même chose que vous faites. – thwiegan

Répondre

0

javadoc extrait

@throws UnsupportedOperationException. Si ce tampon n'est pas sauvegardé par un tableau accessible

le ByteBuffer ne semble pas être complètement initialisé ... De plus, le javadoc dit aussi ce qu'il faut faire

invoquons le {@link #hasArray hasArray } méthode avant d'appeler cette méthode afin de s'assurer que cette mémoire tampon a un support accessible .

+0

C'est correct, le problème est qu'il n'est pas initialisé. En utilisant hasArray, je ne reçois pas l'exception, mais je n'obtiens aucune donnée à désérialiser. C'est vide –

0

En changeant cette ligne: bis = newByteArrayInputStream(arr); à

byte[] arr = new byte[buf.remaining()]; 
buf.get(arr); 
bis = new ByteArrayInputStream(arr); 

Il fonctionne, mais je ne suis pas sûr de savoir pourquoi.