Since: May/18th/2004
EJB は J2EE 仕様に含まれる仕様の一つです。2004 年現在主流の J2EE 1.3 には EJB 2.0 が含まれています。
J2EE 1.3 の EJB 2.0 では、既存の Session Beans, Entity Beans に加えて、Message-Driven Beans (MDB) が追加されました。EJB クライアントからアクセス可能な Session Beans と Entity Beans と異なり、MDB は JMS プロバイダと呼ばれる MOM (Message Oriented Middleware) から呼び出されます。
SessionBean
を実装します。
EntityBean
を実装します。
MessageDrivenBean
と MessageListener
を実装します。
EJB については、Session Bean, Entity Bean, Message-Driven Bean の三種類があり、他の Java クラス(EJB クライアント)から明示的にアクセスできるのは Session Bean と Entity Bean だと説明しました。MDB (Message-Driven Bean) は JMS のメッセージの到着をトリガーとして起動します。
EJB クライアントからは、次の三つの方法でアクセスします。
最も基本的なものが Remote インタフェースです。J2EE 1.3 (EJB 2.0) になって、Local インタフェースが追加されました。Remote インタフェースは、分散オブジェクト実装のための RMI/IIOP のプロトコルを使って、ノードが異なるオブジェクトを呼び出せます。
しかし、この場合は、メソッド引数の値をコピーする値渡しで、パフォーマンス的なボトルネックになっていました。これを改善したのが Local インタフェースで、同一ノード内(同一 JVM 内)でのメソッドの参照であれば、値渡しではなく、参照渡しでメソッド引数を取り扱えるようにしたものです。
従来の EJB では、分散オブジェクトを前提に、ノードへのアプリのデプロメントの自由度を確保することを目的としていました。Local インタフェースは、デプロイメントの自由度を犠牲にして、パフォーマンス的な問題点を解決するものです。
MDB (Message-Driven Beans) のことを説明する前に、JMS (Java Message Service) について説明する必要があります。
JMS は、J2EE 1.3 で必須とされた仕様です。Web 層のサーブレット/JSP、既存の EJB コンテナの Session Beans/Entity Beans は、同期機能と RMI/IIOP (RMI over IIOP) を使用したオンライントランザクション処理 (OLTP) によって、リモート通信を実現してきました。これを、カンバセーション型と呼びます。銀行業務の ATM などは、カンバセーションを確立して即時性を重視した OLTP の最も極端な例です。例えば、IBM MVS の VTAM セッションによる、SNA (Systems Network Architecture) プロトコルがその例として挙げられます。
ミッションクリティカルなシステムでは、リモート間の接続を疎にするために、メッセージング(メッセージ・キューイング)という非同期の仕組みを使ってきた歴史があり、企業間接続のメッセージングハブなどで、その有用性は実証済みです。
メッセージングによる非同期通信のインフラは、MOM (Messaging Oriented Middleware) と呼ばれるソフトウェアによって提供されてきました。プロプライエタリなデファクトスタンダードは、IBM の MQS (MQSeries) です。因みに、 MQS の v5.3 以上で IBM のソフトウェア・ブランディング戦略が変更され、現在は WebSphere MQ と改称されています。
リモートのシステムは、メッセージをプロデュース(生産)して、メッセージブローカ(媒介)が管理する待ちキューに、メッセージを PUT します。ローカルのシステムは、待ちキューを管理するメッセージブローカからメッセージの到着の信号を受け取って、キューからメッセージを GET してコンシューム(消費)します。
メッセージの送信者は、相手先の処理終了を待機する必要がないため、自身のオンライン業務を滞らせることなく、次の処理に進むことができます。このため、即時性が要求されるシステムでは、待ちキューによる非同期処理は必須の仕組みとなっています。
メッセージブローカを実装する MOM 製品では、キューのマネージャ機能だけではなく、メッセージの Expiry や Dead Letter Queue (送達不能キュー)、トランザクションのロールバック/フォーワードリカバリ、トランザクションの独立性レベルなどがサポートされています。
尚、OLTP による同期処理と、メッセージングによる非同期処理の中間に位置するものとして、 RPC (Remote Procedure Call) と呼ばれるものがあります。メッセージ・キューイングによる非同期処理から見れば、OLTP の一つなのですが、カンバセーションを確立する OLTP に比べると、若干ながらリモート間の結合が疎になっています。
RPC では、各システムごとにスタブ (stub) と呼ばれる境界に位置するプログラムを用意して、各々のシステムは、自身のローカルのスタブに向かって機能の呼び出しを実行して待機します。スタブは、自分に実装された仕組みで相手のスタブに要求を転送して、処理結果を受け取るので、ローカルの呼び出し側/受け取り側では、あたかも、その機能が、ローカルのスタブに実装されているかのように振舞うことが可能です。
但し、スタブの呼び出し側は、ローカルのサブルーチン呼び出しと同様なので、処理結果が返ってくるまで待機(ブロック)されますし、呼び出された側のスタブは、要求を同期処理する必要があるので、個々の要求を処理して応答を返すまで、溜まった要求を溜めておくバッファ/取り消されたときのための管理タスクなどを実装する必要があり、オンライン処理の困難は継承します。
同一筐体(クラスタ)内でも、OS のシステムを呼び出す場合はスタブを使うことがあります。IBM MVS の RRS (Resource Recovery Service) は、OS である MVS が提供する RRS のサービスを利用するために、各ミドルウェアが各々 RRS スタブを実装しています。リモートの場合は、Java では、RMI/IIOP によって実装され、SOAP の場合も、プロキシクラスがスタブと呼ばれることがあり、AX-RPC 仕様によって標準化されています。
トランザクションとは、一連の処理の流れのことで、UOW (Unit of Work) と呼ばれています。トランザクションは、TCP/IP のステートレスという特徴が提供できない機能を、アプリケーション(製品と適用業務)によってサポートするものであり、一連の仕事の単位を意味します。
つまり、一連の処理の途中で、H/W 障害が発生すれば、バックアップから処理前の状態に復旧されるし、ソフトウェア障害が発生すれば、変更/更新を記録した更新ログ(トランザクションログ)から最新の状態まで回復するものです。トランザクションは仕事の単位 (UOW) であって、処理前に戻るか、完了後まで進めるかしかありません。このような性質をまとめて、ACID 特性と呼びます。
ACIS 特性の三つ目の分離性(独立性)は、平行に実行されているトランザクションが、逐次的に実行されたものと等価である性質を意味します。一つの UOW から、他の UOW の処理が反映しない/見えないことだとも言えます。一般には次の三つのレベルに分けられます。
J2EE 仕様には、トランザクションをコンテナが管理する仕様である JTA (Java Transaction API) が含まれます。JTA が規定するインタフェースの実装として、コンテナがサポートする実装は JTS (Java Transaction Services) が提供します。JTS は OMG の OTS (Object Transaction Service) の実装になります。
トランザクションを EJB のコードで管理する場合は BMT (Bean Managed Transaction) と呼び、コンテナに管理を任す場合は CMT (Container Managed Transaction) と呼びます。
BMT では、トランザクションをインタフェース javax.transaction.UserTransaction
を実装することで管理コードを実装します。トランザクションの開始は UserTransaction#begin()
であり、コミットは UserTransaction#commit()
になります。
CMT では、配備記述子 (DD, Deployment Descriptor) に、トランザクション属性として記述します。選択できるトランザクション・モードは次の六つです。
Entity Bean では、CMT しか利用できません。Session Bean と Message-Driven Bean (MDB) では BMT と CMT の両方が利用できます。但し、MDB の場合は、Required か NotSupported の何れかしか利用できません。
データベースや MOM 製品などのトランザクションを発生させる製品では、分離レベル (isolation level) が定義されています。
例えば、IBM DB2 での分離レベルは次の四つが定義されています。
同様に、JDBC では次の四つが定義されています。
J2EE 2.0 仕様では、明確な規定がありません。IBM WAS 5.0 では次の三つの分離レベルを、アクセスインテントポリシーで指定します。