2009-03-06 14 views
6

C'è un modo per "iscriversi" da oggetti GWT a oggetti JSON e ascoltare gli eventi in entrata sulla connessione keep-alive, senza provare a recuperarli tutti in una volta? Credo che la buzzword-du-jour per questa tecnologia sia "Comet".GWT/Cometa: qualche esperienza?

Supponiamo che io abbia servizio HTTP che si apre keep-alive di connessione e mettere JSON oggetti con quotazioni in arrivo in tempo reale:

{"symbol": "AAPL", "bid": "88.84", "ask":"88.86"}
{"symbol": "AAPL", "bid": "88.85", "ask":"88.87"}
{"symbol": "IBM", "bid": "87.48", "ask":"87.49"}
{"symbol": "GOOG", "bid": "305.64", "ask":"305.67"}
...

Ho bisogno di ascoltare questi eventi e aggiornare i componenti GWT (tabelle, etichette) in tempo reale. Qualche idea su come farlo?

risposta

6

C'è un GWT Comet modulo per StreamHub:

http://code.google.com/p/gwt-comet-streamhub/

StreamHub è un server Comet con un'edizione comunità libera. C'è un esempio in azione here.

Avrai bisogno di scaricare il server StreamHub Comet e creare un nuovo SubscriptionListener, usare l'esempio StockDemo come punto di partenza, quindi creare un nuovo JsonPayload per lo streaming dei dati:

Payload payload = new JsonPayload("AAPL"); 
payload.addField("bid", "88.84"); 
payload.addField("ask", "88.86"); 
server.publish("AAPL", payload); 
... 

Scarica il JAR da il sito di Google code, aggiungerlo al GWT progetti classpath e aggiungere il includere al modulo GWT:

<inherits name="com.google.gwt.json.JSON" /> 
<inherits name="com.streamhub.StreamHubGWTAdapter" /> 

Collegare e sottoscrivere dal codice GWT:

StreamHubGWTAdapter streamhub = new StreamHubGWTAdapter(); 
streamhub.connect("http://localhost:7979/"); 
StreamHubGWTUpdateListener listener = new StockListener(); 
streamhub.subscribe("AAPL", listener); 
streamhub.subscribe("IBM", listener); 
streamhub.subscribe("GOOG", listener); 
... 

quindi elaborare gli aggiornamenti come ti piace nell'ascoltatore aggiornamento (anche nel codice GWT):

public class StockListener implements StreamHubGWTUpdateListener { 
     public void onUpdate(String topic, JSONObject update) { 
      String bid = ((JSONString)update.get("bid")).stringValue(); 
      String ask = ((JSONString)update.get("ask")).stringValue(); 
      String symbol = topic; 
      ... 
     } 
} 

non dimenticate di includere streamhub-min.js nei vostri progetti GWT pagina HTML principale.

+0

Ehi. C'è un modo per disabilitare il browser dal fare il fastidioso simbolo 'loading' sul cursore, ovvero caricarlo in Chrome, fa apparire un fastidioso cerchio bianco. Come puoi immaginare, avere un'applicazione che deve essere aperta per molto tempo e avere quel simbolo di caricamento costantemente diventa piuttosto fastidioso! Grazie. – Federer

1

Alcune idee preliminari per l'implementazione di Comet per GWT possono essere trovate here... anche se mi chiedo se c'è qualcosa di più maturo.

1

Inoltre, alcune informazioni sull'integrazione GWT/Comet sono disponibili there, utilizzando una tecnologia di taglio ancora più all'avanguardia: "Jetty Continuations". Vale la pena dare un'occhiata.

3

v'è infatti una biblioteca cometd simile per GWT - http://code.google.com/p/gwteventservice/

ma io non ve lo utilizzavano personalmente, quindi non posso davvero garantire per se la sua buona o no, ma il doco sembra abbastanza buono. vale la pena provare.

Ci sono alcuni altri che ho visto, come la libreria gwt-rocket's cometd.

5

Ho usato questa tecnica in un paio di progetti, anche se ha i suoi problemi. Devo notare che l'ho fatto solo specificatamente tramite GWT-RPC, ma il principio è lo stesso per qualunque meccanismo tu stia usando per gestire i dati. A seconda di cosa stai facendo esattamente, potrebbe non esserci molto bisogno di complicare troppo le cose.

Prima di tutto, sul lato client, non credo che GWT possa supportare correttamente qualsiasi tipo di dati di streaming. La connessione deve essere chiusa prima che il client possa effettivamente elaborare i dati. Ciò significa che dal punto di vista del server-push è che il client si connetterà al server e bloccherà fino a quando i dati non saranno disponibili e a quel punto ritornerà. Qualunque codice venga eseguito sulla connessione completata dovrebbe immediatamente riaprire una nuova connessione con il server per attendere ulteriori dati.

Dal lato server, è sufficiente passare a un ciclo di attesa (il pacchetto concorrente java è particolarmente utile per questo con blocchi e timeout), fino a quando non saranno disponibili nuovi dati. A quel punto, il server può restituire un pacchetto di dati al client che si aggiornerà di conseguenza. Ci sono un sacco di considerazioni a seconda di come è il flusso di dati, ma qui ci sono alcuni a cui pensare:

  • Un client riceve ogni singolo aggiornamento importante? In tal caso, il server deve memorizzare nella cache eventuali eventi potenziali tra il momento in cui il client riceve alcuni dati e quindi riconnette.
  • Ci saranno degli aggiornamenti? Se questo è il caso, potrebbe essere più saggio impacchettare un numero di aggiornamenti e spingere i blocchi alla volta ogni qualche secondo invece di fare in modo che il client ottenga un aggiornamento alla volta.
  • Il server probabilmente avrà bisogno di un modo per rilevare se un client è andato via per evitare di accumulare enormi quantità di pacchetti memorizzati nella cache per quel client.

Ho trovato che c'erano due problemi con l'approccio push del server. Con molti client, questo significa molte connessioni aperte sul server web. A seconda del server Web in questione, questo potrebbe significare che molti thread sono stati creati e mantenuti aperti. Il secondo ha a che fare con il limite tipico del browser di 2 richieste per dominio. Se sei in grado di servire le tue immagini, css e altri contenuti statici per domini di secondo livello, questo problema può essere mitigato.

+0

+1 post eccellente con alcune ottime idee. – Federer

+0

+1 Questo è esattamente come lo faccio io. La soluzione al problema "molti thread" è scritta "richieste sospese" nelle specifiche Servlet 3.0. Jetty ha il supporto iniziale per questo in 7.0. Tomcat lo chiama qualcos'altro. –

0

Here è possibile trovare una descrizione (con alcuni esempi di origine) su come eseguire questa operazione per IBM WebSphere Application Server. Non dovrebbe essere troppo diverso con Jetty o qualsiasi altro server J2EE abilitato a Comet. In breve, l'idea è: codifica il tuo oggetto Java nella stringa JSON tramite GWT RPC, quindi utilizza cometd invialo al client, dove viene ricevuto da Dojo, che attiva il tuo codice JSNI, che chiama i tuoi metodi widget, dove deserializzi l'oggetto di nuovo usando GWT RPC. Ecco! :)

La mia esperienza con questa configurazione è positiva, non ci sono stati problemi ad eccezione delle domande di sicurezza. In questo caso non è chiaro come implementare la sicurezza di comet ... Sembra che i servlet di aggiornamento di Comet debbano avere URL diversi e quindi applicare la sicurezza J2EE.

0

Il progetto JBoss Errai dispone di un bus di messaggi che fornisce messaggistica bidirezionale che fornisce una buona alternativa a cometd.

0

Utilizziamo Atmosphere Framewrok (http://async-io.org/) per ServerPush/Comet nell'applicazione GWT.

Da un lato client Framework ha un'integrazione GWT che è piuttosto semplice. Sul lato server utilizza un semplice servlet.

Attualmente lo stiamo utilizzando in produzione con oltre 1000 utenti concurent in ambiente cluster. Abbiamo avuto alcuni problemi sulla via da risolvere modificando la fonte Atmosphere. Anche la documentazione è davvero sottile.

Framework è gratuito.

Problemi correlati