2013-10-19 23 views
1

我從JSF(Mojarra 2.2和Glassfish 4)開始,目前正在與一個web應用程序一起練習,這個應用程序的任務是在數據庫中存儲客戶端和訂單。檢索selectOneMenu複雜對象作爲選定項

創建新訂單時,其中一個功能是允許從JSF <h:selectOneMenu>中選擇現有客戶端。訂單實體保存其他屬性中的客戶端實體...

我已經按照BalusC的偉大回答有關從DB(here)預填充一個<h:selectOneMenu>,並已成功地填充礦從存儲在一個渴望ApplicationScoped ManagedBean數據,但我無法設法將支持bean中的選定項目作爲複雜對象進行檢索。它始終爲空。

這讓我氣瘋了,你的幫助將被真正的讚賞! 下面是相關的代碼片段:

@ManagedBean(eager = true) 
@ApplicationScoped 
public class Data implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @EJB 
    private ClientDao clientDao; 

    private List<Client> clients; 

    @PostConstruct 
    private void init() { 
     clients = clientDao.lister(); 
    } 

    public List<Client> getClients() { 
     return clients; 
    } 

} 

創建訂單豆(注: 'COMMANDE' 是指爲了;)

@ManagedBean 
@RequestScoped 
public class CreerCommandeBean implements Serializable { 
    private static final long serialVersionUID = 1L; 
    private Commande commande; 

    private String choixNouveauClient = "nouveauClient"; 

    @EJB 
    private CommandeDao commandeDao; 

    public CreerCommandeBean() { 
     commande = new Commande(); 
    } 

    public void inscrire() { 

     System.out.println("client : " + commande.getClient()); // prints **NULL** 
      // ... orderService to store in DB 
    } 
... getters and setters 

客戶端轉換器:

@FacesConverter(value = "clientConverter", forClass = Client.class) 
public class ClientConverter implements Converter { 

    @Override 
    public Object getAsObject(FacesContext context, UIComponent component, String value) { 
     if (value == null) { 
      return null; 
     } 

     Data data = context.getApplication().evaluateExpressionGet(context, "#{data}", Data.class); 
     for (Client c : data.getClients()) { 
      if (c.getId().toString().equals(value)) { 
       return c; 
      } 
     } 
     throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to Client", value))); 
    } 

    @Override 
    public String getAsString(FacesContext context, UIComponent component, Object value) { 
     return (value instanceof Client) ? String.valueOf(((Client) value).getId()) : null; 
    } 
} 

的facelet摘錄:

<p:outputPanel id="gridContainerAncienClient"> 
      <p:selectOneMenu value="#{creerCommandeBean.commande.client}" 
       rendered="#{creerCommandeBean.choixNouveauClient == 'ancienClient'}"> 
       <f:converter converterId="clientConverter" /> 
       <f:selectItems value="#{data.clients}" var="cli" 
        itemValue="#{cli}" itemLabel="#{cli.prenom} #{cli.nom}" /> 
      </p:selectOneMenu> 
     </p:outputPanel> 

回答

1

CreerCommandeBean@RequestScoped。這意味着它只能爲一個請求生存。
當您選擇要分配給#{creerCommandeBean.commande.client}的客戶端時,請通過請求執行此操作。 #{creerCommandeBean.commande.client}現在是選定的客戶端。然後請求結束,bean被破壞,你的「更改」丟失。
當您嘗試檢索數據,你這樣做,再次請求:的CreerCommandeBean一個新實例被創建並構造分配財產commandeCommande一個新的實例,其財產client又可能是null

解決方案:
使用更廣泛的範圍。例如@ViewScoped只要你保持在同一個視圖中,這使得bean「活着」 - 無論你做了多少請求。

小費: 閱讀BalusC's Post on Communication is JSF 2.0。 JSF 2.2中的部分可能略有不同,但它仍然是一個很好且全面的介紹。

+0

非常感謝萊斯特!現在一切正常。並感謝與BalusC的帖子一樣,鏈接是非凡的;-) – Zim

+0

不客氣! :) – Lester

0

被類似的問題困住了,只是意識到我忘了在我的Object中實現equals()和hashcode()方法。客戶類在這種情況下。

應該責怪自己在BalusC博客中跳過說明。 http://balusc.blogspot.in/2007/09/objects-in-hselectonemenu.html

」 ......請注意對象#equals()方法的實現。這對JSF非常重要。轉換後,它會針對該列表中的項目選擇的項目進行比較。作爲對象#等號( )還需要Object#hashCode(),這也實現了......「