Comment implémenter le Push to Client à l’aide de Java EE 7 WebSockets?

J’ai parcouru de nombreux exemples Web Socket, des diapositives de présentation et ils sont principalement concentrés sur des scénarios assez simples dans lesquels la communication client-serveur est initiée par le client.

Je suis intéressé par un autre scénario, qui semble être tout aussi pratique: le transfert de serveur pur au client.

L’exemple que j’ai en tête est une application qui met à jour la valeur des stocks sur un site Web. Imaginez qu’il existe un système de bourse système externe, qui envoie un message JMS pour chaque modification de la valeur stock souscrite.

Je voudrais savoir comment traduire un tel événement JMS entrant en un serveur push et de manière efficace et idiomatique du sharepoint vue de Java EE 7.

Autant que je puisse comprendre les spécifications, je suis censé écrire un noeud final de socket Web

@ServerEndpoint("/demo") public class WSEndpoint { private static final Logger LOG = Logger.getLogger(WSEndpoint.class); @OnMessage public void onMessage(Ssortingng message, Session session) { LOG.info("Received : " + message + ", session:" + session.getId()); } @OnOpen public void open(Session session) { LOG.info("Open session:" + session.getId()); } @OnClose public void close(Session session, CloseReason c) { log.info("Close session:" + session.getId()); } } 

Tout est facile lorsque je reçois un message du client, je peux faire tout ce que je veux dans la méthode @OnMessage . Mais dans mon exemple, je ne recevrai aucun message du client, j’obtiendrai un événement d’un système externe.

Il y a quelques approches. Par exemple, je peux créer un thread dans une méthode @OnOpen , comme illustré dans ce blog . Dans la pratique, cette approche pourrait présenter une lacune car pour chaque client, il me faudrait créer un nouveau fil conducteur, potentiellement long.

On peut faire mieux en utilisant des canaux NIO avec des sélecteurs, mais cela demanderait une sorte de gestion de canaux “faite à la main”. Faisable, mais plutôt lourd.

Une autre solution serait de faire un ping sur un autre système pour obtenir des mises à jour, mais encore une fois, ce serait un peu moche. En outre, je ne suis pas sûr non plus @OnOpen méthode @OnOpen soit conçue pour être utilisée de cette manière.

Idéalement, un message JMS entrant déclencherait un push de socket Web sur le client. Des idées comment mettre en application quelque chose comme ceci gentiment?

Ce n’est probablement pas la manière la plus élégante mais juste de démontrer une idée. Méthode broadcast () enverra un message à tous les clients connectés.

 @ServerEndpoint("/echo") public class ServerEndPoint { private static Set userSessions = Collections.newSetFromMap(new ConcurrentHashMap()); @OnOpen public void onOpen(Session userSession) { userSessions.add(userSession); } @OnClose public void onClose(Session userSession) { userSessions.remove(userSession); } @OnMessage public void onMessage(Ssortingng message, Session userSession) { broadcast(message); } public static void broadcast(Ssortingng msg) { for (Session session : userSessions) { session.getAsyncRemote().sendText(msg); } } } 

Je le fais de cette façon (aucune demande du client n’est nécessaire):

 @ServerEndpoint("/hello") public class HelloWebSocket { @OnOpen public void greetTheClient(Session session){ try { session.getBasicRemote().sendText("Hello stranger"); } catch (IOException ioe) { System.out.println(ioe.getMessage()); } } } 

Stocker la sessionList active dans une autre classe SessionManager .

 List socketSessions = new ArrayList<>(); 

Ajouter une session entrante dans @OnOpen à la liste. Supprimer la session de la liste dans @OnClose

 @OnClose public void close(Session session) { sessionManager.removeSession(session); } 

Pour envoyer un message à tout le monde,

 public void broadcast(Ssortingng message){ for(Session session: sessionList){ session.getBasicRemote().sendText(message); } } 

Vous pouvez utiliser la méthode sessionManager.broadcast() partout où l’événement se déclenche.

Voici un exemple complet de la façon dont Websocket peut être utilisé pour faire de la publicité avec l’API HTML5 de Websocket. https://metamug.com/article/java-push-notification-with-websocket.php

J’ai mis en œuvre une solution similaire à votre problème en utilisant le composant socket omnifaces. Les notifications sont déclenchées par des messages JMS et les destinataires peuvent être des utilisateurs spécifiques ou tous. Le blog post url https://konstpan.wordpress.com/2018/03/25/push-notifications-in-a-jee-web-application-secured-by-keycloak/