2

私はこのようなページをたくさん書くプロジェクトにいるので、最も効率的な (書く) コーディング パターンを使用したいと考えています。

背景: 以前は CODI の @ViewAccessScoped を使用してリクエスト間で状態を保持していましたが、最近ではフラッシュ スコープ オブジェクトを使用して状態を保存するようになりました。私は CDI を使用しており、うまく連携できないため、JSF @ViewScoped を使用できません。したがって、@RequestScoped バッキング Bean のみでこれを実行できるかどうかを確認したいと思います。

このページは次のように設計されています (p 名前空間は Primefaces です)。

            <f:metadata>
                <f:viewParam name="ID" value="#{backing.id}" />
            </f:metadata>

                ....

            <h1>Edit Object Page</h1>

            <h:form id="formObj" rendered="#{backing.accessOK}">

                <p:panelGrid columns="2">

                    <h:outputLabel value="Field #1:"/>
                    <p:inputText value="#{backing.record.field1}" />

                          (more input fields)

                    <h:outputLabel value="Action:" />
                    <h:panelGroup>
                        <p:commandButton value="Save"
                                         action="#{backing.save}"
                                         />
                        <p:commandButton value="Cancel" action="backing.cancel" />
                    </h:panelGroup>

                </p:panelGrid>
                <p:messages showDetail="true" showSummary="true" />

            </h:form>

ページが要求された場合、メソッドaccessOK()にはh:formがレンダリングされないようにする機能があります。代わりに、p:messagesは、 accessOK()メソッドが設定するFacesMessage (s)とともに表示されます。

Beanバッキングのパターンは次のようになります。

@Named
@RequestScoped
public class Backing {

    private long id;
    private SomeJPAEntity record;
    private Boolean accessOK;

    public long getId() { return id; }

    public void setId(long value) { id = value; }

    public boolean accessOK() {
        if (accessOK != null) return accessOK;

        if (getRecord() == null) {
             // add a FacesMessage that explains the record
             // does not exist
             return accessOK = false;  // note single =
        }

        // do any other access checks, such as write permissions

        return accessOK = true;
    }

    public SomeJPAEntity getRecord() {
        if (record != null) return record;

        if (getId() > 0) record = // get the record from DB
        else record = new SomeJPAEntity();

        return record;
    }

    public String execute() {

         if (!accessOK()) return null;   // bad edit

         // do other integrity checks here.  If fail, set FacesMessages
         // and return null;

         if (getId() > 0) // merge the record back into the data base
         else  // persist the record

    }

}

このモデルの問題点は次のとおりです。[保存] ボタンをクリックすると、Backingの新しいインスタンスが作成され、setID ()セッターが呼び出される前にgetRecord()ゲッターが多数呼び出されます。したがって、getRecord()のロジックは、呼び出されたときにidプロパティが有効であることに依存できないため、壊れます。

これが@ViewAccessScoped (またはViewScoped ) バッキング Bean であった場合、フォームが commandButton で処理されるときに、id プロパティと record プロパティの両方既に設定れています。または、これらのプロパティをフラッシュ ストレージに保存することもできますが、それには回避したい独自の問題があります。

このプログラミング モデルを仕様内で動作させる方法はありますか?

アップデート:

経験的に、フラッシュまたはビュースコープのバリアントに頼らずにこれを機能させる回避策があります。上記のように、フォームが処理されるとき、setId()への最初の呼び出しの前にgetRecord() への呼び出しがいくつかあります。そして最後にsave()メソッドが呼び出されます。

私がしていることは、次のようにsetId()を変更することです:

public void setId(long value) {
  id = value;
  record = null;
}

これにより、getRecord()がプロパティrecordを再計算 (フェッチ/ビルド) し、その後の呼び出しが機能します。特に、save()メソッドは、レコードエンティティの内容を含めて適切に初期化されたオブジェクトと共に入力されます。getRecord()への以前のすべての呼び出しが何のためにあったのかわかりません。

この時点で、信頼できるかどうかもわかりませんが、 getId()が設定された後、レコードエンティティに書き込まれたすべての値がUIinputコンポーネントから転送されるかどうかです。もしそうなら、私はこのパターンを使用することができます。これは仕様によって制御されていますか、それとも運だけで機能していますか?

コメントや提案はありますか?

4

2 に答える 2

2

CODI (というか、新進気鋭の DeltaSpike) を使用すると安心できると思います。Tomcat では両方をうまく使用しています。そして、彼らは実質的にすべてをサポートします。

Deltaspike は現在 JSF モジュールに取り組んでおり、多くの活動が行われています。その開発が完了すると、あなたはそれに慣れることができると確信しています。プロジェクトはまだ準備中ですが、deltaspike の各モジュールは個別に本番環境に対応しています。

あなたの実際の問題については、あなたからまだ提案されていないものを思いつくことができませんでした。

しかし、これは、バインディングを気にする可能性のあるケースの1つでしょf:viewParamうか? バインディングはほとんど使ったことがないのでわかりません。

于 2012-10-08T20:35:34.387 に答える
1

CODI と DeltaSpike は、CDI の @ViewScoped を有効にします。JSF < 2.2 の Flash-Scope は、複数のウィンドウで完全に壊れています。CODI から離れる唯一の理由は、DeltaSpike への移行であり、準備が整うまで両方を並行して使用できます。

于 2012-10-09T22:17:29.147 に答える