Links

  • 1. Sogeti
  • 2. JBoss
  • 3. IBM
  • 4. Oracle
  • 5. SpringSource
  • 6. NL-JUG
  • 7. Java

Archives

Syndication  RSS 2.0

RSS 1.0
RSS 2.0

Bookmark this site

Add 'JCN Blog' site to delicious  Add 'JCN Blog' site to technorati  Add 'JCN Blog' site to digg  Add 'JCN Blog' site to dzone

Posted by Erwin De Gier at 8:30 on Tuesday 2 July    Add 'Websockets in Java EE 7' site to delicious  Add 'Websockets in Java EE 7' site to technorati  Add 'Websockets in Java EE 7' site to digg  Add 'Websockets in Java EE 7' site to dzone

Een van de nieuwe standaarden in Java Enterprise Edition 7 is de API voor het gebruik van websockets. Websockets zijn onderdeel van de HTML5 specificatie en maken het mogelijk een TCP verbinding op te zetten van een browser naar een server. Het is een bidirectioneel kanaal dat full-duplex gebruikt kan worden. Dit heeft veel voordelen boven technieken als polling of long-polling over HTTP. De bericht overhead is lager en de performance daardoor veel beter. Daarnaast is de API gestandaardiseerd (http://www.w3.org/TR/websockets/ ). Websockets kunnen bijvoorbeeld gebruikt worden als er requirements zijn om realtime data heen en weer te sturen of in het geval van push berichten.

Een websocket verbinding wordt geïnitialiseerd over HTTP. Deze wordt vervolgens geüpgrade naar een websocket verbinding. Een websocket url begint in plaats van met http met ws, bijvoorbeeld: ws://localhost:8080/websockets/echo. Dit upgraden gebeurt tijdens de websocket handshake. 
Met Java EE 7 is er nu ook een standaard API voor de het realiseren van de server kant van de websockets verbinding. We beginnen met de project dependencies. Aangezien de websockets API onderdeel is van Java EE 7 hebben we maar één dependency nodig, die ook nog eens “provided” is en dus niet meegepackaged wordt in de uiteindelijke war file:

<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>

Een websocket bean configureren we doormiddel van annotaties:

import javax.websocket.OnMessage;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(“/echo”  )
public class  EchoBean {

         @OnMessage
         public String echo(String message) {
                return message +  ” (from your server)”  ;
       }

}

De @ServerEndpoint annotatie mapt deze bean op een url, in dit geval /echo. De @OnMessage annotatie wordt door de container aangeroepen op het moment dat er een bericht wordt ontvangen. Als je op internet zoekt op Java websockets vindt je ook voorbeelden die gebruik maken van de annotaties @WebSocket en @WebSocketMessage. Dit zijn Glassfish specifieke annotaties en zijn dus geen onderdeel van de Java EE 7 API !

Naast de @OnMessage zijn er nog twee annotaties, @OnOpen en @OnClose. Deze worden gebruikt om acties te definiëren bij het openen en het sluiten van een websocket verbinding. Voorbeeld:

@Singleton
@ServerEndpoint(“/chatsocket”  )
public class  ChatBean {

         private Set<Session>  clients  =  new HashSet<>();

         @OnOpen
         public void onSocketOpened(Session session) throws  IOException {
                clients .add(session);
       }

         @OnClose
         public void onSocketClosed(Session session)  throws  IOException {
                clients .remove(session);
       }

         @OnMessage
         public void onReceivedFrame(Session session,
                                   String message)  throws  IOException {
                for(Session client : clients ){
                      client.getAsyncRemote().
                      sendText(session.getId()+  “: “ +message);
              }
       }
}

Dit voorbeeld illustreert een simpele chatbox implementatie. De ChatBean is geannoteerd met de EJB annotatie @Singleton, waardoor er maar één instantie van deze EJB bestaat zodat we alle websocket sessies kunnen bewaren. De methode onSocketOpened is geannoteerd met @OnOpen. Deze methode wordt aangeroepen als de websocket verbinding tot stand is gebracht. De optionele methode parameter Session representeert een websocket sessie. Deze sessie wordt opgeslagen in een Set, zodat we later alle chatberichten naar alle sessies kunnen sturen.
De methode onSocketClosed is geannoteerd met de annotatie @OnClose, deze wordt aangeroepen bij het sluiten van de WebSocket verbinding. Hier verwijderen we de sessie uit de Set.
In de methode geannoteerd met @OnMessage versturen we het binnengekomen bericht naar alle websocket clients.

Om het voorbeeld compleet te maken hebben we nog een client nodig:

<html>
<body>
        <div style=” text-align: center ;”>
               <form action= “”>
                     text:
                      <input id= “textID” name =“message” value= “Hello WebSocket!”
                                                      type=“text”>
                      <input onclick= “send_echo()” value =“send” type=“button”>< br>
               </form>
        </div>
        <div id= “output”></div >
        <script language=“javascript” type=“text/javascript”>
               var wsUri = “ws://localhost:8080/websockets/chatsocket” ;
               var websocket = new WebSocket(wsUri);
              websocket.onopen = function(evt) {
                     onOpen(evt)
              };
              websocket.onmessage = function(evt) {
                     onMessage(evt)
              };
              websocket.onerror = function(evt) {
                     onError(evt)
              };

               function init() {
                     output = document.getElementById( “output”);
              }

               function send_echo() {
                     websocket.send(textID.value);
                      //writeToScreen(“SENT: ” + textID.value);
              }

               function onOpen(evt) {
                     writeToScreen( “CONNECTED”);
              }

               function onMessage(evt) {
                     writeToScreen(evt.data);
              }

               function onError(evt) {
                     writeToScreen( ‘<span style=”color: red;”>ERROR:</span> ‘
                                                 + evt.data);
              }

               function writeToScreen(message) {
                      var pre = document.createElement(“p” );
                     pre.style.wordWrap = “break-word”;
                     pre.innerHTML = message;
                     output.appendChild(pre);
              }

              window.addEventListener( “load”, init, false );
        </script>
</body>
</html>
 
In Javascript wordt er een WebSocket object instantie gemaakt op basis van een url. Op dit websocket object zijn methodes beschikbaar voor het versturen van berichten en het registreren van methodes die aangeroepen moeten worden bij de onOpen,onMessage , onClose en onError events.
In dit voorbeeld is het mogelijk om een tekst te versturen naar de server met behulp van websocket.send(String text), deze wordt vervolgens bij alle aangemelde clients op het scherm geschreven (onMessage(event)).

Het volledige voorbeeld is te downloaden van https://bitbucket.org/erwindeg/jee7-websockets-demo. Met mvn clean install kan de war file worden gemaakt. Deze kan gedeployed worden op een Java EE 7 gecertificeerde applicatieserver, bijvoorbeeld Glassfish 4. Na deployment is de chat applicatie beschikbaar op http://localhost:8080/websockets/.
Open 2 browser sessies en navigeer naar http://localhost:8080/websockets/. Als op in de ene sessie tekst verstuurd wordt naar de applicatie, dan verschijnt deze tekst in beide browsers op het scherm.
De browser moet wel ondersteuning bieden voor websockets. Dit voorbeeld is getest op Chrome (versie 27) en Firefox (versie 15).

 


© 2019 Java Competence Network. All Rights Reserved.