I need to get the ServletContext
from inside a @ServerEndpoint
in order to find Spring ApplicationContext
and lookup for a Bean.
For the moment my best approach is to bind that bean in the JNDI naming context and lookup it in the Endpoint
. Any better solution is welcome.
I'm also looking for a reasonable way to sync servlet's HttpSession
with websocket's Session
.
The servlet
HttpSession
is in JSR-356 available byHandshakeRequest#getHttpSession()
which is in turn available when a handshake request is made right before@OnOpen
of a@ServerEndpoint
. TheServletContext
is in turn just available viaHttpSession#getServletContext()
. That's two birds with one stone.In order to capture the handshake request, implement a
ServerEndpointConfig.Configurator
and override themodifyHandshake()
method. TheHandshakeRequest
is here available as method argument. You can put theHttpSession
intoEndpointConfig#getUserProperties()
. TheEndpointConfig
is in turn available as method argument@OnOpen
.Here's a kickoff example of the
ServerEndpointConfig.Configurator
implementation:Here's how you can use it, note the
configurator
attribute of the@ServerEndpoint
:As a design hint, it's the best to keep your
@ServerEndpoint
fully free of servlet API dependencies. You'd in themodifyHandshake()
implementation better immediately extract exactly that information (usually a mutable Javabean) you need from the servlet session or context and put them in the user properties map instead. If you don't do that, then you should keep in mind that a websocket session can live longer than the HTTP session. So when you still carry aroundHttpSession
into the endpoint, then you may run intoIllegalStateException
when you try to access it while it's being expired.In case you happen to have CDI (and perhaps JSF) at hands, you may get inspiration from the source code of OmniFaces
<o:socket>
(links are at very bottom of showcase).See also:
Updated code for BalusC's answer, the onOpen method needs to be decorated with @OnOpen. Then there is no need anymore to extend the Endpoint class:
I tried out BalusC's answer on Tomcat (Versions 7.0.56 and 8.0.14). On both containers, the modifyHandshake's request parameter does not contain a HttpSession (and thus no servletContext). As I needed the servlet context only to access "global" variables (web-application global, that is), I just stored these variables in an ordinary static field of a holder class. This is inelegant, but it worked.
That ooks like a bug in this specific tomcat versions - has anyone out there also seen this?
Somtimes we can't get
session
with aboveServletAwareConfig
of BalusC, this is because that the session is still not created. since we are not seek for session but servletContext, in tomcat we can do as below:if we want init session immediately, we can call request.getSession().
Ref: Websocket - httpSession returns null