简体   繁体   English

如何在ManagedBean中注入CDI Bean?

[英]How to inject a CDI Bean in a ManagedBean?

I want to inject a CDI Bean in a ManagedBean either with the annotation @Inject or @Produce. 我想在ManagedBean中使用注释@Inject或@Produce注入CDI Bean。 The CDI Bean which I use is: 我使用的CDI Bean是:

@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: 我想要注入CDI Bean的ManagedBean是:

@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. 但是在init函数中,它会抛出NullPointerException。 If I use the annotation @Produces instead of @Inject, the result is the same: NullPointerException. 如果我使用注释@Produces而不是@Inject,结果是相同的:NullPointerException。 Is anything wrong with the CDI Bean (improper annotations)? CDI Bean有什么问题(不正确的注释)? 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: 这是JSF代码:

<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. PS:如果我使用无状态Bean作为BaseBean并且我用注释@EJB注入它,它没有问题。

UPDATE: I have tried it with the annotations @SessionScoped ( javax.enterprise.context.SessionScoped ) and @Named on the Hello class. 更新:我已经在Hello类上使用注释@SessionScopedjavax.enterprise.context.SessionScoped )和@Named进行了尝试。 Although I do not receive a NullPointerException , the h:selectManyCheckbox is empty. 虽然我没有收到NullPointerException ,但h:selectManyCheckbox为空。 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. 而且,让我感到StartException的是,当我在META-INF文件夹下添加beans.xml文件时,我收到一个StartException ,尽管该文件应该存在。 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. 更新2:当我在WEB-INF文件夹中添加beans.xml文件时出现此错误。 The beans.xml file is empty, it contains only the line : beans.xml文件为空,它只包含以下行:

<?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\""}}}}

What @patlov is suggesting will work if you use @Named on your CDI beans. 如果你在CDI bean上使用@Named ,那么@patlov的建议将起作用。 However, if you're working in an environment that supports CDI, do not use @ManagedBean . 但是,如果您在支持CDI的环境中工作, 请不要使用@ManagedBean Instead, use CDI all the way. 相反,一直使用CDI。 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. 只需从javax.faces.bean.SessionScoped切换到javax.enterprise.context.SessionScoped ,一切都会神奇地起作用。 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. 你可能遇到的是从CDI看@ViewScoped ,但在这种情况下使用像JBoss Seam或Apache Deltaspike这样的东西为你实现它。 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. 作为额外的好处,如果您已经为JSF编写了现有代码,它们还将自动用CDI作用域自动替换所有JSF作用域。

Update: This should be the content of your beans.xml: 更新:这应该是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>

通过在应用程序中放置WEB-INF/beans.xml文件,确保已启用CDI。

If you are using @ManagedBean use @ManagedProperty to inject properties: 如果您使用@ManagedBean使用@ManagedProperty注入属性:

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

// getter and setter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM