22

最近、いくつかの JSF アプリケーションを開発していますが、Web コンポーネント API の不整合に悩まされています。

サーバー側コードの JSF コンポーネント オブジェクトで .getValue() または .getSubmittedValue() を呼び出すと、非常に予測できない動作が発生することに気付きました。ドロップダウン リスト ボックスで .getValue() を呼び出すと、値を選択する前の値 (つまり、最後のページの更新からの値) を取得していることに気付きました。私は正しい値を次のように:

UIInput name = new UIInput(); // This is the control I have in a bean.

public void submit(ActionEvent ae)
{
    someMethod(name.getValue().toString());          // Retrieves the "old" value
    someMethod(name.getSubmittedValue().toString()); // Retrieves the correct value 
}

また、フォーム フィールドで .getSubmittedValue() を呼び出すと、その値がコンポーネント オブジェクトでインスタンス化されていないため、null ポインター例外が発生する場合があることに気付きました。その場合、その状況で .getValue() を呼び出すと、正しい値。例:

HtmlInputText name = new HtmlInputText(); // This is the control I have in a bean.

public void submit(ActionEvent ae)
{
    someMethod(name.getValue().toString());          // Retrieves the correct value
    someMethod(name.getSubmittedValue().toString()); // Throws NullPointerException 
}

これは JSF フレームワークの単なる「癖」ですか、それとも API を完全に間違って使用しているだけです?? これら 2 つの方法についての洞察をいただければ幸いです。乾杯。

4

4 に答える 4

32

これは、Google で getValue と getSubmittedValue で検索した結果の第 1 位であるため、これらの違いは検証において (つまり、カスタム バリデータを作成する場合) 重要であることを付け加えたいと思います。

getSubmittedValue() の API ドキュメントを引用するには:

これは、デコード フェーズと検証フェーズの間、またはコンポーネントの検証が成功しなかった場合にのみ、null ではありません。変換と検証が成功すると、(変換された) 値はこのコンポーネントのローカルの「値」プロパティに格納され、送信された値は null にリセットされます。

ソース:http://myfaces.apache.org/core11/myfaces-api/apidocs/javax/faces/component/UIInput.html#getSubmittedValue()

これは、アクセスしようとしているバインディングに対して検証/変換が行われた場合は、getValue() を呼び出す必要があることを意味します。それ以外の場合は、getSubmittedValue() を呼び出して自分で解析する必要があります。これらが発生する順序は、UI に表示される順序によって決定されるようですが、保証されているとは思いません。たとえそうであっても、UI のフィールドを変更してもコードが壊れてはならないので、それを当てにするべきではありません。

isLocalValueSet() が返すものを見るだけで、検証/変換が行われたかどうかを検出できます。true が返された場合は、検証/変換が完了しているため、getValue() を呼び出す必要があります。それ以外の場合は、 getSubmittedValue() を呼び出す必要があります。これにより、ユーザーが入力した生の入力が得られ、より意味のあるものに解析する必要が生じる可能性があります。

たとえば、カレンダ オブジェクトは、getValue() が呼び出されると Date オブジェクトを返しますが、getSubmittedValue() が呼び出されると String オブジェクトを返します。検証できるように、文字列を日付に解析するのはコンバーター次第です。

JSF仕様にこれを行うメソッドがあれば素晴らしいと思いますが、そうではありません。特定の日付を他の日付よりも前にする必要があり、特定の状況でのみ必要な日付がある場合は、これを処理するためにいくつかのバリデータを作成する必要があります。そのため、問題になりやすいのです。これは、空のフィールドに対していかなる種類の検証も実行できないという事実に似ています。つまり、そのフィールドを条件付きで必須にすることはできません。検証がすべてのフィールドで実行された場合、空のフィールドも含めて、カスタム バリデーターを記述して、必須であるはずの例外がスローされた場合に例外をスローすることができます。JSF には、面倒なことがいくつかあります。それらが修正されない限り、または修正されるまで、対処する必要があります。

元の投稿の問題の詳細について言えば、ここでの違いは、ライフサイクルのどこにいるかです。このsubmitメソッドは、ボタンのアクション リスナーのように見えます。これにより、ライフ サイクルの最後に配置されます。アクションとアクション リスナーは、「アプリケーションの呼び出し」フェーズでトリガーされます。このフェーズは、レンダリング レスポンスの前ですが、検証後に行われます。JSF でプログラミングする場合は、ライフサイクルを学び、理解する必要があります。時間をかける価値があります。

于 2009-07-17T20:48:47.803 に答える
6

EditableValueHolder.getSubmittedValueに関するドキュメントを引用するには:

このコンポーネントの submitValue 値を返します。このメソッドは、このコンポーネントの encodeBegin() および/または encodeEnd() メソッド、または対応する Renderer でのみ使用する必要があります。

通常、 getValueを呼び出すことさえありません。代わりに、コンポーネントのvalue属性をモデル (おそらく Bean) にバインドする必要があります。ビジネス ロジックは、コンポーネントではなく、モデルと対話します。

送信された値が値として設定されていない場合は、何らかの検証が失敗していると思います。それに関する唯一の問題は、イベントが発生していることです。ここでの問題の2つの推測:

  • コンポーネント オブジェクトへの古い参照があります。
  • UICommandにimmediate属性を設定しました。これは、コンポーネントが不適切な状態になるフェーズでイベントが発生することを意味します。

提供された情報で確実に判断することはできません。

于 2008-11-04T00:23:34.293 に答える
0

TL;DR回答:

UIViewRoot viewRoot = context.getViewRoot();
UIInput input = (UIInput)viewRoot.findComponent(":form:inputID");

String inputValueString;

if (input.isLocalValueSet()) {
  inputValueString = (String)input.getValue(); //validated and converted already
} else {
  inputValueString = (String)input.getSubmittedValue(); //raw input
}

または少なくともそれは他の答えがそうするように言っていることです...

生の入力を変換しなければならない結果を使用.getSubmittedValue()して対処するだけです (必要に応じて、その生の入力を変換する必要がある場合)。.getValue()上記のコードであっても、この点で壊れています。それを使用すると、送信された値が遅れますが、これは受け入れられません。

于 2017-10-10T21:20:58.253 に答える