CDI2.0
アップデート
&
クックブック
NTT
コムウェア株式会社
上妻 宜人
(
あげつま のりと
)
Copyright © NTT COMWARE 2016
上妻
宜人
あげつま のりと
•
SIer技術部門でJavaトラブルシューティングの日々
•
Java EEについて調べて伝えることが好き
•
コミュニティ講演
本日のコンテンツ
•
駆け足で振り返るCDI
•
CDI2.0
•
CDI + α
•
最後に
CDI
C
ontext and
D
ependency
I
njecAon
2009/12 CDI1.0 - Java EE 6
2013/5 CDI1.1 - Java EE 7
2014/4 CDI1.2
(maintenance release)
CDI
の目的
1. DI/AOPを中心とした疎結合コードの実現
@Inject, @InterceptorBinding, @Decorator, Event
2. コンテキストを持つオブジェクトのライフサイクル管理
@RequestScoped, @SessionScoped, @ApplicaAonScoped ...
3. EJB SessionBean と JSF @ManagedBean の統合
CDI
実装製品
•
Weld
(参照実装) - jboss.org
•
GlassFish, WildFly/JBossEAP, WebLogic
•
OpenWebBeans
- Apache So]ware FoundaAon
Context
and Dependency InjecAon
:
CDI管理Beanの定義
//
ライフサイクル
:
デプロイ
〜
アンデプロイまで
%
public class
Controller
{%
%
%
}%
%
%
//
ライフサイクル
:
ユーザセッションごとに生成、ログアウトで破棄
%
public class
ShoppingCart
implements
Cart {...}%
Context
and Dependency InjecAon
:
ランタイム例外を引き起こすコンテキスト操作
public class
Controller { %
...%
HttpSession session = request.getSession();%
session.setAttribute(
“sho
pp
ingCart
”
,
new
ShoppingCart());%
%
....%
%
Context
and Dependency InjecAon
:
CDI管理Beanの定義
@ApplicationScoped%
public class
Controller
{%
%
%
}%
%
%
@SessionScoped%
public class
ShoppingCart
implements
Cart {...}%
@ApplicationScoped%
public class
Controller
{%
%
%
}%
%
%
@SessionScoped%
public class
ShoppingCart
implements
Cart {...}%
%
Scope
•
@RequestScoped
•
@SessionScoped
•
@ApplicaAonScoped
•
@ConversaAonScoped
•
@Dependent
Context
and Dependency InjecAon
:
CDI管理Beanのスコープ
Context and
Dependency InjecAon
:
@Injectでタイプセーフに取得
@ApplicationScoped%
public class
Controller
{%
@Inject%
Cart cart;%
}%
%
%
@SessionScoped%
public class
ShoppingCart
implements
Cart {...}%
%
Context and
Dependency InjecAon
:
@InterceptorBinding
- タイプセーフなインターセプタ適用
Log target
// target%
@ApplicationScope%
public class OrderService {%
public void submit(Order order) {..}% }%
// Log%
@Interceptor%
Context and
Dependency InjecAon
:
@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
)%
Context and
Dependency InjecAon
:
@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
{}
CDI1.1の変更点
(Java EE 7)
beans.xmlのオプション化
•
beans.xmlなしでCDI有効化
•
スコープを持つクラスはすべてCDI管理Bean
@RequestScoped, @SessionScoped, @ApplicationScoped ...
•
@Dependentスコープは明示的に付与が必要
// Java EE 7
デフォルトでは
@Dependent
省略不可
%
@Dependent%
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 {...}%
}
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 2010CDI1.1の変更点
(Java EE 7)
スコープ開始・終了イベント
@ApplicationScoped%
public class
MasterDataCache
{%
public
void
observer
(%
@Observes
@Initialized(ApplicationScoped.class)%
ServletContext context) {%
// initilize code%
}%
}
%
•
スコープの開始・終了タイミングでイベント発火
•
ApplicaAonScopedの場合@Startup代わりに使える
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
本日のコンテンツ
•
駆け足で振り返るCDI
•
CDI2.0
•
CDI + α
•
最後に
CDI2.0
(Java EE 8 / 2017)
•
CDI非同期イベント
•
仕様をサブセットに分割
•
Java SE Support
@ApplicationScoped%
public class
AlertService
{%
@Inject AlertRepository repo;%
%
@Transactinal%
public void
handleAlert
(Alert alert) {%
//
何らかのビジネスロジックを終えた後に
...%
repo.persist(alert);%
}%
}
通常のメソッド呼び出し
最初はシンプルな機能
Alert@ApplicationScoped%
public class
AlertService
{%
@Inject AlertRepository repo;%
@Inject EmailSender email;%
%
@Transactinal%
public void
handleAlert
(Alert alert) {%
//
何らかのビジネスロジックを終えた後に
...%
repo.persist(alert);%
email.send(
“[email protected]”
, alert);%
}%
}
通常のメソッド呼び出し
アラートが来たらメールも
...
Alert
Service Repository Alert Email Sender
@ApplicationScoped%
public class
AlertService
{%
@Inject AlertRepository repo;%
@Inject EmailSender email;%
@Inject AlertCache cache;%
%
@Transactinal%
public void
handleAlert
(Alert alert) {%
//
何らかのビジネスロジックを終えた後に
...%
repo.persist(alert);%
email.send(
“[email protected]”
, alert);%
cache.putIfAbsent(alert);%
}%
}
通常のメソッド呼び出し
アラートが来たらキャッシュ更新も
...
AlertService Repository Alert Email Sender
Alert Cache
通常のメソッド呼び出し
手続き型のデメリット
•
機能追加毎にクラス間依存性が増加
•
やがては蜘蛛の巣になる
•
CDI管理Beanが持つ状態のロールバックが難しい
•
宣言的トランザクションがコミット失敗した場合
、
トランザクション中に変更した
Beanのステートをどう戻すか
•
catch節で頑張れるが
、
長くなることも
CDIイベントの振り返り
イベント発火側のコード
Alert
Service Repository Alert 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);%
...% %
CDIイベントの振り返り
オブザーバの実装
Alert
Service Repository Alert 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);%
}% }
CDIイベントの振り返り
イベントの発火
Alert
Service Repository Alert 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);%
}% }
イベントと同じ引数を持つ
CDIイベントの振り返り
イベントモデルの一般的な利点
Alert
Service Repository Alert Email Sender Alert Cache CDI Event Alert
Service Repository Alert Email Sender Alert Cache
•
プラグイン構造
•
既存に手を入れずに
Observer追加で拡張
•
実行タイミング
/場所の分離
•
非同期実行
、
別マシンでの実行が理論上は可能となる
CDI
Container Subject
@Observe
Observer #1
Observer #2
@Observe1.fire()
2.call back #1
CDI
Container Subject
@Observe
Observer #1
Observer #2
@Observe1.fire()
thread
2.call back #1 3.call back #2fire()の完了
CDI1.2までは同期呼び出しのみ
CDI2.0 #1
CDI2.0 非同期CDIイベント
イベント発火側の実装
@ApplicationScoped%
publilc class
AlertService {%
%
@Inject Event<Alert> event;%
%
public void
handleAlert(Alert alert) {%
event.fire(alert);%
...%
CDI2.0 非同期CDIイベント
イベント発火側の実装
@ApplicationScoped%
publilc class
AlertService {%
%
@Inject Event<Alert> event;%
%
public void
handleAlert(Alert alert) {%
event.
fireAsync
(alert);%
...%
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コア数)
CDI2.0 非同期CDIイベント
コンテナ管理スレッドの利用
(Concurrency UAliAes for Java EE)
@ApplicationScoped%
publilc class
AlertService {%
%
@Inject Event<Alert> event;%
@Resource ManagedExecutor
executor
;%
%
public void
handleAlert(Alert alert) {%
event.fireAsync(alert,
executor
);%
...%
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()
; %
...%
CDI2.0 非同期CDIイベント
Observer側の実装
@ApplicationScoped%
publilc class
AlertCache {%
%
ConcurrentMap<Long, Alert> cache = ...;%
%
public void
updateCache(@Observes Alert alert) {%
cache.putIfAbsent(alert.getId(), alert);%
}%
}
%CDI2.0 非同期CDIイベント
Observer側の実装
@ApplicationScoped%
publilc class
AlertCache {%
%
ConcurrentMap<Long, Alert> cache = ...;%
%
public void
updateCache(
@ObserveAsync
Alert alert) {%
cache.putIfAbsent(alert.getId(), alert);%
}%
}
%CDI
Container Subject
@ObserveAsync
Observer #1
Observer #2
@ObserveAsyncfireAsync() call back call back
fireAsync()は即座にreturnし
、
各
Observerは別スレッドで実行
Request thread
Event thread
CDI
Container Subject
@ObserveAsync
Observer #1
Observer #2
@ObserveAsynccall back call back transacAon #1 transacAon #2 tx #3
トランザクション・コンテキストは
オブザーバに引き継がれない
Request thread
Event thread
call back fireAsync()
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);%
CDI2.0 非同期CDIイベント
CompleAonStage.excepAonallyによる例外ハンドリング
@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;%
CDI2.0 非同期CDIイベント
CDI2.0より非同期実行に対応
CDI1.2
(Java EE 7) (Java EE 8)
CDI2.0
プラグイン
(型依存の分離)
非同期実行
(実行タイミングの分離)
○
○
○
CDI2.0 非同期CDIイベント
@MDBとCDI非同期イベント
CDI1.2
(Java EE 7) (Java EE 8)
CDI2.0
JMS
プラグイン
(型依存の分離)
非同期実行
(実行タイミングの分離)
メッセージ永続化
Observerの
別マシン実行
○
○
○
○
○
○
○
CDI1.2
(Java EE 7) (Java EE 8)
CDI2.0
JMS
プラグイン
(型依存の分離)
非同期実行
(実行タイミングの分離)
メッセージ永続化
Observerの
別マシン実行
CDI2.0 非同期CDIイベント
@MDBとCDI非同期イベント
○
○
○
○
○
○
○
【
JMS
に
付いてくる検討項目】
XAするならクラッシュリカバリ手順は?
ポイズンメッセージ対策は?
メッセージ永続化先は?ファイル
or
DB?
CDI2.0 非同期CDIイベント
@MDBとCDI非同期イベント
CDI1.2
(Java EE 7) (Java EE 8)
CDI2.0
JMS
プラグイン
(型依存の分離)
非同期実行
(実行タイミングの分離)
メッセージ永続化
Observerの
別マシン実行
考えるべき
タスクの多さ
○
○
○
○
○
○
○
△
CDI2.0 非同期CDIイベント
CDI非同期イベントが適するケース
•
順序性
, 依存性のない処理の並列実行
•
例外時の
CDI管理Bean状態ロールバック
•
トランザクション中に変更したステートを元に戻す
•
メッセージ永続化が不要
•
例
: 朝からリクエスト時点までの業務統計レポート生成
•
障害復旧後に永続メッセージから実行しても
、
既に陳腐化
CDI2.0 #2
CDI2.0 仕様をサブセットに分割
CDI Lite 軽量なサブセットの抽出
•
CDIを Java EE 以外の世界で使ってもらいたい
•
Android, 組込みデバイス
•
現状の
CDI仕様はJava EE環境を前提
•
プロキシベースを前提としない軽量実装
•
AnnotaAon Processingによるコンパイル時依存性解決
(Androidでよく使われるDaggerがモデル)
•
省メモリ
、
低
CPU使用率の実現
CDI2.0 仕様をサブセットに分割
CDI Lite 軽量なサブセットの抽出
CDI core
• DI - @Inject, Qualifier • @Produces • Event & @Observes • 疑似スコープ @Dependent, @Singleton • ProgramaAc lookup • Portable ExtenAonCDI Java SE
• Bootstraping API • Scope in Java SE @ApplicaAonScoped • Packaging & deployment
CDI Java EE
• Scope in Java EE • @SessionScoped • @ConversaAonScoped • EJBとの連携
CDI2.0 #3
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コンテナ初期化
CDI2.0 Java SE Support
“仕様”として含める背景
•
Java EE 仕様間での整合性
•
JAX-RS , JPAは Java SE でも利用可能な仕様設計
•
Weld, OpenWebBeansで既に実装されていた
•
実装間で類似
APIが複数存在するのはJava EE思想に反する
CDI2.0 #4
CDI2.0 Java SE 8 Alignment
InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ
public class InterceptorBuilder {%
// デプロイ時にCDIコンテナよりコールバック%
void afterBeanDiscovery(@Observes AfterBeanDiscovery event) {%
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%
}% }%
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%
}% }%
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%
}% }%
CDI2.0 Java SE 8 Alignment
InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ
event.addInterceptor()% ...%
CDI2.0 Java SE 8 Alignment
InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ
event.addInterceptor()% ...% .addBinding(Log.INSTANCE);%@Log%
public void
target() {...}
適用対象メソッドと繋ぐために
、
CDI2.0 Java SE 8 Alignment
InterceptorBuilder: ラムダ or メソッド参照によるインターセプタ
event.addInterceptor()% ...% .addBinding(Log.INSTANCE);% % @Inherited% @InterceptorBinding% @Retention(RUNTIME)% @Target({METHOD, TYPE})%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のAnnotaAonLiteralクラスを継承して
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() {...}
CDI2.0 Java SE 8 Alignment
InterceptorBuilderのメリット
•
1クラスで複数のインターセプタ定義が可能
•
クラスが冗長に増えるのを防ぐ
•
Java EEの何でもアノテーション状態の改善
•
Java 5
から: アノテーションをスキャンしてコンテナ機能を付与
•
Java
8
から
: ラムダを渡すとコンテナが機能付与
CDI2.0 ロードマップ
スケジュール
•
2015/6: Early Dra] Review 1
•
hmps://docs.jboss.org/cdi/spec/2.0.EDR1/cdi-spec.html
•
2016/6: Early Dra] Review 2
予定
•
2016/12
〜
2017/1: CDI2.0 Final
予定
•
2017上半期 Java EE 8 リリース
予定
本日のコンテンツ
•
駆け足で振り返るCDI
•
CDI2.0
•
CDI + α
DI/AOPが標準化され
、
非同期イベントが入るのはわかった
。
Spring Framework
@Autowired
, @Aspect%
CDI
(Java EE)@Inject
, @Interceptor
DI/AOP
プロパティ管理
@Value,
@PropertySource%
Java起動引数による プロファイル切替@Profile
CDIは『材料』のみ提供して、
自作が必要なユースケースも多い
Spring Framework
@Autowired
, @Aspect%
CDI
(Java EE)@Inject
, @Interceptor
DI/AOP
プロパティ管理
@Value,
@PropertySource%
@Producesによる
要自作
Java起動引数による プロファイル切替@Profile
@Alternative
による要自作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 annotaAon like @ConfigProperty from deltapsikehmps://issues.jboss.org/browse/CDI-504 CDI-539: Support for 'profile' in CDI hmps://issues.jboss.org/browse/CDI-539
【
Issue CDI-504】
@Alternative
による要自作【
Issue CDI-539】
・
その機能は本当に
『
CDI
』
か?
過去例:
@TransacAonalをCDIではなくJTAへ
・
やはり
ConfigraAon JSR では?
CDI2.0
(2017
年
)
に向けて議論中ではある
CDI
(Java EE)@Inject
, @Interceptor
プロパティ管理
@Value,
@PropertySource%
@Producesによる
要自作
Java起動引数による プロファイル切替@Profile
CDI-504: have a standard CDI annotaAon like @ConfigProperty from deltapsikehmps://issues.jboss.org/browse/CDI-504 CDI-539: Support for 'profile' in CDI hmps://issues.jboss.org/browse/CDI-539
【
Issue CDI-504】
@Alternative
による要自作【
Issue CDI-539】
Spring Framework
@Autowired
, @Aspect%
DI/AOP
・
その機能は本当に
『
CDI
』
か?
過去例:
@TransacAonalをCDIではなくJTAへ
・
やはり
ConfigraAon JSR では?
2017
年を待てない場合は
Apache Deltaspike
“あったらいいな”は
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.projectstageProjectStage%
Apache Deltaspike
Apache Deltaspike
便利な
CDI拡張ライブラリ
•
CDIのPortable ExtenAonを活かしたライブラリ
•
Seem3 + My Faces CODI + α を統合
Apache Deltaspike #1
@ConfigProperty
@ConfigPropertyによるパラメータ注入
@ApplicationScoped%
public class RemoteConnector {% %
@Inject%
@ConfigProperty(name="remotehost", defaultValue="localhost:8080")% private String remotehost;%
...%
META-INF/apache-deltaspike.properAes
remotehost=192.168.1.2
DeltaspikeによりInject
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;%
}% }
Apache Deltaspike #1
@ConfigProperty
環境変数による値の差し替え
@Inject%
@ConfigProperty(name="remotehost”,defaultValue="localhost:8080")%
private String remotehost;%
【優先順位】
1.
環境変数
export
remotehost
=192.168.1.2
2.
システムプロパティ
java -D
remotehost
=192.168.1.4
3.
JNDI
new InitialContext().bind(“remotehost”, “192.168.1.5”)
Apache Deltaspike #2
ProjectStage
起動オプションで有効な
Beanを切り替える
Service
Repository 【development】H2
【producAon】
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>
Apache Deltaspike #2
ProjectStage
起動オプションで有効な
Beanを切り替える
@ApplicationScoped%
public class
Repository {%
@PersistenceContext(unitName =
“h2 or PostgreSQL??”
)%
private
EntityManager
em
;%
...%
}
Apache Deltaspike #2
ProjectStage
Development環境向けEnAtyManagerの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; %
Apache Deltaspike #2
ProjectStage
Development環境向けEnAtyManagerの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; %
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
Apache Deltaspike #2
ProjectStage
ProducAon向けも同様
@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
Apache Deltaspike #2
ProjectStage
ProducAon向けも同様
@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
Apache Deltaspike
@ConfigPropertyとProjectStage
•
2つに共通するメリット
•
環境変数や
Javaシステムプロパティで振る舞いを変更
•
テスト済
warを『修正なし』で複数環境で動作させる
開発環境 ステージング環境 商用環境 AP Server DB myapp.war Simurator myapp.war myapp.war 関連システム本日のコンテンツ
•
駆け足で振り返るCDI
•
CDI2.0
•
CDI + α
CDI2.0
(Java EE 8 / 2017)
•
CDI非同期イベント
•
仕様をサブセットに分割
•
Java SE Support
CDI2.0をもっと知るには
cdi-spec.org / JIRA / Weld3.0.0.Alpha
•
ホームページ
(CDI spec で検索)
•
hmp://www.cdi-spec.org
•
JIRA
•
hmps://issues.jboss.org/projects/CDI
•
CDI2.0 EarlyDra]Review 1 の参照実装
•
Weld 3.0.0.Alpha16
hmp://weld.cdi-spec.org/news/2016/04/28/weld-300Alpha16/•
WildFly10に組込み可能なpatchもリリース
最後に
CDI2.0 ドラフト仕様は今すぐWildFly10で動きます
ぜひ触ってみてください!
OracleとJavaは、Oracle CorporaAon及びその子会社、関連会社の米国及びその他の国における登録商標です。 文中の社名、商品名等は各社の商標または登録商標である場合があります。