1

JSF 2.0、CDI、EJB、JPAなどの標準のJavaEEコンポーネントを使用してサイトを設計しています。初期段階なので、ナビゲーションは非常に簡単です。問題は、ナビゲートするときに一部のデータを保持するのが難しいことです。

これが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";
    }
}

最初のページは現在、間もなく開催される可能性のあるいくつかのセミナーを一覧表示しています。

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>

これは私が問題を抱え始めているところです。保存ボタンを押したら詳細ページに戻りたい。詳細ページには、新しく更新された詳細とともに現在のセミナーが表示されます。問題は、[保存]ボタンが押されたときに、のseminarオブジェクトがであるということseminarControllerです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.xhtmlた。edit.xhtmlinit()initSeminar()

seminarこれはうまくいくようですが、オブジェクトがポストバックで使用newして作成され、設定時に上書きされるのはあまり好きではありませんseminarID

4

1 に答える 1

2

seminarモデル値の更新フェーズを実行する前に、自分で準備する必要があります。プリレンダービューイベントは遅すぎます。

方法の1つは、現在のリクエストがポストバックであるかどうかを確認し、ポストバックである場合は、モデル値の更新フェーズ中にJSFがセッターを呼び出す機会があるよう@PostConstructにprecrateするを作成することです。Seminar

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

何をするのかわかりませんinitSeminar()が、それに応じて変更する必要があると思いますif (!FacesContext.getCurrentInstance().isPostback())

于 2012-05-28T12:11:59.290 に答える