X

An Oracle blog about WebLogic Channel

「EJB&CDI入門」レポート

WebLogic勉強会 通信

WebLogic Serverファンの皆様、こんにちは、WebLogic Server勉強会通信です。
2014年8月27日に開催されました
「第49回WebLogic Server勉強会@東京」
の前半のセッション
「はじめてのJava EEアプリケーション開発シリーズ」(全4回)の

「第3回 EJB&CDI入門」

をレポートします。
講師は日本オラクル オラクルユニバーシティの岡田さんです。岡田さんが
EJB(Enterprise JavaBeans)3.1の概要、セッションBeanの種類、トランザクション制御、依存性の注入による
コンポーネント間の連携、Beanのライフサイクル管理などを解説しました。
アプリケーション開発の生産性向上のために、なぜEJBが有効か?EJB3.1は以前のEJBと何が違うのか?など
ぜひ、この機会にEJBとCDIによる開発スタイルの感覚を身に付けてください。
(日本オラクル Fusion Middleware事業統括本部 佐々木 政和)

はじめに

まずは「Java EE」のおさらいから。Java EEは、Java SEをベースにした企業システム向けの
フレームワークで、コミュニティ主導のエンタープライズソフトウェア標準仕様です。
コンポーネント仕様とサービスアクセスのための各種APIが規定されています。
Java EEの標準規格に則ったAPIを使ったプログラムは、アプリケーションの移植性が高く、
企業のIT資産として将来的にも有効に活用できます。
ソフトウェア製品ベンダーは、Java EEに準拠したコンポーネントを制御するための基盤を
アプリケーションサーバ製品として提供しています。そのひとつが、Oracle WebLogic Serverです。

Java EE 6の主要な仕様として、JSF2.1(前回のWebLogic Server勉強会@東京で取り上げました)、
Servlet 3.0、JAX-RSや今回のテーマのEJB3.1, CDIがあります。
Enterprise JavaBeans (EJB) 3.1は、Java EE 6のサーバ側のコンポーネントアーキテクチャベースの仕様です。
EJB 3.1を使用することで、Javaテクノロジに基づいて、安全でポータブルな分散トランザクションアプリケーションを
迅速かつ容易に開発することができます。EJB3.1のメタデータアノテーション(注釈)を使用してアプリケーション開発を
簡略化する方法を中心に説明します。第1回、第2回の資料は、

「第1回 Java EE&WebLogic Server入門」(5月27日)


「第2回 JSF入門」(6月24日)

を参照ください。

アプリケーション構成図

アプリケーションの構成図です。プレゼンテーション層としてユーザインタフェースを行う部分が
第2回で説明した部分。データアクセス層で永続化を取り上げるのが次回第4回のテーマです。
今回は真ん中のビジネスロジック層について説明します。

今回作成するアプリケーションのコードを表示しています。
前回作成したメニューを表示するindex.xhtmlと一覧を表示するlist.xhtml
からManagedBeanで呼ばれるビジネスロジックをステートレスセッションBeanで作成します。
このアプリケーションは最終的にはデータベースに問い合わせて
データを操作するのですが、データ層は次回のテーマなので
その部分はダミーロジックのままです。

コンポーネントアーキテクチャ

EJB(Enterprise JavaBeans)は再利用可能なビジネスロジックを提供するための
コンポーネント仕様です。セッションBeanはクライアントから送られてきたリクエストに対する
ビジネスロジックを記述します。(今回のテーマ)
リクエストに対してレスポンスを返す際に、同期、非同期型処理が可能です。
メッセージドリブンBeanはJMSメッセージ受信時に実行するビジネスロジックを記述します。
エンティティBeanはORマッピングとビジネスロジック(データの操作)を記述します。
ただし、エンティティBeanはEJB 2.1までで、Java EE 6ではORマッピングはJPAを使用します。

アプリケーションプログラムは固有機能と共通機能に分離することができます。
コンポーネントアーキテクチャは、共通の機能をコンテナ(コンポーネントの入れ物をイメージすると分かりやすい)上に
実装し、アプリケーション固有のビジネスロジックをコンポーネントとして開発するアーキテクチャです。

コンテナ(Java EEのWebコンテナやEJBコンテナ)はクライアントに「サービス」を
提供する実行環境です。EJBコンテナは、アプリケーションサーバ上に実装されたEJB用の実行時コンテナです。
このコンテナはアプリケーションサーバの起動時に自動的に作成され、
Beanに対して以下のような実行時サービスを提供します
(ライフサイクル管理、コード生成、セキュリティ、トランザクションの管理、ロックと同時実行性制御)。
コンポーネントはアプリケーション固有のビジネスロジックですが、コンテナが提供しているサービスを
利用しています。コンポーネントはコンテナによって管理されます。


コンテナが提供するサービスには、デプロイ時に宣言可能なサービス
(永続化、トランザクション、セキュリティ、インジェクション)、
コンポーネント制御のためのサービス(ライフサイクル管理、スレッド管理、
クライアントとの通信)、コンテナプロバイダ固有のサービス(クラスタリング、
負荷分散、フェイルオーバー)の3種類があります。コンテナ固有の機能
について、例えば、WebLogic Serverのクラスタ機能はEJBの種類によって
「振る舞い」が変わっています。アプリケーションサーバごとに独自の機能が
提供されています。


コンポーネントがサービスAPIを通じてコンテナにリクエストを出す際に
Java EEのAPIを使用します。(図の青の部分))

EJB Lite

EJB Liteは名前の通りEJB 3.1の軽量版、サブセットとして提供されるものです。
ローカルクライアント、宣言的セキュリティ、トランザクション(CMT/BMT)、
インターセプタなどの機能が使用できますが、メッセージドリブンBeanや非同期メソッド呼び出し
などの機能は使用できません。
Web Profileまたは Java EE 6フルプラットフォームのアプリケーションサーバに
デプロイできます。EJB Liteはできることに限りがあるEJBの機能制限版ですが、
開発予定のアプリケーション要件に合っている場合はEJB LiteでOKでしょう。

EJBはWAR内にパッケージ可能に

EJB 3.1では、EJBクラスをejb-jarファイルの中にパッケージ化しなければならないという制限が取り除かれました。
そのため、Webアプリケーションクラスに適用される同じパッケージ化のガイドラインを使用して、
EJBクラスをWebアプリケーションアーカイブ(WAR)の中に直接パッケージ化できます。
単にEJBクラスをWEB-INF/classesディレクトリかWEB-INF/libディレクトリ内のJARファイルに入れるのみです。
必要に応じて、EJBデプロイメント記述子を使用する場合は、それをWEB-INF/ejb-jar.xmlとしてパッケージ化できます。

セッションBean

セッションBeanはビジネスロジックを記述するコンポーネントです。
クライアントからのリクエスト受信時に実行するビジネスロジックを記述します。
EJB3.0からBeanファイルは、POJO (Plain Old Java Object)に注釈(アノテーション)を追加することで実装できます。
(javax.ejb.SessionBeanを実装する必要はありません。)
原則は同期呼び出しですがEJB3.1から非同期呼び出しの仕様が追加されました。

EJB 3.1では、非同期クライアント呼出しセマンティクスでメソッドを公開できます。
EJBクラスまたは特定のメソッドで@Asynchronousアノテーションを使用すると、メソッドが呼び出されたときに、
クライアントに即座に制御を戻すようにEJBコンテナに指示します。メソッドはFutureオブジェクトを返して、
クライアントにメソッド呼出しのステータスをチェックさせて、非同期に生成される結果の値を取得できます。

EJBコンテナによってライフサイクルが管理されます。
クライアントの呼び出しを受けるとEJBコンテナによってセッションBeanが呼び出されます。
トランザクションやセキュティはデプロイ時に宣言可能なサービスとしてEJBコンテナが提供します。
デプロイメント記述子は無くても構いませんが、カスタマイズが必要な場合は
ejb-jar.xmlやweblogic-ejb-jar.xmlの中で明示的に設定可能です。
(競合がある場合、デプロイメント記述子の値がアノテーションの値をオーバーライドします。)
WebLogic Server EJB 3.1プログラミングモデルでは、Java EE 6メタデータアノテーション機能を使用して、
アノテーション付きEJB 3.1 Beanファイルを作成し、標準Javaコンパイラでクラスをコンパイルします。
生成されたクラスは、デプロイメント用のターゲットモジュールにパッケージ化できます。
実行時に、WebLogic Serverはアノテーションを解析して、必要な動作のアスペクトをBeanファイルに適用します。

セッションBeanの種類


セッションBeanは次の3種類があります。POJOに追加する注釈によりEJBコンテナはそれぞれの
仕様に応じた振る舞いを行います。


1. ステートレスセッションBeanの場合はクライアントごとにインスタンスを割当てます。
クライアントの状態を保持しません。


2. ステートフルセッションBeanの場合はクライアントごとにインスタンスを割当てます。
クライアントの状態を保持します。


3. シングルトンセッションBeanはEJB3.1から加えられた新しい仕様です。
シングルトンセッションBeanの場合は、、特定のJava仮想マシン(JVM)のアプリケーションごとに
1回のみインスタンス化し、すべてのクライアントに共通のインスタンスを割り当てます。

セッションBeanの振る舞い

  • 1. ステートレスセッションBean
    呼び出し間でセッションやクライアントの状態の情報を格納しません。
    唯一格納されることのある状態はクライアントに固有のものではなく、
    キャッシュされたデータベース接続や別のEJBの参照などです。
    ステートレスセッションBeanが状態を格納できるのは、長くてメソッド呼出しの期間だけです。
    メソッドが完了すると、状態情報は維持されません。(ステートレスセッションBeanプールに戻される)


    ステートレスセッションBean:
    ステートレスセッションBeanは、ステートフルセッションBeanよりもパフォーマンスが優れています。
    その理由は、各ステートレスセッションBeanが複数のクライアントをサポートできるからです
    (ただし一度に1つ)。
    ステートレスセッションBeanのクライアントは、Webサービスエンドポイントにできます。

  • 2. ステートフルセッションBean:
    特定のクライアントとの対話を反映する状態情報をメソッドやトランザクションをまたがって維持します。
    ステートフルセッションBeanは、クライアントと他のEJBの対話を管理したり、ワークフローを管理できます。
    クライアントごとに保持されますので、クライアント数が多くなれば大きなHeap領域を使うことになります。

  • 3. シングルトンセッションBean:
    シングルトンセッションBeanは、JVMごとに1つしかインスタンス化されないこと以外は
    ステートレスセッションBeanとほぼ同様の機能を提供します。
    キャッシュやリソースへのアクセスビューを共有化し並列処理を行いたい場合など
    並行処理用のアノテーションを組み合わせて効率良くかつ安全なプログラミングが可能です。
    ステートレスセッションBeanと同様に、Webサービスエンドポイントを実装できます。
    シングルトンセッションBeanではクライアントの呼出し間でその状態を保持しますが、
    サーバーのクラッシュまたは停止時にはその状態を保持しません。
  • ステートレスセッションBeanを作成する

    ファイルタイプを選択のところで、プロジェクト名を指定して、[Enterprise JavaBeans] -> [セッションBean]を選択します。

    (クラスの名前)EJB名の指定、セッションのタイプを選択します。
    EJB3.0では、最低1つのローカルあるいはリモートインタフェースを書く必要がありましたが、
    EJB3.1では、インタフェース無しの実装も可能になりました。
    リモートアクセスをさせる場合はインタフェースが必要です。

    NetBeansでは編集フィールドで右クリックしてメニューからビジネスメソッドを定義できます。
    インタフェース(ローカルインタフェース、リモートインタフェース)のメソッド宣言も
    同期を取ってくれますので実装抜け無くなります。

    セッションBeanのライフサイクルとコールバックメソッド

    EJBは種類によって振る舞いが異なるのでライフサイクルも異なります。、
    いずれもライフサイクル自体はコンテナによって制御され、
    ライフサイクルコールバックを処理するメソッドを実装できます。
    EJBの初期化時や終了時など任意のタイミングでの処理が必要な場合は、
    下記のようなコールバック注釈をつけたメソッドを実装します。




    @PostConstruct … 依存性注入完了後に、初期化処理として呼び出される


    @PreDestroy … インスタンス破棄する直前に呼び出される


    @PrePassivate … パッシベーション前に呼び出される (Stateful Session Beanのみ)


    @PostActivate … アクティベーション後に呼び出される (Stateful Session Beanのみ)

    WebLoic Serverのチューニング

    WebLogic Serverは、EJBコンテナに対してアプリケーション環境に合わせたチューニングパラメータを
    提供しています。weblogic-ejb-jar.xmlファイルに設定することができます。


    1) max-beans-in-free-pool: ステートレスセッションBeanのプールの最大サイズ


    2) initial-beans-in-free-pool: WebLogic Server起動時に作成されるステートレスセッションBeanのプールサイズ。


    設定は initial = max を推奨、maxの値は、 そのEJBへの最大同時アクセス数が目安 ( < 実行スレッド数)


    3) max-beans-in-cache: ステートフルセッションBeanのキャッシュサイズ

    ビジネスインタフェース

    Beanクラスのメソッドはビジネスインタフェースを通して公開可能です。
    EJBクライアントとコンポーネントの結合度を疎に保つためにインタフェースを
    定義し使用します。
    クライアントのアクセスモデル(同じJVMであればローカル、
    異なるJVMは
    リモート)
    を注釈で指定します。ローカルアクセスは@Local、リモートアクセスは@Remoteです。

    Java EE 5のDIを使用したEJBの呼び出し

    EJBの呼び出し方法はシンプルでクライアント側は
    @EJBアノテーションを書けば良く、
    @EJB, @RESOURCEとアノテーションが異なる点に注意が必要です(後半のJava EE 6 CDI参照)。

    トランザクションの管理

    EJBコンテナはトランザクション管理サービスを提供しています。
    CMT(コンテナ管理)とBMT(Bean管理)を選択可能(@TransactionManagement)です。
    CMT … コンテナがトランザクションを管理 (@TransactionAttributeで振る舞いを指定)
    BMT … Beanがトランザクション処理 (begin/commit を記述)
    CMTのトランザクション属性を理解して要件に合ったトランザクション属性を指定する必要が
    あります。

    CDIとは

    Contexts and Dependency Injection for Java EE(CDI 1.0)は、
    Java EE 6標準のDI仕様です。この仕様は
    アプリケーションサーバ上の実行中の処理状態(Context)に関連付けて依存性を注入(Dependency Injection)
    する仕組みを規定したものです。

    EJBコンテナが、インスタンスの生成や削除(ライフサイクル)をコンテキストに応じて管理してくれるので、
    利用者はCDI Beanの型を知っていれば良く、ライフサイクルを意識する必要はありません。
    依存性を注入する場合は、@Injectアノテーションを使用します。

    CDI Beanは注釈により、コンテナがインスタンス化してから破棄するまでの期間を設定することができます。
    @RequestScopedアノテーションは、HTTP リクエストを受けてからレスポンスを返すまでの間、


    @ConversationScopedは、明示的に呼び出されたConversation.begin()からConversation.end()を実行するまでの間、


    @SessionScopedはHTTPセッションが有効な間、


    @ApplicationScopedはWebアプリケーションが起動して終了するまでの間


    @Dependentはインジェクション先と同じライフサイクル(デフォルト)
    です。

    CDIを有効にしてCDI Beanを作って見る

    Java EEでCDIを使う場合の下準備として、
    CDI を有効化
    するために
    beans.xml ファイルをアプリケーションに含めなければなりません。
    META-INF、WEB-INF下にbeans.xmlファイルを作成します。(中身は問いません)

    CDI Beanの実装

    @Namedアノテーションとスコープの注釈を指定します。
    (省略すると @Dependent と同じですが、できるだけ省略しない)
    Java EE 7にアップグレードした場合などを考慮すると、
    CDIのスコープ注釈は省略せずに書くことを推奨します。

    EL式からCDI Beanをアクセスする

    EL式の構文は#{ CDI Beanの名前.プロパティ名 }でCDI Beanを呼び出すことができます。
    またEJBクライアントからは、@Injectアノテーション注釈でEJBへの参照をDIすることができます。

    まとめ

    今回は、セッションBeanの種類、Beanのライフサイクル管理、トランザクション制御、依存性の注入によるコンポーネント
    間の連携などを取り上げました。EJB3.1の仕様EJB3.1+CDI1.0を使ったPOJO + @アノテーションのアプリケーション開発を
    ぜひ体験してください。
    第2回のJSF入門、今回のEJB&CDI入門につづき次回のWebLogic Server勉強会@東京は最終回「JPA入門」です。
    アプリケーションがいよいよ完結します。




    「第1回」 Java EE&WebLogic Server入門(5月27日)のスライド


    クイックレビュー




    「第2回」 JSF入門(6月24日)のスライド


    レポート




    「第3回」 EJB&CDI入門(8月27日)のスライド




    Be the first to comment

    Comments ( 0 )
    Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.