How to inject a CDI Bean in a ManagedBean?

14,184

Solution 1

What @patlov is suggesting will work if you use @Named on your CDI beans. However, if you're working in an environment that supports CDI, do not use @ManagedBean. Instead, use CDI all the way. See this answer and I'm sure you could find numerous other ones that strongly advise against what you're trying to do.

Just switch from javax.faces.bean.SessionScoped to javax.enterprise.context.SessionScoped and everything will magically work. What you may run into is the absense of @ViewScoped from CDI however, in which case use something like JBoss Seam or Apache Deltaspike that implement it for you. As an added benefit, they will also automatically replace all of the JSF scopes with CDI scopes automatically if you already have existing code written for JSF.

Update: This should be the content of your beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

Solution 2

Make sure you have enabled CDI by putting a WEB-INF/beans.xml file in your application.

Solution 3

If you are using @ManagedBean use @ManagedProperty to inject properties:

@ManagedProperty(value = "#{baseBean}")
private BaseBean dBean;

// getter and setter
Share:
14,184
arjacsoh
Author by

arjacsoh

Updated on June 21, 2022

Comments

  • arjacsoh
    arjacsoh almost 2 years

    I want to inject a CDI Bean in a ManagedBean either with the annotation @Inject or @Produce. The CDI Bean which I use is:

    @Named
    @Startup
    @ApplicationScoped
    public class BaseBean {
    
    private List<String> custs;
    
    public List<String> getCusts() {
        return custs;
    }
    
    public void setCusts(List<String> emps) {
        this.custs = emps;
    }
    
    public BaseBean(){
    
    }
    
    @PostConstruct
    void init() {
        custs = new ArrayList<String>();
        custs.add("Cust1");
        custs.add("Cust3");
        custs.add("Cust2");
        custs.add("Cust4");
    }
    
    }
    

    The ManagedBean, in which I want to inject the CDI Bean is:

    @SessionScoped
    @ManagedBean
    public class Hello implements Serializable {
    
    @Inject
    private BaseBean dBean;
    
    private static final long serialVersionUID = 1L;
    private List<String> customers;
    private List<String> customersSelect;
    
    public Hello() {
    }
    
    @PostConstruct
    void init() {
    //  dBean = new BaseBean();
        customers = dBean.getCusts();
    }
    
    public List<String> getCustomers() {
        return customers;
    }
    
    public List<String> getCustomersSelect() {
        return customersSelect;
    }
    
    public void setCustomersSelect(List<String> customersSelect) {
        this.customersSelect = customersSelect;
    }
    }
    

    In the init function however, it throws NullPointerException. If I use the annotation @Produces instead of @Inject, the result is the same: NullPointerException. Is anything wrong with the CDI Bean (improper annotations)? Do I try to inject it with a wrong way? Does my code lack of something? How can I get it work? Here is the JSF code:

    <h:form id ="f">
        <h:selectManyCheckbox layout="pageDirection" border="1"  value="#{hello.customersSelect}">
            <f:selectItems value="#{hello.customers}"></f:selectItems>
        </h:selectManyCheckbox><br />
        <h:commandButton action="response.xhtml" value="Click me" />
    </h:form>
    

    PS: If I use a Stateless Bean as BaseBean and I inject it with the annotation @EJB, it works with no problem.

    UPDATE: I have tried it with the annotations @SessionScoped (javax.enterprise.context.SessionScoped) and @Named on the Hello class. Although I do not receive a NullPointerException, the h:selectManyCheckbox is empty. moreover, it strikes me, that when I add the beans.xml file under META-INF folder, I receive a StartException, although the file is there supposed to be. I think my application lacks the proper configuration to be capable of Dependency Injection. What is likely to need additional configuration?

    UPDATE 2: This error appears when I add the beans.xml file in the WEB-INF folder. The beans.xml file is empty, it contains only the line :

    <?xml version="1.0" encoding="UTF-8"?> 
    

    The error is:

    Services which failed to start:      service jboss.deployment.unit."JSF1.war".PARSE: org.jboss.msc.service.StartException in service jboss.deployment.unit."JSF1.war".PARSE: Failed to process phase PARSE of deployment "JSF1.war"
    
    12:51:11,482 ERROR [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 1) {"JBAS014653: Composite operation failed and was rolled back. Steps that failed:" => {"Operation step-2" => {"JBAS014671: Failed services" => {"jboss.deployment.unit.\"JSF1.war\".PARSE" => "org.jboss.msc.service.StartException in service jboss.deployment.unit.\"JSF1.war\".PARSE: Failed to process phase PARSE of deployment \"JSF1.war\""}}}}
    
  • arjacsoh
    arjacsoh about 11 years
    When I add it under WEB-INF it throws an error by the start of the server: org.jboss.msc.service.StartException . When I add it under META-INF, it starts the server, but the problem is not removed. Still a NullPointerException.
  • rdcrng
    rdcrng about 11 years
    @arjacsoh I'm sorry, I guess I should have mentioned that you should add @Named to any CDI bean that you want accessible from the EL (Expression Language), i.e. your page. So, remove @ManagedBean and add @Named to Hello. As for the exception, post the stack trace please, can't know what's wrong otherwise.
  • arjacsoh
    arjacsoh about 11 years
    That is what I have done. I replaced @ ManagedBean with @ Named and additionally the import Statement javax.enterprise.context.SessionScoped as you stated. The data are not rendered to the JSF page as I explain it in my Update.
  • rdcrng
    rdcrng about 11 years
    You also say in your update that you're getting a start exception - can you post the stack trace for that?
  • arjacsoh
    arjacsoh about 11 years
    Ok, after adjusting the content of beans.xml, this time it works. I was deceived by reading in the books that even an empty beans.xml file is sufficient to do the job.
  • rdcrng
    rdcrng about 11 years
    Yeah, it's misleading, since you still need the root element.
  • David Blevins
    David Blevins about 11 years
    The StartException is the right direction. Likely means now that CDI is enabled you have some CDI related issues to work through before CDI will work.
  • Abhishek Tyagi
    Abhishek Tyagi over 8 years
    I somehow missed that. And stacktrace doesn't give any hint about that either.