2012-08-16 43 views
2

我有這些簡單的網頁:JSF 2基本@RequestScoped CRUD

list.xhtml

<h:form id="form"> 
    <h:dataTable value="#{testBean.model}" var="elem"> 
     <h:column> 
      <f:facet name="header">code</f:facet> 
      #{elem.code} 
     </h:column> 
     <h:column> 
      <f:facet name="header">description</f:facet> 
      #{elem.description} 
     </h:column> 
     <h:column> 
      <f:facet name="header">action</f:facet> 
      <h:commandButton action="#{testBean.edit(elem)}" value="edit"/> 
     </h:column> 
    </h:dataTable> 
</h:form> 

edit.xhtml

<h:form id="form"> 
    <h:panelGrid columns="2"> 
     <h:outputLabel value="code"/> 
     <h:inputText value="#{testBean.selection.code}"/> 

     <h:outputLabel value="description"/> 
     <h:inputText value="#{testBean.selection.description}"/> 
    </h:panelGrid> 

    <h:commandButton action="#{testBean.update}" value="update"/> 
</h:form> 

和這個bean:

@ManagedBean 
public class TestBean implements Serializable 
{ 
    private static final long serialVersionUID = 1L; 

    @EJB 
    private PersistenceService service; 
    private Object selection; 
    private List<UnitType> model; 

    @PostConstruct 
    public void init() 
    { 
     model = service.findAll(UnitType.class); 
    } 

    public String edit(Object object) 
    { 
     System.out.println(Tracer.current(object)); 
     setSelection(object); 
     return "edit"; 
    } 

    public String update() 
    { 
     System.out.println(Tracer.current(selection)); 
     return "list"; 
    } 

    // getters and setters 
} 

所以桌子被渲染,當我點擊其中一個E「編輯」按鈕,將定位爲「edit.jsf」顯示填充輸入, 但是當我點擊「更新」按鈕,它給了我這個錯誤:

javax.el.PropertyNotFoundException: /test2/edit.xhtml @27,54 value="#{testBean.selection.code}": Target Unreachable, 'null' returned null 

注意,我知道如何實現@ViewScoped接口來管理CRUD操作,但這是一個簡單的概念證明,我需要更好地理解JSF生命週期。

,所以我想 「testBean就」 被@RequestScoped


UPDATEf:viewParam努力,仍然不理解......

list.xhtml

<?xml version="1.0" encoding="ISO-8859-1"?> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> 
    <h:head> 
     <title>test list</title> 
    </h:head> 

    <h:body> 
     <h:messages/> 

     <h:form id="form"> 
      <h:dataTable value="#{testBean2.model}" rows="10" var="elem"> 
       <h:column> 
        <f:facet name="header">converterString</f:facet> 
        #{elem.converterString} 
       </h:column> 
       <h:column> 
        <f:facet name="header">first name</f:facet> 
        #{elem.firstName} 
       </h:column> 
       <h:column> 
        <f:facet name="header">last name</f:facet> 
        #{elem.lastName} 
       </h:column> 
       <h:column> 
        <f:facet name="header">action</f:facet> 
        <h:commandButton action="#{testBean2.edit}" value="edit"> 
         <f:param name="entity" value="#{elem.converterString}"/> 
        </h:commandButton> 
        <h:commandButton action="#{testBean2.edit2}" value="edit2"> 
         <f:param name="entity" value="#{elem.converterString}"/> 
        </h:commandButton> 
       </h:column> 
      </h:dataTable> 
     </h:form> 
    </h:body> 
</html> 

edit.xhtml

<?xml version="1.0" encoding="ISO-8859-1"?> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> 
    <f:metadata> 
     <f:viewParam id="entityParam" name="entity" value="#{testBean2.selection}" converter="entityConverter" required="true"/> 
    </f:metadata> 

    <h:head> 
     <title>test edit</title> 
    </h:head> 

    <h:body> 
     <h:messages/> 

     <h:form id="form"> 
      <h:panelGrid columns="2"> 
       <h:outputLabel value="selection"/> 
       <h:outputText value="#{testBean2.selection.converterString}"/> 

       <h:outputLabel value="firstName"/> 
       <h:inputText value="#{testBean2.selection.firstName}"/> 

       <h:outputLabel value="lastName"/> 
       <h:inputText value="#{testBean2.selection.lastName}"/> 
      </h:panelGrid> 

      <h:commandButton action="#{testBean2.update}" value="update" ajax="false"> 
       <f:param name="entity" value="#{testBean2.selection.converterString}"/> 
      </h:commandButton> 
     </h:form> 
    </h:body> 
</html> 

testBean2.java

@ManagedBean 
public class TestBean2 implements Serializable 
{ 
    private static final long serialVersionUID = 1L; 

    @EJB 
    private PersistenceService service; 

    private Object selection; 
    private List<Person> model; 

    @PostConstruct 
    public void init() 
    { 
     Tracer.out(); 
     model = service.queryAll(Person.class); 
    } 

    public String edit() 
    { 
     JsfUtils.addSuccessMessage("edited"); 
     return "edit"; 
    } 

    public String edit2() 
    { 
     JsfUtils.addSuccessMessage("edited"); 
     return "edit?faces-redirect=true&amp;includeViewParams=true"; 
    } 

    public void update() 
    { 
     Tracer.out(selection); 
     JsfUtils.addSuccessMessage("updated"); 
    } 

    // getters and setters 
} 

如果我按「編輯」按鈕,它去edit頁,但選擇爲空,沒有消息顯示。

如果我按「EDIT 2」按鈕,它去edit頁,但選擇爲空,顯示所需信息,網址爲edit.jsf?entity=

我到底做錯了什麼?

+0

閱讀本你會g等想法 [在管理豆查看和請求範圍的差異] [1] [1]:http://stackoverflow.com/questions/6025998/difference-between-view-and-請求範圍在受管理的豆 – 2012-08-16 11:47:43

+0

我已經知道區別。我正在問一些不同的東西。請仔細閱讀這個問題。 – 2012-08-16 11:53:18

+0

嗨米歇爾,你能解決上述問題嗎?我正在使用請求範圍來執行CRUD。你得到同樣的錯誤。 – Unknown 2014-11-04 05:15:18

回答

0

最後我找到了一種方法:數據將會在一個很長的範圍內,簡而言之就是bean。

請注意,這僅僅是一個概念證明,而不是真正的用例。而且要注意,與@RequestScope豆處理PrimeFaces lazy DataTable model scope

@ManagedBean 
public class TestBean 
{ 
    @EJB 
    private PersistenceService service; 

    @ManagedProperty("#{viewScope.item}") 
    private Item item; 

    @ManagedProperty("#{sessionScope.model}") 
    private EntityDataModel<Item> model; 

    @PostConstruct 
    public void init() 
    { 
     if(model == null) 
     { 
      model = new EntityDataModel<Item>(Item.class); 
      Faces.setSessionAttribute("model", model); 
     } 
    } 

    public String update() 
    { 
     Faces.getFlash().setKeepMessages(true); 

     try 
     { 
      item = service.update(item); 
      Faces.setViewAttribute("item", item); 

      JsfUtils.addSuccessMessage("updated"); 

      return "view?faces-redirect=true&includeViewParams=true"; 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
      JsfUtils.addErrorMessage(e); 
     } 

     return null; 
    } 

    // getters and setters, other actions, ... 
} 

list.xhtml時,

<p:dataTable value="#{testBean.model}" var="elem" ...> 
    ... 

    <p:column exportable="false" toggleable="false" headerText="#{bundle.actions}"> 

     <!-- two techniques available for navigation --> 

     <p:button outcome="view?id=#{elem.converterString}" icon="#{icons.view}" /> 

     <p:commandButton rendered="#{user.isEditAllowed(elem)}" 
      action="edit?faces-redirect=true&amp;includeViewParams=true" process="@form" 
      icon="#{icons.edit}"> 
      <f:param name="id" value="#{elem.converterString}" /> 
     </p:commandButton> 
    </p:column> 
</p:dataTable> 

view.xhtml

<f:metadata> 
    <o:viewParam id="itemId" name="id" value="#{viewScope.item}" required="true" 
     converter="entityConverter" /> 
</f:metadata> 

<ui:composition template="/WEB-INF/templates/template.xhtml"> 
    <ui:define name="content"> 
     <p:panelGrid columns="2"> 
      <h:outputLabel value="#{bundle.name}" /> 
      <h:outputText value="#{item.name}" /> 

      ... 
     </p:panelGrid> 

     <p:button outcome="list" value="#{bundle.list}" icon="#{icons.list}" /> 

     <p:button rendered="#{user.isEditAllowed(item)}" 
      outcome="edit?id=#{item.converterString}" value="#{bundle.edit}" 
      icon="#{icons.edit}" /> 
    </ui:define> 
</ui:composition> 

edit.xhtml

<f:metadata> 
    <o:viewParam id="itemId" name="id" value="#{viewScope.item}" required="true" 
     converter="entityConverter" /> 
</f:metadata> 

<ui:composition template="/WEB-INF/templates/template.xhtml"> 
    <ui:define name="content"> 
     <p:panelGrid columns="2"> 
      <h:outputLabel value="#{bundle.name}" /> 
      <h:panelGroup> 
       <p:inputText id="name" value="#{item.name}" /> 
       <p:message for="name" /> 
      </h:panelGroup> 

      ... 
     </p:panelGrid> 

     <p:commandButton process="@form" update="@form" action="#{testBean.update}" 
      value="#{bundle.update}" icon="#{icons.update}" /> 

     <p:button outcome="view?id=#{item.converterString}" value="#{bundle.cancel}" 
      icon="#{icons.cancel}" /> 
    </ui:define> 
</ui:composition> 
+1

我沒有看到這在第一名。我會檢查這一點。謝謝。 – Unknown 2014-11-04 09:16:11

+0

歡迎:) – 2014-11-04 09:27:02

1

據我所知,當你的第二個請求來到testBean時,選擇對象爲null。如果你使用會話bean來運行,你可能不會得到這個錯誤。

+0

第二次,仔細閱讀我的問題。它用粗體書寫,我要「testBean」爲@RequestScoped – 2012-09-05 10:26:43

1

我看到它的方式,沒有乾淨的方式來實現你想要的。

我會建議你簡單地在請求之間傳遞一個Id attr作爲一個簡單的請求參數。因此,在你的post構造函數中,檢查參數值是否已設置,並基於此,在持久層中查看。

<h:inputText value="#{testBean.selection.code}"/> 

組件來支持bean並調用它getValue()必要時:

或者,使用您已有的設置,綁定。無論哪種方式,仍然不整潔。

如果您發現任何其他方式,請告訴我們。

+0

你是對的,它似乎是不可能實現它在一個乾淨的方式,我嘗試了我所知道的一切。你的第二個解決方案是我沒有嘗試過,有趣,但仍然太多勤奮,但值得upvote :) – 2012-08-28 08:50:50