メディアフォース 開発者ブログ

株式会社メディアフォースの開発者による非公式ブログです。

JavaSEでCDIのObserversを試してみる

利用方法

今回は、JavaSEで使ってみたいと思います。
話し変わりますが、JavaEE7 から色々なライブラリの仕様取り込んだりしてEJBが駆逐されつつあっていい感じに見える。

事前準備

  • お好みでeclipseなど。
  • Weldを落としてくる。
    • ここ からダウンロードできる。
    • Mavenの場合
<dependency>
    <groupId>org.jboss.weld.se</groupId>
    <artifactId>weld-se-core</artifactId>
    <version>2.4.0.Final</version>
</dependency>
  • パスの通っている場所にMETA-INFディレクトリおよび空のbeans.xmlを作る。
  • 今回使ったプロジェクトはこちらにうp github.com
  • src配下にMETA-INFディレクトリ作ってあるけど良くない気がする。(サンプルだしまぁいいか)

何ができるんじゃろか

@Observers アノテートされた引数の型とEventの型が一致した場合に勝手に通知してくれるっぽい。

試してみる

java:ObserverSample.java(通知用)

public class ObserversSample {
	@javax.inject.Inject
	javax.enterprise.event.Event<User> event;
    
	public static void main(String[] args) {
		Weld weld = new org.jboss.weld.environment.se.Weld();
		WeldContainer container = weld.initialize();
		ObserversSample obsSample = container.instance().select(ObserversSample.class).get();

		obsSample.run();
	}

	public void run() {
		this.event.fire(new User().name("山田").age(30));
	}
}


java:User.java

public class User {
    //単なるPOJOなのでgetter/setterは省略
	private String name;
	private int age;
}

java:UserEventListener.java

public class UserEventListener {
	public void fire(@Observes User user) {
		System.out.println("Event Fire:" + user.getName());
	}
}

実行すると

Event Fire:山田

が出る。Eventを介して見事に通知された。楽すぎる・・・。

通知先を指定する

せっかくなので、InsertイベントとUpdateイベントで分けたい。
今のままだと、Insert用UserクラスとUpdate用Userクラスを作るか、Userクラスの中でイベントタイプを持つかしないとならないのでちょっとイケてない感がある。

ということで、Qualifier を作る。

アノテーションなので @interface で定義する。

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Insert {}

Eventに @Insert アノテーションを付ける。

public class ObserversSample {
	@Inject
	@Insert
	Event<User> insertEvent;

	public void run() {
		this.insertEvent.fire(new User().name("山田").age(30));
	}
}

EventListener の引数に @Insert を付与する。

public class UserEventListener {

	// @Insertあり
	public void insert(@Observes @Insert User user) {
		System.out.println("Insert:" + user.getName());
	}

	// @Insert無し
	public void any(@Observes User user) {
		System.out.println("Any:" + user.getName());
	}
}

実行してみる

Insert:山田

@Insertのメソッドのみが通知され、@Insertなしは通知されない。

通知されたメソッドで例外が発生すると、呼び出し元に例外がthrowされてそれ以降は伝播しないもよう。