Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
CDI2.0アップデート	
& クックブック	
2016/05/24 上妻 宜人 (あげつま のりと)	
Java Day Tokyo 2016/Java EE Session 4-C
上妻 宜人 あげつま のりと	
•  SIer技術部門でJavaトラブルシューティングの日々	
•  Java EEについて調べて伝えることが好き	
•  コミュニティ講演	
•  GlassFish.JP, JJUG CCC, Java Da...
本日のコンテンツ	
•  駆け足で振り返るCDI	
•  CDI2.0	
•  CDI + α 	
•  最後に
CDI	Context	and	Dependency	Injec0on	
2009/12	CDI1.0	-	Java	EE	6	
2013/5			CDI1.1	-	Java	EE	7	
2014/4			CDI1.2			(maintenan...
CDIの目的	
1.	DI/AOPを中心とした疎結合コードの実現	
					@Inject,	@InterceptorBinding,	@Decorator,	Event	
	
2.	コンテキストを持つオブジェクトのライフサイクル管理	
		...
CDI	実装製品	
•  Weld	(参照実装)	-	jboss.org	
•  GlassFish,	WildFly/JBossEAP,	WebLogic	
•  OpenWebBeans	-	Apache	SoZware	Founda0on...
Context	and	Dependency	Injec0on:	
CDI管理Beanの定義	
// ライフサイクル: デプロイ〜アンデプロイまで%
public class Controller {%
%
%
}%
%
%
// ライフサイク...
Context	and	Dependency	Injec0on:	
ランタイム例外を引き起こすコンテキスト操作	
public class Controller { %
...%
HttpSession session = request.ge...
Context	and	Dependency	Injec0on:	
CDI管理Beanの定義	
@ApplicationScoped%
public class Controller {%
%
%
}%
%
%
@SessionScoped%
...
@ApplicationScoped%
public class Controller {%
%
%
}%
%
%
@SessionScoped%
public class ShoppingCart implements Cart {...}%...
Context	and	Dependency	Injec0on:	
@Injectでタイプセーフに取得	
@ApplicationScoped%
public class Controller {%
@Inject%
Cart cart;%
}...
Context	and	Dependency	Injec0on:	
@InterceptorBinding	-		タイプセーフなインターセプタ適用	
Log	 target	
// target%
@ApplicationScope%
publ...
Context	and	Dependency	Injec0on:	
@InterceptorBinding	-		タイプセーフなインターセプタ適用	
Log	 target	
// target%
@ApplicationScope%
publ...
Context	and	Dependency	Injec0on:	
@InterceptorBinding	-		タイプセーフなインターセプタ適用	
Log	 target	
// target%
@ApplicationScope @Log%...
CDI1.1の変更点 (Java	EE	7)		
beans.xmlのオプション化	
•  beans.xmlなしでCDI有効化	
•  スコープを持つクラスはすべてCDI管理Bean	
@RequestScoped, @SessionScop...
CDI1.1の変更点 (Java	EE	7)	
beans.xmlのオプション化	
•  @Priority	
•  主にインターセプタ有効化 & 優先順位付けに使用	
•  Interceptorの有効化にbeans.xmlが不要に	
@In...
CDI1.1の変更点 (Java	EE	7)	
@Priorityによるインターセプト順序の定義	
@Interceptor @Timeout%
@Priority(Interceptor.Priority.APPLICATION + 10)%...
CDI1.1の変更点 (Java	EE	7)	
スコープ開始・終了イベント	
@ApplicationScoped%
public class MasterDataCache {%
public void observer(%
@Observe...
CDI1.2の変更点 (Java	EE	7)	
JSR-330との互換性確保	
•  @javax.inject.Singletonをスキャン対象外へ	
•  デフォルトでは@SingletonはCDI管理Beanと見なされない	
•  代わり...
本日のコンテンツ	
•  駆け足で振り返るCDI	
•  CDI2.0 	
•  CDI + α	
•  最後に
CDI2.0	(Java	EE	8	/	2017)	
•  	CDI非同期イベント	
•  	仕様をサブセットに分割	
•  	Java	SE	Support	
•  	Java	SE	8	Alignment
@ApplicationScoped%
public class AlertService {%
@Inject AlertRepository repo;%
%
@Transactinal%
public void handleAlert(A...
@ApplicationScoped%
public class AlertService {%
@Inject AlertRepository repo;%
@Inject EmailSender email;%
%
@Transactina...
@ApplicationScoped%
public class AlertService {%
@Inject AlertRepository repo;%
@Inject EmailSender email;%
@Inject AlertC...
通常のメソッド呼び出し	
手続き型のデメリット	
•  機能追加毎にクラス間依存性が増加	
•  やがては蜘蛛の巣になる	
•  CDI管理Beanが持つ状態のロールバックが難しい	
•  宣言的トランザクションがコミット失敗した場合、	
トラ...
CDIイベントの振り返り	
イベント発火側のコード	
Alert	
Service	
Alert	
Repository	
Email	
Sender	
Alert	
Cache	
CDI	Event	
@ApplicationScoped%
...
CDIイベントの振り返り	
オブザーバの実装	
Alert	
Service	
Alert	
Repository	
Email	
Sender	
Alert	
Cache	
CDI	Event	
@ApplicationScoped%
pub...
CDIイベントの振り返り	
イベントの発火	
Alert	
Service	
Alert	
Repository	
Email	
Sender	
Alert	
Cache	
CDI	Event	
@ApplicationScoped%
publ...
CDIイベントの振り返り	
イベントモデルの一般的な利点	
Alert	
Service	
Alert	
Repository	
Email	
Sender	
Alert	
Cache	
CDI	Event	
Alert	
Service	
A...
CDI	
Container	
Subject	
@Observe	
Observer	#1	
@Observe	
Observer	#2	
1.fire()	
2.call	back	#1	
3.call	back	#2
CDI	
Container	
Subject	
@Observe	
Observer	#1	
@Observe	
Observer	#2	
1.fire()	
thread	
2.call	back	#1	
3.call	back	#2	
fi...
CDI2.0	#1	
CDI2.0	非同期イベント
CDI2.0	非同期CDIイベント	
イベント発火側の実装	
@ApplicationScoped%
publilc class AlertService {%
%
@Inject Event<Alert> event;%
%
public v...
CDI2.0	非同期CDIイベント	
イベント発火側の実装	
@ApplicationScoped%
publilc class AlertService {%
%
@Inject Event<Alert> event;%
%
public v...
CDI2.0	非同期CDIイベント	
イベント発火側の実装	
@ApplicationScoped%
publilc class AlertService {%
%
@Inject Event<Alert> event;%
%
public v...
CDI2.0	非同期CDIイベント	
コンテナ管理スレッドの利用 (Concurrency	U0li0es	for	Java	EE)	
@ApplicationScoped%
publilc class AlertService {%
%
@I...
CDI2.0	非同期CDIイベント	
全オブザーバの終了待ち受け	
@ApplicationScoped%
publilc class AlertService {%
%
@Inject Event<Alert> event;%
@Resour...
CDI2.0	非同期CDIイベント	
Observer側の実装	
@ApplicationScoped%
publilc class AlertCache {%
%
ConcurrentMap<Long, Alert> cache = ...;...
CDI2.0	非同期CDIイベント	
Observer側の実装	
@ApplicationScoped%
publilc class AlertCache {%
%
ConcurrentMap<Long, Alert> cache = ...;...
CDI	
Container	
Subject	
@ObserveAsync	
Observer	#1	
@ObserveAsync	
Observer	#2	
fireAsync()	
call	back	
call	back	
fireAsy...
CDI	
Container	
Subject	
@ObserveAsync	
Observer	#1	
@ObserveAsync	
Observer	#2	
call	back	
call	back	
transac0on	#1	
tran...
CDI2.0	非同期CDIイベント	
Observerから例外がスローされたらどうなる?	
@ApplicationScoped%
publilc class AlertService {%
%
@Inject Event<Alert> eve...
CDI2.0	非同期CDIイベント	
Comple0onStage.excep0onallyによる例外ハンドリング	
@ApplicationScoped%
publilc class AlertService {%
%
@Inject Eve...
CDI2.0	非同期CDIイベント	
CDI2.0より非同期実行に対応	
CDI1.2		
(Java	EE	7)	
CDI2.0	
(Java	EE	8)	
プラグイン	
(型依存の分離)	
非同期実行	
(実行タイミングの分離)	
○	 ○...
CDI2.0	非同期CDIイベント	
@MDBとCDI非同期イベント	
CDI1.2		
(Java	EE	7)	
CDI2.0	
(Java	EE	8)	
JMS	
プラグイン	
(型依存の分離)	
非同期実行	
(実行タイミングの分離)	
...
CDI1.2		
(Java	EE	7)	
CDI2.0	
(Java	EE	8)	
JMS	
プラグイン	
(型依存の分離)	
非同期実行	
(実行タイミングの分離)	
メッセージ永続化	
Observerの	
別マシン実行	
CDI2.0	...
CDI2.0	非同期CDIイベント	
@MDBとCDI非同期イベント	
CDI1.2		
(Java	EE	7)	
CDI2.0	
(Java	EE	8)	
JMS	
プラグイン	
(型依存の分離)	
非同期実行	
(実行タイミングの分離)	
...
CDI2.0	非同期CDIイベント	
CDI非同期イベントが適するケース	
•  順序性,	依存性のない処理の並列実行	
•  例外時のCDI管理Bean状態ロールバック	
•  トランザクション中に変更したステートを元に戻す	
•  メッセー...
CDI2.0	#2	
仕様をサブセットに分割
CDI2.0	仕様をサブセットに分割	
CDI	Lite	軽量なサブセットの抽出	
•  CDIを	Java	EE	以外の世界で使ってもらいたい	
•  Android,	組込みデバイス	
•  現状のCDI仕様はJava	EE環境を前提	
•...
CDI2.0	仕様をサブセットに分割	
CDI	Lite	軽量なサブセットの抽出	
CDI	core	
•  DI	-	@Inject,	Qualifier	
•  @Produces	
•  Event	&	@Observes	
•  疑似スコ...
CDI2.0	#3	
Java	SE	Support
public static void main(String ... args) {%
try (CDI<Object> cdi = CDI.getCDIProvider().initialize()) {%
Service service =...
CDI2.0	Java	SE	Support	
“仕様”として含める背景	
•  Java	EE	仕様間での整合性	
•  JAX-RS	,	JPAは Java	SE	でも利用可能な仕様設計	
•  Weld,	OpenWebBeansで既に実...
CDI2.0	#4	
Java	SE	8	Alignment
CDI2.0	Java	SE	8	Alignment	
InterceptorBuilder:	ラムダ	or	メソッド参照によるインターセプタ	
public class InterceptorBuilder {%
// デプロイ時にCDIコン...
CDI2.0	Java	SE	8	Alignment	
InterceptorBuilder:	ラムダ	or	メソッド参照によるインターセプタ	
public class InterceptorBuilder {%
// デプロイ時にCDIコン...
CDI2.0	Java	SE	8	Alignment	
InterceptorBuilder:	ラムダ	or	メソッド参照によるインターセプタ	
public class InterceptorBuilder {%
// デプロイ時にCDIコン...
CDI2.0	Java	SE	8	Alignment	
InterceptorBuilder:	ラムダ	or	メソッド参照によるインターセプタ	
public class InterceptorBuilder {%
// デプロイ時にCDIコン...
CDI2.0	Java	SE	8	Alignment	
InterceptorBuilder:	ラムダ	or	メソッド参照によるインターセプタ	
event.addInterceptor()%
...%
.addBinding(Log.INST...
CDI2.0	Java	SE	8	Alignment	
InterceptorBuilder:	ラムダ	or	メソッド参照によるインターセプタ	
event.addInterceptor()%
...%
.addBinding(Log.INST...
CDI2.0	Java	SE	8	Alignment	
InterceptorBuilder:	ラムダ	or	メソッド参照によるインターセプタ	
event.addInterceptor()%
...%
.addBinding(Log.INST...
CDI2.0	Java	SE	8	Alignment	
InterceptorBuilder:	ラムダ	or	メソッド参照によるインターセプタ	
event.addInterceptor()%
...%
.addBinding(Log.INST...
CDI2.0	Java	SE	8	Alignment	
InterceptorBuilder:	ラムダ	or	メソッド参照によるインターセプタ	
event.addInterceptor()%
...%
.addBinding(Log.INST...
CDI2.0	Java	SE	8	Alignment		
InterceptorBuilderのメリット	
•  1クラスで複数のインターセプタ定義が可能	
•  クラスが冗長に増えるのを防ぐ	
•  Java	EEの何でもアノテーション状態の...
CDI2.0	ロードマップ	
スケジュール	
•  2015/6:	Early	DraZ	Review	1		
•  hkps://docs.jboss.org/cdi/spec/2.0.EDR1/cdi-spec.html	
•  2016/...
本日のコンテンツ	
•  駆け足で振り返るCDI	
•  CDI2.0 	
•  CDI + α	
•  最後に
DI/AOPが標準化され、非同期イベントが入るのはわかった。	
でも、まだ Spring	より足りないのでは?
Spring	Framework	
@Autowired,	@Aspect%
CDI	(Java	EE)	
@Inject,	@Interceptor	DI/AOP	
プロパティ管理	
@Value,
@PropertySource%
Java...
CDIは『材料』のみ提供して、	
自作が必要なユースケースも多い	
Spring	Framework	
@Autowired,	@Aspect%
CDI	(Java	EE)	
@Inject,	@Interceptor	DI/AOP	
プロパテ...
CDI2.0(2017年)に向けて議論中ではある	
Spring	Framework	
@Autowired,	@Aspect%
CDI	(Java	EE)	
@Inject,	@Interceptor	DI/AOP	
プロパティ管理	
@Va...
CDI2.0(2017年)に向けて議論中ではある	
CDI	(Java	EE)	
@Inject,	@Interceptor	
プロパティ管理	
@Value,
@PropertySource%
@Producesによる要自作	
Java起動引...
“あったらいいな”はDeltaspikeにある	
Spring	Framework	
@Autowired,	@Aspect%
CDI	(Java	EE)	
@Inject,	@Interceptor	DI/AOP	
プロパティ管理	
@Val...
Apache	Deltaspike	
便利なCDI拡張ライブラリ		
•  CDIのPortable	Exten0onを活かしたライブラリ	
•  Seem3	+	My	Faces	CODI	+	α	を統合	
•  2014/6:	1.0.0	...
Apache	Deltaspike	#1	@ConfigProperty	
@ConfigPropertyによるパラメータ注入		
@ApplicationScoped%
public class RemoteConnector {%
%
@Inj...
Apache	Deltaspike	#1	@ConfigProperty	
任意のプロパティファイルの適用	
@Dependent%
public class MyAppFileConfig implements PropertyFileConf...
Apache	Deltaspike	#1	@ConfigProperty	
環境変数による値の差し替え	
@Inject%
@ConfigProperty(name="remotehost”,defaultValue="localhost:808...
Apache	Deltaspike	#2	ProjectStage	
起動オプションで有効なBeanを切り替える	
Service	 Repository	
【development】	
H2		
【produc0on】	
PostgreSQL...
Apache	Deltaspike	#2	ProjectStage	
起動オプションで有効なBeanを切り替える	
@ApplicationScoped%
public class Repository {%
@PersistenceConte...
Apache	Deltaspike	#2	ProjectStage	
Development環境向けEn0tyManagerのBean定義	
@ApplicationScoped%
public class Repository {%
@Per...
Apache	Deltaspike	#2	ProjectStage	
Development環境向けEn0tyManagerのBean定義	
@ApplicationScoped%
public class Repository {%
@Inj...
Apache	Deltaspike	#2	ProjectStage	
システムプロパティで有効プロファイルを指定	
@ApplicationScoped%
public class Repository {%
@Inject%
private ...
Apache	Deltaspike	#2	ProjectStage	
Produc0on向けも同様	
@ApplicationScoped%
public class Repository {%
@Inject%
private EntityM...
Apache	Deltaspike	#2	ProjectStage	
Produc0on向けも同様	
@ApplicationScoped%
public class Repository {%
@Inject%
private EntityM...
Apache	Deltaspike	
@ConfigPropertyとProjectStage	
•  2つに共通するメリット	
•  環境変数やJavaシステムプロパティで振る舞いを変更	
•  テスト済warを『修正なし』で複数環境で動作させ...
本日のコンテンツ	
•  駆け足で振り返るCDI	
•  CDI2.0	
•  CDI + α	
•  最後に
CDI2.0	(Java	EE	8	/	2017)	
•  	CDI非同期イベント	
•  	仕様をサブセットに分割	
•  	Java	SE	Support	
•  	Java	SE	8	Alignment
CDI2.0をもっと知るには	
cdi-spec.org	/	JIRA	/	Weld3.0.0.Alpha	
•  ホームページ (CDI	spec	で検索)	
•  hkp://www.cdi-spec.org	
•  JIRA	
•  hk...
最後に	
CDI2.0 ドラフト仕様は今すぐWildFly10で動きます	
ぜひ触ってみてください!	
OracleとJavaは、Oracle	Corpora0on及びその子会社、関連会社の米国及びその他の国における登録商標です。	
文中の社名...
CDI2.0アップデート&クックブック #JavaDayTokyo #jdt2016_4c
Upcoming SlideShare
Loading in …5
×

CDI2.0アップデート&クックブック #JavaDayTokyo #jdt2016_4c

3,699 views

Published on

Java Day Tokyo2016 #jdt2016_4c のセッション資料です。

Published in: Software
  • Be the first to comment

CDI2.0アップデート&クックブック #JavaDayTokyo #jdt2016_4c

  1. 1. CDI2.0アップデート & クックブック 2016/05/24 上妻 宜人 (あげつま のりと) Java Day Tokyo 2016/Java EE Session 4-C
  2. 2. 上妻 宜人 あげつま のりと •  SIer技術部門でJavaトラブルシューティングの日々 •  Java EEについて調べて伝えることが好き •  コミュニティ講演 •  GlassFish.JP, JJUG CCC, Java Day Tokyo 2015 など
  3. 3. 本日のコンテンツ •  駆け足で振り返るCDI •  CDI2.0 •  CDI + α •  最後に
  4. 4. CDI Context and Dependency Injec0on 2009/12 CDI1.0 - Java EE 6 2013/5 CDI1.1 - Java EE 7 2014/4 CDI1.2 (maintenance release) 2017/1 CDI2.0 - Java EE 8
  5. 5. CDIの目的 1. DI/AOPを中心とした疎結合コードの実現 @Inject, @InterceptorBinding, @Decorator, Event 2. コンテキストを持つオブジェクトのライフサイクル管理 @RequestScoped, @SessionScoped, @Applica0onScoped ... 3. EJB SessionBean と JSF @ManagedBean の統合
  6. 6. CDI 実装製品 •  Weld (参照実装) - jboss.org •  GlassFish, WildFly/JBossEAP, WebLogic •  OpenWebBeans - Apache SoZware Founda0on •  WebSphere, Apache TomEE
  7. 7. Context and Dependency Injec0on: CDI管理Beanの定義 // ライフサイクル: デプロイ〜アンデプロイまで% public class Controller {% % % }% % % // ライフサイクル: ユーザセッションごとに生成、ログアウトで破棄% public class ShoppingCart implements Cart {...}% %
  8. 8. Context and Dependency Injec0on: ランタイム例外を引き起こすコンテキスト操作 public class Controller { % ...% HttpSession session = request.getSession();% session.setAttribute(“shoppingCart”, new ShoppingCart());% % ....% % Cart cart = (Cart)session.getAttribute(“shopingCart”);%
  9. 9. Context and Dependency Injec0on: CDI管理Beanの定義 @ApplicationScoped% public class Controller {% % % }% % % @SessionScoped% public class ShoppingCart implements Cart {...}% %
  10. 10. @ApplicationScoped% public class Controller {% % % }% % % @SessionScoped% public class ShoppingCart implements Cart {...}% % Scope •  @RequestScoped •  @SessionScoped •  @Applica0onScoped •  @Conversa0onScoped •  @Dependent Context and Dependency Injec0on: CDI管理Beanのスコープ
  11. 11. Context and Dependency Injec0on: @Injectでタイプセーフに取得 @ApplicationScoped% public class Controller {% @Inject% Cart cart;% }% % % @SessionScoped% public class ShoppingCart implements Cart {...}% % CDIコンテナがインスタンスをセット
  12. 12. Context and Dependency Injec0on: @InterceptorBinding - タイプセーフなインターセプタ適用 Log target // target% @ApplicationScope% public class OrderService {% public void submit(Order order) {..}% }% // Log% @Interceptor% public class LogInterceptor {...}%
  13. 13. Context and Dependency Injec0on: @InterceptorBinding - タイプセーフなインターセプタ適用 Log target // target% @ApplicationScope% public class OrderService {% public void submit(Order order) {..}% }% // Log% @Interceptor% public class LogInterceptor {...}% @Inherited% @InterceptorBinding% @Target({TYPE, METHOD})% @Retention(RUNTIME)% public @interface Log {}
  14. 14. Context and Dependency Injec0on: @InterceptorBinding - タイプセーフなインターセプタ適用 Log target // target% @ApplicationScope @Log% public class OrderService {% public void submit(Order order) {..}% }% // Log% @Interceptor @Log% public class LogInterceptor {...}% @Inherited% @InterceptorBinding% @Target({TYPE, METHOD})% @Retention(RUNTIME)% public @interface Log {} Binding
  15. 15. CDI1.1の変更点 (Java EE 7) beans.xmlのオプション化 •  beans.xmlなしでCDI有効化 •  スコープを持つクラスはすべてCDI管理Bean @RequestScoped, @SessionScoped, @ApplicationScoped ... •  @Dependentスコープは明示的に付与が必要 // Java EE 7デフォルトでは@Dependent省略不可% @Dependent% public class DependentBean {...}%
  16. 16. CDI1.1の変更点 (Java EE 7) beans.xmlのオプション化 •  @Priority •  主にインターセプタ有効化 & 優先順位付けに使用 •  Interceptorの有効化にbeans.xmlが不要に @Interceptor% @Priority(Interceptor.Priority.APPLICATION)% public class LoggingInterceptor { % @AroundInvoke% public Object log(InvocationContext ic) % throws Exception {...}% }
  17. 17. CDI1.1の変更点 (Java EE 7) @Priorityによるインターセプト順序の定義 @Interceptor @Timeout% @Priority(Interceptor.Priority.APPLICATION + 10)% public class TimeoutInterceptor {...}% Log @Interceptor @Logging% @Priority(Interceptor.Priority.APPLICATION)% public class LogInterceptor {...}% 【値が小さいほど早く起動】% Priority.PLATFORM_BEFORE: 0% @Transactional = 200% Priority.LIBRARY_BEFORE: 1000% Priority.APPLICATION: 2000% アプリケーション向け有効範囲:〜2999% Time out target Priority: 2000 2010
  18. 18. CDI1.1の変更点 (Java EE 7) スコープ開始・終了イベント @ApplicationScoped% public class MasterDataCache {% public void observer(% @Observes @Initialized(ApplicationScoped.class)% ServletContext context) {% // initilize code% }% }% •  スコープの開始・終了タイミングでイベント発火 •  Applica0onScopedの場合@Startup代わりに使える
  19. 19. CDI1.2の変更点 (Java EE 7) JSR-330との互換性確保 •  @javax.inject.Singletonをスキャン対象外へ •  デフォルトでは@SingletonはCDI管理Beanと見なされない •  代わりに @ApplicationScoped を使う •  背景はGuavaを含むAPがCDI1.1からデプロイエラーになったこと Guava 14.0.1 cannot be deployed in a JEE7 Container #1433 https://github.com/google/guava/issues/1433
  20. 20. 本日のコンテンツ •  駆け足で振り返るCDI •  CDI2.0 •  CDI + α •  最後に
  21. 21. CDI2.0 (Java EE 8 / 2017) •  CDI非同期イベント •  仕様をサブセットに分割 •  Java SE Support •  Java SE 8 Alignment
  22. 22. @ApplicationScoped% public class AlertService {% @Inject AlertRepository repo;% % @Transactinal% public void handleAlert(Alert alert) {% // 何らかのビジネスロジックを終えた後に ...% repo.persist(alert);% }% } 通常のメソッド呼び出し 最初はシンプルな機能 Alert Service Alert Repository
  23. 23. @ApplicationScoped% public class AlertService {% @Inject AlertRepository repo;% @Inject EmailSender email;% % @Transactinal% public void handleAlert(Alert alert) {% // 何らかのビジネスロジックを終えた後に ...% repo.persist(alert);% email.send(“test@test.com”, alert);% }% } 通常のメソッド呼び出し アラートが来たらメールも ... Alert Service Alert Repository Email Sender
  24. 24. @ApplicationScoped% public class AlertService {% @Inject AlertRepository repo;% @Inject EmailSender email;% @Inject AlertCache cache;% % @Transactinal% public void handleAlert(Alert alert) {% // 何らかのビジネスロジックを終えた後に ...% repo.persist(alert);% email.send(“test@test.com”, alert);% cache.putIfAbsent(alert);% }% } 通常のメソッド呼び出し アラートが来たらキャッシュ更新も ... Alert Service Alert Repository Email Sender Alert Cache
  25. 25. 通常のメソッド呼び出し 手続き型のデメリット •  機能追加毎にクラス間依存性が増加 •  やがては蜘蛛の巣になる •  CDI管理Beanが持つ状態のロールバックが難しい •  宣言的トランザクションがコミット失敗した場合、 トランザクション中に変更したBeanのステートをどう戻すか •  catch節で頑張れるが、長くなることも
  26. 26. CDIイベントの振り返り イベント発火側のコード Alert Service Alert Repository Email Sender Alert Cache CDI Event @ApplicationScoped% publilc class AlertService {% @Inject AlertRepository repo;% @Inject Event<Alert> event;% % public void handleAlert(Alert alert) {% repo.persist(alert);% event.fire(alert);% ...% %
  27. 27. CDIイベントの振り返り オブザーバの実装 Alert Service Alert Repository Email Sender Alert Cache CDI Event @ApplicationScoped% publilc class AlertService {% @Inject AlertRepository repo;% @Inject Event<Alert> event;% % public void handleAlert(Alert alert) {% repo.persist(alert);% event.fire(alert);% ...% @ApplicationScoped% public class AlertCache {% ...% public void updateCache(@Observes Alert alert) {% cache.putIfAbsent(alert.getId(), alert);% }% }
  28. 28. CDIイベントの振り返り イベントの発火 Alert Service Alert Repository Email Sender Alert Cache CDI Event @ApplicationScoped% publilc class AlertService {% @Inject AlertRepository repo;% @Inject Event<Alert> event;% % public void handleAlert(Alert alert) {% repo.persist(alert);% event.fire(alert);% ...% @ApplicationScoped% public class AlertCache {% ...% public void updateCache(@Observes Alert alert) {% cache.putIfAbsent(alert.getId(), alert);% }% } イベントと同じ引数を持つ 全てのオブザーバに通知
  29. 29. CDIイベントの振り返り イベントモデルの一般的な利点 Alert Service Alert Repository Email Sender Alert Cache CDI Event Alert Service Alert Repository Email Sender Alert Cache •  プラグイン構造 •  既存に手を入れずにObserver追加で拡張 •  実行タイミング/場所の分離 •  非同期実行、別マシンでの実行が理論上は可能となる
  30. 30. CDI Container Subject @Observe Observer #1 @Observe Observer #2 1.fire() 2.call back #1 3.call back #2
  31. 31. CDI Container Subject @Observe Observer #1 @Observe Observer #2 1.fire() thread 2.call back #1 3.call back #2 fire()の完了 CDI1.2までは同期呼び出しのみ
  32. 32. CDI2.0 #1 CDI2.0 非同期イベント
  33. 33. CDI2.0 非同期CDIイベント イベント発火側の実装 @ApplicationScoped% publilc class AlertService {% % @Inject Event<Alert> event;% % public void handleAlert(Alert alert) {% event.fire(alert);% ...% %
  34. 34. CDI2.0 非同期CDIイベント イベント発火側の実装 @ApplicationScoped% publilc class AlertService {% % @Inject Event<Alert> event;% % public void handleAlert(Alert alert) {% event.fireAsync(alert);% ...% %
  35. 35. CDI2.0 非同期CDIイベント イベント発火側の実装 @ApplicationScoped% publilc class AlertService {% % @Inject Event<Alert> event;% % public void handleAlert(Alert alert) {% event.fireAsync(alert);% ...% % CDI2.0 EDR1ではObserver側 スレッドはコンテナ実装依存 Weld 3.0.0.Alpha16の場合: Weld自体が持つスレッドプールを使用 (max-size -> CPUコア数)
  36. 36. CDI2.0 非同期CDIイベント コンテナ管理スレッドの利用 (Concurrency U0li0es for Java EE) @ApplicationScoped% publilc class AlertService {% % @Inject Event<Alert> event;% @Resource ManagedExecutor executor;% % public void handleAlert(Alert alert) {% event.fireAsync(alert, executor);% ...% %
  37. 37. CDI2.0 非同期CDIイベント 全オブザーバの終了待ち受け @ApplicationScoped% publilc class AlertService {% % @Inject Event<Alert> event;% @Resource ManagedExecutor executor;% % public void handleAlert(Alert alert) {% CompletionStage<Alert> asyncEvent = % event.fireAsync(alert, executor);% // block until complete observes% asyncEvent.toCompletableFuture().join(); % ...% %
  38. 38. CDI2.0 非同期CDIイベント Observer側の実装 @ApplicationScoped% publilc class AlertCache {% % ConcurrentMap<Long, Alert> cache = ...;% % public void updateCache(@Observes Alert alert) {% cache.putIfAbsent(alert.getId(), alert);% }% } %
  39. 39. CDI2.0 非同期CDIイベント Observer側の実装 @ApplicationScoped% publilc class AlertCache {% % ConcurrentMap<Long, Alert> cache = ...;% % public void updateCache(@ObserveAsync Alert alert) {% cache.putIfAbsent(alert.getId(), alert);% }% } %
  40. 40. CDI Container Subject @ObserveAsync Observer #1 @ObserveAsync Observer #2 fireAsync() call back call back fireAsync()は即座にreturnし、 各Observerは別スレッドで実行 Request thread Event thread
  41. 41. CDI Container Subject @ObserveAsync Observer #1 @ObserveAsync Observer #2 call back call back transac0on #1 transac0on #2 tx #3 トランザクション・コンテキストは オブザーバに引き継がれない Request thread Event thread call back fireAsync()
  42. 42. CDI2.0 非同期CDIイベント Observerから例外がスローされたらどうなる? @ApplicationScoped% publilc class AlertService {% % @Inject Event<Alert> event;% @Resource ManagedExecutor executor;% % public void handleAlert(Alert alert) {% CompletionStage<Alert> stage = event% .fireAsync(alert, executor);%
  43. 43. CDI2.0 非同期CDIイベント Comple0onStage.excep0onallyによる例外ハンドリング @ApplicationScoped% publilc class AlertService {% % @Inject Event<Alert> event;% @Resource ManagedExecutor executor;% % public void handleAlert(Alert alert) {% CompletionStage<Alert> stage = event% .fireAsync(alert, executor)% .exceptionally(ex -> {% // observer exception logging% Arrays.stream(ex.getSuppressed())% .forEach(e -> System.err.println(e));% return null;% }); %
  44. 44. CDI2.0 非同期CDIイベント CDI2.0より非同期実行に対応 CDI1.2 (Java EE 7) CDI2.0 (Java EE 8) プラグイン (型依存の分離) 非同期実行 (実行タイミングの分離) ○ ○ ○
  45. 45. CDI2.0 非同期CDIイベント @MDBとCDI非同期イベント CDI1.2 (Java EE 7) CDI2.0 (Java EE 8) JMS プラグイン (型依存の分離) 非同期実行 (実行タイミングの分離) メッセージ永続化 Observerの 別マシン実行 ○ ○ ○ ○ ○ ○ ○
  46. 46. CDI1.2 (Java EE 7) CDI2.0 (Java EE 8) JMS プラグイン (型依存の分離) 非同期実行 (実行タイミングの分離) メッセージ永続化 Observerの 別マシン実行 CDI2.0 非同期CDIイベント @MDBとCDI非同期イベント ○ ○ ○ ○ ○ ○ ○ 【JMSに付いてくる検討項目】 XAするならクラッシュリカバリ手順は? ポイズンメッセージ対策は? メッセージ永続化先は?ファイル or DB?
  47. 47. CDI2.0 非同期CDIイベント @MDBとCDI非同期イベント CDI1.2 (Java EE 7) CDI2.0 (Java EE 8) JMS プラグイン (型依存の分離) 非同期実行 (実行タイミングの分離) メッセージ永続化 Observerの 別マシン実行 考えるべき タスクの多さ ○ ○ ○ ○ ○ ○ ○ △
  48. 48. CDI2.0 非同期CDIイベント CDI非同期イベントが適するケース •  順序性, 依存性のない処理の並列実行 •  例外時のCDI管理Bean状態ロールバック •  トランザクション中に変更したステートを元に戻す •  メッセージ永続化が不要 •  例: 朝からリクエスト時点までの業務統計レポート生成 •  障害復旧後に永続メッセージから実行しても、既に陳腐化
  49. 49. CDI2.0 #2 仕様をサブセットに分割
  50. 50. CDI2.0 仕様をサブセットに分割 CDI Lite 軽量なサブセットの抽出 •  CDIを Java EE 以外の世界で使ってもらいたい •  Android, 組込みデバイス •  現状のCDI仕様はJava EE環境を前提 •  プロキシベースを前提としない軽量実装 •  Annota0on Processingによるコンパイル時依存性解決 (Androidでよく使われるDaggerがモデル) •  省メモリ、低CPU使用率の実現
  51. 51. CDI2.0 仕様をサブセットに分割 CDI Lite 軽量なサブセットの抽出 CDI core •  DI - @Inject, Qualifier •  @Produces •  Event & @Observes •  疑似スコープ @Dependent, @Singleton •  Programa0c lookup •  Portable Exten0on CDI Java SE •  Bootstraping API •  Scope in Java SE @Applica0onScoped •  Packaging & deployment CDI Java EE •  Scope in Java EE •  @SessionScoped •  @Conversa0onScoped •  EJBとの連携
  52. 52. CDI2.0 #3 Java SE Support
  53. 53. public static void main(String ... args) {% try (CDI<Object> cdi = CDI.getCDIProvider().initialize()) {% Service service = cdi.select(Service.class).get();% service.doSomething(); % }% }% % public class ServiceImpl implements Service {% @Inject % Repository repo;% % public void doSomething() {...}% }% CDI2.0 Java SE Support Java SE Bootstrap API CDIコンテナ初期化 InjectされたBeanの取得
  54. 54. CDI2.0 Java SE Support “仕様”として含める背景 •  Java EE 仕様間での整合性 •  JAX-RS , JPAは Java SE でも利用可能な仕様設計 •  Weld, OpenWebBeansで既に実装されていた •  実装間で類似APIが複数存在するのはJava EE思想に反する
  55. 55. CDI2.0 #4 Java SE 8 Alignment
  56. 56. CDI2.0 Java SE 8 Alignment InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ public class InterceptorBuilder {% // デプロイ時にCDIコンテナよりコールバック% void afterBeanDiscovery(@Observes AfterBeanDiscovery event) {% event.addInterceptor() // return InterceptorBuilder%
  57. 57. CDI2.0 Java SE 8 Alignment InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ public class InterceptorBuilder {% // デプロイ時にCDIコンテナよりコールバック% void afterBeanDiscovery(@Observes AfterBeanDiscovery event) {% event.addInterceptor()% .intercept(InterceptionType.AROUND_INVOKE, this::log)% % % % % Object log(InvocationContext ic) {% // interceptor impl% }% }% @AroundInvoke相当
  58. 58. CDI2.0 Java SE 8 Alignment InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ public class InterceptorBuilder {% // デプロイ時にCDIコンテナよりコールバック% void afterBeanDiscovery(@Observes AfterBeanDiscovery event) {% event.addInterceptor()% .intercept(InterceptionType.AROUND_INVOKE, this::log)% .priority(Priority.APPLICATION)% .addBinding(Log.INSTANCE);% }% % Object log(InvocationContext ic) {% // interceptor impl% }% }%
  59. 59. CDI2.0 Java SE 8 Alignment InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ public class InterceptorBuilder {% // デプロイ時にCDIコンテナよるコールバック% void afterBeanDiscovery(@Observes AfterBeanDiscovery event) {% event.addInterceptor()% .intercept(InterceptionType.AROUND_INVOKE, this::log)% .priority(Priority.APPLICATION)% .addBinding(Log.INSTANCE);% }% % Object log(InvocationContext ic) {% // interceptor impl% }% }%
  60. 60. CDI2.0 Java SE 8 Alignment InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ event.addInterceptor()% ...% .addBinding(Log.INSTANCE);%
  61. 61. CDI2.0 Java SE 8 Alignment InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ event.addInterceptor()% ...% .addBinding(Log.INSTANCE);% @Log% public void target() {...} 適用対象メソッドと繋ぐために、 アノテーションの“インスタンス”を渡す必要がある
  62. 62. CDI2.0 Java SE 8 Alignment InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ event.addInterceptor()% ...% .addBinding(Log.INSTANCE);% % @Inherited% @InterceptorBinding% @Retention(RUNTIME)% @Target({METHOD, TYPE})% public @interface Log {}%
  63. 63. CDI2.0 Java SE 8 Alignment InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ event.addInterceptor()% ...% .addBinding(Log.INSTANCE);% % @Inherited% @InterceptorBinding% @Retention(RUNTIME)% @Target({METHOD, TYPE})% public @interface Log {% class Literal extends AnnotationLiteral<Log> implements Log {% private Literal() {}% }% final Log INSTANCE = new Literal();% }% CDIのAnnota0onLiteralクラスを継承して アノテーションの”インスタンス”を取得
  64. 64. CDI2.0 Java SE 8 Alignment InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ event.addInterceptor()% ...% .addBinding(Log.INSTANCE);% % @Inherited% @InterceptorBinding% @Retention(RUNTIME)% @Target({METHOD, TYPE})% public @interface Log {% class Literal extends AnnotationLiteral<Log> implements Log {% private Literal() {}% }% final Log INSTANCE = new Literal();% }% @Log% public void target() {...} Interceptor Binding
  65. 65. CDI2.0 Java SE 8 Alignment InterceptorBuilderのメリット •  1クラスで複数のインターセプタ定義が可能 •  クラスが冗長に増えるのを防ぐ •  Java EEの何でもアノテーション状態の改善 •  Java 5 から: アノテーションをスキャンしてコンテナ機能を付与 •  Java 8 から: ラムダを渡すとコンテナが機能付与
  66. 66. CDI2.0 ロードマップ スケジュール •  2015/6: Early DraZ Review 1 •  hkps://docs.jboss.org/cdi/spec/2.0.EDR1/cdi-spec.html •  2016/6: Early DraZ Review 2 予定 •  2016/12 〜 2017/1: CDI2.0 Final 予定 •  2017上半期 Java EE 8 リリース 予定
  67. 67. 本日のコンテンツ •  駆け足で振り返るCDI •  CDI2.0 •  CDI + α •  最後に
  68. 68. DI/AOPが標準化され、非同期イベントが入るのはわかった。 でも、まだ Spring より足りないのでは?
  69. 69. Spring Framework @Autowired, @Aspect% CDI (Java EE) @Inject, @Interceptor DI/AOP プロパティ管理 @Value, @PropertySource% Java起動引数による プロファイル切替 @Profile
  70. 70. CDIは『材料』のみ提供して、 自作が必要なユースケースも多い Spring Framework @Autowired, @Aspect% CDI (Java EE) @Inject, @Interceptor DI/AOP プロパティ管理 @Value, @PropertySource% @Producesによる要自作 Java起動引数による プロファイル切替 @Profile @Alternativeによる要自作
  71. 71. CDI2.0(2017年)に向けて議論中ではある Spring Framework @Autowired, @Aspect% CDI (Java EE) @Inject, @Interceptor DI/AOP プロパティ管理 @Value, @PropertySource% @Producesによる要自作 Java起動引数による プロファイル切替 @Profile CDI-504: have a standard CDI annota0on like @ConfigProperty from deltapsike hkps://issues.jboss.org/browse/CDI-504 CDI-539: Support for 'profile' in CDI hkps://issues.jboss.org/browse/CDI-539 【Issue CDI-504】 @Alternativeによる要自作 【Issue CDI-539】 ・ その機能は本当に『CDI』か? 過去例: @Transac0onalをCDIではなくJTAへ ・ やはり Configra0on JSR では?
  72. 72. CDI2.0(2017年)に向けて議論中ではある CDI (Java EE) @Inject, @Interceptor プロパティ管理 @Value, @PropertySource% @Producesによる要自作 Java起動引数による プロファイル切替 @Profile CDI-504: have a standard CDI annota0on like @ConfigProperty from deltapsike hkps://issues.jboss.org/browse/CDI-504 CDI-539: Support for 'profile' in CDI hkps://issues.jboss.org/browse/CDI-539 【Issue CDI-504】 @Alternativeによる要自作 【Issue CDI-539】 Spring Framework @Autowired, @Aspect%DI/AOP ・ その機能は本当に『CDI』か? 過去例: @Transac0onalをCDIではなくJTAへ ・ やはり Configra0on JSR では? 2017年を待てない場合は Apache Deltaspike
  73. 73. “あったらいいな”はDeltaspikeにある Spring Framework @Autowired, @Aspect% CDI (Java EE) @Inject, @Interceptor DI/AOP プロパティ管理 @Value, @PropertySource% org.apache.deltaspike.core.api.config.% @ConfigProperty Java起動引数による プロファイル切替 @Profile org.apache.deltaspike.core.api.projectstage ProjectStage% Apache Deltaspike
  74. 74. Apache Deltaspike 便利なCDI拡張ライブラリ •  CDIのPortable Exten0onを活かしたライブラリ •  Seem3 + My Faces CODI + α を統合 •  2014/6: 1.0.0 リリース (2016/4 現在 1.6.1が最新)
  75. 75. Apache Deltaspike #1 @ConfigProperty @ConfigPropertyによるパラメータ注入 @ApplicationScoped% public class RemoteConnector {% % @Inject% @ConfigProperty(name="remotehost", defaultValue="localhost:8080")% private String remotehost;% ...% META-INF/apache-deltaspike.proper0es remotehost=192.168.1.2 DeltaspikeによりInject デフォルトのプロパティファイル
  76. 76. Apache Deltaspike #1 @ConfigProperty 任意のプロパティファイルの適用 @Dependent% public class MyAppFileConfig implements PropertyFileConfig {% @Override% public String getPropertyFileName() {% return "META-INF/application.properties";% }% % @Override% public boolean isOptional() {% return false;% }% }
  77. 77. Apache Deltaspike #1 @ConfigProperty 環境変数による値の差し替え @Inject% @ConfigProperty(name="remotehost”,defaultValue="localhost:8080")% private String remotehost;% 【優先順位】 1.  環境変数 export remotehost=192.168.1.2 2.  システムプロパティ java -Dremotehost=192.168.1.4 3.  JNDI new InitialContext().bind(“remotehost”, “192.168.1.5”) 4.  プロパティファイル
  78. 78. Apache Deltaspike #2 ProjectStage 起動オプションで有効なBeanを切り替える Service Repository 【development】 H2 【produc0on】 PostgreSQL META-INF/persistence.xml% <?xml version="1.0" encoding="UTF-8"?>% <persistence>% <persistence-unit name="h2”>...</persistence-unit>% <persistence-unit name="PostgreSQL”>...</persistence-unit>% </persistence>
  79. 79. Apache Deltaspike #2 ProjectStage 起動オプションで有効なBeanを切り替える @ApplicationScoped% public class Repository {% @PersistenceContext(unitName = “h2 or PostgreSQL??”)% private EntityManager em;% ...% }
  80. 80. Apache Deltaspike #2 ProjectStage Development環境向けEn0tyManagerのBean定義 @ApplicationScoped% public class Repository {% @PersistenceContext(unitName = “h2 or PostgreSQL??”)% private EntityManager em;% ...% } @Exclude(exceptIfProjectStage = ProjectStage.Development.class)% @ApplicationScoped% public class DevEntityManagerProducer {% @Produces% @PersistenceContext(unitName = "h2")% private EntityManager em; % }
  81. 81. Apache Deltaspike #2 ProjectStage Development環境向けEn0tyManagerのBean定義 @ApplicationScoped% public class Repository {% @Inject% private EntityManager em;% ...% } @Exclude(exceptIfProjectStage = ProjectStage.Development.class)% @ApplicationScoped% public class DevEntityManagerProducer {% @Produces% @PersistenceContext(unitName = "h2")% private EntityManager em; % }
  82. 82. Apache Deltaspike #2 ProjectStage システムプロパティで有効プロファイルを指定 @ApplicationScoped% public class Repository {% @Inject% private EntityManager em;% ...% } @Exclude(exceptIfProjectStage = ProjectStage.Development.class)% @ApplicationScoped% public class DevEntityManagerProducer {% @Produces% @PersistenceContext(unitName = "h2")% private EntityManager em; % } java -Dorg.apache.deltaspike.ProjectStage=Development Repository H2 PostgreSQL
  83. 83. Apache Deltaspike #2 ProjectStage Produc0on向けも同様 @ApplicationScoped% public class Repository {% @Inject% private EntityManager em;% ...% } @Exclude(exceptIfProjectStage = ProjectStage.Production.class)% @ApplicationScoped% public class ProdEntityManagerProducer {% @Produces% @PersistenceContext(unitName = ”PostgreSQL")% private EntityManager em; % } Repository H2 PostgreSQL
  84. 84. Apache Deltaspike #2 ProjectStage Produc0on向けも同様 @ApplicationScoped% public class Repository {% @Inject% private EntityManager em;% ...% } @Exclude(exceptIfProjectStage = ProjectStage.Production.class)% @ApplicationScoped% public class ProdEntityManagerProducer {% @Produces% @PersistenceContext(unitName = ”PostgreSQL")% private EntityManager em; % } Repository H2 PostgreSQL java -Dorg.apache.deltaspike.ProjectStage=Produc0on
  85. 85. Apache Deltaspike @ConfigPropertyとProjectStage •  2つに共通するメリット •  環境変数やJavaシステムプロパティで振る舞いを変更 •  テスト済warを『修正なし』で複数環境で動作させる 開発環境 ステージング環境 商用環境 AP Server DB myapp.war Simurator myapp.war myapp.war 関連システム
  86. 86. 本日のコンテンツ •  駆け足で振り返るCDI •  CDI2.0 •  CDI + α •  最後に
  87. 87. CDI2.0 (Java EE 8 / 2017) •  CDI非同期イベント •  仕様をサブセットに分割 •  Java SE Support •  Java SE 8 Alignment
  88. 88. CDI2.0をもっと知るには cdi-spec.org / JIRA / Weld3.0.0.Alpha •  ホームページ (CDI spec で検索) •  hkp://www.cdi-spec.org •  JIRA •  hkps://issues.jboss.org/projects/CDI •  CDI2.0 EarlyDraZReview 1 の参照実装 •  Weld 3.0.0.Alpha16 hkp://weld.cdi-spec.org/news/2016/04/28/weld-300Alpha16/ •  WildFly10に組込み可能なpatchもリリース
  89. 89. 最後に CDI2.0 ドラフト仕様は今すぐWildFly10で動きます ぜひ触ってみてください! OracleとJavaは、Oracle Corpora0on及びその子会社、関連会社の米国及びその他の国における登録商標です。 文中の社名、商品名等は各社の商標または登録商標である場合があります。

×