開発メモ。特殊なケースなので、あまり参考にせず、最終手段としての方法かなと。
JSFのFacesContextでは様々な情報を管理していますが、Applicationクラスが持つevaluateExpressionGet()なる黒魔術なメソッドを知りました。
https://javaserverfaces.java.net/docs/2.2/javadocs/javax/faces/application/Application.html
簡単にいうと、コード側からEL式を記述すると、そのEL式を評価して値を取ってくれます。
例えば、以下のようなコードです。
FacesContext context = FacesContext.getCurrentInstance();
boolean beanChecked =
context.getApplication().evaluateExpressionGet(context, "#{actressBean.checked}", boolean.class);
画面に置いたチェックボックスをActressBeanという管理Beanのcheckedというboolean変数にバインドしているイメージです。
上記コードでは、その値をいつでも取れるという……なにこれ。
注意
これをあちこちで多用し出すと(ユニット)テストが死ぬので、なるべく使わないほうがいいと思います。
JSFはそもそもFacesContextを利用し出すと、モックで頑張るか、Arquillianなどを使うか、となっていくので、この辺を意識して上手く作らないとテストしやすいコードにならなかったり。(だから.NETもWebFormからMVCにいったのだし…)
以下は補足と備忘で、どんな状況でこれを使いたくなかったのか?書いておきます。
やろうとしたこと
元々やりたかったのは、PrimeFacesのajaxにおいて、EL式からバインドしてる呼出し先へパラメータを渡したいというものでした。
PrimeFacesではTreeコンポーネントのノードを選択したイベントを以下のようなajaxで書きます。
<p:tree var="act" value="#{actressBean.tree}"
selection="#{actressBean.selectedNode}" selectionMode="single">
<p:ajax event="select" listener="#{act.hello}" />
<p:treeNode>
<h:outputText value="#{act.name}" />
</p:treeNode>
</p:tree>
ちなみにイベントにはselectの他にもツリーノードを展開したか閉じたか(expand/collapse)などもあります。
http://www.primefaces.org/showcase/ui/data/tree/events.xhtml
で、EL式で書いているactというのは、以下Actressクラスで、管理Beanではない普通のPOJOです。
helloは引数にPrimeFacesのNodeSelectEventを指定して、ここに画面で選択されたノード情報が入ってきます。
@AllArgsConstructor
@Getter @Setter
public class Actress {
private String name;
private int age;
public Actress(String name){
this.name = name;
}
public void hello(NodeSelectEvent event){
Actress me = ((Actress)event.getTreeNode().getData());
System.out.println("画面でクリックされたのは"+ me.name);
}
}
で、このときに、EL式から呼んでるhelloに引数を渡したいケースがあったのですが、呼び出すメソッドとEL式に引数を追加しても、シグネチャが合わなくてメソッドがみつからない、と言われました。
<p:ajax event="select" listener="#{act.hello(actressBean.checked)}" />
おまけ
@megascusさんはこのメソッドをご存じだったようで
とのこと…すごいなぁ。
3年くらいJSF使ってて初めて知りました(^^;