15.2. Créer une application WebSocket

Une application WebSocket nécessite les composants et les changements de configuration suivants :
  • Un client Java ou un client WebSocket : http://caniuse.com/websockets
  • Une classe de point de terminaison de serveur WebSocket.
  • Un fichier jboss-web.xml configuré pour activer WebSockets.
  • Dépendances de projet configurées pour déclarer une dépendance sur l'API WebSocket.
  • Activer le connecteur NIO2 dans le sous-système web du fichier de configuration du serveur JBoss EAP. Si vous installez les composants natifs de votre système d'exploitation dans votre installation JBoss EAP et que vous avez déjà installé l'APR (Apache Portability Runtime), vous pouvez choisir d'activer le connecteur APR à la place.

Note

Les applications WebSocket requièrent un environnement Java Runtime de version 7 ou supérieure. Sinon, WebSocket ne sera pas activé.

Procédure 15.1. Créer l'application WebSocket

Voici un exemple simple d'application WebSocket. Vous trouverez des boutons pour ouvrir une connexion, envoyer un message, et fermer une connexion. Cet exemple n'implémente pas d'autres fonctions, ni n'inclut de gestion d'erreurs dont on aurait besoin dans une application réelle.
  1. Créer un client HTML JavaScript.

    Voici un exemple de client WebSocket. Il contient les fonctions JavaScript suivantes :
    • connect() : cette fonction crée la connexion webSocket qui donne l'URI de WebSocket. L'emplacement de la ressource correspond à la ressource définie dans la classe de point de terminaison du serveur. Cette fonction intercepte et gère les WebSockets onopen, onmessage, onerror, et onclose.
    • sendMessage() : cette fonction a le même nom que celui qui se trouve sur le formulaire, crée un message, et l'envoie par la commande WebSocket.send().
    • disconnect() : cette fonction génère la commande WebSocket.close().
    • displayMessage() : cette fonction détermine le message affiché sur la page à la valeur donnée par la méthode de point de terminaison de WebSocket.
    • displayStatus() : cette fonction afficher le statut de la connexion de WebSocket.
    l
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
        <head>
            <title>WebSocket: Say Hello</title>
            <link rel="stylesheet" type="text/css" href="resources/css/hello.css" />
            <script type="text/javascript">
                var websocket = null;
    
                function connect() {
                    var wsURI = 'ws://' + window.location.host + '/jboss-websocket-hello/websocket/helloName';
                    websocket = new WebSocket(wsURI);
    
                    websocket.onopen = function() {
                        displayStatus('Open');
                        document.getElementById('sayHello').disabled = false;
                        displayMessage('Connection is now open. Type a name and click Say Hello to send a message.');
                    };
                    websocket.onmessage = function(event) {
                        // log the event                
                        displayMessage('The response was received! ' + event.data, 'success');
                    };
                    websocket.onerror = function(event) {
                        // log the event
                        displayMessage('Error! ' + event.data, 'error');
                    };
                    websocket.onclose = function() {
                        displayStatus('Closed');
                        displayMessage('The connection was closed or timed out. Please click the Open Connection button to reconnect.');
                        document.getElementById('sayHello').disabled = true;
                    };
                }
    
                function disconnect() {
                    if (websocket !== null) {
                        websocket.close();
                        websocket = null;
                    }
                    message.setAttribute("class", "message");
                    message.value = 'WebSocket closed.';
                    // log the event
                }
    
                function sendMessage() {
                    if (websocket !== null) {
                        var content = document.getElementById('name').value;
                        websocket.send(content);
                    } else {
                        displayMessage('WebSocket connection is not established. Please click the Open Connection button.', 'error');
                    }
                }
    
                function displayMessage(data, style) {
                    var message = document.getElementById('hellomessage');
                    message.setAttribute("class", style);
                    message.value = data;
                }
    
                function displayStatus(status) {
                    var currentStatus = document.getElementById('currentstatus');
                    currentStatus.value = status;
                }
    
            </script>
        </head>
        <body>
    
            <div>
                <h1>Welcome to JBoss!</h1>
                <div>This is a simple example of a WebSocket implementation.</div>
                <div id="connect-container">
                    <div>
                        <fieldset>
                            <legend>Connect or disconnect using WebSocket :</legend>
                            <input type="button" id="connect" onclick="connect();" value="Open Connection" />
                            <input type="button" id="disconnect" onclick="disconnect();" value="Close Connection" />
                        </fieldset>
                    </div>
                    <div>
                        <fieldset>
                            <legend>Type your name below. then click the `Say Hello` button :</legend>
                            <input id="name" type="text" size="40" style="width: 40%"/>
                            <input type="button" id="sayHello" onclick="sendMessage();" value="Say Hello" disabled="disabled"/>
                        </fieldset>
                    </div>
                    <div>Current WebSocket Connection Status: <output id="currentstatus" class="message">Closed</output></div>
                    <div>
                        <output id="hellomessage" />
                    </div>
                </div>
            </div>
        </body>
    </html>
  2. Créer le point de terminaison du serveur de WebSocket.

    Vous pouvez créer un point de terminaison de serveur WebSocket par l'une des méthodes suivantes.
    • Programmatic Endpoint : le point de terminaison prolonge la classe de point de terminaison.
    • Annotated Endpoint : la classe de point de terminaison utilise des annotations pour interagir avec les événements WebSocket. Plus facile à codifier qu'un point de terminaison programmatique.
    L'exemple de code ci-dessous utilise une approche de point de terminaison annoté et gère les événements suivants.
    • L'annotation @ServerEndpoint identifie cette classe comme point de terminaison de serveur WebSocket et indique le chemin d'accès.
    • L'annotation @OnOpen s'active quand la connexion de WebSocket est ouverte.
    • L'annotation @OnMessage s'active quand un message est envoyé vers une connexion de WebSocket.
    • L'annotation @OnClose s'active quand la connexion de WebSocket est fermée.
    package org.jboss.as.quickstarts.websocket_hello;
    
    import javax.websocket.CloseReason;
    import javax.websocket.OnClose;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    
    @ServerEndpoint("/websocket/helloName")
    public class HelloName {
    
        @OnMessage
        public String sayHello(String name) {
            System.out.println("Say hello to '" + name + "'");
            return ("Hello" + name);    
        }
    
        @OnOpen
        public void helloOnOpen(Session session) {
            System.out.println("WebSocket opened: " + session.getId());
        }
        
        @OnClose
        public void helloOnClose(CloseReason reason) {
            System.out.println("Closing a WebSocket due to " + reason.getReasonPhrase());
        }
    }
    
  3. Configurer le fichier jboss-web.xml.

    Vous devez créer l'élément <enable-websockets> dans l'application WEB-INF/jboss-web.xml et la définir à true.
    <?xml version="1.0" encoding="UTF-8"?>
    <!--Enable WebSockets -->
    <jboss-web>
       <enable-websockets>true</enable-websockets>
    </jboss-web>
  4. Déclarer la dépendance de l'API de Websocket dans votre fichier POM de projet.

    Si vous utilisez Maven, vous devrez ajouter la dépendance suivante au fichier pom.xml du projet.
    <dependency>
      <groupId>org.jboss.spec.javax.websocket</groupId>
      <artifactId>jboss-websocket-api_1.0_spec</artifactId>
      <version>1.0.0.Final</version>
      <scope>provided</scope>
    </dependency>
    
  5. Configurer le serveur JBoss EAP.

    Configurer le <connector> http dans le sous-système web du fichier de configuration du serveur pour qu'il puisse utliser le protocole NIO2.
    1. Démarrer le serveur JBoss EAP.
    2. Lancer l'interface CLI par la commande pour votre système d'exploitation.
      Dans Linux :
      EAP_HOME/bin/jboss-cli.sh --connect
      Dans Windows :
      EAP_HOME\bin\jboss-cli.bat --connect
    3. Activer le connecteur NIO2 ou APR dans le sous-système web du fichier de configuration du serveur JBoss EAP.
      • Saisir la commande suivante pour pouvoir utiliser le protocole de connecteur NIO2 Java non bloquant :
        /subsystem=web/connector=http/:write-attribute(name=protocol,value=org.apache.coyote.http11.Http11NioProtocol)
      • Si vous avez installé l'APR (Apache Portability Runtime), vous pourrez saisir les commandes suivantes pour utiliser le protocole de connecteur APR natif :
        /subsystem=web:write-attribute(name=native,value=true)
        /subsystem=web/connector=http/:write-attribute(name=protocol,value=org.apache.coyote.http11.Http11AprProtocol)
      Quelle que soit la commande dont il s'agit, vous devrez voir le résultat suivant apparaître :
      {
          "outcome" => "success",
          "response-headers" => {
              "operation-requires-reload" => true,
              "process-state" => "reload-required"
          }
      }
    4. Indiquer au serveur de charger la configuration à nouveau.
      :reload
      Vous devriez voir apparaître le résultat suivant :
      {
          "outcome" => "success",
          "result" => undefined
      }
      
    5. Réviser les changements apportés au fichier de configuration du serveur JBoss EAP. Le sous-système web doit maintenant contenir l'XML suivant pour le <connector> http.
      Pour la configuration de connecteur NIO2  :
      <subsystem xmlns="urn:jboss:domain:web:2.1" default-virtual-server="default-host" native="false">
          <connector name="http" protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="http" socket-binding="http"/>
          <virtual-server name="default-host" enable-welcome-root="true">
          <alias name="localhost"/>
              <alias name="example.com"/>
          </virtual-server>
      </subsystem>
      Pour la configuration de connecteur APR :
      <subsystem xmlns="urn:jboss:domain:web:2.1" default-virtual-server="default-host" native="true">
          <connector name="http" protocol="org.apache.coyote.http11.Http11AprProtocol" scheme="http" socket-binding="http"/>
          <virtual-server name="default-host" enable-welcome-root="true">
              <alias name="localhost"/>
              <alias name="example.com"/>
          </virtual-server>
      </subsystem>