2015-10-05 24 views
12

Sto cercando di implementare una soluzione basata su WebSockets con Play2 e Java. Attualmente non sto usando Actor Model per la gestione della concorrenza. Invece, è solo handling the WebSockets using callbacks.Java - Sono necessari gli attori Play2 per l'implementazione di WebSockets?

Il problema è che il server non è in grado di "trasmettere" i messaggi a più client. Ad esempio, ho bisogno di tutte le sessioni attive del browser per ricevere una semplice notifica dopo che un'azione è stata attivata tramite un client. Invece, sono solo in grado di simularlo per una singola sessione client. In effetti, agisce semplicemente come uno scenario di richiesta/risposta Ajax regolare.

La mia ipotesi è la soluzione WebSockets con Play2 & Java con callback semplici non è in grado di trasmettere i messaggi a tutti i browser client connessi.

codice del server di richiamata

public static WebSocket<String> heartUpdate() { 
     return new WebSocket<String>() { 
      public void onReady(final WebSocket.In<String> in, 
        WebSocket.Out<String> out) { 
       in.onMessage(new Callback<String>() { 
        @Override 
        public void invoke(String event) throws Throwable { 
         Product product = Product.find.byId(Long.decode(event)); 
         // Other business stuff 
         out.write(entity.id + " " + decimalValue); 
        } 
       }); 
       in.onClose(new Callback0() { 
        @Override 
        public void invoke() throws Throwable { 

        } 
       }); 
       out.write(DELIM_USERID_REP); 
      } 
     }; 
    } 

vie d'ingresso

GET /repsocket controllers.Application.heartUpdate 

lato client

<script> 
    // Onto the WebSockets now 
    var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket; 
    var socket = new WS("@routes.Application.heartUpdate.webSocketURL(request)"); 

    var receiveEvent = function(event) { 
     alert(event.data); 
     // Notification badge visible with a common text 
     $('#notify').text(event.data); 
     $('#notify').addClass('visible'); 
    } 
     $('#heart').click(function(e) { 
      e.preventDefault(); 
      socket.send(@product.id); 
     }); 
    socket.onmessage = receiveEvent; 
    </script> 

In Nel caso precedente, il client che attiva l'azione è quello che riceve il messaggio correttamente dal server, mentre altre sessioni del browser non lo fanno.

Non sono riuscito a trovare alcuna documentazione allineata con Play2 con Java & WebSockets che suggerisce un uso obbligatorio di Actors per mantenere una comunicazione coerente con tutti i client attivi connessi.

Domanda: Le WebSockets in Play2 con Java devono essere implementate con Actor Model per trasmettere il messaggio a tutte le sessioni client attive?

Edit: La figura seguente riflette i 2 stati di browser per cui ho registrato per l'utilizzo di 2 credenziali utente valide.

Idealmente, la risposta di WebSockets dal server dovrebbe creare gli stessi badge di notifica su entrambi i browser.

enter image description here

+0

Che errore hai? –

+0

@nikpon Nessun errore, il messaggio dal server si riflette solo in 1 sessione del browser - che ha attivato la richiesta e non in altre sessioni client connesse – PopoFibo

+0

come hai ottenuto una sessione del browser? –

risposta

5

Guardando il codice che hai postato, sembra che il problema è che non sta salvando un riferimento ad ogni connessione, in modo da poter poi trasmettere i messaggi. Qualcosa di simile a questo:

// Just an example: does not deal with concurrency problems 
private static final Set<WebSocket.Out<String>> SOCKETS = new HashSet<>(); 

public static WebSocket<String> heartUpdate() { 
    return new WebSocket<String>() { 
     public void onReady(final WebSocket.In<String> in, 
        final WebSocket.Out<String> out) { 
      SOCKETS.add(out); 
      in.onMessage(new Callback<String>() { 
       @Override 
       public void invoke(String event) throws Throwable { 
        for(WebSocket.Out<String> s: SOCKETS) { 
         s.write("SOME MESSAGE");  
        } 
       } 
      }); 
      in.onClose(new Callback0() { 
       @Override 
       public void invoke() throws Throwable { 
        SOCKETS.remove(out); 
       } 
      }); 
     } 
    }; 
} 

È inoltre possibile utilizzare gli attori per modellare questo problema: avere un attore responsabile per tenere traccia delle connessioni e per affrontare le nuove prese di connessione/vicino.

Se si desidera utilizzare Akka ci sono some activator templates per iniziare.

+0

In realtà è andato nel ciclo solo una volta, in pratica lo stesso comportamento del problema originale - forse mi manca qualcosa di più semplice – PopoFibo

+0

Scratch che, stavo testando tutto sbagliato. Funziona davvero, grazie mille. Lascerò questa domanda come accettata con una taglia aperta per una certa trazione alla tua risposta. – PopoFibo

Problemi correlati