EJBはJ2EE仕様の重要な技術の一つです。 J2EE 1.5 認証サーバーとしてApache Geronimo はEJBコンテナーであるOpenEJBを利用し、幅広くEJB をサポートします。 通常の(非EJBの)Javaオブジェクトでビジネスロジックを実装する事も可能ですがEJBを利用すると、そこで発生する課題(スケーラビリティ、ライフサイクル管理、状態管理 etc)EJBが対応してくれます。 本稿では、簡単なデータベース・アプリケーションを拡張して、クライアントのアプリケーションがEJBをローカル参照とリモート参照の両方で利用する方法を紹介します。 当該アプリケーションは、Apache Derbyを利用します。 この記事を通じて、エンタープライズアプリケーションの開発作業を簡単にする方法を学ぶ事ができます。
バンキング・アプリケーションは、2種類のクライアント "バンキング リモート" と"バンキングWeb"から利用されます。これらのクライアントは、それぞれEJBのリモート参照とローカル参照のデモです。 両方とも、セッション・ビーンとエンティティ・ビーンにより実装された、共通のビジネス・レイヤーを参照します。 ステートレス・セッション・ビーンは、アプリケーション・クライアントとビジネス・エンティティを接続するビジネスサービス・インターフェースとなります。 アプリケーション層の全てのビジネス・インタフェースは、エンティティー・ビーンとして実装されています。
本稿を読んだ後、EJBの定義、EJBと異なる参照方法との関連を管理する方法を学事ができ、GeronimoのEJB機能を最大限に利用する事ができるようになります。
本章は、以下のセクションから構成されています。
EJB 機能の概要
EJBの実装はベンダー毎に異なっているかも知れません。下記のリストが、J2EE コンテナーとしてのApache Geornimoの機能です。
- ステートフルとステートレスのセッション・ビーン
- エンティティー・ビーン
- メッセージ・ドリブン・ビーン (MDB)
- RMI-IIOP と、JAXRPCを利用した相互運用性
- Web Serviceとして外部から利用可能な、ステートレスセッション・ビーンとMDB
- Web Service経由のメッセージ送受信のサポート
- EJBとJMXベースのWebサービスの、簡単な準備とホット・デプロイ
- 外部 CORBA オブジェクトからのEJBの利用
アプリケーションの概要
バンキング・アプリケーションについて簡単に説明すると、2種類のクライアン・アプリケーショントがあり、それぞれのアプリケーションの概要は以下の通りです。
- バンキング・リモート
簡単なswingのクライアント・アプリケーションで、銀行の管理者向けです。 限られた銀行の行員だけが、このアプリケーションを利用可能です。 銀行口座の預金残高の照会と更新をすることができます。 - バンキングWeb
このアプリケーションは顧客に開放されています。 顧客が自分の口座情報を照会する事ができます。 加えて、銀行の為替レートを照会する事ができます。 Geronimoの環境ではセキュリティ機能を簡単に実装する事ができますが、単純可のために、それぞれのアプリケーションのセキュリティ機能は省略しています。
各クライアントは、共通のビジネス・サービス層を利用します。 ビジネス・サービス層の背後には、バンキング・アプリケーションで使われる3つの共通ビジネスエンティティ(Account, Customer, ExchangeRate)が有ります。 顧客は一つ以上の口座を持ち、口座は一人の顧客によって所有されます。 ExchangeRate は、銀行によって決められる対USドルの為替レートを表現します。
アプリケーションの内容
バンキング・アプリケーションには以下のパッケージとクラスが有ります。
- org.apache.geronimo.samples.bank.ejb
- Account - エンティティ・ビーン,DBに格納されている account テーブルの情報を表します。
- BankManagerFacadeBean - ステートレスセッション・ビーン。クライアント・アプリケーションから利用されるサービスクラスです。
- Customer - エンティティ・ビーン, DBに格納されている Customer テーブルの情報を表します。
- ExchangeRate - エンティティ・ビーン, 対USドルの為替レートを表します。
- org.apache.geronimo.samples.bank.web
- CustomerServiceServlet - 顧客の口座残高照会のWebリクエストを受け取って、サービスレイヤーを呼び出します。
- CommonServiceServlet - 為替レート照会のWebリクエストを受け取って、サービスレイヤーを呼び出します。
最終的に、バンキング・アプリケーションはEARファイルとして、アプリケーション・サーバーにデプロイされます。 EARファイルの内容は、下記の通りです。
|-Bank.ear |-BankEJB.jar |-META-INF |- persistence.xml |- openejb-jar.xml |-BankWeb.war |-jsp |- customer_info.jsp |- customer_main.jsp |- error.jsp |- exchange_rates.jsp |- index.jsp |-WEB-INF |- web.xml |- geronimo-web.xml |- classes |-META-INF |- application.xml |- geronimo-application.xml
最初に、アプリケーションのビジネス・サービス層がEJBを利用してどの様に実装されているか、見てみましょう
openejb-jar.xml の定義は、Geronimo 独自のEJB機能と一致します。 アプリケーションと共にデータベース・プールをデプロイするので、既存のデータベース・プールへの依存関係は不要です。
<?xml version="1.0" encoding="UTF-8"?> <openejb-jar xmlns="http://www.openejb.org/xml/ns/openejb-jar-2.1"> <dep:environment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2"> <dep:moduleId> <dep:groupId>${pom.groupId}</dep:groupId> <dep:artifactId>${pom.artifactId}</dep:artifactId> <dep:version>${version}</dep:version> <dep:type>jar</dep:type> </dep:moduleId> <dep:dependencies> <dep:dependency> <dep:groupId>org.apache.geronimo.configs</dep:groupId> <dep:artifactId>openjpa</dep:artifactId> <dep:type>car</dep:type> </dep:dependency> </dep:dependencies> <dep:hidden-classes/> <dep:non-overridable-classes/> </dep:environment> </openejb-jar>
persistence.xmlは、永続化の定義で、BankPool経由でBankDBに接続するためにEntityMangerFactoryによって使われます。 <persistent-unit>の名前が、EJBのアノテーションによって参照されます。 SynchronizeMappings属性の構成により、データベースに保存されている既存のデータを更新しない様に指定する事ができます。 これはデータを削除したくない場合には、重要な指定です。 jta-data-source と non-jta-data-source には同じ値を指定する必要が有ります。
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="BankPU"> <description>Entity Beans for Bank</description> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <class>org.apache.geronimo.samples.bank.ejb.Account</class> <class>org.apache.geronimo.samples.bank.ejb.Customer</class> <class>org.apache.geronimo.samples.bank.ejb.ExchangeRate</class> <properties> <property name="openjpa.jdbc.SynchronizeMappings" value="false" /> </properties> <jta-data-source>BankPool</jta-data-source> <non-jta-data-source>BankPool</non-jta-data-source> </persistence-unit> </persistence>
web.xml には、特別な指定は何も要りません。 web-apにサーブレットの定義と、各サーブレットのマッピングが有るだけです。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd" version="2.5"> <welcome-file-list> <welcome-file>/index.html</welcome-file> </welcome-file-list> <servlet> <display-name>CustomerServiceServlet</display-name> <servlet-name>CustomerServiceServlet</servlet-name> <servlet-class>org.apache.geronimo.samples.bank.web.CustomerServiceServlet</servlet-class> </servlet> <servlet> <display-name>CommonServiceServlet</display-name> <servlet-name>CommonServiceServlet</servlet-name> <servlet-class>org.apache.geronimo.samples.bank.web.CommonServiceServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CustomerServiceServlet</servlet-name> <url-pattern>/customer_info</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>CommonServiceServlet</servlet-name> <url-pattern>/exchange_rates</url-pattern> </servlet-mapping> </web-app>
geronimo-web.xml は、is Geronimo 独自のデプロメイント・プランです。 通常、モジュール情報とコンテキスト・ルートを指定します。 これで、このアプリケーションを表示するためにURLは、http://localhost:8080/Bank になります。
<web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-1.1" xmlns:naming="http://geronimo.apache.org/xml/ns/naming-1.1"> <dep:environment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.1"> <dep:moduleId> <dep:groupId>${pom.groupId}</dep:groupId> <dep:artifactId>${pom.artifactId}</dep:artifactId> <dep:version>${version}</dep:version> <dep:type>war</dep:type> </dep:moduleId> <dep:dependencies/> <dep:hidden-classes/> <dep:non-overridable-classes/> </dep:environment> <context-root>/Bank</context-root> </web-app>
BankPool.xml には、データベースの接続情報を記述します。 今回は、Geronimoにビルトインされている、Derbyデータベースを利用します。 依存関係には、org.apache.geronimo.configs/system-database//carを指定する必要が有ります。 私の場合、これを違う物にしてしまい障害が発生しました。 下記のデータベース接続プールのプランは、管理コンソールにより生成されたものです。 私が実施した変更は、依存関係を 稼働中のDerbyエンジンであるsystem-databaseにした事だけです。 このデータベース・プールの情報は、EARアプリケーションの一部としてデプロイされます。
<connector xmlns="http://geronimo.apache.org/xml/ns/j2ee/connector-1.1"> <dep:environment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.1"> <dep:moduleId> <dep:groupId>console.dbpool</dep:groupId> <dep:artifactId>BankPool</dep:artifactId> <dep:version>1.0</dep:version> <dep:type>rar</dep:type> </dep:moduleId> <dep:dependencies> <dep:dependency> <dep:groupId>org.apache.geronimo.configs</dep:groupId> <dep:artifactId>system-database</dep:artifactId> <dep:type>car</dep:type> </dep:dependency> </dep:dependencies> </dep:environment> <resourceadapter> <outbound-resourceadapter> <connection-definition> <connectionfactory-interface>javax.sql.DataSource</connectionfactory-interface> <connectiondefinition-instance> <name>BankPool</name> <config-property-setting name="Driver">org.apache.derby.jdbc.EmbeddedDriver</config-property-setting> <config-property-setting name="UserName">app</config-property-setting> <config-property-setting name="ConnectionURL">jdbc:derby:BankDB</config-property-setting> <connectionmanager> <local-transaction/> <single-pool> <max-size>10</max-size> <min-size>0</min-size> <match-one/> </single-pool> </connectionmanager> </connectiondefinition-instance> </connection-definition> </outbound-resourceadapter> </resourceadapter> </connector>
geronimo-application.xml には、データベースプールがあるアプリケーションがあり、これもデプロイする必要がある。データベースプールはBankPool.xmlに定義され、デプロイをするために必要なドライバーはtranql-connector-ra-1.3.rar ファイルです。これら2つのファイルはEARファイルのトップレベルに配置します。
<?xml version="1.0" encoding="UTF-8"?> <application xmlns="http://geronimo.apache.org/xml/ns/j2ee/application-1.2"> <environment xmlns="http://geronimo.apache.org/xml/ns/deployment-1.2"> <moduleId> <groupId>${pom.groupId}</groupId> <artifactId>${pom.artifactId}</artifactId> <version>${version}</version> <type>ear</type> </moduleId> </environment> <module> <connector>tranql-connector-ra-1.3.rar</connector> <alt-dd>BankPool.xml</alt-dd> </module> </application>
サンプル・データベース
今回のデモのサンプル・データベースは、Geronimo内蔵のDerbyデータベースを利用します。サンプル・データベースの名前は、BankDBで、CUSTOMER, ACCOUNT, EXCHANGE_RATEという3テーブルから構成されます。各テーブルの定義は以下の通りです。
Table Name |
Fields |
---|---|
CUSTOMER |
customerId (PRIMARY KEY) |
ACCOUNT |
accountNumber (PRIMARY KEY) |
EXCHANGERATE |
rateId (PRIMARY KEY) |
CUSTOMERテーブルは、顧客の情報を保存します。IDと名前を管理するだけのテーブルです。ACCOUNT テーブルは、ユニークな口座番号が主キーです。口座の種類と残高を管理します。AccountテーブルのcustomerIdは、Customerテーブルへの外部キー で、口座の所有者の情報を保持します。EXCHANGERATE テーブルは rateId が主キーです。EXCHANGERATEの各レコードは、 通過名と支払い時に利用される為替レートを保持します。
利用ツール
バンキング・アプリケーションのビルドとデプロイで利用されるツールは、
Apache Derby
Apache DBサブプロジェクトのApache DerbyはJavaで実装されたリレーショナル・データベースです。フットプリントが非常に小さいので、Javaベースのあらゆるソリューションに容易に埋め込めます。更にこのような埋め込み型のフレームワークだけではなく、Derby Network Serverを使えば、一般的なクライアント-サーバー型のフレームワークをサポートできます。
http://db.apache.org/derby/index.html
Apache Maven 2
MavenはエンタープライズJavaプロジェクト向けに広く使われているオープンソースのビルド・ツールで、ビルド作業に伴う大変な仕事を肩代わりしてくれます。MavenはAntやmakeのようなタスク・べースのアプローチではなく、プロジェクトの構造やコンテンツを記述するという宣言的アプローチを採用しています。これにより全社的な開発標準の遵守が容易になり、ビルド・スクリプトの開発と保守の時間を削減できます。Maven1は宣言的でライフサイクル・ベースのアプローチを採用したことで従来のトラディショナルなビルド・テクニックから劇的に飛躍しました。Maven2では、この点が更に推し進められています。Maven2は以下のURLからダウンロードできます。
http://maven.apache.org
サンプル・アプリケーションの構成、ビルドとデプロイ
以下からバンキング・アプリケーションをダウンロードします。
Bank
圧縮ファイルを復元すると、bank というディレクトリーが作られます。
ソースコード
当サンプルのソースコードはSVNからチェックアウトできます。
svn checkout http://svn.apache.org/repos/asf/geronimo/samples/trunk/samples/bank
構成
当アプリケーションでの構成作業は、データベースの作成とデータベースにアクセスするためのコネクション・プールの定義です。
データベースの作成と操作
Bank DB を作成するには、Apache Geronimoを開始してコンソールにログインしてから、以下のステップを実行してください。
CREATE TABLE Customer( customerId VARCHAR(255) PRIMARY KEY, name VARCHAR(255) ); CREATE TABLE Account( accountNumber VARCHAR(255) PRIMARY KEY, accountType VARCHAR(255), balance DOUBLE, customerId VARCHAR(255), FOREIGN KEY (customerId) REFERENCES customer ); CREATE TABLE ExchangeRate( rateId VARCHAR(255) PRIMARY KEY, currency VARCHAR(255), rate DOUBLE ); INSERT INTO Customer(customerId, name) VALUES('12345','John Doe'); INSERT INTO Account(accountNumber, accountType, balance, customerId) VALUES('1234567890','Savings',1005.35,'12345'); INSERT INTO Account(accountNumber, accountType, balance, customerId) VALUES('2345678901','Current',999.95,'12345'); INSERT INTO ExchangeRate(rateId,currency,rate) VALUES('001','EURO',0.812); INSERT INTO ExchangeRate(rateId,currency,rate) VALUES('002','YEN',111.15); INSERT INTO ExchangeRate(rateId,currency,rate) VALUES('003','SLR',99.18);
- 左側のConsole Navigationから DB Manager のリンクを選択
- database nameに BankDB と入力して Create ボタンを押す
- Use DBフィールドで BankDB を選択
- テキスト・エディターでbankディレクトリーにある BankDB.sqlを開く
- BankDB.sql の中身を SQL Commands テキスト・エリアに貼り付け、Run SQL ボタンを押す
ビルド
コマンド・プロンプトで bank ディレクトリーに移動して、mvn install site コマンドをそのまま入力するとビルドが始まります。結果、bankフォルダーの下に bank-ear-2.0-SNAPSHOT.ear が作成されます。さあ、これでbankアプリケーションをGeronimoアプリケーション・サーバーにデプロイする準備が整いました。
アプリケーションのデプロイ
サンプルアプリケーションのデプロイは管理コンソールを使えば非常に簡単です。
- Console Navigation パネルで Deploy New までスクロール・ダウン
- Archive 入力ボックスに bank フォルダー上の bank-ear-2.0-SNAPSHOT.ear を指定
- Install ボタンを押すとアプリケーションがサーバーにデプロイされる.
Banking Web アプリケーション
サンプルのWebアプリケーションをテストするには、ブラウザーを開いて http://localhost:8080/Bank とタイプします。すると、bankアプリケーションのインデックス・ページが表示され、そこには顧客と交換レートの情報を表示するためのダイレクト・リンクがあります。顧客の個々の口座の情報を見るには、DB上で該当する顧客idを入力します。交換レート・ページは交換レート・テーブル上の全ての通貨のリストを表示します。('Bank'はケース・センシティブであることに注意ください)
サマリー
当記事ではApache GeroimoのEJB機能の使用方法を紹介しました。各種の機能を理解いただくため、アプリケーションをビルド、デプロイし、実行するところまでをステップ・バイ・ステップでご紹介しました。
以下が当記事のハイライトです。
- Apache Geronimo は J2EE 1.5 準拠のアプリケーション・サーバーであり、エンタープライズ・アプリケーション用に必要な全ての機能を持っています。
- セッション・ビーンとエンティティ・ビーンの作成と構成
- 様々な種類のクライアントから、エンタープライズ・レベルのサービスへのアクセス定義