2

I googled a lot for this problem before posting this question and Accessing HttpSession from HttpServletRequest in a Web Socket @ServerEndpoint is one of the best Questions/Answers I was able to found, but it appears to not solve my problem.

I was able to access HttpSession from websocket in this way, but I can't access the same CDI session bean instances as from normal HTTP requests.

I tried to store in session the HttpSessionContextImpl Weld instance too and tried to use it on WebSocket side, but it didn't expose previous beans.

Then my question: Is it possible to access the same CDI managed session bean instances in both cases (WebSocket events and HTTP normal requests)?

At the moment it is important for me to have this feature working in Wildfly 9/10, but it would be great to have a general solution working for example on Tomcat > 7 too (using jBoss Weld or any other implementation).

Thanks in advance for your support.

Community
  • 1
  • 1
Ivano85
  • 98
  • 1
  • 11
  • Did you check you are accessing the same session? Do you get any session scoped cdi beans when using web sockets? If yes then the sessions are probably not the same if no then the listener/interceptor responsible for initializing the session context is probably not running (then either do that manually or try ro roll your own session context). – Thomas Mar 23 '16 at 12:12
  • Yes, I debugged the wildfly version and the HttpSession instance is the same seen in both context and it contains the same bean instances seen during http request, but I'm not able to make them managed in web socket context (during both onOpen and ServerEndpointConfig executions). – Ivano85 Mar 23 '16 at 13:15

1 Answers1

2

Then my question: Is it possible to access the same CDI managed session bean instances in both cases (WebSocket events and HTTP normal requests)?

Only during the handshake request, because that's a HTTP request. The HTTP session is only available during a HTTP request, not during a WS request. Hopefully the reason is by now obvious as CDI stores session scoped beans in HTTP session which is only identifiable by a HTTP request, and during a WS request there's no means of a physical HTTP request anywhere and therefore HTTP session is also unavailable.

Your best bet is generating an unique identifier, store it in a session scoped bean, add it to the WS URL (as either path or request parameter), extract it during onOpen and store it in an application scoped bean. In normal Java EE servers, application scoped CDI beans are available via @Inject in a WS endpoint class the usual way (but not in Tomcat/Jetty/etc, you'd have to manually grab it via BeanManager). Finally, just let the session scoped bean containing the unique identifier consult the application scoped bean for any opened sockets by that identifier.

At least, I went this path while developing the OmniFaces <o:socket> tag for JSF. It's all open source, you can find source code links at the bottom of its showcase page.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thank you for your reply. I will take a look at the link you posted as soon as possibile. Although I was looking for a cleaner solution, if there isn't one, I will end implementing a custom solution like yours. – Ivano85 Mar 23 '16 at 13:17
  • There isn't one. As explained, there isn't a HTTP request/session anywhere at that moment. No magic can change that. I've however a new CDI scope like `@WebsocketScoped` for that in mind. – BalusC Mar 23 '16 at 13:19
  • Yes of course, I already implemented custom `@RequestScoped` and `@SessionScoped` contexts to be used in all cases when the "official" ones are not available (i.e. most theaded contexts). So I would actually appreciate any idea for implementing this. In worst case, does someone know how a custom implementation of `@SessionScoped` context could reliably find (and make managed) session beans available in HttpSession attributes? This "magic" would be an actually clean solution in my opinion... – Ivano85 Mar 23 '16 at 13:36
  • There's no HTTP session during a WS request/session. There's no way to inject HTTP/CDI request/session related thing in a WS related thing. From the other side on, there's however a way to inject a fictive WS related scope in a HTTP/CDI request/session (via an application scoped bean as I detailed in my answer). On a side note, perhaps this related Q&A is also helpful: http://stackoverflow.com/q/32426674 – BalusC Mar 23 '16 at 13:59
  • I'm thinking to put all together and maybe I will try to use only my custom `@RequestScoped` and `@SessionScoped` contexts in place of the container ones or use a similar solution to have the cleanest implementation possible. Then I will post my solution if I'm successful. In the meantime I accept your answer ;-). Thank you for your suggestions. – Ivano85 Mar 23 '16 at 16:21