- - PR -
JSFでactionListenerが勝手に動作してしまう現象について
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-01-25 11:09
初投稿です。初心者ですがよろしくお願いします。
卒業研究のためにJSFでオークションサイトをつくっているんですが、手に負えないバグが出てしまったので、どうかお力をお貸しください。 commodityList.jsp //商品一覧を表示する <h:inputText id="key" value="#{searchBean.key}"/> <h:commandButton id="search" value="検索" action="#{searchBean.search}"/> <h:dataTable value="#{searchBean.result}" var="result"> <h:column> <f:facet name="header"> <h:outputText value="商品名"/> </f:facet> <h:commandLink id="name" value="#{result.name}" actionListener="#{searchDetailsBean.detectId}" action="commodityDetails"> <f:param name="id" value="#{result.id}"/> </h:commandLink> </h:column> </h:dataTable> commodityDetails.jsp //商品詳細を表示する SearchBean.java //一覧検索するクラス public String search() { // 一覧検索処理 return "commodityList"; } SearchDetails //詳細検索するクラス // 商品一覧のどのリンクがクリックされたかを受け取る public void detectId(ActionEvent e) { UIComponent comp = e.getComponent(); List childList = new ArrayList(); childList = comp.getChildren(); for (int i = 0, leng = childList.size(); i < leng; i++) { UIComponent childComp = (UIComponent)childList.get(i); if (childComp instanceof UIParameter) { UIParameter param = (UIParameter)childComp; FacesContext facesContext = FacesContext.getCurrentInstance(); Map map = facesContext.getExternalContext().getRequestMap(); String key = param.getValue().toString(); searchDetails(key); } } } public void searchDetails(String key) { // 詳細検索処理 } このようなプログラムを作ったのですが、商品一覧から商品詳細画面にを遷移後ブラウザの戻るを押して商品一覧画面から再検索を行うとsearchメソッドの実行後にdetectIdメソッドが呼ばれてしまい詳細画面に遷移してしまいます。 本来はsearchメソッドのみを実行し商品一覧画面を表示したいのですが、うまくいきません。 原因が分かる方がいらっしゃいましたら、ぜひご教授お願いします。 | ||||||||
|
投稿日時: 2008-01-26 19:06
actionとactionListenerの両方があるって、どーゆーこと?
| ||||||||
|
投稿日時: 2008-01-26 19:38
actionListnerを登録しているので、アクションが発生した後にdetectIdが発生しているのは正しい気がしますね。
なんか作り方間違ってますね。 DataTableのcommandイベント発生行に対応するBeanはこの場合JavaでEL式「#{result}」を解決するととれます。わざわざコンポーネントツリーを見なくてもいいですよ。 JSFでコンポーネントツリーをいちいち見ないといけないような状況にはほとんどならないと思います。 | ||||||||
|
投稿日時: 2008-01-26 23:32
JSFではブラウザの戻るボタンを使った場合の挙動は制御しにくいです。
HttpSessionに入ったBacking Beanの状態に依存しないアクションの場合は、 STATE_SAVING_METHODをclientにすると動くかもしれないです。
私はよくこの設計をします。 actionはリクエスト結果の遷移先の確定のみを行い、 actionListenerで実際の処理を行うように分担します。 この場合、actionListenerでは引数のActionEvent経由で <f:param>のパラメータでオブジェクトの受け渡しができるので、 Backing Beanの状態に依存しないアクションが実装しやすくなります。 別機能からのアクションの再利用などにも便利ですよ。 | ||||||||
|
投稿日時: 2008-01-27 12:02
ご回答ありがとうございます
コンポーネントツリーの値が維持されているため、detectIdも実行されてしまうということでしょうか?そしてコンポーネントツリーの値を復元しないためにjavaのEL式を使うという事でよろしいでしょうか?
戻るボタンを使った時は制御しづらいのですか。STATE_SAVING_METHODですがclientで設定されていました。 | ||||||||
|
投稿日時: 2008-01-28 11:41
あと、このへんは試してみましたか?
<% response.setHeader("Cache-Control", "no-cache"); %> <% response.addHeader("Cache-Control", "no-store"); %> <% response.setHeader("Expires", "-1"); %> <% response.setHeader("Pragma", "no-cache"); %> | ||||||||
|
投稿日時: 2008-01-28 15:29
動作確認してみました。 自機からのアクセスでは詳細ページから一覧ページに戻った時に有効期限切れが表示され、情報を再送信することによりバグ?は回避できました。 ですが他PCからアクセスしたところ有効期限切れが表示されずに一覧ページにに直接戻ってしまい、検索ボタンなどを押すとエラーになってしまいました。 |
1