我想在ManagedBean中使用注释@Inject或@Produce注入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:如果我使用无状态Bean作为BaseBean并且我用注释@EJB注入它,它没有问题。
更新:我在@SessionScoped
课程中使用注释javax.enterprise.context.SessionScoped
(@Named
)和Hello
进行了尝试。虽然我没有收到NullPointerException
,但h:selectManyCheckbox
为空。而且,令我感到震惊的是,当我在beans.xml
文件夹下添加META-INF
文件时,我会收到一个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\""}}}}
答案 0 :(得分:9)
如果您在CDI bean上使用@Named
,那么@patlov的建议将起作用。但是,如果您在支持CDI的环境中工作,请勿使用@ManagedBean
。相反,一直使用CDI。请参阅此answer,我相信您可以找到许多其他强烈建议您反对您尝试做的事情。
只需从javax.faces.bean.SessionScoped
切换到javax.enterprise.context.SessionScoped
,一切都会神奇地起作用。你可能遇到的是来自CDI @ViewScoped
的缺席,但在这种情况下使用像JBoss Seam或Apache Deltaspike这样的东西为你实现它。作为额外的好处,如果您已经为JSF编写了现有代码,它们还将自动用CDI作用域自动替换所有JSF作用域。
<强>更新强> 这应该是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>
答案 1 :(得分:3)
确保通过在应用程序中放置WEB-INF/beans.xml
文件来启用CDI。
答案 2 :(得分:1)
如果您使用@ManagedBean
使用@ManagedProperty
注入属性:
@ManagedProperty(value = "#{baseBean}")
private BaseBean dBean;
// getter and setter