如何在支持组件中使用@ManagedProperty
?
这是合作伙伴选择器复合组件。组件检查数据库中键入的合作伙伴代码,并在代码有效时填写合作伙伴名称。
组件:
<cc:interface componentType="partnerSelComp">
<cc:attribute name="value" type="java.lang.Long"/>
</cc:interface>
<cc:implementation>
<span id="#{cc.clientId}" style="white-space:nowrap">
<p:inputText id="id" type="hidden" binding="#{cc.partnerId}"/>
<p:inputText id="code" binding="#{cc.code}">
<p:ajax event="blur" update="id code name" listener="#{cc.validate}" />
</p:inputText>
<p:inputText id ="name" disabled="true" binding="#{cc.name}" />
<p:message for="code"/>
</span>
</cc:implementation>
在encodeBegin()
我得到了NPE因为service
为空:
@FacesComponent("partnerSelComp")
public class PartnerSelComp extends UIInput implements NamingContainer {
private InputText partnerId;
private InputText code;
private InputText name;
@ManagedProperty("#{partnerService}")
private PartnerService service;
@Override
public void encodeBegin(FacesContext context) throws IOException {
Partner p=null;
Long i = (Long) getValue();
if (i != null) {
p = findPartnerById(service.getList(), i);
}
fill( (i==null) , p); // fills the code and name fields
}
...
}
这是我想要访问的bean。 (稍后它将替换为JPA查询。)
@ManagedBean(name = "partnerService")
@ApplicationScoped
public class PartnerService {
private List<Partner> list;
public PartnerService() {
list = new ArrayList<>();
list.add( new Partner(1, "A", "Partner A"));
list.add( new Partner(2, "B", "Partner B"));
list.add( new Partner(3, "C", "Partner C"));
list.add( new Partner(4, "D", "Partner D"));
list.add( new Partner(5, "E", "Partner E"));
list.add( new Partner(6, "E", "Partner F"));
}
public List<Partner> getList() {
return list;
}
public void setList(List<Partner> list) {
this.list = list;
}
}
解决方案:
组件的使用:
<my:PartnerSelComp value="#{myBean.partnerId}" service="#{partnerService}"/>
组件xhtml:
<cc:interface componentType="partnerSelComp">
<cc:attribute name="value" type="java.lang.Long"/>
<cc:attribute name="service"/>
</cc:interface>
<cc:implementation>
<span id="#{cc.clientId}" style="white-space:nowrap">
<p:inputText id="id" type="hidden" binding="#{cc.partnerId}"/>
<p:inputText id="code" binding="#{cc.code}">
<p:ajax event="blur" update="id code name" listener="#{cc.validate}" />
</p:inputText>
<p:inputText id ="name" disabled="true" binding="#{cc.name}" />
<p:message for="code"/>
</span>
</cc:implementation>
我注意到,我尝试将参考作为属性默认值传递:<cc:attribute name="service" default="#{partnerService}"/>
和<my:PartnerSelComp value="#{myBean.partnerId}"/>
我不知道为什么但它没有帮助我,我不得不如上所示,在service
中设置my:PartnerSelComp
属性。
支持组件:
@FacesComponent("partnerSelComp")
public class PartnerSelComp extends UIInput implements NamingContainer {
private InputText partnerId;
private InputText code;
private InputText name;
@ManagedProperty("#{partnerService}")
private PartnerService service;
@Override
public void encodeBegin(FacesContext context) throws IOException {
Partner p=null;
Long i = (Long) getValue();
PartnerService service = getAttributeValue("service", null );
if (i != null) {
p = findPartnerById(service.getList(), i);
}
fill( (i==null) , p); // fills the code and name fields
}
@SuppressWarnings("unchecked")
private <T> T getAttributeValue(String key, T defaultValue) {
T value = (T) getAttributes().get(key);
return (value != null) ? value : defaultValue;
}
...
}
我必须使用getAttributes().get(key)
来获取引用并将其转换为PartnerService
。
感谢您的回答。
答案 0 :(得分:2)
尝试使用html配置界面加载它:
<cc:interface componentType="partnerSelComp">
<cc:attribute name="value" type="java.lang.Long"/>
<cc:attribute name="service" default="#{partnerService}"/>
</cc:interface>
这主要是为了在html实现中使用,因为无论如何你必须手动获取它的bean类:
FacesContext.getCurrentInstance().getAttributes().get("service");
关于直接注入@FacesComponent,直到下一版本的JSF(2.3)才能实现。
可能的解决方法是使用"@Named
而不是@FacesComponent
,或者如果您不能这样做,请尝试使用http://omnifaces.org/库的某些功能。它可以注入@FacesConverter,所以也许你也可以将它应用于这个注释。