By default …
… a WebSocket implementation creates a new (server) endpoint instance per client. In case you need a single instance, you can implement this using a custom ServerEndpointConfig.Configurator
(by overriding the getEndpointInstance
method)
The catch: you might have to sacrifice some of the (Java EE) platform related services like dependency injection and interceptors
More details here
Alternate solution ?
A similar behavior can be achieved by decorating the WebSocket endpoint with @Singleton
This approach has the caveat of not being a standard feature outlined by the spec (although injection of EJBs as well as interceptors support is clearly mentioned in the Java WebSocket spec Sec 7.1)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Singleton | |
@ServerEndpoint("/singleton/") | |
public class SingletonEndpoint { | |
@OnOpen | |
public void onopen(Session s) throws IOException { | |
s.getBasicRemote().sendText(String.valueOf(hashCode())); | |
} | |
@PreDestroy | |
public void onDestroy() { | |
System.out.println("Singleton bean " + hashCode() + " will be destroyed"); | |
} | |
@OnClose | |
public void onClose(Session session, CloseReason closeReason) { | |
System.out.println("Closed " + session.getId() + " due to " + closeReason.getCloseCode()); | |
} | |
} |
Concurrency semantics ?
In case of a @Singleton
, all the clients will interact with the one-and-only server endpoint instance. Here is a quick summary of how the EJB as well as WebSocket threading semantics are applied
- The
Singleton
bean default approach WRITE lock ensures single threaded access across all connected clients - If thread-safety is not a concern (e.g. in case where you do not deal with client specific data/state in your logic) and in case the single-threaded access model proves to be a bottleneck, override the default behavior by switching to a READ lock which allows concurrent threads to access the methods (unless of course a WRITE lock is not already in effect)
Note: The above mentioned semantics are with respect to ALL the WebSocket clients. From the point of view of a single client, the default strategy of one thread at a time, per endpoint instance per client continues to apply (more details here)
Further reading..
- eBook: Java WebSocket API Handbook
- WebSocket specification
- JSR 356 RI: Tyrus
Cheers!
Dear Abhishek,
I have to deploy a Websocket @ServerEndPoint in the EJB level (jar), so I have used the Singleton’s approach. The problem is that, the singleton websocket endpoint is not discoverable by the clients (Response code was not 101: 404). Should the Websocket being deployed in a war file or is there any alternative? Please Advice. Thanks In Advance.
LikeLike
Yes. The WebSocket endpoint needs to be deployed in a WAR file (as it is a web component). In fact you can deploy EJB in WAR files too. You are not forced to have a structure with an EAR, EJB JAR and different WAR files (although you can do that as well)
LikeLike
Thank you for the prompt reply
LikeLike