actionとactionListenerの違いって…
複合コンポーネントでcommandButton使ったものを調べていて、ふと疑問が。
ネット上のサンプルをみてるとcommandButtonに紐づけるイベントをactionで記述するものと、actionListenerで記述するものとがあって、一見何が違うのか、よくわからない…!
そもそも何が違うんだっけ…と。
自分の使い方、曖昧だったようです(-_-;
とりあえず困ったときの…という感じで以下の本で探したところp.312にありました。
actionsとaction listenersを区別するのは大事なことだ!とドーンと書いてありました。
そーです、まさにそれが知りたかったんです。
ざっくり翻訳すると…
ビジネスロジックとナビゲーションのハンドリングに使う
UIロジックで使う、ナビゲーションのハンドリングでは使わない
とのこと(^^;以下サイトも冒頭に上記書籍と似た内容で説明されています。
ちなみにStack Overflowなどを見ると
等の質問があるので、結構混乱してるんだなぁ、と。
ナビゲーション(画面遷移)でactionを使う、というのはわかりやすいですが、ビジネスロジックとUIロジックで使い分けるというのは一瞬「ん?」と思ってしまったり(^^;
書籍ではわかりやすいサンプルコードがあって、ラシュモア山(上記書籍の表紙にあるアメリカ大統領の顔が彫刻された山)の画像で、大統領の顔をクリックすると、その大統領の詳細説明するページへ遷移する処理、が書かれてました。
ページの座標からどの大統領が選ばれたかを判断する処理がactionListenerから呼び出され、その情報を取得してactionで画面遷移する、ものでした。
UIロジックってそういう感じのことでいいのかー、となんとなく納得したのですが、開発では足並み揃えないとずれそうな気も。。
ちなみに上記違いに行き着く前に元々調べていたのは、PrimeFacesのcommandButtonコンポを複合コンポで包んだ際に
WARNING: Unable to resolve composite component from using page using EL expression '#{cc.attrs.action}'
javax.faces.FacesException: Unable to resolve composite component from using page using EL expression '#{cc.attrs.action}'
at com.sun.faces.facelets.tag.TagAttributeImpl$AttributeLookupMethodExpression.invoke(TagAttributeImpl.java:444)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
…
というエラーが出て、なんでだろー、と悩んでいたものでした。
複合コンポーネントの定義は
<composite:interface>
...
<composite:attribute name="action" targets="btn" method-signature="java.lang.String action()" />
<composite:attribute name="actionListener" targets="btn" method-signature="void actionListener(javax.faces.event.ActionEvent)" />
...
</composite:interface>
<composite:implementation>
<p:commandButton
id="btn"
...
action="#{cc.attrs.action}"
actionListener="#{cc.attrs.actionListener}"
...
/>
</composite:implementation>
みたいに書いてたのですが、targetsを書いていれば内部での定義は不要なんですね…。
<composite:interface>
<composite:attribute name="action" targets="btn" method-signature="java.lang.String action()" />
<composite:attribute name="actionListener" targets="btn" method-signature="void actionListener(javax.faces.event.ActionEvent)" />
</composite:interface>
<composite:implementation>
<p:commandButton
id="btn"
...
/>
</composite:implementation>
これで普通に動きました。うーむ。