1. ホーム
  2. jsf

[解決済み] commandButton/commandLink/ajax アクション/リスナーメソッドが呼び出されないか、入力値が設定/更新されない。

2022-03-15 17:31:06

質問

を使用すると、時々 <h:commandLink> , <h:commandButton> または <f:ajax> を指定します。 action , actionListener または listener タグに関連付けられたメソッドが呼び出されていないだけです。あるいは、ビーンプロパティは、提出された UIInput の値を指定します。

この場合、どのような原因や解決策が考えられるでしょうか。

解決方法は?

はじめに

を使用する場合は、必ず UICommand コンポーネント( <h:commandXxx> , <p:commandXxx> など) が関連するアクションメソッドを呼び出すことができないか、あるいは UIInput コンポーネント( <h:inputXxx> , <p:inputXxxx> など) が送信された値の処理やモデルの値の更新に失敗し、サーバーログに googlable 例外や警告が表示されない場合、また JSFのajaxリクエストにおける例外処理 のコンテキストパラメータを以下のように設定した場合、また web.xml ,

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>

また、ブラウザの JavaScript コンソールで googlable エラーや警告が表示されていないこと (Chrome/Firefox23+/IE9+ で F12 キーを押してウェブ開発者ツールセットを開き、[Ctrl] キーを押しながら コンソール タブをクリックし、以下の可能性のある原因を確認してください。

考えられる原因

  1. UICommandUIInput コンポーネントは UIForm コンポーネントで、例えば <h:form> (したがって、プレーンなHTMLではなく <form> を使用しないと、サーバーに何も送ることができません。 UICommand コンポーネントもまた type="button" そうでない場合は、JavaScript の onclick . 以下もご参照ください。 JSF Beanでフォーム入力値を送信し、メソッドを呼び出す方法 <h:commandButton> でポストバックが開始されません。 .

  2. を複数ネストすることはできません。 UIForm コンポーネントの中に入っています。これは HTML では違法です。ブラウザの動作は未定です。インクルードファイルの扱いに注意 インクルードファイルで UIForm コンポーネントを並列に並べることができますが、送信時に互いに処理し合うことはありません。また、quot;God Form" のアンチパターンに注意する必要があります。意図せずして、まったく同じフォームで他のすべての (目に見えない) 入力が処理/検証されないようにしましょう (たとえば、まったく同じフォームに必須入力を持つ隠しダイアログが存在する場合など)。以下も参照してください。 JSFのページで<h:form>を使用するにはどうすればよいですか?単一フォーム?複数のフォーム?ネストされたフォーム? .

  3. いいえ UIInput 値の検証/変換エラーが発生したはずです。あなたは <h:messages> で表示されないメッセージを表示するには、入力に特化した <h:message> コンポーネントを使用します。を含めることを忘れないでください。 id<h:messages> の中に <f:ajax render> があれば、ajaxリクエストの際に同様に更新されるようにします。また p:commandButtonが押されてもh:messagesはメッセージを表示しない .

  4. もし UICommand または UIInput のような繰り返しコンポーネントの中に置かれます。 <h:dataTable> , <ui:repeat> などの場合、まったく同じ value は、フォーム送信リクエストのリクエスト値適用フェーズで保存されます。JSFは、クリックされたリンク/ボタンと送信された入力値を見つけるために、その上で繰り返し処理を行います。ビュースコープにビーンを置くこと、および/または、データモデルを @PostConstruct この問題を解決するには、Bean のゲッターメソッドではなく、Bean を作成する必要があります。以下も参照してください。 h:dataTableのモデルをいつ、どのようにデータベースからロードすればよいですか? .

  5. もし UICommand または UIInput のような動的なソースによってコンポーネントが含まれます。 <ui:include src="#{bean.include}"> を使用する場合、まったく同じ #{bean.include} の値は、フォーム送信リクエストのビュー構築時に保存されます。JSFはコンポーネントツリーを構築する際に、この値を再実行します。ビュースコープにビーンを置くこと、および/または、データモデルを @PostConstruct この問題は、Bean の (つまりゲッターメソッドではない) 部分を修正する必要があります。以下もご参照ください。 ナビゲーションメニューの動的インクルードコンテンツをajax-refreshする方法は?(JSF SPA) .

  6. rendered 属性と、そのすべての親コンポーネントの test 属性は、任意の親 <c:if> / <c:when> とは評価されないはずです。 false は、フォーム送信リクエストのリクエスト値の適用フェーズにおいて JSFは、改ざんやハッキングされたリクエストに対する安全策の一環として、これを再チェックします。この条件に対応する変数を @ViewScoped ビーンに、あるいは @PostConstruct@RequestScoped ビーンで修正する必要があります。同じことが disabledreadonly と評価されるべきではありません。 true リクエストの値を適用するフェーズで また JSF CommandButtonアクションが呼び出されない , 条件付きレンダリングコンポーネントのフォーム送信は処理されない , h:commandButton を <h:panelGroup rendered> で囲むと、動作しなくなりました。 そして 読み取り専用/無効の入力コンポーネントをとにかくJSFに強制的に処理、検証、更新させる

  7. onclick 属性があります。 UICommand コンポーネントと onsubmit 属性は UIForm コンポーネントは false またはJavaScriptのエラーを発生させる。の場合は <h:commandLink> または <f:ajax> は、ブラウザのJSコンソールに表示されるJSエラーはありません。通常、正確なエラーメッセージをググれば、すでに答えが見つかります。以下もご参照ください。 PrimeFacesでjQueryを手動で追加/ロードすると、Uncaught TypeErrorsが発生する .

  8. JSF 2.x経由でAjaxを使用する場合 <f:ajax> またはPrimeFacesなど <p:commandXxx> を使用する場合は、必ず <h:head> の代わりにマスターテンプレートで <head> . そうしないと、JSFはAjax関数を含む必要なJavaScriptファイルを自動でインクルードすることができません。その結果、ブラウザのJSコンソールに "mojarra is not defined" または "PrimeFaces is not defined" といったJavaScriptエラーが表示されます。以下も参照してください。 h:commandLink actionlistener は、f:ajax と ui:repeat と一緒に使用すると呼び出されません。 .

  9. Ajaxを使用していて、送信された値が最終的に null を指定した場合、その UIInputUICommand のコンポーネントが対象となります。 <f:ajax execute> または、例えば <p:commandXxx process> そうでない場合は、実行/処理されません。以下もご参照ください。 h:commandButton> に <f:ajax> を追加しても、投稿されたフォームの値がモデルに反映されないのですが。 PrimeFacesのprocess/update属性とJSFのf:ajax execute/render属性を理解する。 .

  10. もし、送信された値がまだ null CDI を使用して Bean を管理している場合は、 適切なパッケージからスコープアノテーションをインポートするようにしてください。 @Dependent これは、EL式の評価ごとに効果的にBeanを再作成するものです。また SessionScoped Beanはスコープを失い、常に再作成され、フィールドはNULLになります。 そして JSF 2アプリケーションのデフォルトのマネージド・ビーン・スコープとは何ですか?

  11. の親がいる場合、その親は <h:form> と共に UICommand ボタンが、同じページ内の別のフォームから来るajaxリクエストによって事前にレンダリング/更新されている場合、最初のアクションはJSF 2.2またはそれ以前では常に失敗します。2番目以降のアクションは動作します。これはビューの状態処理のバグによるもので、次のように報告されています。 JSF仕様の問題点 790 で、現在JSF2.3で修正されています。古いバージョンのJSFの場合、明示的に <h:form> での render<f:ajax> . 以下もご参照ください。 h:commandButton/h:commandLink は最初のクリックでは動作せず、2回目のクリックで動作します。 .

  12. もし <h:form> があります。 enctype="multipart/form-data" が設定されている場合、少なくとも JSF 2.2 を使用しているか、 multipart/form-data リクエストの解析を担当するサーブレットフィルタが適切に設定されていることを確認する必要があります。 FacesServlet は、結局リクエストパラメータをまったく受け取らないので、 リクエストの値を適用することができません。このようなフィルタをどのように設定するかは、使用するファイルアップロードコンポーネントに依存します。Tomahawk の場合 <t:inputFileUpload> , チェック この回答 とPrimeFacesの場合 <p:fileUpload> を確認します。 この回答 . または、実際にファイルをアップロードしないのであれば、この属性を完全に削除してください。

  13. を確認します。 ActionEvent の引数は actionListenerjavax.faces.event.ActionEvent であるため java.awt.event.ActionEvent これは、ほとんどのIDEが1番目のオートコンプリートオプションとして提案しているものです。引数がないのも間違いです。 actionListener="#{bean.method}" . もし、メソッドに引数を与えたくない場合は actionListener="#{bean.method()}" . あるいは、実際に使用したいのは action の代わりに actionListener . 以下もご参照ください。 actionとactionListenerの違い .

  14. がないことを確認してください。 PhaseListener または任意の EventListener を呼び出すことで、JSF のライフサイクルを変更し、アクションを呼び出すフェーズをスキップするようにしました。 FacesContext#renderResponse() または FacesContext#responseComplete() .

  15. がないことを確認してください。 Filter または Servlet が同じリクエストレスポンスチェーンにあるリクエストをブロックしています。 FacesServlet を何とかしてください。例えば、Spring Securityのようなログイン/セキュリティフィルタ。特に、デフォルトではUIフィードバックが全くないまま終わってしまうようなajaxリクエストの場合。以下も参照してください。 Spring Security 4とPrimeFaces 5のAJAXリクエストの扱いについて .

  16. もし、PrimeFacesの <p:dialog> または <p:overlayPanel> を使用する場合は、それらに独自の <h:form> . なぜなら、これらのコンポーネントはJavaScriptによってデフォルトでHTMLの末尾に再配置されるからです。 <body> . そのため、もしそれらが元々 <form> にはもう座らないでしょう。 <form> . 参照 p:commandbuttonアクションはp:dialogの内部では動作しません。

  17. フレームワークのバグ。例えば、RichFacesでは、" 変換エラー を使用した場合 rich:calendar UI要素に defaultLabel 属性(場合によっては rich:placeholder のサブ要素)。このバグにより、カレンダーの日付に値が設定されていない場合、ビーンメソッドが呼び出されなくなります。フレームワークのバグを追跡するには、単純な動作例から始めて、バグが発見されるまでページを構築し直すとよいでしょう。

デバッグのヒント

それでも動かない場合は、デバッグの出番です。クライアント側で、ウェブブラウザで F12 キーを押して、ウェブ開発者ツールセットを開きます。以下の項目をクリックします。 コンソール タブをクリックし、JavaScriptのコンソールを確認します。JavaScriptのエラーはないはずです。以下のスクリーンショットは、Chromeの例です。 <f:ajax> 有効なボタンでありながら <h:head> が宣言されています(上記7で説明したとおりです)。

をクリックします。 ネットワーク タブをクリックすると、HTTPトラフィックモニタが表示されます。フォームを送信し、リクエストヘッダ、フォームデータ、レスポンスボディが期待通りであるかどうかを調査します。以下のスクリーンショットは、Chrome の例です。 <h:inputText> と、1つの <h:commandButton><f:ajax execute="@form" render="@form"> .

(警告: 本番環境から上記のような HTTP リクエストヘッダのスクリーンショットを投稿する場合は、セッションハイジャック攻撃を避けるために、スクリーンショット内のセッションクッキーをスクランブル/難読化することを確認してください!)

サーバー側では、サーバーがデバッグモードで起動されていることを確認します。フォーム送信の処理中に呼び出されることが予想される、対象のJSFコンポーネントのメソッドにデバッグブレークポイントを設定します。例えば UICommand コンポーネントの場合、次のようになります。 UICommand#queueEvent() の場合は UIInput コンポーネントは、次のようになります。 UIInput#validate() . コード実行のステップを踏んで、フローと変数が期待通りかどうかを検査するだけです。下のスクリーンショットは、Eclipseのデバッガーによる例です。