Using a CDI #SessionScoped bean from a WebSocket #ServerEndpoint - websocket

In a web application, users use a servlet HTTP session. Some data are stored in CDI #SessionScoped beans. Later in some pages WebSocket communications are performed between the user browser and the server.
With GlassFish 4, when using an injected #SessionScoped CDI bean from a WebSocket #ServerEndpoint with GlassFish 4.0 I get an error message:
org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.SessionScoped
From JSP/servlet type requests, using the #SessionScoped CDI bean is fine, but not from the WebSocket #ServerEndpoint.
Also note that using #Singleton CDI beans from the #ServerEndpoint works fine, so this is not a general purpose dependency injection problem.
Maybe I did something wrong.
So my questions is can #SessionScoped CDI beans be used from methods of WebSocket #ServerEndpoint beans? If yes, how?
Thank you for your time.

It may not be the exact same question, but the issue is similar enough that the answers there apply here. Basically, as #JoakimErdfelt notes websocket support for CDI is problematic at best. The websocket spec neglected to mention what scopes are active.
Out of the box, this is what Tyrus supports: https://github.com/tyrus-project/tyrus/tree/master/samples/cdi/src/main/java/org/glassfish/tyrus/sample/cdi
If you want, you can extend it to start a session scope (for reference, Apache DeltaSpike's CDI Context Control), but because of the protocol difference it would be a different session than the one already established via HTTP.

Related

How to lookup a JSF bean from a Spring bean

I am having a JSF application and I am using Spring for bean management. I registered all JSF beans as Spring beans and everything was running very smoothly. Now, I have got a requirement to use JSF's view scope, so it means I have to create a JSF managed bean (which I did using JSF annotations and all).
Now, I want to access this JSF bean in a Spring bean, certainly I cannot inject or get it using Spring's application context because Spring container doesn't know about this bean. So, currently in my Spring bean code I am getting this JSF bean using JSF's EL Resolver (examples mentioned here).
What I want to know is that is there any better way to do this?
My application is on Spring 4.0 and JSF 2.0 (MyFaces implementation), please let me know if you need any other information. I have not placed code because all my code is in remote server, moreover I think code is not required for this as there is no debugging over here.

relationship between CDI , Stateful session bean, stateless session bean ,pojo and different scopes

Im learning j2ee , pardon me if questions appear very basic.
In httpsession session ID is stored in client side and the data associated with it is stored in server side.
When stateful session bean interacts with web client a browser makes an initial request to a Java EE web application it gets a JSESSIONID that the server can associate with a specific HTTPSession instance. By holding on to this JSESSIONID, the browser can provide it with each follow-up request and this will activate the same http session server-side.
Ref:
Using a Stateful Session Bean to track an user's session
Now when I use CDI #SessionScoped on sfb does that mean just JSESSIONID will be returned for that SFB or EJB container (?) will store another
copy of sfb on server side ?
(session.setAttribute(SFB-Another-Reference) )
Now when I use CDI #RequestScoped on sfb is it useless as SFB lives till session?
Now when I use CDI #SessionScoped on slb is it useless to use #SessionScoped since slb live only for method invocation ?
Now when I use CDI #SessionScoped on POJO
Does that mean the EJB container (?) store the pojo in session. (session.setAttribute(POJO))
Can CDI differentiate between SFB ,SLB and a POJO ?
Now when I use CDI #SessionScoped on sfb does that mean just JSESSIONID will be returned for that SFB or EJB container (?) will store another copy of sfb on server side ?
JSESSIONID is related to the http session, not to any EJB (Statless nor Stateful). When you use #SessionScoped your sfb will be associated by CDI with you http session.
Now when I use CDI #RequestScoped on sfb is it useless as SFB lives till session?
No, it is useless from other reason, as new stateful bean will be created on each request, which in effect breaks the whole idea of stateful bean, which should store state between requests.
Now when I use CDI #SessionScoped on slb is it useless to use
#SessionScoped since slb live only for method invocation ?
More or less yes. Some CDI frameworks (OWB for example) won't even allow that, and only allows #Dependent scope. SLB actually lives longer, but since it doesn't store any state its instances can be pooled and used by many clients.
Now when I use CDI #SessionScoped on POJO Does that mean the EJB
container (?) store the pojo in session. (session.setAttribute(POJO))
That POJO is associated by the CDI framework with http session, it is not directly stored in session as attribute.
Can CDI differentiate between SFB ,SLB and a POJO ?
Yes, CDI container can differentiate these and treats them differently e.g. types visibility, allowed scopes. For example fragment of the spec:
A stateless session bean must belong to the #Dependent pseudo-scope. A
singleton bean must belong to either the #ApplicationScoped scope or
to the #Dependent pseudo-scope. If a session bean specifies an illegal
scope, the container automatically detects the problem and treats it
as a definition error. A stateful session bean may have any scope.

How can I access Spring bean from Message-driven bean in JBoss AS 7

I want to make a call to a Spring bean (a #Component) from my message-driven bean (MDB) but have problems getting a reference to it. I've tried with a class implementing org.springframework.context.ApplicationContextAware which stores the Spring ApplicationContext in a static field in a class MyAppContext. The static field in MyAppContext is then accessed from the MDB. But MyAppContext is loaded from different classloaders. The Spring application context is correctly set in the web module classloader context, but in the MDB's classloader context, it's null.
Can I somehow instruct JBoss to use the same classloader for the web app and the MDB?
Or is there a better way than storing the Spring application context in a static field?
Thanks for any advice!
A static holder for the context is not really a good idea. To make your beans available to other applications in a Java EE environment, you should consider making use of JNDI.
Unfortunately, there is no plain JNDI exporter available out of the box, but it's fairly easy to write one yourself, as shown in this blog post: http://maestro-lab.blogspot.ro/2009/01/how-to-export-spring-managed-bean-to.html
There is however a JndiRmiServiceExporter that you may want to look at.
Once your beans are bound to names in JNDI, they can be referenced using standard CDI in your message bean without worrying about class loading issues.
Why not use "ClassPathXmlApplicationContext" to load and look up for the Spring bean you require in your MBean?

Spring: Serialization of session scoped bean

I have a Spring bean with scope session. This bean holds a reference to another singleton bean which is not serializable. What is the best approach if I want to serialize the session scoped bean?
The same question is already asked here: Spring session-scoped beans (controllers) and references to services, in terms of serialization
The accepted answer is that:
[...]this issue is resolved in spring 3.0 by providing a proxy of non-serializable beans, which obtains an instance from the current application context
As far as I understand the speaker in the linked video it should "just work". But in my case it doesn't! When I try to serialize my session scoped bean i get a NotSerializableException.
How can I solve this problem?
You need to instruct Spring to create that proxy. In XML-based config, via <aop:scoped-proxy/> tag, in component-scan mode via annotation:
#Scope(proxyMode = ScopedProxyMode.INTERFACES)
on your controller class.
You may mark singleton reference field as transient. Then check How to execute method after deserialization and load reference from ApplicationContext.
Also, please provide stacktrace.
P.S.
It is not too good idea to use session passivation.

JSF2 managed bean annotation + scope + injection confusion

I would like to achieve this idealism :
To have only 1 implementation for the JSF Bean container, like to use only Spring or Weld but not both. Currently i am using Spring for my backend, so i prefer Spring.
To have only 1 annotation, to choose between #ManagedBean, #Named, #Model
To be able to use all supported scopes, like #RequestScoped, #SessionScoped, #ViewScoped, #FlashScoped, maybe also #ConversationScoped
The JSF Beans could be injected with spring-managed-services (The backend services), perhaps using #Inject or #Autowired
So far i've been finding no best combination to achieve these because as far as i know, please correct me if i am wrong, :
#ManagedBean can not be injected with spring services ?
#Named can be injected with spring services using #Inject, but #Named is using Weld. Can i just use spring to managed the #Named instead of Weld ?
#Named doesnt support #ViewScoped and FlashScope ?
Please share your thoughts and experiences.
Thank you :-)
UPDATE 15 March 2011
Found an interesting page that describes how to replace Jboss Weld with Spring as the JSR 299 CDI implementation. So basically, the question number 2 is answered. Number 1 is also answered indirectly since i can now inject spring services.
But still, the number 3 question remains. I would find very helpful if i can use the #ViewScoped and Flash Scope in the #Named, something like this article. Flash scope implementation has yet to be seen, but the closest one i can get so far is this page.
Hopefully, replacing weld with spring as the jsr 299 implementation will still enable me to use #ConversationScoped.
Gotta test things now, wish me luck :-)
UPDATE 18 MARCH 2011
Successfully make use of Spring 3 instead of weld to do the #Named, #Inject. The important thing is to set the el-resolver in the faces-config.xml.
AFAIK, Spring 3 currently doesnt support CDI yet, so bye2 #ConversationScoped.
For the scoping, i must still use #Scope("request") or #Scope("session"), but if i prefer the #RequestScoped (javax.enterprise.context.RequestScoped) and #SessionScoped, i can make use of the bridge provided from this article.
The Scope("view") for spring from this article works like magic :-)
One problem remain though, how to pass objects between Scope("view")-beans ..
Wish me luck !
update
Ahhh .. finally done ..
Passing the variables using Flash provided by JSF2 really works like magic.
I dont need an 3rd party implementation for that.
So basically, i can do without weld, but with spring, with the common scopes available, including the view scope, dan can pass between beans using the flash object.
One thing missing is the conversation scope, which isnt a major problem to me yet.
Hopefully the future spring can support this conversation scope.
Cheers :-)
I can successfully Inject Spring bean using ManagedProperty annotation like below. This is on JSF Managed Bean. Spring bean is for backend and I prefer spring for backend.
#ManagedProperty(name="userRepository", value="#{userRepository}")
private UserRepository userRepository;
//Setter and/or Getter
value is the most important thing here. It's actually the bean name of spring. I hope this helps.
Weld (actually, the reference implementation of JSR-299 Context and Dependency Injection, also known as Java EE 6 CDI) was less or more invented to supplant Spring in Java EE 6 environments. I would suggest to use Java EE 6 CDI instead of Spring. Why would you use a 3rd party framework when Java EE 6 provides the same functionality out the box?
If the Spring backend really cannot be changed, then I'd suggest to stick to it and not to intermix with Java EE 6 CDI annotations to save yourself from confusions and maintenance headache.

Resources