- PR -

JSF valueChangeListenerについて

投稿者投稿内容
いなふみ
常連さん
会議室デビュー日: 2005/09/14
投稿数: 20
投稿日時: 2006-01-20 15:05
JSFでシステム開発を行っています。

valueChangeListenerを使用してselectboxの変更時に
表示内容を変更しているのですが、ValueChangeEventで
バッキングビーンを取得すると他の項目(textboxなど)値が
入力した値が取得出来ません。
[scope=session]を使用していてします。

ValueChangeEvent直前のFormの情報はどのように取得すればよろしいのでしょうか?

どなたか、ご教授お願い親します。
よしだひろゆき
大ベテラン
会議室デビュー日: 2004/11/22
投稿数: 141
投稿日時: 2006-01-23 14:38
引用:

ValueChangeEventで
バッキングビーンを取得すると他の項目(textboxなど)値が
入力した値が取得出来ません。
ValueChangeEvent直前のFormの情報はどのように取得すればよろしいのでしょうか?


ValueChangeEventはデフォルトでProcess Validationsフェーズの最後に処理します.
immediate="true"を指定した場合はApply Request Valuesフェーズです.
いずれにしてもUpdate Model Valuesフェーズの前に処理するので,バッキングビーンへの
値の反映前になります.

方法はいくつかあります.

(1) イベントの対象になっているselectboxの新しい値が必要なのであれば,
ValueChangeListenerの引数に渡されたイベントからgetNewValueで取れます.

(2) 他の入力値の場合は,イベントからgetComponentで取ったコンポーネントに対して
findComponentで入力コンポーネントを探して,そこから取り出します.
findComponentの引数は":"で始まる絶対パスを指定します.
パス名が何かは<h:output value="#{param}"/>で表示して確認できます.

ValueChangeListenerがimmediate="false"でProcess Validationsフェーズで処理する
場合には,入力パラメタの変換と検証はすべて終わっていますから,見つけたコンポーネ
ントに対してgetLocalValueで値が取れます.(UIInputへのキャストを忘れずに)
immediate="true"の場合は,入力値がまだ変換されていないので
getSubmmittedValueでないと取れません.型変換も検証もされていない値なので
扱いがやっかいです.

(3) 私見ではバッキングビーンとコンポーネント構造はできるだけ独立性を持たせたいと
考えます.その場合,ValueChangeListenerのロジックはどちらの分担かが問題です.
私はバッキングビーン側の分担だと思うので(2)の方法は愉快ではありません.
バッキングビーン側の開発者はコンポーネントの構造によらないロジックに専念
すべきなので,findComponentなどのコンポーネントAPIは避けるべきだと考えます.
そうすると,やはりValueChangeListenerをUpdate Model Valuesフェーズで
処理したくなります.それはちょっとした工夫で可能です.
ValueChangeListenerを以下のようにすればできます.

public void processValueChange(ValueChangeEvent event) {
if (!event.getPhaseId().equals(PhaseId.UPDATE_MODEL_VALUES)){
  UIComponent comp = event.getComponent();
  event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES );
  comp.queueEvent(event);
} else {
// 通常の処理
}
}
いなふみ
常連さん
会議室デビュー日: 2005/09/14
投稿数: 20
投稿日時: 2006-01-23 19:39
ご回答、有難うございます。

(3)の処理を試してみましたが、結果は変更前と変わりませんでした。
ValueChangeEventでApplication.createValueBinding("key");でFormの情報を
取得していますが、ValueChangeEvent直前のFormの情報が反映されているものと
反映されていない項目が存在します。

また、再度反映されていない項目に入力し、他の項目のValueChangeEvent処理では
反映されていなかった項目が反映されたりします。

(3)の処理を行う以前にFormの情報をApplicationから取得することが間違っているのでしょうか??

度々すみませんが、ご教授お願い致します。
よしだひろゆき
大ベテラン
会議室デビュー日: 2004/11/22
投稿数: 141
投稿日時: 2006-01-24 13:27
引用:

(3)の処理を行う以前にFormの情報をApplicationから取得することが間違っているのでしょうか??


何か行き違いがある気がします.

「(3)の処理を行う以前に」と言う意味が理解しかねます.
私の説明が分かりにくかったのかもしれませんが,「 // 通常の処理 」と書いたところで
createValueBinding("key")等々の処理を実行して下さい.
この部分はif文のelse部ですから,必ずUpdate Model Valuesフェーズで実行されます.
イベントはフェーズの最後で実行されるので,バッキングビーンへの反映は
すべて終了している筈です.
いなふみ
常連さん
会議室デビュー日: 2005/09/14
投稿数: 20
投稿日時: 2006-01-24 14:55
引用:

私の説明が分かりにくかったのかもしれませんが,「 // 通常の処理 」と書いたところで
createValueBinding("key")等々の処理を実行して下さい.



申し訳ありません。誤解を招くような書き方をしてしまって・・・
よしださんのおっしゃるとおり、else部でcreateValueBinding("key")よりバッキングビーンを取得しました。
デバッグした結果、[getPhaseId()=UPDATE_MODEL_VALUES]に変更後createValueBinding("key")を実行していますが、下記のような項目がありテキストボックスに値を入力しセレクトボックスのChangeEventを実行するとaBean.noteの入力値は取得出来るがaBean.noは取得出来ませんでした。

項目により反映される、されない等の現象が発生する原因が他にあるのでしょうか??

[aBean.java]
public class aBean implements Serializable {
private String no;
private String itemNo;
private Collection items = null;
private String note;

public String getNo() {
return this.no;
}
public void setNo(String no) {
this.no = no;
}
<<以下省略>>
}

[a.jsp]
<<抜粋>>
<h:inputText id="no" value="#{aBean.no}" onfocus="this.style.imeMode='disabled';this.select()"/>
<h:selectOneMenu id="items" value="#{aBean.itemNo}">
<f:selectItems value="#{aBean.items}"/>
</h:selectOneMenu>
<h:inputText id="note" value="#{aBean.note}"/>
よしだひろゆき
大ベテラン
会議室デビュー日: 2004/11/22
投稿数: 141
投稿日時: 2006-01-25 14:53
イベントはどのフェーズであろうが必ずフェーズの最後に実行されます.
ですから,イベントの処理中で,あるコンポーネントについてはある処理が完了していて
別のコンポーネントでは完了していない,ということは考えにくいです.

ちゃんとパラメタとして来ているかどうかを確認してみてはどうでしょうか?
<h:outputText value="#{param}"/>で表示できるはずです.

ちなみに,例示されたように,同一のビーンaBeanばかり参照するのであれば,
valueChangeListenerもaBeanのメソッドにしておけば,
createValueBindingなどという姑息な手段を使わないですみます.
いなふみ
常連さん
会議室デビュー日: 2005/09/14
投稿数: 20
投稿日時: 2006-01-25 18:26
引用:

ちゃんとパラメタとして来ているかどうかを確認してみてはどうでしょうか?
<h:outputText value="#{param}"/>で表示できるはずです.


確認したところ、processActionで渡ってきているパラメタがprocessValueChangeでは来ていませんでした。
ActionとValueChangeではパラメタの数が変わることはありえるのでしょうか??

今回のシステムでは基底クラスが用意されているのですが、ビーンはあくまでデータ格納用として使用し、Action、ValueChangeイベントは基底クラスを敬称した別クラスを作成する仕組みになっています。
この基底クラスでcreateValueBindingを使用していますので、全てがreateValueBindingでビーンの情報を取得していることになります。
(姑息な手段・・・システム全体が姑息な作りになってるような気がしてきました。。)
よしだひろゆき
大ベテラン
会議室デビュー日: 2004/11/22
投稿数: 141
投稿日時: 2006-01-26 12:02
引用:

確認したところ、processActionで渡ってきているパラメタがprocessValueChangeでは来ていませんでした。
ActionとValueChangeではパラメタの数が変わることはありえるのでしょうか??


ちょっと意味が分かりかねます.JSPソースを開示していただいた方が良いのですが..
想像してお答えしてみます.
「processActionで渡ってきているパラメタがprocessValueChangeでは来ていません」
というのは,リクエストによってActionListenerで処理する場合と,ValueChangeListener
で処理する場合と,二通りあるということですね.となると察するに,
h:selectOneMenuはonclickのJavaScriptにてsubmitするようになっているのではないかと
思います.違いますか?
ようするに,ボタンをクリックしたときと,セレクトメニューをクリックした時とで,
リクエストパラメタが違っているのが問題,と解釈しました.

原因として私が思いつくのは二つです:
(1)ボタンとセレクトメニューが異なるformに含まれている
(2)JavaScriptを使って,入力値を変更している

引用:

(姑息な手段・・・システム全体が姑息な作りになってるような気がしてきました。。)


考え方は人それぞれだとは思いますが,私はこう考えています.
JSFの最大のメリットは,画面設計をしてJSPを作る人(JSFの仕様書ではPage Authorと
呼ばれています)と,処理ロジックを書く人(同じくApplication Developer)の役割
分担がはっきりできることだと思っています.Page AuthorはJSF/JSP/HTMLのタグの知識
さえあれば基本的にはOKで,バッキングビーンのプロパティとアクションだけ教えて
もらえば作業ができ,Javaプログラミングの知識は要らない.逆にApplcation Developer
は,JSPはあまり知らなくてもよいけど,JDBCやEJBなどのエキスパート.

そもそもJ2EEって難し過ぎて,HTML/JSP/Servlet/JDBC/EJB/...など全部をちゃんと
知っている開発者を必要な人数揃えるのってたいへんじゃないですか.
JSFはそれに対する解決策だと期待してます.

で,話は戻りますが,マネージドビーンの名前を決めるのは誰かというとそれは
Page Authorのはずです.それをApplication Developerがハードコーディングするのは
いかがなもんかな,というのが私の根本的な感覚です.しかも文字列でコーディングする
のですから,構文エラーにならないので潜在バグの温床になりかねないと危惧もします.

理想としてはApplication DeveloperはPage Authorがどんな名前をつけようと構わない
ようなバッキングビーンを提供すべきです.また,もし名前が固定であるなら,
それはバッキングビーン側だけで使い,Page Authorには見えないようにしたいです.

スキルアップ/キャリアアップ(JOB@IT)