【问题标题】:How to inject a CDI Bean in a ManagedBean?如何在 ManagedBean 中注入 CDI Bean?
【发布时间】:2013-02-26 19:46:21
【问题描述】:

我想使用@Inject 或@Produce 注释在ManagedBean 中注入一个CDI Bean。我使用的 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");
}

}

我要在其中注入 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;
}
}

然而,在 init 函数中,它会抛出 NullPointerException。如果我使用注解@Produces 而不是@Inject,结果是一样的:NullPointerException。 CDI Bean 有什么问题(不正确的注释)吗?我是否尝试以错误的方式注入它?我的代码缺少什么吗?我怎样才能让它工作?这是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:如果我使用 Stateless Bean 作为 BaseBean 并使用注解 @EJB 注入它,它可以正常工作。

更新:我已经在Hello 类上使用注释@SessionScoped (javax.enterprise.context.SessionScoped) 和@Named 进行了尝试。虽然我没有收到NullPointerException,但h:selectManyCheckbox 是空的。此外,令我震惊的是,当我在META-INF 文件夹下添加beans.xml 文件时,我收到了StartException,尽管该文件应该存在。我认为我的应用程序缺少能够进行依赖注入的正确配置。什么可能需要额外的配置?

更新 2: 当我在 WEB-INF 文件夹中添加 beans.xml 文件时出现此错误。 beans.xml 文件是空的,它只包含以下行:

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

错误是:

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

【问题讨论】:

    标签: jsf jakarta-ee ejb java-ee-6 cdi


    【解决方案1】:

    如果您在 CDI bean 上使用 @Named,@patlov 的建议将起作用。但是,如果您在支持 CDI 的环境中工作,请勿使用@ManagedBean。相反,一直使用 CDI。请参阅此answer,我相信您会找到许多其他强烈建议您不要尝试做的事情。

    只需从javax.faces.bean.SessionScoped 切换到javax.enterprise.context.SessionScoped,一切都会神奇地工作。但是,您可能会遇到 CDI 缺少 @ViewScoped,在这种情况下,请使用 JBoss Seam 或 Apache Deltaspike 之类的工具来为您实现它。作为一个额外的好处,如果您已经为 JSF 编写了现有代码,它们还会自动将所有 JSF 范围替换为 CDI 范围。

    更新: 这应该是 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>
    

    【讨论】:

    • @arjacsoh 对不起,我想我应该提到您应该将@Named 添加到您希望从 EL(表达式语言)访问的任何 CDI bean 中,即您的页面。因此,删除@ManagedBean 并将@Named 添加到Hello。至于异常,请发布堆栈跟踪,否则不知道是什么问题。
    • 这就是我所做的。我用@Named 替换了@ManagedBean,另外还替换了你所说的import Statement javax.enterprise.context.SessionScoped。正如我在更新中解释的那样,数据不会呈现到 JSF 页面。
    • 您还在更新中说您遇到了启动异常 - 您可以为此发布堆栈跟踪吗?
    • 好了,调整beans.xml的内容后,这次可以了。我被书中的内容所欺骗,即使是一个空的 beans.xml 文件也足以完成这项工作。
    • 是的,这是误导,因为您仍然需要根元素。
    【解决方案2】:

    通过将WEB-INF/beans.xml 文件放入您的应用程序,确保您已启用 CDI。

    【讨论】:

    • 当我在 WEB-INF 下添加它时,它会在服务器启动时引发错误: org.jboss.msc.service.StartException 。当我在 META-INF 下添加它时,它会启动服务器,但问题并没有消除。仍然是 NullPointerException。
    • StartException 是正确的方向。可能意味着现在启用了 CDI,您需要解决一些与 CDI 相关的问题,然后 CDI 才能工作。
    • 我不知何故错过了这一点。而且 stacktrace 也没有给出任何提示。
    【解决方案3】:

    如果您使用@ManagedBean,请使用@ManagedProperty 注入属性:

    @ManagedProperty(value = "#{baseBean}")
    private BaseBean dBean;
    
    // getter and setter
    

    【讨论】:

      猜你喜欢
      • 2019-06-04
      • 1970-01-01
      • 2013-03-03
      • 2019-08-04
      • 2014-06-02
      • 1970-01-01
      • 2015-04-15
      相关资源
      最近更新 更多