问题
I've browsed a lot of Web Socket examples, presentation slides and they are mostly concentrated on a rather simple scenarios in which client-server communication is initiated by the client.
I am interested in another scenario, which seems to be equally practical: pure server push to client.
Example I have in mind is an application that updates stocks value on a website. Imagine there is an external system stock exchange system, which is sending a JMS message for every subscribed stock value change.
I would like to know how to translate such incoming JMS event into a server push and to it efficiently and idiomatically from a Java EE 7 point of view.
As far as I can understand the spec, I am supposed to write a web socket endpoint
@ServerEndpoint("/demo")
public class WSEndpoint {
private static final Logger LOG = Logger.getLogger(WSEndpoint.class);
@OnMessage
public void onMessage(String 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());
}
}
Everything is easy when I am getting a message from the frontend, I can do whatever I like in the @OnMessage
method. But in my example I will not get any message from the client, I'll get an event from some external system.
There are a few approaches. For instance I can create a thread in an @OnOpen
method, as demonstrated in this blog. In practice that approach might show a shortcoming since for every client I would need to create a new, potentially long living thread.
One can do better using NIO channels with selectors, but this would demand some kind of "hand made" channels management. Doable, but rather cumbersome.
Another solution would be to ping some other system for updates, but again it would be kind of ugly. In addition I am also not sure if an @OnOpen
method is meant to be used in that way.
Ideally an incoming JMS message would trigger a Web Socket push to the client. Any ideas how to implement something like this nicely?
回答1:
Probably this is not most elegant way but just to demonstrate idea. Method broadcast() will send message to all connected clients.
@ServerEndpoint("/echo")
public class ServerEndPoint {
private static Set<Session> userSessions = Collections.newSetFromMap(new ConcurrentHashMap<Session, Boolean>());
@OnOpen
public void onOpen(Session userSession) {
userSessions.add(userSession);
}
@OnClose
public void onClose(Session userSession) {
userSessions.remove(userSession);
}
@OnMessage
public void onMessage(String message, Session userSession) {
broadcast(message);
}
public static void broadcast(String msg) {
for (Session session : userSessions) {
session.getAsyncRemote().sendText(msg);
}
}
}
回答2:
I do it this way (no client request is needed):
@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());
}
}
}
回答3:
Store the active sessionList
in another class SessionManager
.
List<Session> socketSessions = new ArrayList<>();
Add incoming session in @OnOpen
to list. Remove session from list in @OnClose
@OnClose
public void close(Session session) {
sessionManager.removeSession(session);
}
To send a message to everyone,
public void broadcast(String message){
for(Session session: sessionList){
session.getBasicRemote().sendText(message);
}
}
You can use the sessionManager.broadcast()
method wherever the event triggers.
Here is a complete example of how websocket can be used to make push with HTML5 websocket API. https://metamug.com/article/java-push-notification-with-websocket.php
回答4:
I have implemented a solution similar to your problem using omnifaces socket component. Notifications are triggered by JMS messages and recipients may be specific users or all of them. The blog post url https://konstpan.wordpress.com/2018/03/25/push-notifications-in-a-jee-web-application-secured-by-keycloak/
来源:https://stackoverflow.com/questions/26409937/how-to-implement-push-to-client-using-java-ee-7-websockets