Cannot inject bean of non-serializable type into bean of passivating scope - jsf

I'm learning Java EE 7.
I'm trying to store the user session in a #SessionScoped Backing Bean but my IDE is telling me that I have an error because "Cannot inject bean of non-serializable type into bean of passivating scope".
The #SessionScoped bean:
import negocio.Autenticacion;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.Serializable;
#Named
#SessionScoped
public class UserSesion implements Serializable{
#Inject
private Autenticacion auth; // Error by IDE
}
#Stateless EJB code:
import modelo.Usuario;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.security.MessageDigest;
#Stateless
public class AutenticacionBean implements Autenticacion{
#PersistenceContext(unitName = "Banco-PU")
private EntityManager em;
...
Why can't I Inject the EJB in the backing bean?
IDE: Intellij IDEA 14.1.4

This is a false error. The IDE in question apparently isn't smart enough to detect that it's actually an EJB, not a "simple" CDI (or JSF) managed bean. EJBs are always implicitly serializable.
You've 4 options:
Ignore it. It'll run perfectly fine.
Bow for the false error and let EJB class implement Serializable anyway.
Use #javax.ejb.EJB instead of #javax.inject.Inject to inject it. It'll also inject the EJB, but the average IDE must be smart enough to not complain about serialization this way, because the IDE now knows for sure that it's actually an EJB, not a CDI managed bean.
Upgrade IDE to a newer version where this is fixed, if any. The ability to use #Inject instead of #EJB on EJBs is new since Java EE 7 (althouth the support is less complete; e.g. referencing self in #Asynchronous won't work when using #Inject). If still not fixed in latest IDE version, even though it claims to be Java EE 7 compatible, report a bug to them.

Related

How to set #ManagedProperty in CDI

recently I was migrating JSF managed beans to CDI managed beans, but now I need to set a property from one bean to another in CDI, I mean how to adapt the annotation #ManagedProperty(value="#{articleBean.cverev}") using CDI. A fragment of my code is:
#Named
#SessionScoped
public class UserBean implements Serializable{
#Inject #Named
private ArticleBean articleBean;
/*In this part*/
#ManagedProperty(value="#{articleBean.cverev}")
private long cverev;
How can I do it?

How to access #SessionScoped beans from #WebFilter

I am working on an AuthenticationFilter to redirect the user when he's not logged in. I am using TomEE 7.0.0-M2, so with Java-EE7 support.
AuthenticationFilter
#WebFilter(urlPatterns = "/*", dispatcherTypes = {DispatcherType.FORWARD, DispatcherType.REQUEST})
public class AuthenticationFilter implements Filter {
#Inject
private LoginBean loginBean;
...
LoginBean
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import java.io.Serializable;
#Named
#SessionScoped
public class LoginBean implements Serializable {
The problem is that the injected LoginBean is not the instance from the login.xhtml. So i can not verify if the user is successfully logged in.
The LoginBean is not in the session attributes, but i found the right loginBean here, but i have no idea how i can access it. But it looks like that the bean is in CDI but how can i access it from the WebFilter?
I still don't have an answer but an another solution that BalusC mentioned here:
When the user is successfully logged i just add the loginBean manually to the sessionMap
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("loginBean", this);
In the WebFilter i access the loginBean with
session.getAttribute("loginBean")
Is this a good solution? I mean.. sounds like a workaround.

Inject an application scoped managed bean in a websocket

I'm developing a real time application. I have websockets and application scoped managed bean. I'm trying to access the application scoped managed bean from a websocket but I can't. Is this possible?
This is my websocket and managed bean (application scoped):
#ServerEndpoint("/mediador")
#ManagedBean(eager = true)
#ApplicationScoped
public class Mediador implements Serializable {
#ManagedProperty(value = "#{aplicacion}")
private Aplicacion aplicacion;
...
And my "Aplicacion" managed bean:
#ManagedBean(eager = true)
#ApplicationScoped
public class Aplicacion implements Serializable {
...
If I try to access in Mediador class to de managed property "aplicacion" it's null so I get a NullPointerException.
Thanks
This is really not right.
#ServerEndpoint("/mediador")
#ManagedBean(eager = true)
#ApplicationScoped
public class Mediador implements Serializable {
WS (JSR-356 WebSocket) API and JSF API are completely independent from each other. They know nothing from each other and won't take mixed annotations from each other into account.
Effectively, you end up with two instances of the class. One as a WS managed server endpoint as available by ws://.../mediador, and one as a JSF managed bean as available by #{mediador}. The #ManagedProperty is only recognized by JSF managed bean facility and it'll work in the JSF managed bean instance only.
Use CDI instead. It works across the entire Java EE web application. Not only in WebSocket endpoints, but also in JSF managed beans, WebServlets, WebFilters, WebListeners, JAX-RS resources, JAX-WS resources, etcetera. Eventually, JSF managed bean facility will be deprecated in favor of CDI. This will happen in Java EE 9 or perhaps already 8.
#ServerEndpoint("/mediador")
public class Mediador { // Shouldn't be serializable!
#Inject
private Aplicacion aplicacion;
// ... (no getter+setter needed!)
}
#Named
#ApplicationScoped // javax.enterprise.context
public class Aplicacion { // Shouldn't be serializable!
// ...
}
Unrelated to the concrete problem: implementing websockets in JSF rightly is not exactly trivial, certainly not if you'd like to take into account JSF session and view scopes, and would like to be able to target a specific user during push. You'd better look at an existing push component. See also How can server push asynchronous changes to a HTML page created by JSF?

Inject an EJB into a JSF managed bean

I have a war application with some JSF managed beans and EJB for some business logic. I'm using JSF 1.2, JBoss 5 and java 1.6
My managed bean:
#ManagedBean(name = "managedBean")
#SessionScoped
public class MyManagedBean implements Serializable {
#EJB(mappedName = "ejbBean")
public MyEjbBean ejbBean;
....
}
EJB bean:
#Singleton(name = "ejbBean")
public class MyEjbBean {
....
}
Page not rendered, error:
javax.naming.NamingException: Could not dereference object [Root exception is javax.naming.NameNotFoundException: ejb not bound]
What am I doing wrong?
JBoss 5 doesn't support #Singleton EJB (added in EJB3.1 spec), you can use the JBoss #Service annotation to create a singleton.
See the instructions here.

application scoped bean's view is not updated

I have a variable inside an application scoped bean. A user can trigger an update of this variable through a method call. Now the problem is that the user doesn't get an updated view of this variable after refreshing the jsf page. If have tested if the variable is updated properly and it is, so the method for updating is working correctly. Are variables inside an application scoped bean declared as final or what is the problem here?
That can happen if you used the wrong combination of annotations. E.g.
import javax.enterprise.context.ApplicationScoped;
import javax.faces.bean.ManagedBean;
#ManagedBean
#ApplicationScoped
public class App {}
Here, the scope annotation is from CDI and the bean management annotation is from JSF. JSF doesn't recognize CDI scope annotations and hence defaults to #NoneScoped. I.e. the bean is reconstructed on every single EL #{app} evaluation. This explains the symptoms you're seeing.
You'd need to fix the scope annotation to be from JSF as well.
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
#ManagedBean
#ApplicationScoped
public class App {}
The CDI scope annotations can only be used in combination with the CDI bean management annotation #Named.

Resources