このエントリは、Java Advent Calendar 2017の17日目(遅刻&代行)です。本当は19日目担当でしたが、何日も前に書き終えて下書きのまま忘れていました。@ukiuniさん、お手数をおかけしてすみません。
以前からWeld SEという、CDIをJava SEでも使えるようにしてくれるライブラリを存じいていたのですが、秋に登場したJava EE 8に含まれるCDI 2.0にはJava SEでも使用できるAPIがあると耳にしたので、せっかくなので試してみました。わたしのCDIに対する理解は浅くて、
- インスタンスの代入をよろしくやってくれる仕組み
- インスタンスの生存期間をある程度制御できる仕組み
くらいにしか思っていないのですが、とりあえず試してみます。
準備
Java SEでCDI 2.0を使えるようにするためには、pom.xmlにちょこっと追記が必要です。
<dependency> <groupId>javax.enterprise</groupId> <artifactId>cdi-api</artifactId> <version>2.0</version> </dependency> <dependency> <groupId>org.jboss.weld.se</groupId> <artifactId>weld-se-shaded</artifactId> <version>3.0.0.Final</version> </dependency>
最初のはCDI 2.0のAPIですね。2番目は名前からしてWeld SEそのものと思われます。たぶんですが、Weld SEが基となってCDI 2.0のJava SE向け機能が作られたのだと思います。
実はそれだけでは動かなくて、META-INF/beans.xmlを作成してあげないといけないようです。わたしの環境 (Eclipse Oxygen 1a) では CDI 2.0 用のbeans.xmlは生成できないのですが、CDI 1.1用のものを使用しても特に問題はなさそうです。
そしていよいよJavaのプログラミングですが、今回は簡単にメッセージを返すだけのCDI Beanを順に呼び出すものを作成してみました。
- Bootstrap - メインクラス、CDIの初期化とEntryPointのインスタンス生成を行う
- EntryPoint - HelloとMessageからメッセージを集めて返すCDI Bean
- Hello - "Hello"を返すDependentスコープのCDI Bean
- Message - "Greeting"を返すApplicationスコープのCDI Bean
ソースコードはGitHubにアップロードしましたので、そちらを参照してください。
CDIがJava SEでも使えるようになり、Java EEで培われたテクニックが使えるようになることはとても素晴らしいことだと思います。以前からWeld SEに注目していたわたしとしては、この新しいAPIに多いな期待を寄せています。
さて、最後にCDIをJava SEで使用する上での注意点です。当然ですが、Java EEで当たり前のように使える機能の一部はJava SEではサポートされません。一例をあげると、スコープを規定するアノテーションは、Java SEでは@Dependentと@ApplicationScopedしか使用できません。@Singletonが使用できなかったのは意外ですが、@RequestScopedや@SessionScopedなどはWebシステム固有のスコープだったため、サポートされなくても仕方ないと割り切っています(必要とされる場面も思い浮かびませんし)。また、Java EE 7以降はbeans.xmlを省略可能ですが、前述の通りJava SEではbeans.xmlが必須です。適当に書いても動きそうなので、プロジェクトを作成したら忘れないうちに入れておきましょう。
その他、CDIに関する注意事項はだいたいJava SE環境でも当てはまるようです。