@Stateful
EJBs can be injected in WebSocket endpoints (supported by the WebSocket specification). There is an one-to-one association between the WebSocket client & endpoint (which is by default) as well as the injected Stateful
EJB instance, which makes it an good candidate for storing client specific state. It offers advanced semantics as compared to simple java.util.Map
interface exposed by getUserProperties
method in javax.websocket.Session
)
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
@Stateful | |
public class ClientChatState { | |
//…who needs details ! | |
} | |
@ServerEndpoint("/letschat/{login-id}") | |
public class ChatEndpoint { | |
@EJB | |
private ClientChatState ccs; //stateful EJB | |
private String userID; | |
@OnOpen | |
public void connOpened(@PathParam("login-id") String loginID, Session session) { | |
ccs.setUser(loginID) | |
.currentState(State.JOINED); //everyone likes a fluent API! | |
} | |
…. | |
} |
But, what happens to the EJB when ….
… the WebSocket session terminates (either from the client or server side) ?? The Stateful instance can still linger in memory before its destroyed
- Their removal can be tuned by using the
@StatefulTimeout
annotation (but why wait ??), or - you can choose to passivate them by using
passivationCapable=true
with@Stateful
(but why passivate the EJB when the WebSocket connection itself is closed ?)
The Tip
Implement a @Remove
annotated method in the Stateful
EJB and call it from the @OnClose
callback method ni your WebSocket server endpoint implementation. This will ensure that the EJB is removed from the memory immediately rather than depending upon other factors
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
@Stateful | |
public class ClientChatState { | |
… | |
@Remove | |
public void dispose(){ | |
//this can just be a marker method | |
} | |
@PreDestroy | |
public void closeResources(){ | |
//close connections, resources etc. | |
} | |
} | |
@ServerEndpoint("/letschat/{login-id}") | |
public class ChatEndpoint { | |
…. | |
@OnClose | |
public void disconnected(Session session) { | |
ccs.dispose(); //method annotated with @Remove | |
} | |
…. | |
} |
Further reading
- eBook: Java WebSocket API Handbook
- JSR 356 specification
- eBook: EJB Annotations Primer
- Tyrus (JSR 356 RI)