jjug 11月ナイトセミナー cdiをはじめよう
DESCRIPTION
JJUG 11月ナイトセミナーの発表資料です。 DI使用時のインタフェース使用の要否については、はてなブログにて補足しています。 http://n-agetsuma.hatenablog.com/entry/2013/12/11/211017TRANSCRIPT
CDIをはじめよう NTTコムウェア株式会社 上妻 宜人 (あげつま のりと)
はてなブログ : n-agetsuma.hatenablog.com
JJUG ナイト・セミナー 『Java EE 特集』
Copyright © NTT COMWARE 2013
Java EE 6 からついにEJBを使わない
DI/AOPコンテナ仕様が入りました
(2009年リリース)
少し前の話になりますが…
DI求めてSpringに行かれた方、帰ってきて!
ロッド・ジョンソン 氏 著 邦訳 : 実践J2EEシステムデザイン
(Spring Framework 2002~)
本日のテーマ
Context and Dependency InjecOon
本日のコンテンツ
• Dependency Injection - DI の復習
• CDIの機能紹介
• インジェクション と スコープ
• EL式との連携
• インターセプタ
• CDIのコンフィグ beans.xml
• CDIの使いどころ/EJBとの機能比較
• CDIをもっと学ぶためには – 参考文献
コンテキスト (スコープ)を持った
依存性の注入
Context and Dependency InjecOon
Context and Dependency InjecOon
コンテキスト (スコープ)を持った
依存性の注入
Web3層構造で振り返る Dependency InjecOon の復習
Web3層構造とnewによる依存性の連続性
ClassA
依存先 クラス
依存先 クラス
さらなる 依存先クラス
さらなる 依存先クラス
さらなる 依存先クラス
new
new
new
new
new
DBMS
関連他システム
メールサーバ
Service
Service
REST Endpoint
DAO/Repository
JAX-‐WS Client
Mail Client
Web3層構造とnewによる依存性の連続性
ClassA
依存先 クラス
依存先 クラス
さらなる 依存先クラス
さらなる 依存先クラス
さらなる 依存先クラス
new
new
new
new
new
DBMS
関連他システム
メールサーバ
Service
Service
REST Endpoint
DAO/Repository
JAX-‐WS Client
Mail Client
テストしたいのはREST Endpointだけの場合
ClassA
依存先 クラス
依存先 クラス
さらなる 依存先クラス
さらなる 依存先クラス
さらなる 依存先クラス
new
new
new
new
new
DBMS
関連他システム
メールサーバ
Service
Service
REST Endpoint
DAO/Repository
JAX-‐WS Client
Mail Client
テスト 対象
依存性の連続で結局全部必要になる
ClassA
依存先 クラス
依存先 クラス
さらなる 依存先クラス
さらなる 依存先クラス
さらなる 依存先クラス
new
new
new
new
new
DBMS
関連他システム
メールサーバ
Service
Service
REST Endpoint
DAO/Repository
JAX-‐WS Client
Mail Client
テスト 対象
ユニットテストに
必要なクラス
依存性でユニットテストしにくい
時間がないのでユニットテスト困難
ユニットテストしない
時間を消費
終的に
こうしてテストのない レガシーコードが生まれ続ける。
参考 : 翔泳社 レガシーコード改善ガイド
まずはインタフェースに依存を切り替えて
ClassA
インタフェース
インタフェース
さらなる 依存先クラス
さらなる 依存先クラス
さらなる 依存先クラス
call
call
new
new
new
DBMS
関連他システム
メールサーバ
Service
Service
REST Endpoint
DAO/Repository
JAX-‐WS Client
Mail Client
実装クラス
実装クラス
ここでnewしてしまうと効果があまりない
ClassA
インタフェース
インタフェース
さらなる 依存先クラス
さらなる 依存先クラス
さらなる 依存先クラス
call
call
new
new
new
DBMS
関連他システム
メールサーバ
Service
Service
REST Endpoint
DAO/Repository
JAX-‐WS Client
Mail Client
実装クラス
実装クラス
public class ServiceImpl implements Service { … @Override public void doBusiness() { dao.select(); } } @Path (“/sample”) public class SampleResource {
public Entity sampleMethod () { Service service = new ServiceImpl(); service.doBusiness(); …
自分でローカル変数にnewすると ユニットテスト時にDBにアクセス してしまう。
実装クラスでDBにアクセス
誰かが実装クラスを探して、 自動でnewしてほしい
DIコンテナの出番
DIコンテナが実装クラスをnewして注入
ClassA
インタフェース
インタフェース
さらなる 依存先クラス
さらなる 依存先クラス
さらなる 依存先クラス
call
call
new
new
DBMS
関連他システム
メールサーバ
Service
Service
REST Endpoint
DAO/Repository
JAX-‐WS Client
Mail Client
実装クラス
実装クラス
DIコンテナ (Spring, Seaser2, Guice, CDI)
Inject
DIコンテナが実装クラスをnewして注入
ClassA
インタフェース
インタフェース
さらなる 依存先クラス
さらなる 依存先クラス
さらなる 依存先クラス
call
call
new
new
DBMS
関連他システム
メールサーバ
Service
Service
REST Endpoint
DAO/Repository
JAX-‐WS Client
Mail Client
実装クラス
実装クラス
DIコンテナ (Spring, Seaser2, Guice, CDI)
Inject
@Path (“/sample”) public class SampleResource {
@Inject Service service;
public Entity sampleMethod () { service.doBusiness(); ..
DIコンテナが型が合う実装クラスを 探してインスタンス注入する。
ClassA
インタフェース
インタフェース
さらなる 依存先クラス
さらなる 依存先クラス
さらなる 依存先クラス
call
call
new
new
DBMS
関連他システム
メールサーバ
Service
Service
REST Endpoint
DAO/Repository
JAX-‐WS Client
Mail Client
フェイク実装
フェイク実装
JUnitテストケース
フィールドにセット
テスト時はフェイクに差替て、依存を断ち切る
再掲 : 各クラスを new で繋いだ場合
ClassA
依存先 クラス
依存先 クラス
さらなる 依存先クラス
さらなる 依存先クラス
さらなる 依存先クラス
new
new
new
new
new
DBMS
関連他システム
メールサーバ
Service
Service
REST Endpoint
DAO/Repository
JAX-‐WS Client
Mail Client
テスト 対象
ユニットテストに
必要なクラス
結果UTもしやすく、クラス間の依存も下がる
ClassA
インタフェース
インタフェース
さらなる 依存先クラス
さらなる 依存先クラス
さらなる 依存先クラス
call
call
new
new
DBMS
関連他システム
メールサーバ
Service
Service
REST Endpoint
DAO/Repository
JAX-‐WS Client
Mail Client
フェイク実装
フェイク実装
JUnitテストケース
フィールドにセット
テスト 対象
ユニットテストに
必要なクラス
DIの主なメリット
• 特にユニットテストしにくい外部リソースへの依存に効果的 • データベースへのアクセス
• メールの送信
• 他システムとの連携
• インタフェースの切り出しとDIをセットで使う
• インタフェースに依存させて実装を差し替えやすくする
• 結果的に依存の連鎖を止めることができる
各クラス間の依存性を弱めることができる
CDIはここまで説明したDIコンテナの
Java EE 版 仕様です
CDIについて
Context And Dependency Injection(コンテキストと依存性の注入)
• Java EE 6 から CDI1.0 導入
• Java EE 7 で CDI1.1 として小規模なアップデート
• DIを使って、クラス間を依存性を少なく連携させる為の仕様
JBoss AS 7 CDI1.0 準拠
GlassFish 4.0 CDI1.1 準拠
WildFly8 CDI1.1 準拠予定
Tomee 1.x CDI1.0 準拠
CDIが使えるオープンソースAPサーバ
Java EE 仕様の中でのCDI位置づけ
Web 層 ビジネス 層 永続化層
CDI (3層をDIコンテナで繋ぐ)
EJB
JAX-RS
WebSocket
JPA
Client EIS
PCブラウザ
モバイル
RDBMS 等
Java EE 7 Specifications
JSF
CDI EJBを使わない
ビジネスロジックの実現
• DI機能によって各層間の依存性を解決する
• EJB を使わないビジネスロジックの実現
→ Java EE 5 まではEJBのみDIができた
CDIの代表的な機能
• 実装インスタンスのインジェクション @Inject
- 静的な型解決 @Qualifiler
- 動的な型解決 @Produces
• スコープ @RequestScoped, @SessionScoped など
• EL式との組み合わせ
• インターセプタ @InterceptorBinding
• コンフィグ beans.xml
CDIの代表的な機能
• 実装インスタンスのインジェクション @Inject
- 静的な型解決 @Qualifiler
- 動的な型解決 @Produces
• スコープ @RequestScoped, @SessionScoped など
• EL式との組み合わせ
• インターセプタ @InterceptorBinding
• コンフィグ beans.xml
@WebServlet(“/sample”) public class SampleServlet extends HcpServlet {
@Inject private Service service;
例 : Servlet に @Inject する
APサーバが自動的にServiceインタフェースの 実装クラスを探してnewして注入
例 : RESTエンドポイントに @Inject する
@Path(“/sample”) public class SampleResource {
@Inject private Service service;
APサーバが自動的にServiceインタフェースの 実装クラスを探してnewして注入
例 : EJBも@Injectでインジェクション可能
@Path(“/sample”) public class SampleResource { // @EJB @Inject private SampleSessionBean service;
APサーバが自動的に SessionBean実装を探して注入
インジェクションされる側の条件
? <<interface>> Service
インジェクションされる側 (@Injectを書く方)
call
ServiceImpl
条件 : コンテナ管理Bean (newしてないインスタンス) であること
• Servlet 関連 @WebServlet @WebFilter @WebListener
• EJB Session Bean : @Stateless など
• JAX-‐RS RESTエンドポイント : @Path など
• CDIによって生成されたインスタンス
@Path(“/test”) public class SampleResource { @Inject Service service;
public class ServiceImpl implements Service { @Inject Repository repository;
CDIによって生成されたインスタンスには注入可能
実装クラスServiceImplの インスタンスをインジェクション
CDIによって生成されたインスタンスには注入可能
CDIによって インスタンス生成
@Path(“/test”) public class SampleResource { @Inject Service service;
public class ServiceImpl implements Service { @Inject Repository repository;
CDIによって生成されたインスタンスには注入可能
@Path(“/test”) public class SampleResource { @Inject Service service;
public class ServiceImpl implements Service { @Inject Repository repository;
public class RepositoryImpl implements Repository {…}
さらなるインジェクションが可能
CDIによって インスタンス生成
CDIに生成される側の条件
REST Endpoint 等 <<interface>> Service
call
ServiceImpl
CDIに生成される側
• 引数なしコンストラクタを含むクラス
• インタフェースの実装はなくても @Inject でインジェクション可能
• アノテーションもいらない完全なPOJO (Plain Old Java Object)
引数なしコンストラクタがあれば、どんなクラスも注入可能
CDIの代表的な機能
• 実装インスタンスのインジェクション @Inject
- 静的な型解決 @Qualifiler
- 動的な型解決 @Produces
• スコープ @RequestScoped, @SessionScoped など
• EL式との組み合わせ
• インターセプタ @InterceptorBinding
• コンフィグ beans.xml
インタフェースの実装が複数ある場合は?
A. インジェクションフィールドがnullのまま
B. デプロイに失敗する
C. 初にロードしたクラスをインジェクション
<<interface>> DAO
OracleDAO
PostgresDAO
@Inject private DAO dao;
インジェクション先コード
実装クラスが複数ある
インタフェースの実装が複数ある場合は?
A. インジェクションフィールドがnullのまま
B. デプロイに失敗する
C. 初にロードしたクラスをインジェクション
<<interface>> DAO
OracleDAO
PostgresDAO
@Inject private DAO dao;
インジェクション先コード
実装クラスが複数ある
静的な型解決 : Qualifier (修飾子) の使用
1. @Qualifier が付与されたアノテーションを作成
@Qualifier @RetenOon (RunOme) @Target ({METHOD, FIELD, PARAMETER, TYPE}) public @interface Oracle {}
静的な型解決 : Qualifier (修飾子) の使用
2. インジェクション先とBean両方に付与する
@Inject @Oracle private DAO dao;
@Oracle public class OracleDAO …
@PostgreSQL public class PostgresDAO …
OracleDAOをインジェクションしたい場合は@Injectと@Oracleを指定
静的な型解決 : Qualifier (修飾子) の使用
3. インジェクション対象を変更したい場合
@Inject @PostgreSQL private DAO dao;
@Oracle public class OracleDAO …
@PostgreSQL public class PostgresDAO …
PostgresDAOをインジェクションしたい場合は修飾子を書き換える。
実行時に実装型の解決をしたい場合
<<REST Endpoint>> ChargeResource
@Path(“/charge”)
PaypalService
で支払う
で支払う SquareService
<<interface>> ChargeService
ユーザA
ユーザB ユーザに応じて実装を変えたい
動的な型解決 : @Produces
<<REST Endpoint>> ChargeResource
@Path(“/charge”) @Credit
PaypalService SquareService
<<interface>> ChargeService
<<Producer>> PaymentStrategy
@Credit @Produces
return結果をInject
依存 依存
@Produces メソッドと限定子を併用して動的な型の解決を行う
インジェクションする型の 判断ロジックを実装
プロデューサのコード例
<<REST Endpoint>> ChargeResource
@Path(“/charge”)
PaypalService SquareService
<<interface>> ChargeService
<<Producer>> PaymentStrateg
y
@Produces
return結果をInject
依存 依存
@RequestScoped public class PaymentStrategy {
private PaymentType paymentType;
@Credit @Produces public ChargeService getStrategy(PaypalService paypal, SqureService square) { switch (paymentType) { case PayPal : return paypal; case Square : return square; }
}
…
@Path (“/charge”) public class ChargeResource { @Inject @Credit ChargeService service; …
プロデューサメソッドのコード例
<<REST Endpoint>> ChargeResource
@Path(“/charge”)
PaypalService SquareService
<<interface>> ChargeService
<<Producer>> PaymentStrateg
y
@Produces
return結果をInject
依存 依存
@RequestScoped public class PaymentStrategy {
private PaymentType paymentType;
@Credit @Produces public ChargeService getStrategy(PaypalService paypal, SqureService square) { switch (paymentType) { case PayPal : return paypal; case Square : return square; }
}
…
返り値型(ChargeService)と 限定子(@Credit)で括り付けられる。
@Path (“/charge”) public class ChargeResource { @Inject @Credit ChargeService service; …
限定子を忘れると、型が不定となるデプロイエラーが発生するので注意
プロデューサメソッドのコード例
<<REST Endpoint>> ChargeResource
@Path(“/charge”)
PaypalService SquareService
<<interface>> ChargeService
<<Producer>> PaymentStrateg
y
@Produces
return結果をInject
依存 依存
@RequestScoped public class PaymentStrategy {
private PaymentType paymentType;
@Credit @Produces public ChargeService getStrategy(PaypalService paypal, SqureService square) { switch (paymentType) { case PayPal : return paypal; case Square : return square; }
}
…
実装インスタンスはメソッド引数に APサーバから渡される
@Path (“/charge”) public class ChargeResource { @Inject @Credit ChargeService service; …
プロデューサメソッドのコード例
<<REST Endpoint>> ChargeResource
@Path(“/charge”)
PaypalService SquareService
<<interface>> ChargeService
<<Producer>> PaymentStrateg
y
@Produces
return結果をInject
依存 依存
@RequestScoped public class PaymentStrategy {
private PaymentType paymentType;
@Credit @Produces public ChargeService getStrategy(PaypalService paypal, SqureService square) { switch (paymentType) { case PayPal : return paypal; case Square : return square; }
}
…
インジェクションしたい実装を 条件に応じてreturnする。
@Path (“/charge”) public class ChargeResource { @Inject @Credit ChargeService service; …
CDIの代表的な機能
• 実装インスタンスのインジェクション @Inject
- 静的な型解決 @Qualifiler
- 動的な型解決 @Produces
• スコープ @RequestScoped, @SessionScoped など
• EL式との組み合わせ
• インターセプタ @InterceptorBinding
• コンフィグ beans.xml
@RequestScoped : リクエスト受付~応答まで
クライアント サーバ
request
response
リクエスト毎にインジェクションしなおす
@RequestScoped public class SampleBean { … } @Path (“/sample”) public class SampleResource { @Inject SampleBean bean;
@SessionScoped public class User implements Serializable { … } @Model // JSF2.x public class SampleController { @Inject User user;
@SessionScoped : ログイン~ログアウト
クライアント サーバ
同一セッション中は、状態が保持された 同じインスタンスがインジェクションされる
Login
Logout
@ConversaOonScoped : Session未満の任意長さ
クライアント サーバ
@Named @ConversaOonScoped public class ConversaOonController implements Serializable { @Inject private ConversaOon conversaOon; public void begin() { … conversaOon.begin(); } public void end() { … conversaOon.end(); }
Begin
End
Login
Logout
アプリケーションスコープの使い分け
生存期間 初期化から~ アンデプロイまで
デプロイ時初期化 @Startup
ない
同じ 同じ
@ApplicaOonScoped (CDI)
@Singleton (JSR-‐330)
@Singleton (EJB)
ある
ロック制御 @Lock ない ある
ない @WebListnerと組合せが必要
ない 左記に同じ
シリアライズ対応 (クラスタ考慮?) ある ない 仕様に言及なし
• アプリケーションスコープ @javax.enterprise.context.ApplicaOonScoped
• JSR-330のシングルトン @javax.inject.Singleton
• EJBのシングルトン @javax.ejb.Singleton
似たような機能が複数ある
@Startupや@Lockが使いたい場合はEJBがお勧め。
@WebServlet(“/sample”) public class SampleServlet extends HcpServlet {
@Inject private Service service; // デフォルトは @Dependent であると暗黙的に判定 public class ServiceImpl extends Service {…}
@Dependent : インジェクション先に合わせる (default)
Servlet <<interface>> Service
サーブレットは シングルインスタンス
call
ServiceImpl
サーブレット生成時に 一度だけインジェクション
CDIで使用可能なスコープ一覧
• リクエストスコープ @javax.enterprise.context.RequestScoped
• 会話スコープ @javax.enterprise.context.ConversaOonScoped
• セッションスコープ @javax.enterprise.context.SessionScoped
• アプリケーションスコープ @javax.enterprise.context.ApplicaOonScoped
短い
長い
• 依存先に応じる(デフォルト) @javax.enterprise.context.Dependent
• シングルトン @javax.inject.Singleton
スコープ
擬似スコープ (pseudo scope)
CDIの代表的な機能
• 実装インスタンスのインジェクション @Inject
- 静的な型解決 @Qualifiler
- 動的な型解決 @Produces
• スコープ @RequestScoped, @SessionScoped など
• EL式との組み合わせ
• インターセプタ @InterceptorBinding
• コンフィグ beans.xml
JSF 2.x / CDI : @NamedによるELバインディング
<h:inputSecret value=“#{password.now} “ ..
@Named @RequestScope public class Password { private String now; …
@Named @RequestScope public class PassController { @Inject private Password password; …
CDIの代表的な機能
• 実装インスタンスのインジェクション @Inject
- 静的な型解決 @Qualifiler
- 動的な型解決 @Produces
• スコープ @RequestScoped, @SessionScoped など
• EL式との組み合わせ
• インターセプタ @InterceptorBinding
• コンフィグ beans.xml
インターセプタとは
Intercep
tor
Intercep
tor
注文受付クラス
課金業務クラス
発送業務クラス
メソッド開始 完了
メソッドの開始・終了に割込み,業務とは直接関連ないシステム処理を実行
共通処理
代表的なインターセプタ
• ロギング
• セキュリティ関連 (認証や認可処理)
• トランザクションの開始、コミット、ロールバック制御
共通処理
インターセプタの作り方
@InterceptorBinding @Target ({Method, TYPE}) @RetenOon(RunOme) public @interface Logging {}
1. アノテーション作る 2. インターセプタ実装を作る
@Logging @Interceptor public class LoggingInterceptor { … @AroundInvoke public void log(InvocaOonContext ic) { logger.debug(“log message”); return ic.proceed(); }
@Logging public void charge(int amount) {…}
3. インターセプタ対象にバインドさせる
@InterceptorBindingを付与した自作アノテーションで実装と対象を関連付け
インターセプタの優先順位は?
注文受付クラス
課金業務クラス
発送業務クラス
インターセプタ順序を定義したい
トラ
ンザ
クシ
ョン
開始
セキ
ュリ
ティ
処理
ロギ
ング
処理
業務処理 1 2 3開始 終了
インターセプタの順序が重要な場合も多くある。
インターセプタとコンフィグ Java EE 6 ではXMLが必須、 EE 7 では @Priority が導入
• Java EE 6 の場合 : WEB-‐INF/beans.xml に設定 (1つしかなくても必須)
<beans> <interceptors> <class>interceptor.LoggingInterceptor</class> <class>intreceptor.SampleIntreceptor</class> </interceptors> </beans>
先に実行される
後に実行される
• Java EE 7 の場合 : XMLなしで、@Priority で代用が可能
@Logging @Interceptor @Dependent @Priority(ApplicaOon+10) public class LoggingInterceptor {
@Sample @Interceptor @Dependent @Priority(ApplicaOon+20) public class SampleInterceptor {
先に実行される 後に実行される
CDIの代表的な機能
• 実装インスタンスのインジェクション @Inject
- 静的な型解決 @Qualifiler
- 動的な型解決 @Produces
• スコープ @RequestScoped, @SessionScoped など
• EL式との組み合わせ
• インターセプタ @InterceptorBinding
• コンフィグ beans.xml
beans.xmlの配置
• Java EE 6 の場合 : WEB-‐INF/beans.xml を含めるとCDIが有効化
Java EE 6 ではbeans.xmlが必須、EE 7 からはオプション化
• Java EE 7 の場合 : beans.xmlなしで有効化されるが、スコープ指定が必須
@Dependent public class ServiceImpl implements .. {
インジェクション先のスコープと同じにする場合でも、 省略せずに明示的に @Dependent を付与する。
インターセプタがない場合は、 中身は空ファイルで良い。
CDIを Java EE アプリでどう使うか
REST Endpoint (JAX-‐RS2.x)
Service (CDI Bean)
Repository (JPA2.x)
RDBMS BackingBean (JSF2.x)
WebSocket
Web 層 ビジネス 層 永続化層
RDBMS以外の 永続化機構 (KVSなど)
クライアント
Java EE の 3層アーキテクチャ
Servlet
技術の変化が激しい部分は、ロジックとは別層 (クラス)に切り出す
3層モデルの依存性をDIで繋ぐ
3層モデルの依存性をDIで繋ぐ
REST Endpoint (JAX-‐RS2.x)
Service (CDI Bean)
Repository (JPA2.x)
RDBMS BackingBean (JSF2.x)
WebSocket
Web 層 ビジネス 層 永続化層
RDBMS以外の 永続化機構 (KVSなど)
クライアント
Java EE の 3層アーキテクチャ
Servlet
ビジネスロジックは特定技術に依存したくない
業務例 : ・ 電話設備の登録/削除を行う ・ 支払いがなければ督促する
WebSocketが出ても、KVSが出ても 業務ロジックコードは変えたくない
3層モデルの依存性をDIで繋ぐ
REST Endpoint (JAX-‐RS2.x)
Repository (JPA2.x)
RDBMS BackingBean (JSF2.x)
WebSocket
Web 層 ビジネス 層 永続化層
RDBMS以外の 永続化機構 (KVSなど)
クライアント
Java EE の 3層アーキテクチャ
Servlet
シンプルに new で繋いでいくと …
Service (CDI Bean)
new new
new
3層モデルの依存性をDIで繋ぐ
REST Endpoint (JAX-‐RS2.x)
Repository (JPA2.x)
RDBMS BackingBean (JSF2.x)
WebSocket
Web 層 ビジネス 層 永続化層
RDBMS以外の 永続化機構 (KVSなど)
クライアント
Java EE の 3層アーキテクチャ
Servlet
冒頭の通り依存性が強くテストできない等 の課題
Service (CDI Bean)
new new
new
テスト 対象
テストに必要
3層モデルの依存性をDIで繋ぐ
REST Endpoint (JAX-‐RS2.x)
Service (CDI Bean)
Repository (JPA2.x)
RDBMS
Web 層 ビジネス 層 永続化層
クライアント
Java EE の 3層アーキテクチャ
@Injectでユニットテストしやすく、依存性を少なく。
@Path(“/sample”) public class Resource {
@Inject private Service service;
public class Service {
@Inject private Repository …
public class Repository {
@PersistenceContext private EnOtyManager ..
REST処理 業務処理 DBアクセス
インジェクション
インジェクション
EJBとの使い分け
@Transactional の導入 (Java EE 7)
EJBの宣言的トランザクションがCDIでもできるようになった
public class BankService { … // 口座振り替えメソッド @TransacOonal(TransacOonal.TxType.REQUIRED) public void transfer(int amount) { pay(amount); // 振り込み元から出金 receipt(amount); // 振込み先に入金 }
• Spring の@TransacOonalと同じように使える
• RunOmeExcepOonがthrowされたら自動的にロールバック
CDIとEJBの機能の比較
DI/AOP
CDI1.1 EJB3.1
EL式連携
ある (@Inject 等)
ある (@Inject, @EJB 等)
ない ある
(@Named)
ある (@RequestScoped 等) スコープ ない
(@Stateless or @Stateful)
宣言的 トランザクション
ある (@Stateless or @Stateful)
ある (@TransacOonal)
非同期実行 ある (@Asynchronous)
ない
MQ連携 ある (@MDB)
ない
リモート実行 ある (@Remote)
ない
タイマ機能 ある (@Schedule)
ない
Web構築にはCDIで十分、基幹機能はEJB継続使用
DI/AOP
CDI1.1 EJB3.1
EL式連携
ある (@Inject 等)
ある (@Inject, @EJB 等)
ない ある
(@Named)
ある (@RequestScoped 等) スコープ ない
(@Stateless or @Stateful)
宣言的 トランザクション
ある (@Stateless or @Stateful)
ある (@TransacOonal)
非同期実行 ある (@Asynchronous)
ない
MQ連携 ある (@MDB)
ない
リモート実行 ある (@Remote)
ない
タイマ機能 ある (@Schedule)
ない
Web構築 に使う
基幹システムで 使う
CDIをより深く学ぶためには
CDIのマニュアル・ドキュメント 等
• Weldのドキュメント (CDI参照実装) • hcp://docs.jboss.org/weld/reference/2.0.3.Final/en-‐US/
• Java EE 7 Turial -‐ PartⅤ Context and Dependency InjecOon for Java EE
• hcp://docs.oracle.com/javaee/7/tutorial/doc/partcdi.htm
• CDI 1.1 仕様書
• hcp://jcp.org/en/jsr/detail?id=346
• 書籍 : O’Reilly Java EE 7 EssenOals
• hcp://shop.oreilly.com/product/0636920030614.do
• 書籍 : Apress Beginning Java EE 7
• hcp://www.apress.com/9781430246268
© O’Reilly Media, Inc.
© Apress Media LLC
GlassFish4 を今すぐダウンロードして是非試してみてください!
ご清聴ありがとうございました。
hcps://glassfish.java.net/download.html
OracleとJavaは、Oracle CorporaOon 及びその子会社、関連会社の米国及びその他の国における登録商標です。 文中の社名、商品名等は各社の商標または登録商標である場合があります。