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.
Related
I need to modify a user session object (SessionScoped bean - CDI) in a Servlet, so I have to obtain that bean somehow. I used injection in the following way:
#Inject
private UserSession user;
where UserSession is the SessionScoped CDI bean. user methods are called from either doPost or doGet servlet methods.
This works perfectly; every time the #Inject annotation injects the appropriate UserSession bean, but I don't understand how this behavior is achieved.
I assumed that the beans, annotated with #Inject, are injected only once (when the object - Servlet instance in this case - is created), but it is obviously a wrong presumption.
So, when are these beans injected into the servlet? Per request? And how does this approach avoids conflicts (one servlet instance - multiple threads to deal with it) when there are multiple UserSession objects?
The CDI uses the proxy pattern. The injected instance is actually not the real instance, but a proxy which locates the real instance depending on the current context and delegates all methods to it (like as how EJBs work). The autogenerated class of your UserSession bean looks roughly like this:
public UserSessionCDIProxy extends UserSession implements Serializable {
public String getSomeProperty() {
UserSession instance = CDI.resolveItSomehow();
return instance.getSomeProperty();
}
public void setSomeProperty(String someProperty) {
UserSession instance = CDI.resolveItSomehow();
instance.setSomeProperty(someProperty);
}
}
This mechanism allows you to inject instances of a narrower scope in instances of a broader scope and allows you to still get the expected instance in the current context. The standard JSF #ManagedProperty annotation doesn't support it, simply because it does not use a proxy, but injects the desired instance directly. That's why it's not possible to inject something of a narrower scope by #ManagedProperty.
See also:
Backing beans (#ManagedBean) or CDI Beans (#Named)?
Get JSF managed bean by name in any Servlet related class
When using #EJB, does each managed bean get its own #EJB instance?
How to choose the right bean scope?
Your answer lies in the C of CDI, which stands for Contexts.
What happens is that not the actual bean is injected, but a proxy. This proxy is contextual and resolves to the actual session scoped bean depending on the context of the caller on who's behalf the proxy is executed.
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.
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?
I have a JSF2 project (Mojarra on GlassFish 3.1).
I have a ViewScoped bean that references services through a utility class like so:
#ManagedBean
#ApplicationScoped
public static class ServicesUtil {
#EJB
UserService userService;
#EJB
EmailService emailService;
/** getters/setters **/
}
and
#ManagedBean
#ViewScoped
public class UserHandler {
public String method() {
ServicesUtil.getUserService().doUserStuff();
return "newPage";
}
}
My question is, since the ServicesUtil is ApplicationScoped, does that mean there is only one instance of each service for the entire application? And is this bad practice? If done correctly, would the CDI in GlassFish actually create new instances as they are needed?
Similarly, if the Services were injected into the UserHandler instead would the application be more scalable?
The reason we added the ServicesUtil layer is one of my coworkers said that he occasionally had problems getting the injection to work in the Handler when it is ViewScope. Should there be any difficulty using #EJB in a ViewScoped bean?
Any help is greatly appreciated!
Rob
The pattern you're using doesn't seem to make a lot of sense. There should be no problem with injecting EJBs into a view scoped bean.
Depending on the type of EJB you are using (stateless, stateful or singleton) different things hold.
If the userService and emailService are stateless (they most likely should be), you gain nothing by using a bean that's injected into an application scoped bean first. Namely, what's injected is not the bean itself but a proxy and every request to that is routed to a different real bean instance anyway (see http://en.wikipedia.org/wiki/Enterprise_JavaBean#Stateless_Session_Beans).
If the userService and emailService are stateful, you do get a single instance here, but I highly doubt you need to share actual between every user in your application. But even if you would want that, only a single user (thread) can access the stateful bean at a time.
If those services are singleton, you can just inject them right away into the view scoped bean. There is absolutely no reason to go via an application scoped bean.
Furthermore, ServicesUtil.getUserService() is a static method, so using this to get an injected service is brittle. If you want to use this (you shouldn't, but suppose) ServicesUtil should be injected into UserHandler.
Then, it seems you are confusing CDI and JSF managed beans. I agree this is confusing, but it's currently the way it is. #ViewScoped does not work in combination met CDI beans. From your code it's not clear if #ManagedBean is the JSF variant or the Java EE/CDI one. In this case it should be javax.faces.bean.ManagedBean if you want to use the view scope.
We have JSF2.0 in Tomcat6.0 , need to initialize a ApplicationScope Bean while web server is started.
I tried using the PostConstructApplicationEvent processEvent method to initialize the Bean , but the managed bean from faces-config.xml is returning null.
Is there any other better way to instantiate the bean after startup?
Remove any faces-config.xml declarations related to the bean (they will otherwise override the JSF 2.0 annotations) and then annotate the bean with #ManagedBean(eager=true) as follows:
#ManagedBean(eager=true)
#ApplicationScoped
public class Bean {
// ...
}
This way the bean will always be instantiated on JSF webapp startup, without the need to view any page. You can then do the initialization job in the constructor and/or #PostConstruct of the bean.