7

としてマークされ、サーバー側required="true"でカスタムを持つ入力テキスト コンポーネントを含むページがあります。Validator

ここでクライアントとして、そのコンポーネントによってレンダリングされた HTML 要素なしでページを送信します (これは、ブラウザーの組み込み DOM 要素インスペクターを使用して DOM ツリーから要素を削除することで簡単に実現できます)。この必須コンポーネントのサーバー側検証なしで、フォームは正常に送信されます。

これは JSF 仕様に従っていますか? 投稿されたページにバリデーターが含まれていなくても、ページ内のバリデーターが実行されるように指定する方法はありますか?

4

1 に答える 1

7

これは確かに仕様どおりです。UIInput#validate()これは、 javadocからの関連性の抜粋です(強調は私のものです)。

で送信された値を取得しますgetSubmittedValue()。これが を返しnullALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUEcontext-param の値が true (大文字と小文字を区別しない) の場合、"required" プロパティの値を調べます。「required」の値が true の場合は、以下に進みます。"required" の値が false であるか、required 属性が設定されていない場合は、それ以上処理せずに終了します。context-param が設定されていないか、false に設定されている場合 (大文字と小文字を区別しない)、それ以上処理せずに終了します。(これは、このコンポーネントの値が送信されなかったことを示します。)

空の入力は、ではなく空の文字列を送信しますnull。入力が完全に存在しない場合は、null空の文字列ではなく が送信されます。

したがって、次のコンテキスト パラメータを追加することで、観察された動作を無効にすることができます。

<context-param>
    <param-name>javax.faces.ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE</param-name>
    <param-value>true</param-value>
</context-param>

このコンテキスト パラメータは JSF 2.3 以降で新しく、Mojarra 2.2.16、2.1.29-10、および 1.2_15-06 にバックポートされていることに注意してください。古いバージョンではサポートされていません。JSFSPEC-1433およびこの問題に関する専門家グループの議論も参照してください。

それが有害かどうかは、ビジネス ロジックに依存します。null適切に設計されたモデル (ビジネス ロジックおよび/またはデータ モデル) が想定どおりに考慮されていないと、別の場所でヌル ポインター例外が発生するか、SQL 制約違反 ( NOT NULL) が発生し、通常は HTTP 500 エラー レスポンスで終了します。しかし、モデルが実際にnull想定されたケースと見なす場合、それはモデルの障害である可能性があります。ビュー (JSF ページ) は、単にモデルを提示することを目的としており、モデルに対してほとんど何もできません。

ビジネス ロジックまたはデータ モデルを変更して例外的なケースと見なすことが実際には不可能でありnull(つまり、指定された値を として想定/受け入れないnull)、たまたま JPA を使用している場合、最善の策@NotNullはプロパティに を追加することです。JSF は検証をバイパスしますが、JPA は引き続き検証を行うため、依然として例外と HTTP 500 エラーが発生します。NOT NULLこの場合、そもそも DB 列に制約がないのはなぜだろうと思います。または、クラス レベルの検証を行います。

MyFaces はこれについて以下のような警告を記録することに注意してください。

2016 年 3 月 16 日 8:55:52 AM org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils decodeUIInput
警告: 入力がレンダリングされ、そのフォームが送信された場合、入力に対して送信された値が常に存在する必要があります。もともと無効または読み取り専用にレンダリングされていました。JavaScript で入力要素を無効にすると、フォームを送信できません。フォームを送信する前に、代わりに読み取り専用を true に設定するか、無効な値を false にリセットすることを検討してください。
Component : {Component-Path : [Class: javax.faces.component.UIViewRoot,ViewId: /test.xhtml][Class: javax.faces.component.html.HtmlBody,Id: j_id_5][Class: javax.faces.component] .html.HtmlForm,Id: j_id_6][クラス: javax.faces.component.html.HtmlInputText,Id: j_id_7] 場所: /test.xhtml 22 行目 33 列目}

于 2015-08-24T10:39:00.473 に答える