2012-05-28 101 views
1

我正在設計一個使用標準Java EE組件的站點,如JSF 2.0,CDI,EJB和JPA。它處於早期階段,所以導航非常簡單。問題是我在導航時難以保留一些數據。請求作用域頁面導航

這裏是seminarController支持bean:

SeminarController.java

@Named 
@RequestScoped 
public class SeminarController { 
    @Inject 
    private SeminarDao seminarDao; 

    private int seminarID; 
    private Seminar seminar; 

    ... 
    // Getters and setters 
    ... 

    public Collection<Seminar> getSeminars() {...} 

    public Collection<Seminar> getUpcomingSeminars() {...} 

    public void initSeminar() { 
     seminar = seminarDao.findSeminar(seminarID); 
    } 

    public String save() { 
     seminarDao.save(seminar); 
     return "details"; 
    } 
} 

第一頁,目前剛剛上市的一些研討會,是即將到來的,可能是interrest的。

index.xhtml

<ul> 
     <ui:repeat value="#{seminarController.upcomingSeminars}" var="seminar"> 
      <li> 
       <h:link value="#{seminar.title}" outcome="details"> 
        <f:param name="id" value="#{seminar.seminarID}"/> 
       </h:link> 
       on 
       <h:outputText value="#{seminar.eventDate}"/> 
      </li> 
     </ui:repeat> 
    </ul> 

正如你可以看到我有那個會帶我到詳細信息頁面,如果我點擊鏈接的鏈接列表。我正在使用f:param將研討會的ID添加到HTTP請求參數中。

詳情頁面顯示了一些關於即將舉行的研討會的更多細節(當然)。研討會也可以通過點擊鏈接進行編輯。

details.xhtml

<f:metadata> 
    <f:viewParam name="id" value="#{seminarController.seminarID}"/> 
    <f:event type="preRenderView" listener="#{seminarController.initSeminar}"/> 
</f:metadata> 
<ui:define name="body"> 

    <h2>#{seminarController.seminar.title}</h2> 

    <p> 
     <strong>When:</strong> 
     #{seminarController.seminar.eventDate} 
    </p> 
    <p> 
     <strong>Where:</strong> 
     #{seminarController.seminar.address}, 
     #{seminarController.seminar.country} 
    </p> 
    ... 
    <p> 
     <h:link value="Edit" outcome="edit"> 
      <f:param name="id" value="#{seminarController.seminarID}"/> 
     </h:link> | 
     <h:link value="Back to List" outcome="index"/> 
    </p> 

到目前爲止好,一切工作正常。

現在我們按照鏈接編輯研討會,我們進入編輯頁面。我們仍在使用f:param作爲本次研討會的ID。

edit.xhtml

<f:metadata> 
    <f:viewParam name="id" value="#{seminarController.seminarID}"/> 
    <f:event type="preRenderView" listener="#{seminarController.initSeminar}"/> 
</f:metadata> 
<ui:define name="body"> 
    <h:form> 
     <h:messages title="Please correct the errors and try again."/> 
     <fieldset> 
      <h:panelGroup class="editor-label" layout="block"> 
       <h:outputLabel value="Seminar Title:" for="title"/> 
      </h:panelGroup> 
      <h:panelGroup class="editor-field" layout="block"> 
       <h:inputText id="title" value="#{seminarController.seminar.title}"/> 
       <h:message for="title" title="*"/> 
      </h:panelGroup> 
      ... 
      <p> 
       <h:commandButton value="Save" action="#{seminarController.save}"> 
        <f:param id="id" value="#{seminarController.seminar.seminarID}"/> 
       </h:commandButton> 
      </p> 
     </fieldset> 
    </h:form> 

這是我開始有問題。當按下保存按鈕時,我想回到詳細信息頁面。詳細信息頁面應顯示當前研討會的最新更新細節。問題是當按下Save按鈕時,seminarController中的seminar對象是null

當編輯視圖呈現時,研討會對象被初始化並用於顯示錶單中的當前值。但是當按下保存按鈕時,研討會對象不再存在於seminarController中。而且initSeminar方法也不被調用。

所以問題是我應該如何設計設計 - 編輯 - 設計頁面導航?

由於我在按下保存時導航到新視圖,ViewScope無法正常工作。無論如何使用CDI時ViewScope不存在。

任何幫助將不勝感激!


編輯

研討會類有某些字段不會在表格中可以看出。

Seminar.java

@Entity 
public class Seminar { 
    @Id 
    private int seminarID; 
    @Column 
    private String title; 
    @Column 
    private Date eventDate; // Date when the seminar occurs 
    @Column 
    private Date createdDate; // Not visible in forms 
    ... 
    // Some more fields and Getters/Setters 
} 

EDIT2:

我結束了在SeminarController這樣做:

SeminarController.java

@PostConstruct 
public void init() { 
    if (FacesContext.getCurrentInstance().isPostback()) { 
     seminar = new Seminar(); 
    } else { 
     seminar = seminarDao.findSeminar(seminarID); 
    } 
} 

public void setSeminarID(int seminarID) { 
    if (this.seminarID != seminarID) { 
     seminar = seminarDao.findSeminar(seminarID); 
     this.seminarID = seminarID; 
    } 
} 

public String save() { 
    seminarDao.save(seminar); 
    return "details?faces-redirect=true&includeViewParams=true"; 
} 

然後我將<h:inputHidden value="#{seminarController.seminarID}"/>添加到edit.xhtml

<f:event/>details.xhtmledit.xhtml相應改變調用init()方法,而不是舊initSeminar()

這似乎工作,雖然我不太喜歡seminar對象是使用new在回發中創建的,然後當seminarID被設置時它被覆蓋。

回答

2

在更新模型值階段發生之前,您需要自己準備seminar。預渲染視圖事件太晚了。

的方法之一是創建一個@PostConstruct其中你檢查當前請求是回發,如果是的話precrate的Seminar使JSF具有值階段更新模型時調用其制定者的機會。

@PostConstruct 
public void init() { 
    if (FacesContext.getCurrentInstance().isPostback()) { 
     seminar = new Seminar(); 
    } 
} 

我不知道什麼initSeminar()做,但我想你也需要相應地改變它的是它的工作只if (!FacesContext.getCurrentInstance().isPostback())

+0

好的,我明白了你的觀點。當我從'detail.xhtml'轉到'edit.xhtml'時,'seminar'將使用我的'initSeminar'創建,它使用'seminarID'和DAO實例化'seminar'。當我從'edit.xhtml'返回'details.xhtml'時,我在你建議的'init'方法中創建'seminar'。我會嘗試一下,然後再回來。謝謝! – maba

+0

此解決方案的問題是當我按下保存時,研討會對象不包含來自從數據庫加載的原始研討會的所有信息。我需要研討會ID,以便我可以從數據庫中查找研討會並更改值並保存回數據庫。那有意義嗎? – maba

+0

使用''。 – BalusC