CDIを使ったプログラムの単体テスト(2)

前回のブログに引き続きJava SE上でCDIプログラムの単体テストをする方法について書きます。今回はDeltaSpike Coreモジュールに含まれるProjectStageと@Exclude、そして最後にCdiTestRunnerと組み合わせて使う方法を紹介します。

ProjectStageとは

単体テスト、結合テスト、システムテストなど、テストのフェーズ応じてテスト用のプログラムやデータを切り替えたいということがあります。単体テストの場合はDerbyのような軽量なDBを使い、システムテストでは本番と同等の構成のDBを使うというような場合です。この切り替えのために手作業で設定ファイルを変更するのでは自動ビルドに対応するのが難しくなるので、プログラム起動のパラメーターによって切り替えられる仕組みが望まれるところです。

DeltaSpikeのProjectStageは、プロジェクトの開発ステージを実行時に指定できるようにすることで、指定されたステージに応じた処理を書けるようにするものです。ProjectStageが提供する既定義のステージとして以下が提供されています。

  • UnitTest
  • Development
  • SystemTest
  • IntegrationTest
  • Staging
  • Production

実行時にどのステージかを指定するには、次のようにJavaプログラムの起動時にシステムプロパティ(org.apache.deltaspike.ProjectStage)を設定します。

-Dorg.apache.deltaspike.ProjectStage=UnitTest

起動されたプログラム側では指定されたステージを@Injectで取得することができるので、その値にもとづいて起動のときに指定されたステージを知り、そのステージに対応した処理を書くことができます。

@Inject
ProjectStage projectStage;

// ...

if (ProjectStage.UnitTest.equals(this.projectStage)) {
    // 単体テストのステージでの処理
} else {
    // その他のステージでの処理
}

ProjectStageによる@Excludeの制御

DeltaSpikeの@Excludeは、指定されたクラスをインジェクションの対象から明示的に外すためのアノテーションです。CDI 1.1仕様では@Vetoedという同じ目的のアノテーションがありますが、@Excludeは、アノテーションの引数としてインジェクションの対象から外す条件を指定できるのが特徴です。そして、このときの条件としてProjectStageを使うことができます。

具体例を見てみましょう。MessageSenderというインタフェースを型として変数にインジェクトするシーンを考えます。

@Inject
MessageSender messageSender;

MessageSenderはメールを送信するBeanです。これを利用するBeanのテストを考えたとき、単体テストではMessageSenderにはメール送信の代わりにログを書くだけにしてもらいたいと思います。このようなときにProjectStageを使って実行時に指定されたステージに従って、単体テストのときと、それ以外のときでインジェクトされるMessageSenderを切り替えることが可能です。

次のプログラムは単体テスト以外の場合にインジェクトされるべきクラスです。@Exclude(ifProjectStage =<ステージクラス>)とすると、指定されたステージの場合にはそのクラスが排除されます。

package org.tanoseam.examples;

import javax.enterprise.context.ApplicationScoped;
import org.apache.deltaspike.core.api.exclude.Exclude;
import org.apache.deltaspike.core.api.projectstage.ProjectStage;

@ApplicationScoped
@Exclude(ifProjectStage = ProjectStage.UnitTest.class)
public class MessageSenderImpl implements MessageSender {

	public MessageSenderImpl() {}

	public void send(String message) {
		System.out.println("MessageSenderImpl: " + message);
	}
}

次に、単体テストのときにインジェクトされるクラスの定義です。指定されたステージでインジェクトされないことを設定するには@Exclude(exceptIfProjectStage = <ステージクラス>)とします。
「〜以外のステージの場合はインジェクションの対象としない」ということは、二重否定の書き方で少々わかりにくいのですが、指定されたステージではインジェクションの対象になるいうことです。

package org.tanoseam.examples;

import javax.enterprise.context.ApplicationScoped;
import org.apache.deltaspike.core.api.exclude.Exclude;
import org.apache.deltaspike.core.api.projectstage.ProjectStage;

@ApplicationScoped
@Exclude(exceptIfProjectStage = ProjectStage.UnitTest.class)
public class TestMessageSenderImpl implements MessageSender {
	
	public TestMessageSenderImpl() {}
	
	public void send(String message) {
		System.out.println("TestMessageSenderImpl: " + message);
	}
}

DeltaSpike Coreモジュールの使い方

ここまで説明してきたProjectStageと@Excludeは、JUnitのようなテスティングフレームワークとの併用が必須というわけありません。プログラム起動時にシステムプロパティでステージを指定すれば、実行時にステージ情報を取得でき、それに従って@Excludeが動作します。以下はJava SE上でWeldを使ったサンプルになります。

package org.tanoseam.examples;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

import org.apache.deltaspike.core.api.projectstage.ProjectStage;
import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;

@ApplicationScoped
public class ProjectStageExample {
	
	public ProjectStageExample() {}

	@Inject
	ProjectStage projectStage;
	
	@Inject
    MessageSender messageSender;

	public void testSend() {
		messageSender.send("ProjectStage=" + projectStage);
    }
	
	static public void main(String args[]) {
		Weld weld = new Weld();
	    WeldContainer container = weld.initialize();
	    container.instance().select(ProjectStageExample.class).get().testSend();
	    weld.shutdown();
	}
}

ProjectStageと@Excludeは、DeltaSpike Coreモジュールに含まれます。このモジュールはMaven pom.xmlに以下の依存モジュールを設定することで有効になります。

 	<dependency>
            <groupId>org.apache.deltaspike.core</groupId>
            <artifactId>deltaspike-core-api</artifactId>
            <version>${deltaspike.version}</version>
            <scope>compile</scope>
	</dependency>
		
	<dependency>
            <groupId>org.apache.deltaspike.core</groupId>
            <artifactId>deltaspike-core-impl</artifactId>
            <version>${deltaspike.version}</version>
            <scope>runtime</scope>
	</dependency> 

上のプログラムではWeldをテストではなく、実行時に使っているので、Weldの依存ライブラリのスコープをcompileにしておいてください。

	<dependency>
            <groupId>org.jboss.weld.se</groupId>
            <artifactId>weld-se-core</artifactId>
            <version>${weld.version}</version>
            <scope>compile</scope>
            <!-- <scope>test</scope> -->
	</dependency>

それから、CDIを使うので前回のブログと同様にMETA-INF/beans.xmlが必要になります。忘れずにファイルを作成してください。

準備ができたらシステムプロパティorg.apache.deltaspike.ProjectStageでステージをいくつか変更して実行してみましょう。ステージにUnitTestを指定すると、messageSender変数に次のようにテスト用のMessageSenderがインジェクトされます。

$ mvn clean install exec:java -Dexec.mainClass=”org.tanoseam.examples.ProjectStageExample” -Dorg.apache.deltaspike.ProjectStage=UnitTest

INFO: WELD-ENV-002003: Weld SE container STATIC_INSTANCE initialized
TestMessageSenderImpl: ProjectStage=UnitTest
11 03, 2015 1:21:10 午後 org.jboss.weld.environment.se.WeldContainer shutdown
INFO: WELD-ENV-002001: Weld SE container STATIC_INSTANCE shut down

次に、ステージをProductionへ変更すると本番用のMessageSenderがインジェクトされているのがわかります。

$ mvn clean install exec:java -Dexec.mainClass=”org.tanoseam.examples.ProjectStageExample” -Dorg.apache.deltaspike.ProjectStage=Production

11 03, 2015 1:31:31 午後 org.jboss.weld.environment.se.WeldContainer initialize
INFO: WELD-ENV-002003: Weld SE container STATIC_INSTANCE initialized
MessageSenderImpl: ProjectStage=Production
11 03, 2015 1:31:31 午後 org.jboss.weld.environment.se.WeldContainer shutdown
INFO: WELD-ENV-002001: Weld SE container STATIC_INSTANCE shut down

CdiTestRunnerを使ったテストでのProjectStageの指定

最後に、JUnitのテストプログラム内でProjetStageを指定する方法について書きます。JUnit のテストでは、これまでの説明と反するように聞こえるかもしれませんが、実行時に指定されたステージによって結果が変わるのでは正しいテストを実行することができません。そこで、@TestControlというアノテーションを指定することで、テストの実行で想定されるステージをテストごとに指定します(@TestControlを指定しない場合のステージのデフォルトはUnitTestです)。以下の例はUnitTestのステージを指定したときのサンプルになります。

package org.tanoseam.examples;

import javax.inject.Inject;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.apache.deltaspike.core.api.projectstage.ProjectStage;
import org.apache.deltaspike.testcontrol.api.TestControl;
import org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner;

@RunWith(CdiTestRunner.class)
@TestControl(projectStage = ProjectStage.UnitTest.class)
public class ProjectStageTest {

	@Inject
	ProjectStage projectStage;
	
	@Inject
    MessageSender messageSender;

	@Test
	public void testSend() {
		messageSender.send("ProjectStage=" + projectStage);
    }
}

今度はCdiTestRunnerを使っているのでWeldの起動・停止のコードを書く必要がなく、 mvn test だけで実行できます。
全体的にテストコードがすっきりしましたね。

1 03, 2015 7:34:41 午後 org.apache.deltaspike.testcontrol.api.junit.CdiTestSuiteRunner$LogRunListener testStarted
情報: [run] org.tanoseam.examples.ProjectStageTest#testSend
11 03, 2015 7:34:41 午後 org.apache.deltaspike.testcontrol.api.junit.CdiTestSuiteRunner$LogRunListener testStarted
情報: [run] org.tanoseam.examples.ProjectStageTest#testSend
TestMessageSenderImpl: ProjectStage=UnitTest
11 03, 2015 7:34:41 午後 org.apache.deltaspike.testcontrol.api.junit.CdiTestSuiteRunner$LogRunListener testFinished
情報: [finished] org.tanoseam.examples.ProjectStageTest#testSend
11 03, 2015 7:34:41 午後 org.apache.deltaspike.testcontrol.api.junit.CdiTestSuiteRunner$LogRunListener testFinished
情報: [finished] org.tanoseam.examples.ProjectStageTest#testSend
広告

CDIを使ったプログラムの単体テスト(1)

これから何回かに分けてCDIベースのテストを支援するDeltaSpikeのモジュールを紹介します。今回はDeltaSpike Test-Controlモジュールです。

CDIベースの単体テストの問題

CDIを使ったインジェクション、プロデューサ、インタセプタ、イベントなどを使ったクラスをどうやってテストしたらよいのでしょう。setterインジェクションを使うなど、無理をすればある程度はコンテナ無しでもテストができるかもしれませんが、できればCDIの普通の使い方をしたままでテストをしたいものです。そうなると、JUnitとCDIコンテナを連携させる仕組みが必要になります。

テスト対象がEJBやコンテナ管理のJPAを使っている場合など、Java EEコンテナに依存する場合には、Arquillianを使うのが定番ですが、Arquillianはテストをアプリサーバー上で実行するためにアプリサーバーの起動・停止が必要となり、どうしてもテストの実行時間が長くなる傾向があります。

ここで紹介するDeltaSpike Test-Controlモジュールは、CdiTestRunnerというJUnitのTestRunnerとして提供されるモジュールで、JUnitと組み合わせて使うことで、Java SE上でCDIのテストができます。CdiTestRunnerは、ArquillianのようにJava EEの機能を使ったテストはできませんが、Java SE上でのテストですのでArquillianに比べて短時間にテストを実行することができるというメリットがあります。

CdiTestRunnerの使い方

使い方は簡単です。まず、Mavenでプロジェクトを作って、以下のような依存ライブラリを設定したpom.xmlファイルを設定します。このpom.xmlではCDIコンテナとしてWeldを使うことを想定していますが、他のコンテナを使うときにはマニュアルを参照してください。また、バージョンについては以下のサンプルでは現時点での最新バージョンを指定しましたが、お使いのプロジェクトに合わせて変更してください。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.tanoseam.example</groupId>
	<artifactId>tanoseam-example</artifactId>
	<version>1.0-SNAPSHOT</version>

	<properties>
		<junit.version>4.12</junit.version>
		<weld.version>2.3.1.Final</weld.version>
		<deltaspike.version>1.5.1</deltaspike.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.deltaspike.modules</groupId>
			<artifactId>deltaspike-test-control-module-api</artifactId>
			<version>${deltaspike.version}</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.deltaspike.modules</groupId>
			<artifactId>deltaspike-test-control-module-impl</artifactId>
			<version>${deltaspike.version}</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.deltaspike.cdictrl</groupId>
			<artifactId>deltaspike-cdictrl-weld</artifactId>
			<version>${deltaspike.version}</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.jboss.weld.se</groupId>
			<artifactId>weld-se-core</artifactId>
			<version>${weld.version}</version>
			<scope>test</scope>
		</dependency>

	</dependencies>
</project>

次に、テストクラスでは@RunWithにCidTestRunnerを指定します。以下はTest-Controlの使用例を示すために作ったインジェクションを使った簡単なサンプルです。

package org.tanoseam.examples;

import org.junit.Test;
import org.junit.runner.RunWith;
import javax.inject.Inject;
import org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner;

@RunWith(CdiTestRunner.class)
public class CdiUnitTest {
		
	@Inject
    private MyBean myBean;
	
	@Test
	public void testLog() {
      myBean.log("hello");

    }
}

CdiUnitRunnerはRequestScope/SessionScope/ApplicationScopeをサポートしています。このテストがインジェクトしているMyBeanはSessionScopeのBeanです。このMBeanは、さらにApplicationScopeのLoggingBeanというBeanをインジェクトしています。

package org.tanoseam.examples;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;

@SessionScoped
public class MyBean implements Serializable {
	
	@Inject 
	LoggingBean loggingBean;

	public MyBean() {}

	@PostConstruct
	public void initialize() {
		log("MyBean::initialize");
	}

	@PreDestroy
	public void destroy() {
		log("MyBean::destroy");
	}

	void log(String message) {
		loggingBean.log(message);
	}
}

LogginBeanの定義は次のようになります。

package org.tanoseam.examples;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class LoggingBean {
	
	public LoggingBean() {}

	@PostConstruct
	public void initialize() {
		log("LoggingBean::initialize");
	}

	@PreDestroy
	public void destroy() {
		log("LoggingBean::destroy");
	}

	void log(String message) {
		System.out.println("CDI: " + message);
	}
}

最後に忘れてはいけないのがbeans.xmlです。以下のファイルをMETA-INF/beans.xmlに配置してください。ここではbean-discovery-modeとして”annotated”を指定しています。このモードのときはCDIコンテナはスコープアノテーションがついてるクラスしかスキャン対象にしませんので注意してください。

※ beans.xmlにversion=”1.1″を付け忘れていたので追記しました(11/02)

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" 
version="1.1" 
bean-discovery-mode="annotated">
</beans>

このテストを実行するとコンソールに以下のように表示されます。実際にはWeldの起動や停止の部分のログが大量に出力されますが、ここではテストプログラムの出力前後のみを掲載します。

10 31, 2015 4:25:19 午後 org.apache.deltaspike.testcontrol.api.junit.CdiTestSuiteRunner$LogRunListener testStarted
情報: [run] org.tanoseam.examples.CdiUnitTest#testLog
CDI: LoggingBean::initialize
CDI: MyBean::initialize
CDI: hello
10 31, 2015 4:25:19 午後 org.apache.deltaspike.testcontrol.api.junit.CdiTestSuiteRunner$LogRunListener testFinished
情報: [finished] org.tanoseam.examples.CdiUnitTest#testLog
CDI: MyBean::destroy
CDI: LoggingBean::destroy
10 31, 2015 4:25:19 午後 org.jboss.weld.environment.se.WeldContainer shutdown

CdiTestRunnerでは、RequestScopeやSessionScopeのBeanはテストごとに作成されます。上のテストでは、MyBeanはSessionScopedなのでテストごとに生成されますが、LoggingBeanはApplicationScopeなので、一回作成されると複数のテスト実行中に同じものが使いまわされます。

ここでスコープの違いによるBeanのライフサイクルの違いを見るためにテストプログラムの一部を以下のように変更します。ご覧の通り、単に同じテストを2回実行しているだけです。

	@Test
	public void testLog() {
      myBean.log("myBean=" + myBean);
	 //myBean.log("hello");
    }
	
	@Test
	public void testLog2() {
	  myBean.log("myBean=" + myBean);
    }

実行後のコンソールログを見ると、LoggingBean::initializeとLoggingBean::destroyはそれぞれテストの先頭と最後にしか呼び出されていないのに対し、MyBean::initializeとMyBean::destroyはテストメソッドの呼び出しごとに呼び出されていることが確認できます。

10 31, 2015 4:36:23 午後 org.apache.deltaspike.testcontrol.api.junit.CdiTestSuiteRunner$LogRunListener testStarted
情報: [run] org.tanoseam.examples.CdiUnitTest#testLog
CDI: LoggingBean::initialize
CDI: MyBean::initialize
CDI: myBean=org.tanoseam.examples.MyBean@67c33749
10 31, 2015 4:36:23 午後 org.apache.deltaspike.testcontrol.api.junit.CdiTestSuiteRunner$LogRunListener testFinished
情報: [finished] org.tanoseam.examples.CdiUnitTest#testLog
CDI: MyBean::destroy
10 31, 2015 4:36:23 午後 org.apache.deltaspike.testcontrol.api.junit.CdiTestSuiteRunner$LogRunListener testStarted
情報: [run] org.tanoseam.examples.CdiUnitTest#testLog2
CDI: MyBean::initialize
CDI: myBean=org.tanoseam.examples.MyBean@fa49800
10 31, 2015 4:36:23 午後 org.apache.deltaspike.testcontrol.api.junit.CdiTestSuiteRunner$LogRunListener testFinished
情報: [finished] org.tanoseam.examples.CdiUnitTest#testLog2
CDI: MyBean::destroy
CDI: LoggingBean::destroy
10 31, 2015 4:36:23 午後 org.jboss.weld.environment.se.WeldContainer shutdown

CDIのDI(Dependency Injection)は、もともとBean間を疎結合連携をさせるための仕組みです。アプリケーション全体としてはJava EE上でないと動作できない場合であっても、それを構成する個々のBeanについてはJava SE上で単体テストが十分可能な場合もあるでしょう。今回紹介したCdiTestRunnerはそのような場合に活用できると思います。

DeltaSpikeモジュールの概要

久しぶりのブログへの投稿になります。当ブログではJava EE仕様のバックボーン的な重要な仕様であるContexts and Depenency Injection (CDI)とその拡張モジュールについて書いています。特に、CDI拡張モジュールについてはDeltaSpikeの活動について注目しています。しばらく更新が滞っていましたが、WildFly 10などJava EE 7ベースのアプリサーバーが普及するとアプリケーション開発の現場でCDIを使う機会が益々増えると思いますので、またブログを再開したいと思います。今ままで同様、不定期の更新になるかとは思いますが、今後ともよろしくお願いします。

DeltaSpikeはポータブルなCDI拡張モジュール

Apache DeltaSpikeはオープンソースで開発されているCDIの拡張モジュール集です。DeltaSpikeは、CDIコンテナの代表的な実装であるWeldやOpenWebBeansの両方で動作し、以下のアプリサーバー上でテストが行われています(Jenkins上でのビルドはこちら)。

  • JBoss AS7
  • JBoss WildFly 8
  • Oracle GlassFish 3
  • Oracle GlassFish 3.1
  • Oracle GlassFish 4
  • Oracle WebLogic 12c

このようにDeltaSpikeの大きな魅力の一つは特定のCDIコンテナやアプリサーバーに依存しないポータルブルなモジュールを開発しているということです。DeltaSpikeはオープンソースですので、ユーザからのフィードバックを得て機能を改善していきます。これらの中で有用なものは将来のCDI仕様やJava EE仕様そのものに影響を与えていくと思います。実際、CDI 2.0 (JSR-365)の活動の中でもDeltaSpikeからのフィードバックが期待されています。その意味で、DeltaSpikeはすぐに使える便利ライブラリを提供するプロジェクトというだけでなく、CDIの将来の動向を知る上でも重要なプロジェクトだと言えるでしょう。

DeltaSpikeの提供モジュール

1年前に投稿したブログの記事ではDeltaSpikeのバージョン1.0について書きましたが、現在ではバージョン1.5まで開発が進んでいます。ここで、今ままでの振り返りを兼ねて、現在のDeltaSpikeの提供モジュールについてご紹介します。以下の表はDeltaSpike 1.5が提供するモジュールの概要になります。

表1:DeltaSpike 1.5のモジュール
モジュール 説明
Core DeltaSpike APIとユーティリティクラスを定義する基盤となるもの
Bean Validation EJBやManagedBeanのようなビジネスオブジェクでバリデーションをするときに使えるCDIを使ったBeanバリデーション
Container Control CDIコンテナの起動/シャットダウンと関連するコンテキストのライフサイクル管理をするためのもの
Data ボイラープレートなコードを減らすために宣言的クエリを使えるようにJPAを改善するためのもの
JPA トランザクション・コンテキストとスコープのためのもの
JSF タイプセーフなビューの構成、マルチウィンドウ処理、新しいスコープ(WindowScoped, ViewScope, ViewAccessScoped, GroupedConversationScoped)などCDIを使ったJSF向けの統合
Partial-Bean インタフェースや抽象クラスを手で実装する代わりにジェネリックハンドラーを実装するためのもの
Scheduler Quartz v2(デフォルト)やジョブクラスのためのcron式をサポートする他のスケジューラとのシンプルな統合のためのもの
Security メソッド呼び出し時に割り込んでセキュリティをチェックするためのもの
Servlet Servletオブジェクトでインジェクションを可能にしServletイベントをCDIイベントとして伝播させるようにするServlet APIとの統合のためのもの
Test-Control CDIベースのテストを簡単に書けるようにするためのもの

DeltaSpikeモジュールの使い方

DeltaSpikeの機能は独立した複数のモジュールとして提供されています。各モジュールはMavenのライブラリとして提供されていて、開発者はモジュールを選択してpom.xmlの依存ライブラリとして設定します。つまり、アプリケーション開発者はそのプロジェクトが必要とするモジュールだけを選択して取り込むことが可能です。

Java EEアプリケーションであればJSFやJPAのモジュールを含むDeltaSpikeのフル機能を使うことができます。しかし、JSFやJPAを使わないJava EEアプリケーションであってもDeltaSpikeを十分活用することができます。GUIはJSFではなくてJavaScriptライブラリを使うという場合は、JSF以外のモジュールについては利用可能です。Java SEアプリケーション開発の場合は、CDIコンポーネント開発を楽にするユーティリティや単体テストのためにCoreモジュールを使うことができるでしょう。

当ブログでは、今後、DeltaSpikeの代表的なモジュールについて紹介していこうと考えています。CDIを使って開発をするときの単体テストの方法は切実な問題だと思います。さらに、テスト時に、本番環境とは異なるテスト専用のBeanに差し替える方法も重要です。次回はこれらのテーマをカバーするCoreモジュールのProjectStageとTest-Controlモジュールについて紹介する予定です。

 

Apache DeltaSpike 1.0

待望のApacheDeltaSpike 1.0が6月14日にリリースされました。2011年の12月にincubatorプロジェクトとして開始してから、約2年半の歳月を経て、バージョン1.0がようやくリリースされたのです(DeltaSpikeプロジェクトの誕生の経緯はこちらを参照ください)。言うまでもなく、1.0というバージョンはプロジェクトにとって多くのユーザが使いはじめる重要なバージョンになります(このブログを公開した時点ではすでにバージョン1.0.1がリリースされていますので、これからダウンロードする方は最新版を使ってくださいね)。

DeltaSpikeの機能概要

DeltaSpike 1.0が提供する機能は3つに分類できます。

  • Java EE以外の環境に提供するJava EE 7ライクな機能 (表1)
  • JSFをより使いやすくするための機能 (表2)
  • アプリケーション開発の生産性を改善する機能 (表3)
表1:非Java EE環境に提供するJava EE 7 機能
機能 概要
@Transactionalアノテーション EJB以外のBeanでトランザクションを制御可能にする
インジェクション可能なサーブレットオブジェクト Java EE 6/CDI 1.0環境でCDI Beanをサーブレットにインジェクションできる
インジェクション可能なリソース コンフィギュレーションやリソースバンドルを簡単にインジェクトできる
@Excludeアノテーション CDIの有効な環境でもCDIの処理の対象にならないようにする
スケジューリングタスク 非Java EE 7環境で実行可能な非同期プロセス
Beanバリデーション統合 CDI BeanIとEJBバリデーションをConstraint-Validatorにインジェクトできる
BeanProvider JPA-2.0 EntityListenersやSpring BeansBeanManagerのような非管理クラスにおいて CDI beansにアクセスできる
表2:JSFの改善機能
機能 概要
マルチウィンドウ処理  バッチのための論理的なウィンドウを管理できるようにする。JSFの場合はブラウザタブを独立して扱えるようになる。
タイプセーフ view-config (セキュリティなどの) メタデータをビューに柔軟に結びつけることを可能にする。JSFの場合はより頑丈なナビゲーションを提供し、メンテナンスフェーズの助けとなる。
View-Controller タイプセーフ view-configをベースとして、view-controllerアノテーションは標準タグのタイプセーフな代替を提供する。
コンバータとバリデータに関するインジェクション CDI BeanとEJZBをJSFコンバータとバリデータへインジェクト可能にする。
CDIへのJSFイベントブロードキャスト JSFイベントに関する通知をCDIで受けられるようにする。
表3:生産性の改善機能
機能 概要
アノテーションベースのセキュリティ 頑強で、使えて、アプリケーションに侵入しない(non invasive) なセキュリティソリューションを構築する基盤※ non invasive(非侵襲的)とはアプリのコードにフレームワークやコンテナ依存のコードが入り込まないような方法
新しい CDI スコープ TransactionScoped, WindowScoped, ViewScoped, ViewAccess scope, Grouped conversion scope
コンテナ制御とテスト制御 Java SEでCDIが使える。開始、停止、実行中のCDIコンテナへのクラスの追加などの統一されたAPIを提供。
データモジュール エンティティ・フレームワークのソリューション。JDBCとともに、コンテナ管理またはアプリケーション管理の永続コンテキストをサポートする。
分離された例外処理 CDIオブザーバと同様に例外処理を一箇所で実行できるようにする。
JMXの統合 任意のCDI Beanが1つのアノテーションによって簡単にJMXで公開できる。
タイプセーフi18n メッセージ インタフェースやリソースバンドルと一緒にローカライズされたメッセージを簡単に使える。メッセージがソースコードという文脈の中でわかりやすくなる。
タイプセーフProject-Stages JSFでのProject stageと比べて、DeltaSpikeはタイプセーフであるにもかかわらず拡張可能な方法を提供できるし、CDIベースのアプリケーションで使うことができる。

CDI仕様は、拡張可能なコンテキスト(スコープの実装)とタイプセーフなインジェクションを提供します。DeltaSpikeが提供する機能には、「新しいスコープ」、「タイプセーフ」、「インジェクション」という言葉が目立つのはそのような理由からです。DeltaSpikeはこれらのCDIのコンセプトを使ったユーティリティやライブラリ機能をCDIコンテナ上で動作するポータブルなCDI拡張 (Extension) として提供します。

新しいJava EE はCDIをベースにサービスが統合され、サービス間で連携します。CDIは単なるインジェクションのフレームワークではなく、Java EEの背骨に相当するコアな仕様です。古いJava EEではEJBやJMSなどの仕様ごとに縦割りでアノテーションが決められてきました。CDIはJava EEを構成するサービスを横方向に連携させるものです。

将来Java EEが提供する新しいサービスとユーザによってCDIで作られたサービスは、同じCDI上のサービスという点では違いが無くなっていくことでしょう。私は、CDIの登場によって、Java EEが閉じたJava EEから、拡張可能な開かれたJava EEになったと考えています。DeltaSpikeの提供する機能は、Java EEに取り込むことでJava EEの機能をコミュニティの力によって拡張するものです。足りないものがあれば作れば良い。そこに魅力を感じます。

 

Apache DeltaSpike 0.6 リリース

DeltaSpike 0.6がリリースされました。MLでの議論をみると0.6の次のバージョンは1.0になるようです。

DeltaSpike

リリースノート

Git Repository

ドキュメント

Apache DeltaSpike 0.5 リリース

9月18日にTwitterの@DeltaSpikeTeamからバージョン0.5のリリースアナウンスがありました。
ソースコードはApacheのgitリポジトリから以下のようにしてダウンロードできます。

git clone https://git-wip-us.apache.org/repos/asf/deltaspike.git

リリースノートはプロジェクトの deltaspike/readme/ReleaseNotes-0.5.txt にあります。
0.5になってオプションモジュールが増えました。新モジュールは以下の3つ。

  • DeltaSpike-Data
  • DeltaSpike-Servlet
  • DeltaSpike-BeanValidation

DeltaSpikeのモジュール全体のドキュメントはhttp://deltaspike.apache.orgにありますが、0.5のモジュールについては現時点ではまだ説明が十分されていません。これらのモジュールのAPIや使い方については各モジュールディレクトリ配下のドキュメントやサンプルを見てください(Dataについてはdeltaspike/modules/data/README.adocに説明が書いてありましたよ)。

Apache DeltaSpike 0.4 リリース

6月1日にApache DeltaSpike 0.4がリリースされました。これはDeltaSpikeがApacheトッププロジェクトに昇格したからの最初のリリースになります。

DeltaSpike

JIRA

0.4 リリースノート

Git Repository

ドキュメント

Git Repositoryは、トッププロジェクトに昇格後に従来のGitHubから現在の場所に変更されていますので注意してください。

今回のリリースでは、JSFモジュールが追加されてタイプセーフなビューのナビゲーションがサポートされています。0.3がリリースされてからだいぶ時間が経過しているので、既存機能についてもいろいろと改善されています。詳しくはリリースノートをチェックしてください。

%d人のブロガーが「いいね」をつけました。