読者です 読者をやめる 読者になる 読者になる

Challenge Java EE !

Java EEを中心に趣味や仕事における開発メモを書いています。

JSFのcommandButtonにおけるactionとactionListenerで迷う

複合コンポーネント JSF

actionとactionListenerの違いって…

複合コンポーネントでcommandButton使ったものを調べていて、ふと疑問が。
ネット上のサンプルをみてるとcommandButtonに紐づけるイベントをactionで記述するものと、actionListenerで記述するものとがあって、一見何が違うのか、よくわからない…!

そもそも何が違うんだっけ…と。

自分の使い方、曖昧だったようです(-_-;

とりあえず困ったときの…という感じで以下の本で探したところp.312にありました。

actionsとaction listenersを区別するのは大事なことだ!とドーンと書いてありました。
そーです、まさにそれが知りたかったんです。

ざっくり翻訳すると…

  • action

ビジネスロジックとナビゲーションのハンドリングに使う

  • 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>

これで普通に動きました。うーむ。

にほんブログ村 IT技術ブログへ
にほんブログ村
にほんブログ村 IT技術ブログ Javaへ
にほんブログ村