Upload
inatus
View
4.520
Download
4
Embed Size (px)
DESCRIPTION
JavaEE 6のEJB (Enterprise JavaBean) についての説明
Citation preview
Beginning JavaEE6 勉強会 (3)-Enterprise JavaBean-
Hiroki Inagaki@inatus
http://github.com/inatus
2
目次
5/16/2012 Beginning JavaEE6 勉強会 (1)
6. Enterprise JavaBeans
7. セッション Beanとタイマーサービス
8. コールバックとインターセプタ
9. トランザクションとセキュリティ
3
第6章Enterprise JavaBeans
5/16/2012 Beginning JavaEE6 勉強会 (3)
4
EJBとは トランザクションとセキュリティを扱うサーバサイドのコンポーネント
ビジネスロジックをカプセル化 メッセージング、スケジューリング、リモートアクセス、 SOAP/REST、 DI、 AOPを扱う
JDBC、 JavaMail、 JPA、 JTA、 JMS、 JAAS、 JNDI、 RMIと統合
5/16/2012 Beginning JavaEE6 勉強会 (1)
5
第7章セッションBeanとタイマーサービス
5/16/2012 Beginning JavaEE6 勉強会 (3)
6
セッション Bean
EJBの核 ビシネスロジックをカプセル化する 以下の種類がある
ステートレス対話状態を保持しない 1つのメソッドで完結
ステートフル対話状態を保持する複数のメソッドにまたがって利用
シングルトン複数のクライアントが同時にアクセス
5/16/2012 Beginning JavaEE6 勉強会 (1)
7
ステートレス Bean
最も良く使用される 単一のメソッド呼び出しでタスクが完了するビジネスプロセスを実行する
一定の数のインスタンスがプール内に格納される複数のクライアント間で再利用できるため、最も効率が良い
5/16/2012 Beginning JavaEE6 勉強会 (3)
インスタンスプールインスタンス インスタン
スインスタンス
クライアントクライアント
EJBコンテナ
8
ステートレス Bean
5/16/2012 Beginning JavaEE6 勉強会 (3)
@Statelesspublic class MemberEJB {
@PersistenceContext(unitName = "sample") private EntityManager em;
public Member findMemberById(Long id) { return em.find(Member.class, id); } public Member createMember(Member member) { em.persist(member); return member; }}
9
ステートフル Bean
前のステップの状態に依存する複数ステップを含むタスクに使用できる
例えば、ショッピングサイトのように、商品を選択してから決済が完了するまでショッピングカートの中身が保持されなければならないといった場合に使用する
Beanインスタンスとクライアントは一対一で紐付けられる
5/16/2012 Beginning JavaEE6 勉強会 (3)
EJBコンテナ
インスタンス インスタン
スクライアントクライアント
①要求②生成
③呼出し
10
ステートフル Bean
5/16/2012 Beginning JavaEE6 勉強会 (3)
@Stateful@StatefulTimeout(value = 15, unit = TimeUnit.MINUTES)public class CartEJB {
private Set<Item> cart = new LinkedHashSet<Item>();
public void addItem(Item item) { cart.add(item); } public void removeItem(Item item) { cart.remove(item); }}
11
アプリケーションごとに 1つのインスタンスが生成される
各クライアントは 1つのインスタンスを共有する
同時実行の制御を行う必要がある 初期化の次期や、複数のシングルトン Beanを初期化する順序を考慮する必要がある
EJBコンテナ
シングルトン Bean
5/16/2012 Beginning JavaEE6 勉強会 (3)
インスタンス
クライアント
クライアント
クライアント
12
シングルトン Bean
5/16/2012 Beginning JavaEE6 勉強会 (3)
@Singletonpublic class CacheEJB {
private Map<Long, Object> cache = new HashMap<Long, Object>(); public void addToCache(Long id, Object target) { if (!cache.containsKey(id)) { cache.put(id, target); } } public void removeFromCache(Long id) { cache.remove(id); }}
13
セッション Beanモデル Beanクラスの定義にインタフェースを用いる方法と用いない方法があるリモート・インタフェース
EJBコンテナが動作している JVMインスタンスの外部にクライアントが存在する場合に使用
RMIを利用するローカル・インタフェース
同じ JVM内の別の EJBやWebコンポーネントを呼び出すインタフェースのないビュー
ローカルビューの一種すべてのパブリックメソッドをローカルに公開する
5/16/2012 Beginning JavaEE6 勉強会 (3)
14
アプリケーションサーバ 2EJBコンテナ
EJBコンテナコンポーネント
Bean
Bean
アプリケーションサーバ 1EJBコンテナ
EJBコンテナ
セッション Beanモデル
5/16/2012 Beginning JavaEE6 勉強会 (3)
コンポーネント
クライアント
ローカル リモート
Bean
Bean
15
ローカル&リモート・インタフェース
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Localpublic interface MemberEJBLocal { Member findMemberById(Long id);}
@Remotepublic interface MemberEJBRemote { Member createMember(Member member);}
@Statelesspublic class MemberEJB implements MemberEJBLocal,
MemberEJBRemote { ...}
16
インタフェースのないビュー
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Stateless@LocalBeanpublic class MemberEJB { ...}
17
クライアントからの Bean呼び出し リモート&ローカル・インタフェースの場合インタフェースオブジェクトに@EJBで DIする
インタフェースのないビューの場合クラスのオブジェクトに@EJBで DIする
5/9/2012 Beginning JavaEE6 勉強会 (3)
@EJB MemberEJBRemote memberEJBRemote;@EJB MemberEJBLocal memberEJBLocal;
@EJB MemberEJB memberEJB;
18
DI(依存性注入)
以下のような方法がある @EJB
EJBのリモート&ローカル・インタフェース、インタフェースのないビューの参照を注入
@PersistenceContext, @PersistenceUnit EntityManager, EntityManagerFactoryの依存関係を表す
@WebServiceRef Webサービスへの参照を注入
@Resource JDBCデータソース、セッション・コンテキスト、ユーザ・トランザクション等の参照を注入
5/9/2012 Beginning JavaEE6 勉強会 (3)
19
非同期呼び出し 印刷やメール送信などの処理が終了するまで待たずに、続く処理を続行する
セッション Beanのメソッドまたはクラスに@Asynchronousを付加する
非同期呼び出しからの戻り値を用いる場合は戻り値の型に Future<V>を使用する
5/9/2012 Beginning JavaEE6 勉強会 (3)
20
非同期呼び出し
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Stateless@Asynchronouspublic class OrderEJB {
public void sendEmailConfirmation(Order order) {// Emailの送信処理
}
public void printOrder(Order order) {// 注文書の印刷処理
}
public Future<Integer> CalcShippingCost(Order order) {int shippingCost = 0;// 送料計算処理return AsyncResult<Integer>(shippingCost);
}
21
タイマサービス 特定の時間に特定の処理を起動する
毎晩在庫レポートを出力毎月売上を集計毎年ユーザの誕生日にメールを送信
起動対象のメソッドに@Scheduleアノテーションとタイマを設定
5/9/2012 Beginning JavaEE6 勉強会 (3)
22
タイマサービス
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Statelesspublic class TimerEJB {
// 毎日 0時 0分 0秒に実行 @Schedule(second = "0", minute = "0", hour = "0") public void outputReport() { // 日次レポート出力処理 }
// 毎月の最終日の 22時に実行 @Schedule(hour = "22", dayOfMonth = "Last") public void addUpSales() { // 月次の売上を集計 }}
23
タイマサービス
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Statelesspublic class MemberEJB {
@Resource TimerService timerService; // Memberの誕生日にタイマを設定 public Member createMember(Member member) { em.persist(member); ScheduleExpression membersBirthday
= new ScheduleExpression().dayOfMonth(member.getBirthDay()).month(member.getBirthMonth());
timerService.createCalendarTimer(membersBirthday, new TimerConfig(member, true));
return member; }// 次頁へ続く
24
タイマサービス
5/9/2012 Beginning JavaEE6 勉強会 (3)
// 前頁から続き // タイマが切れたときに Eメールを送信 @Timeout public void sendBirthdayEmail(Timer timer) { Member member = (Member) timer.getInfo(); // Eメール送信処理 }}
25
第8章コールバックとインターセプタ
5/9/2012 Beginning JavaEE6 勉強会 (3)
26
コールバックとインターセプタ コールバック
Beanの状態遷移が起きる際に任意のメソッドを呼び出すこと
Beanごとに設定する
インターセプタ AOPと同様の機能 Beanのメソッドを呼び出す際に、別のメソッドを呼び出し割り込み処理を行う
複数の Beanに対して横断的に設定できる
5/9/2012 Beginning JavaEE6 勉強会 (3)
27
コールバック ステートレス Bean、シングルトン Beanのライフサイクル
5/9/2012 Beginning JavaEE6 勉強会 (3)
存在しない状態
準備状態
5.@PreDestroy呼出し1.インスタンス生成2.依存性注入3.@PostConstruct呼出し
4.メソッド呼出し
28
コールバック ステートフル Beanのライフサイクル
5/9/2012 Beginning JavaEE6 勉強会 (3)
存在しない状態
準備状態
1.インスタンス生成2.依存性注入3.@PostConstruct 呼出し 6.@PostActive呼出し
4.メソッド呼出し
非活性化状態
5.@PrePassive呼出し
7.タイムアウト
8.@Removeおよび @PreDestroy呼出し
29
コールバック
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Statefulpublic class CartEJB { @Resource private DataSource ds; private Connection conn; @PostConstruct @PostActivate private void init() throws SQLException { conn = ds.getConnection(); } @PreDestroy @PrePassivate private void close() throws SQLException { conn.close(); }
30
コールバックメソッド 引数なしの voidメソッドであること チェック例外のスロー不可、実行時例外は可 アクセス修飾子はすべて使用可 static、 finalは不可 1メソッドに複数のアノテーションを指定可 同じアノテーションを 2度以上指定不可
5/9/2012 Beginning JavaEE6 勉強会 (3)
31
インターセプタ AroundInvokeインターセプタ
Beanごとに適用 Bean内のすべてのメソッドに対して適用される
クラス・インターセプタ 複数の Beanに横断的に適用 インターセプト用のクラスを定義
ライフサイクル・インターセプタ コールバックの機能を複数の Beanに横断的に適用
5/9/2012 Beginning JavaEE6 勉強会 (3)
32
AroundInvokeインターセプタ
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Statelesspublic class MemberEJB { public Member findMemberById(Long id) { ... } public Member createMember(Member member) { ... }
@AroundInvoke private Object recordLog(InvocationContext ic) throws Exception { // メソッド呼び出し前ログ書き込み処理 try { return ic.proceed(); finally { // メソッド呼び出しログ書き込み処理 {
33
AroundInvokeインターセプタの定義@AroudInvokeObject <メソッド名 >(InvocationContext ic) throws Exception;
引数は javax.interceptor.InvocationContext型
戻り値は Object型 チェック例外をスロー可 アクセス修飾子はすべて使用可 static、 finalは不可 proceedメソッドでビジネスメソッドを呼び出し、結果を返すただしチェーン内に次のインターセプタメソッドがある場合はそのインターセプタメソッドを呼び出す
5/9/2012 Beginning JavaEE6 勉強会 (3)
@AroudInvokeObject <メソッド名 >(InvocationContext ic) throws Exception;
34
クラス・インターセプタ
5/9/2012 Beginning JavaEE6 勉強会 (3)
public class LoggingInterceptor { @AroundInvoke private Object recordLog(InvocationContext ic) throws Exception { // メソッド呼び出し前ログ書き込み処理 try { return ic.proceed(); finally { // メソッド呼び出しログ書き込み処理 {{
35
クラス・インターセプタ
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Statelesspublic class MemberEJB { @Interceptors(LoggingInterceptor.class) public Member findMemberById(Long id) { ... } public Member createMember(Member member) { ... }}
36
クラス・インターセプタ インターセプタとする任意のクラスのメソッドに@AroundInvokeアノテーションを使用
インターセプタを適用したいメソッドまたはクラスに@Interceptorsアノテーションを使用メソッドに指定すると指定したメソッドのみインターセプタを適用する
クラスに指定するとクラス内のすべてのメソッドにインターセプタを適用する
特定のメソッドのみをインターセプタ適用外とする場合は@ExcludeClassInterceptorsアノテーションを用いる
5/9/2012 Beginning JavaEE6 勉強会 (3)
37
ライフサイクル・インターセプタ
5/9/2012 Beginning JavaEE6 勉強会 (3)
public class LoggingInterceptor { @PostConstruct private void init() { // 初期化処理 {{
38
ライフサイクル・インターセプタ
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Stateless@Interceptors(LoggingInterceptor.class)public class MemberEJB { public Member findMemberById(Long id) { ... } public Member createMember(Member member) { ... }}
39
ライフサイクル・インターセプタ Beanのライフサイクルに応じたコールバックを複数の Beanを横断的に適用可能
@PostConstruct, @PrePassivate, @PostActivate, @PreDestroyが指定可能
インターセプタを適用したいクラスに@Interceptorsアノテーションを使用
5/9/2012 Beginning JavaEE6 勉強会 (3)
40
第9章トランザクションとセキュリティ
5/9/2012 Beginning JavaEE6 勉強会 (3)
41
EJBでのトランザクションサポート コンテナ管理トランザクション( CMT)
トランザクションの開始、コミット、ロールバックをコンテナが自動的に管理
なにも設定しない時のデフォルトの動作 Bean管理トランザクション( BMT)
トランザクションの開始、コミット、ロールバックを Bean内に明示的に記述
04/13/2023 Beginning JavaEE6 勉強会 (3)
42
コンテナ管理トランザクション( CMT)
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Statelesspublic class MemberEJB {
@PersistenceContext(unitName = "sample") private EntityManager em; public Member createMember(Member member) { em.persist(member); return member; }}
43
CMTの属性 クライアントがトランザクション対応のメソッドを呼び出すときに、そのメソッドがトランザクション内で呼び出されているか否かによって、以下の 4つうちどの動作をするかを設定できるコンテナがクライアントのトランザクションを利用する
新しいトランザクションを開始してメソッドを実行する
トランザクションを使用しないでメソッドを実行する
例外をスローする クラスやメソッドに@TransactionAttributeを付加
5/9/2012 Beginning JavaEE6 勉強会 (3)
44
CMTの属性CMT属性 トランザクション内でない トランザクション内REQUIRED 新しいトランザクション 呼出し元のトランザクションREQUIRED_NEW 新しいトランザクション 新しいトランザクションSUPPORTS トランザクションを使用し
ない呼出し元のトランザクション
MANDATORY 例外 呼出し元のトランザクションNOT_SUPPORTED トランザクションを使用し
ないトランザクションを使用しない
NEVER トランザクションを使用しない
例外
5/9/2012 Beginning JavaEE6 勉強会 (3)
45
CMTの属性
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Stateless@TransactionAttribute (TransactionAttributeType.SUPPORTS)public class MemberEJB {
@PersistenceContext(unitName = "sample") private EntityManager em; public Member createMember(Member member) { em.persist(member); return member; }}
46
CMTのロールバック デフォルトでは非チェック例外が発生した場合のみトランザクションがロールバックされる
明示的にトランザクションをロールバックするには DIにより SessionContextを取得しsetRollBackOnly()メソッドを呼び出す
5/9/2012 Beginning JavaEE6 勉強会 (3)
47
CMTのロールバック
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Statelesspublic class MemberEJB {
@PersistenceContext(unitName = "sample") private EntityManager em; @Resource private SessionContext ctx; public Member createMember(Member member) { if (member.isValidMember) { ctx.setRollBackOnly(); } em.persist(member); return member; }}
48
例外処理 デフォルトでは非チェック例外が発生した場合のみトランザクションがロールバックする
ユーザ例外クラスに@ApplicationExceptionを付加することでチェック例外/非チェック例外に関わらず、ロールバックの有無を設定可能
5/9/2012 Beginning JavaEE6 勉強会 (3)
49
例外処理
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Statelesspublic class MemberEJB {
@PersistenceContext(unitName = "sample") private EntityManager em; @Resource private SessionContext ctx; public Member createMember(Member member) throws MemberInvalidException { if (member.isValidMember) { throw new MemberInvalidException(); } em.persist(member); return member; }}
50
例外処理
5/9/2012 Beginning JavaEE6 勉強会 (3)
@ApplicationException(rollback = true)public class MemberInvalidException extends Exception {
public MemberInvalidException() {
}
public MemberInvalidException(String message) { super(message); }}
51
Bean管理トランザクション( BMT) Beanのメソッド内に明示的にトランザクションの開始・コミット・ロールバックを記述
@TransactionManagementアノテーションを Beanクラスに付加すると Bean管理のトランザクションとなる
DIにより UserTransactionのインスタンスを生成し、 begin(), commit(), rollback()メソッドによりトランザクションの操作を行う
5/9/2012 Beginning JavaEE6 勉強会 (3)
52
Bean管理トランザクション( BMT)
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Stateless@TransactionManagement( TransactionManagementType.BEAN)public class MemberEJB {
@PersistenceContext(unitName = "sample") private EntityManager em; @Resource private UserTransaction ut; public Member createMember(Member member) { ut.begin(); em.persist(member); if (member.isValidMember) { ut.rollback(); } ut.commit(); return member; }
53
セキュリティ プリンシパルのロールごとに Bean全体または一部メソッドのアクセスを制御することができる
プリンシパル認証を行ったユーザのユーザ名
making kjstylepp inatus など
ロールプリンシパルごとに割り当てられるグループ名
Employee Admin User など
5/9/2012 Beginning JavaEE6 勉強会 (3)
54
宣言型のセキュリティ アノテーションを Beanクラスまたはメソッドに付加し、アクセスを制御する
@PermitAllすべてのロールにアクセス許可を与える
@DenyAllすべてのロールからのアクセスを拒否する特定の環境でメソッドへのアクセスを拒否する場合などに利用する
@RollsAllowedリストに指定されているロールにアクセス許可を与える
5/9/2012 Beginning JavaEE6 勉強会 (3)
55
宣言型のセキュリティ
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Stateless@RolesAllowed({“user”, “employee”, “admin”})public class MemberEJB {
@PermitAll public Member findMemberById(Long id) { ... } public Member createMember(Member member) { ... } @RolesAllowed(“admin”) public void deleteMember(Member member) { ... } @DenyAll public Member findConfidentialMember(Long id) { ... }
56
プログラムによるセキュリティ 以下の場合に用いる
メソッド内のコードのブロックにアクセスを許可または拒否をする場合
個人へのアクセス許可または拒否をする場合 DIで SessionContextのインスタンスを生成し、以下のメソッドを用いる isCallerInRole():指定したロールであるかを判定し boolean値を返す
getCallerPrincipal(): Principalオブジェクト返す
Principal.getName()でプリンシパルの名前を取得可能
5/9/2012 Beginning JavaEE6 勉強会 (3)
57
宣言型のセキュリティ
5/9/2012 Beginning JavaEE6 勉強会 (3)
@Stateless@RolesAllowed({“user”, “employee”, “admin”})public class MemberEJB {
@resource SessionContext ctx;
public Member findMemberById(Long id) { if (ctx.isCallerInRole(“user”) { // 本の検索処理 } if (ctx.getCallerPrincipal().getName() .equals(“inatus”) { return findConfidentialMember(id); } ...}