7.9. コンポーネント駆動イベント
Seam コンポーネント同士は互いのメソッドを呼び出して通信します。 ステートフルコンポーネントは監視側または監視可能パターンを実装することもできます。 ただし、より疎結合な通信を有効にするために Seam には コンポーネント駆動イベント が備わっています。
イベントリスナー (監視側) を
components.xml に指定します。
<components>
<event type="hello">
<action execute="#{helloListener.sayHelloBack}"/>
<action execute="#{logger.logHello}"/>
</event>
</components>
ここでは イベントタイプ は任意の文字列です。
イベントが発生すると、 そのイベント用に登録されたアクションが
components.xml で出現する順番に従って呼び出されます。 イベントを発生させるために Seam は組み込みコンポーネントを提供します。
@Name("helloWorld")
public class HelloWorld {
public void sayHello() {
FacesMessages.instance().add("Hello World!");
Events.instance().raiseEvent("hello");
}
}
また、 以下のようにアノテーションを使うことも可能です。
@Name("helloWorld")
public class HelloWorld {
@RaiseEvent("hello")
public void sayHello() {
FacesMessages.instance().add("Hello World!");
}
}
このイベント生成側はイベント消費側には依存しません。 イベントリスナーはまったく生成側に依存関係を持つことなく実装することができます。
@Name("helloListener")
public class HelloListener {
public void sayHelloBack() {
FacesMessages.instance().add("Hello to you too!");
}
}
上記の
components.xml で定義されたメソッドバインディングはイベントを消費側にマッピングします。 アノテーションを使用してこれを行うこともできます。
@Name("helloListener")
public class HelloListener {
@Observer("hello")
public void sayHelloBack() {
FacesMessages.instance().add("Hello to you too!");
}
}
コンポーネント駆動のイベントを知っている方なら、 なぜイベントオブジェクトについて今まで言及してこなかったか疑問に思われるかもしれません。 Seam ではイベントオブジェクトはイベント生成側とリスナー間で状態を伝播する必要がありません。 状態は Seam コンテキストで保持されコンポーネント間で共有されます。 ただし、 イベントオブジェクトを渡したければ次のようにすることも可能です。
@Name("helloWorld")
public class HelloWorld {
private String name;
public void sayHello() {
FacesMessages.instance().add("Hello World, my name is #0.", name);
Events.instance().raiseEvent("hello", name);
}
}
@Name("helloListener")
public class HelloListener {
@Observer("hello")
public void sayHelloBack(String name) {
FacesMessages.instance().add("Hello #0!", name);
}
}