- PR -

MyFaces x:treeのイベントリスナに関して

1
投稿者投稿内容
Dog
常連さん
会議室デビュー日: 2003/10/16
投稿数: 24
投稿日時: 2006-05-25 15:39
お世話になっております。
ただいまJSF(MyFaces)を用いた開発を行っております。

JSPの中でMyFacesの拡張タグである<x:tree>を用いたビューの作成をしているのですが、<x:treeSelectionListner>の挙動がビューに反映されず困っています。

■目的
Tree.jspのツリーをクリックしたイベントで<h:inputText id="focus"/>の値を変化させたい。

***Tree.jsp***
<f:view>
<h:form id="test">
<h:inputText id="focus" value="#{treeBean.focus}" />
<x:tree id="tree"
value="#{treeBean.tree}"
nodeClass="treenode"
selectedNodeClass="treenodeSelected"
expandRoot="true">
<x:treeSelectionListener type="controller.TreeAction" />
</x:tree>
</h:form>
</f:view>

***faces-config.xml***
(略)
<managed-bean>
<managed-bean-name>treeBean</managed-bean-name>
<managed-bean-class>controller.TreeBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

***TreeBean.java***
public class TreeBean implements Serializable {

private TreeModel tree;
private MutableTreeNode root;
private String focus;

public TreeBean(){
root = new MutableTreeNode("ROOT");
(略)
tree = new DefaultTreeModel(root);
//@focusに初期値をセット
focus = "default";
}

public TreeModel getTree() {
return tree;
}
public void setTree(TreeModel tree) {
this.tree = tree;
}
public String getFocus() {
return focus;
}
public void setFocus(String focus) {
this.focus = focus;
}
}

***TreeAction.java***
public class TreeAction implements TreeSelectionListener{

public TreeAction(){
super();
}

public void valueChanged(TreeSelectionEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
TreeBean tree = (TreeBean)context.getApplication().getVariableResolver().resolveVariable(context,"treeBean");
//Afocusの値を変更
tree.setFocus("update");
}
}

@で初期化したfocusプロパティに対し、ツリークリック時のイベントTreeAction(リスナクラス)の中でAのようにsetメソッドで値をセットしています。
一旦は値がセットされているようなのですが、TreeAction→JSPの表示の間にでもう一度TreeBean.setFocus()が呼ばれ、以前(前画面)のfocusプロパティがセットし直されているようです。
※TreeBean.setFocusを空のダミーメソッドとして、Aで別のsetter(例TreeBean.setFocus2())からセットするという解決方法もありますがスッキリしません・・。

初歩的なJSFのライフサイクルの問題なのかもしれませんが、解決できず困っています。
どなたかご存知の方がいらっしゃいましたら、ご教授いただけませんでしょうか?
宜しくお願い致します。
よしだひろゆき
大ベテラン
会議室デビュー日: 2004/11/22
投稿数: 141
投稿日時: 2006-05-26 13:52
MyFace(Tomahawk)の使用経験が無くて恐縮ですが...

一般的にValueChangeEventはProcess Validationsフェースで処理されます
MyFacesのTreeSelectionEventもおそらくそうなのではないでしょうか.

その後のModel Values Updateフェーズで入力値をバッキングビーンに設定します.
ですから現象のようなことが起きているのだと思います.

PhaseListenerを設定してフェーズ名をロギングしてみると,上記が確認できると思います.

回避方法は二つ
(1)Model Values UpdateとInvoke Applicationフェーズを完全にスキップしてかまわないのであれば,
リスナーの中でfacesContext.renderResponse()を呼びます.

(2)Model Values UpdateとInvoke Applicationフェーズをスキップして困る場合は,
Eventの処理をModel Values Updateフェーズの後で実行するようにします.
こんな感じでできるのではないでしょうか?
if (!event.getPhaseId().equals(PhaseId.UPDATE_MODEL_VALUES)){
  UIComponent comp = event.getComponent();
  event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
  comp.queueEvent(event);
} else {
// 通常の処理
}
Dog
常連さん
会議室デビュー日: 2003/10/16
投稿数: 24
投稿日時: 2006-05-26 17:48
よしだひろゆき様 ご回答ありがとうございます。

引用:

一般的にValueChangeEventはProcess Validationsフェースで処理されます
MyFacesのTreeSelectionEventもおそらくそうなのではないでしょうか.

その後のModel Values Updateフェーズで入力値をバッキングビーンに設定します.
ですから現象のようなことが起きているのだと思います.


その通りだったようです。

ご教授いただいた回避方法を試してみました。

  • 回避方法(1)
    TreeSelectionEventのみ呼び出されるようになりましたが、
    <h:inputText id="focus" value="#{treeBean.focus}" />
    に対して値がセットされなくなりました。
    (Model Values Updateフェーズをスキップしてしまったからでしょうか?)

  • 回避方法(2)
    狙ったとおりの挙動になりました!ありがとうございます!
    この方法を用いようと思います。

    これは本来Process Validationsフェーズで処理されるリスナイベントをModel Values Updateフェーズで実行されるようにキューにセットし直しているという認識でよいのでしょうか?


問題解決と同時に非常に勉強になりました。ありがとうございました。
よしだひろゆき
大ベテラン
会議室デビュー日: 2004/11/22
投稿数: 141
投稿日時: 2006-05-29 14:17
引用:

TreeSelectionEventのみ呼び出されるようになりましたが、
<h:inputText id="focus" value="#{treeBean.focus}" />
に対して値がセットされなくなりました。
(Model Values Updateフェーズをスキップしてしまったからでしょうか?)


そうです.renderResponseフラグが立っていると,次はRender Responseフェーズになります.
ちなみにresponseCompleteというフラグもあって,これが立つとライフサイクルを終了します

引用:

これは本来Process Validationsフェーズで処理されるリスナイベントをModel Values Updateフェーズで実行されるようにキューにセットし直しているという認識でよいのでしょうか?


そうです.一度Process Validationsフェーズで実行されて,その時にif-then部分を
実行してキューイングし直します.Model Values Updateフェーズでは再びブロード
キャストされてelse部分を実行します.
Dog
常連さん
会議室デビュー日: 2003/10/16
投稿数: 24
投稿日時: 2006-05-30 18:12
返信が遅くなってしまいました・・。

よしだひろゆき様
丁寧なご回答ありがとうございました。
やはりイベントリスナのような局所的なところだけでなく、リクエストがどのようなフェーズで処理されるかという全体的な理解が必要なのですね。
1

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