#javax.faces.bean.ManagedProperty in CDI #Named bean returns null - jsf

I'm trying to deal with #javax.faces.bean.ManagedProperty but without success !
I've been following this guide, and it not seems that hard.
But my code simply won't work!
Here's a little snippet
#ManagedBean
#SessionScoped
public class LoginBean {
private User user;
// ...
}
#Named
#RequestScoped
public class MessagesBean {
#ManagedProperty(value = "#{loginBean}")
private LoginBean loginBean;
public String getUser() {
System.err.println(loginBean == null);
return loginBean.getUser().getUsername();
}
// ...
}
This code gives me a NullPointerException, saying that loginBean is null!
Any suggestion?

You are mixing JSF managed beans with CDI beans. Your LoginBean is a JSF managed bean (it has the #ManagedBean annotation). Your MessageBean is a CDI bean (it has the #Named annotation). If you changed the Message bean to a JSF managed bean (replacing #Named with #ManagedBean) then the problem should be solved (It should work with two CDI beans as well). Or if you're using JSF 2.3 or newer, then use javax.faces.annotation.ManagedProperty instead in the CDI bean.
Here is a short overview of how injection works between both bean types:
CDI #Named --> CDI #Named (works)
CDI #Named --> JSF #ManagedBean (works only if scope of injected bean is broader)
JSF #ManagedBean --> JSF #ManagedBean (works only if scope of injected bean is broader)
JSF #ManagedBean --> CDI #Named (won't work)
But take care of the scope import classes. There are different classes for #SessionScoped and #RequestScoped depending on the bean type.
javax.faces.bean.SessionScoped for #ManagedBeans
javax.enterprise.context.SessionScoped for CDI #Named beans
In addition, for #Named (CDI) use #Inject and for #ManagedBean use #ManagedProperty. There is one thing that does not work in CDI. Your #ManagedProperty(value = "#{loginBean}") gets a full bean, but #ManagedProperty(value = "#{loginBean.user}") to get a 'property' of a bean works to. This is not directly possible in CDI with #Inject. See CDI Replacement for #ManagedProperty for a 'solution'

Related

Can I put #ManagedBean in CDI scope?

I'm using GlassFish 3.0.1. I want to know if I can use:
#ManagedBean
#ConversationScoped
Instead of #Named?
#ManagedBean is a JSF annotation while #ConversationScoped is a CDI annotation, I can't think of any valid scenario to combine them.
In general #Named will cover almost all you needs and it make your bean available to EL thus the JSF pages.

Inject CDI bean into JSF #ViewScoped bean

I have a problem with JSF, CDI project. I did a lot of research and I found that in CDI there is no #ViewedScoped annotation. I solving problem with ajax based page with dialog. I want to pass variable to dialog from datatable. For this purpose, I can't use #RequestedScoped bean because value is discard after end of request. Can anyone help me to solve it? I can't use #SessionScoped but it's a bad practice IMHO. Or maybe save only this one variable into session who knows. Can you guys give me any hints how to solve this problem elegantly?
import javax.enterprise.context.ApplicationScoped;
#ApplicationScoped
public class ServiceBean implements Serializable {
...
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class SomeBean {
#Inject
ServiceBean serviceBean;
#Postconstruct ...
Here is the error message:
com.sun.faces.mgbean.ManagedBeanCreationException: An error occurred performing resource injection on managed bean warDetailBean
First, If you are attempting to use CDI, you need to activate it by putting a WEB-INF/beans.xml file in your application (note that this file can be empty), more informations about that file could be found in the Weld - JSR-299 Reference Implementation.
As you are using Tomcat, please be sure to respect all the configuration requirements by following the steps in How to install CDI in Tomcat?
Second, Even if you can use #Inject inside a JSF managed bean, It's preferable that you don't mix JSF managed beans and CDI, please see BalusC's detailed answer regarding Viewscoped JSF and CDI bean.
So if you want to work only with CDI #Named beans, you can use OmniFaces own CDI compatible #ViewScoped:
import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;
#Named
#ViewScoped
public class SomeBean implements Serializable {
#Inject
ServiceBean serviceBean;
}
Or, if you want to work only with JSF managed beans, you can use #ManagedProperty to inject properties:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class SomeBean{
#ManagedProperty(value = "#{serviceBean}")
ServiceBean serviceBean;
}
See also:
ManagedProperty in CDI #Named bean returns null
Omnifaces CDI ViewScoped

What makes a bean a CDI bean?

In the top answer to this question for example : Java EE 6 #javax.annotation.ManagedBean vs. #javax.inject.Named vs. #javax.faces.ManagedBean I read that:
To deploy CDI beans, you must place a file called beans.xml in a
META-INF folder on the classpath. Once you do this, then every bean in
the package becomes a CDI bean.
And also it is said that:
If you want to use the CDI bean from a JSF page, you can give it a
name using the javax.inject.Named annotation.
I have a sample code that goes like this:
#ManagedBean
#ViewScoped
public class SignUpPage {
private User user;
#PostConstruct
public void init() {
user = new User();
}
#Inject
private UserDao userDao;
// rest of the class
So as far as I understand, my bean is still a JSF Managed Bean, it is not a CDI bean(or is it?). By the way, I have a beans.xml in my WEB-INF folder.
And #Inject works just fine in here. Also, I can access the bean with EL just fine(which makes me think it is still a JSF Managed Bean)
The UserDao class looks something like this:
#Stateless
public class UserDao {
EntityManager em;
#PostConstruct
public void initialize(){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Persistence");
em = emf.createEntityManager();
}
So, it is as far as I know an EJB..
So do I have any CDI beans in this example? How does #Inject work here?
Hope my question is clear, Regards!
By CDI specification, every JavaBean is a Managed Bean (do not confuse it with JSF #ManagedBean, this is a different one) in project where the beans.xml is present. So every class is also eligible for dependency injection. Note that default scope of this class is Dependent.

Inject Bean that uses #Named with value

how can I Inject a Bean, that uses a #Named annotation along with a value?
#Named
public class LanguageService{
...
}
public class SomeOtherBean{
#Inject
private LanguageService languageService
}
works without Problem - but how to inject, if i'm using:
#Named("lang")
public class LanguageService{
...
}
#Inject can't have a value as #ManagedProperty does. (But I wan't to stay with CDI)
Edit:
I noticed that it doesn't matter how the bean is named. My Fault that leads to an NPE was simple that i created SomeOtherBean manually, and ofc. no Injection was done. My fault.
CDI selects injectable beans by type (and qualifiers) and not by the annotation parameter. The name is used to address a CDI bean from views, e.g. facelets.

Passing data between managed components in JSF

Is it actually possible to pass any data between managed components in JSF? If yes, how to achieve this?
Could anyone provide any sample?
There are several ways. If the managed beans are related to each other, cleanest way would be injection. There are different ways depending on JSF version and whether CDI is available.
CDI
Just use #Inject.
#Named
#SessionScoped
public class Bean1 {
// ...
}
#Named
#RequestScoped
public class Bean2 {
#Inject
private Bean1 bean1; // No getter/setter needed.
}
Other way around can also, the scope doesn't matter because CDI injects under the covers a proxy.
JSF 2.x
Use #ManagedProperty.
#ManagedBean
#SessionScoped
public class Bean1 {
// ...
}
#ManagedBean
#RequestScoped
public class Bean2 {
#ManagedProperty("#{bean1}")
private Bean1 bean1; // Getter/setter required.
}
Other way around is not possible in this specific example because JSF injects the physical instance and not a proxy instance. You can only inject a bean of the same or broader scope into a bean of a particular scope.
JSF 1.x
Use <managed-property> in faces-config.xml.
public class Bean1 {
// ...
}
public class Bean2 {
private Bean1 bean1; // Getter/setter required.
}
<managed-bean>
<managed-bean-name>bean1</managed-bean-name>
<managed-bean-class>com.example.Bean1</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>bean2</managed-bean-name>
<managed-bean-class>com.example.Bean2</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>bean1</property-name>
<value>#{bean1}</value>
</managed-property>
</managed-bean>
See also:
Backing beans (#ManagedBean) or CDI Beans (#Named)?
How to choose the right bean scope?
Get JSF managed bean by name in any Servlet related class
To add to BalusC's answer, if you are using a dependency-injection framework (spring, guice, etc.), or if using JSF 2.0, you can have one managed bean set into the other using just:
#Inject
private Bean2 bean2;
(or the appropriate annotation based on your DI framework)

Resources