1

Как использовать @ManagedProperty в компоненте подложки?Использование @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 
     } 

    ... 


    } 

Это боб я хотел бы получить доступ. (Позже он будет заменен на запрос 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

Покажите нам свою конфигурацию. Скорее всего, ваш компонент PartnerSelComp находится в пакете, который не загружен вашей конфигурацией. –

ответ

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, поэтому, возможно, вы также можете применить его для этой аннотации.

+0

Да, вы не можете напрямую связать компонент, только объявляйте его как атрибут и извлекаете, как и вы. –

+0

Я добавил дополнительную информацию, которая может быть полезна –

+0

Спасибо за помощь! – BgY

Смежные вопросы