S_a_k_Uの日記みたいなDB

~サクゥーと呼ばないで~

ファイルダウンロード後のAjaxリクエストが処理されない

MyFaces 1.2.4
Trinidad 1.2.9
RichFaces 3.2.2
ひさびさにソースを追っかけ回った。


事象はこんな感じ。
1)ファイルダウンロードのボタンを押す。
2)ファイルがダウンロードされる。
3)同じページのAjaxリクエストのボタンを押す。
4)書き換わるハズの値が書き換わらない。


【原因】

MyFacesのイベントでは、ボタン等のイベントが発生した時点で、JavaScriptでUIコンポーネントのIDを、"source"というhidden属性にセットしている。
それをServlet側で受け取り、どのボタンが押されたかを判定して(HtmlCommandButtonRenderer#decode)、アクションの処理を実行している。
通常の遷移では、MyFacesのイベントが実行されれば、再描画時に"source"というhidden属性は空になる。
しかし、ダウンロードのイベントでは、画面が再描画されないため、"source"というhidden属性にダウンロードのイベントを実行したUIコンポーネントのIDが残っている。
その状態でAjaxのリクエストを送信した場合、Servlet側のMyFacesレベルでは、再度ダウンロードボタンが押されたものと判定して、その処理を行ってしまう。
Ajax4jsfでは、独自にAjax4jsfのリクエストを解釈して処理している。
そのため2つのアクション(ファイルダウンロードとAjaxリクエストのアクション)が実行される。
ファイルダウンロードのアクションで、通常のHTTPレスポンスを返えそうとしているため、ブラウザ側はAjaxのレスポンスとして解釈できないため、何事もなかったように何もしない。


【対応策】

onclick="this.form.source.value='';" />

みたいな感じで、"source"というhidden属性をクリアしてからAjaxのリクエストを投げてもらう。
でも、全部のa4jタグに入れるのは…ってことで、Ajax4jsfのリクエストはA4J.AJAX.Submitというメソッドから行ってるので、
richfaces-impl-3.2.2.GA.jarファイルの
org.ajax4jsf.javascript.scriptsパッケージの
AJAX.jsファイル
にそのメソッドがあるので、それをオーバーライドして、その先頭で
this.form.source.value='';
を実行するのが現実的。


ページの更新(F5)での再送信で問題ないのなら、MyFaces側で対処する方がいいのかな???
MyFacesのリクエストはsubmitFormというメソッドから行ってるので、
trinidad-impl-1.2.9.jarファイルの
META-INF/adf/jsLibsフォルダの
Core.jsファイル
にそのメソッドがあるので、それをオーバーライドして、その最後で?a0.submit()ってステートメントの後で?
this.form.source.value='';
を実行するってのでもOK?


ちなみに、h:commandButtonタグでしか動作を確認してないけど、h:commandLinkタグでも"source"というhidden属性にIDをセットしてるので、同じ動作となることが予想される。