【问题标题】:Use of @ManagedProperty in backing component在支持组件中使用 @ManagedProperty
【发布时间】:2017-06-14 09:47:16
【问题描述】:

如何在支持组件中使用@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>

我注意到,我尝试将引用作为属性默认值传递:&lt;cc:attribute name="service" default="#{partnerService}"/&gt;&lt;my:PartnerSelComp value="#{myBean.partnerId}"/&gt; 我不知道为什么但它对我不起作用,我必须在 @987654332 中设置 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();        

            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

感谢您的回答。

【问题讨论】:

  • 向我们展示您的配置。您的 PartnerSelComp 组件很可能位于您的配置未加载的包中。

标签: java jsf dependency-injection jsf-2.2 composite-component


【解决方案1】:

尝试使用html配置界面加载:

<cc:interface componentType="partnerSelComp">
    <cc:attribute name="value" type="java.lang.Long"/>
    <cc:attribute name="service" default="#{partnerService}"/>
</cc:interface>

这主要用于 html 实现内部的使用,因为无论如何您都必须手动获取它:

FacesContext.getCurrentInstance().getAttributes().get("service");

关于直接注入到@FacesComponent 中,直到 JSF 的下一个版本(2.3)才可能。

一种可能的解决方法是使用"@Named 而不是@FacesComponent,或者如果您不能这样做,请尝试http://omnifaces.org/ 库的一些功能。它可以注入到@FacesConverter,所以也许你也可以将它应用到这个注解中。

【讨论】:

  • 是的,你不能直接绑定bean,只能将它声明为属性并像你一样检索。
  • 我添加了一些可能有用的附加信息
  • 感谢您的帮助!
  • stackoverflow.com/questions/19223294/… 支持组件中没有注入。坏消息...
  • 在 2.3 的支持组件中有 注入... 好消息
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-26
  • 2013-07-18
  • 1970-01-01
  • 2016-08-06
  • 1970-01-01
  • 2012-03-10
相关资源
最近更新 更多