紹介
Java Naming and Directory Interface (JNDI) は、Apache Geronimo アプリケーション・サーバーのコネクション・プールへのインターフェースです。このインターフェースを通して、開発者はエンタープライズ Java Beans (EJB) も含むすべての Java オブジェクトに接続できます。
データソース、Java Messaging Services (JMS)、メール・セッション、URL 接続用のコネクション・プールに接続するための概念的文章を紹介します。Apache Geronimo JNDI naming and Java resource connection pools, Part 1: Data source connections. URL: http://www-128.ibm.com/developerworks/opensource/library/os-ag-jndi1
ただし、上記文章は Geronimo 1.x 向けに書かれています。このサンプルのチュートリアルは同じような内容ですが、EJB 3.0 を利用しています。
アプリケーションの概略
CustomerService アプリケーションは EJB を使ってデータベースへ接続し、画面に結果を戻します。このサンプルのポイントは、JNDI を使って EJB へ接続する方法を示します。今回の EAR ファイルの中身の構造の概略は次のとおりです。
|-CustomerService-ear-2.0-SNAPSHOT.ear |-CustomerService-ejb-2.0-SNAPSHOT.jar |-META-INF |-persistence.xml |-openejb-jar.xml |-CustomerService-war-2.0-SNAPSHOT.war |-WEB-INF |-web.xml |-geronimo-web.xml |-META-INF |-application.xml |-geronimo.application.xml
persistence.xml は、エンティティ Bean に利用するデータベース・プールを明示的に割り当てるために参照されます。今回は、Customer というエンティティ Bean が CustomerServicePool というデータベース・プールを利用します。
<?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="CustomerPU"> <description>Entity Beans for Customer</description> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <class>com.service.customer.ejb.Customer</class> <properties> <property name="openjpa.jdbc.SynchronizeMappings" value="false"/> </properties> <jta-data-source>CustomerServicePool</jta-data-source> <non-jta-data-source>CustomerServicePool</non-jta-data-source> </persistence-unit> </persistence>
openejb-jar.xml は OpenEJB で利用しますが、次のとおりです。MDB (訳注: メッセージ駆動 Bean) を利用していないので、特別に定義することはありません。
<?xml version="1.0" encoding="UTF-8"?> <openejb-jar xmlns="http://www.openejb.org/xml/ns/openejb-jar-2.1" xmlns:naming="http://geronimo.apache.org/xml/ns/naming-1.1" xmlns:security="http://geronimo.apache.org/xml/ns/security-1.1" xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2"> <dep:environment> <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:dependencies> <dep:hidden-classes/> <dep:non-overridable-classes/> </dep:environment> </openejb-jar>
web.xml は ProcessCustomerSessionBean.java で作られた EJB を参照しています。こうすることで、WAR の内部からのこの EJB の利用を許可します。
<?xml version="1.0" encoding="ISO-8859-1"?> <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_4.xsd" version="2.4"> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <ejb-local-ref> <ejb-ref-name>ejb/ProcessCustomerSessionBean</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <local>com.service.customer.ejb.ProcessCustomerSessionLocal</local> </ejb-local-ref> </web-app>
geronimo-application.xml へは、モジュール情報とウェブ・アプリケーションのコンテキスト・ルートを記述します。さらに、データベース・プールのプランを記述します。Geronimo にこのプランをデプロイするために必要なコネクタにしたがってデプロイするようにプランを書きます。
<application xmlns="http://geronimo.apache.org/xml/ns/j2ee/application-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>ear</dep:type> </dep:moduleId> <dep:dependencies/> <dep:hidden-classes/> <dep:non-overridable-classes/> </dep:environment> <module> <connector>tranql-connector-ra-1.3.rar</connector> <alt-dd>CustomerServicePool.xml</alt-dd> </module> </application>
application.xml へは、EAR が組み込みデータベース・プール (CustomerServicePool.xml) をデプロイする際に利用されるコネクタを記述します。
<?xml version="1.0" encoding="UTF-8"?> <application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd" version="5"> <description>Geronimo Sample EAR for CustomerService</description> <display-name>Geronimo Sample EAR for CustomerService</display-name> <module> <ejb>CustomerService-ejb-2.0-SNAPSHOT.jar</ejb> </module> <module> <web> <web-uri>CustomerService-war-2.0-SNAPSHOT.war</web-uri> <context-root>/service</context-root> </web> </module> <module> <connector>tranql-connector-ra-1.3.rar</connector> </module> </application>
CustomerServiceJavaBean.java は JNDI をつかって ProcessCustomerSessionBean という EJB を探します。
package com.service.customer.web; import com.service.customer.ejb.Customer; import com.service.customer.ejb.ProcessCustomerSessionLocal; import java.util.Locale; import java.util.ResourceBundle; import java.util.List; import javax.naming.InitialContext; public class CustomerServiceJavaBean { private ProcessCustomerSessionLocal process = null; private ResourceBundle bundle = null; public CustomerServiceJavaBean() { InitialContext initial = null; bundle = ResourceBundle.getBundle("customer", Locale.getDefault(), CustomerServiceJavaBean.class.getClassLoader()); String jndiName = bundle.getString("jndi.process.ejb"); try { initial = new InitialContext(); process = (ProcessCustomerSessionLocal) initial.lookup(jndiName.trim()); System.out.println("Successful looking up: '" + jndiName.trim() + "'"); } // end try catch (Exception e) { e.printStackTrace(); } // end catch } // end CustomerServiceJavaBean public List<Customer> getAllCustomers() { List<Customer> customerList = null; try { customerList = process.findAllCustomers(); } // end try catch (Exception e) { e.printStackTrace(); } // end catch return customerList; } // end getAllCustomerss } // end CustomerServiceJavaBean
ProcessCustomerSessionBean.java は persistence.xml を利用して EntityManagerFactory が保持している ProcessCustomerSessionLocal を実装しています。保持には @PersistenceUnit アノテーションを利用しています。 persistence.xml には定義するたった一つの永続化ユニットしかないので、特にこのアノテーションに加えるパラメーターはありません。
package com.service.customer.ejb; import java.rmi.RemoteException; import java.util.Collection; import java.util.Iterator; import java.util.List; import javax.persistence.PersistenceUnit; import javax.ejb.EJBException; import javax.ejb.Stateless; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; @Stateless public class ProcessCustomerSessionBean implements ProcessCustomerSessionLocal { @PersistenceUnit protected EntityManagerFactory emf; public ProcessCustomerSessionBean() { } public List<Customer> findAllCustomers() { EntityManager em = emf.createEntityManager(); String query = "SELECT * FROM customer"; List<Customer> customerList = (List<Customer>)em.createNativeQuery(query, Customer.class).getResultList(); em.close(); return customerList; } public Customer findCustomer(String key) { EntityManager em = emf.createEntityManager(); String query = "SELECT * FROM customer WHERE id='"+key+"'"; List<Customer> customerList = (List<Customer>)em.createNativeQuery(query, Customer.class).getResultList(); if(customerList.size() == 1) { return (Customer)customerList.get(0); } else { return null; } } }
ProcessCustomerSessionLocal.java へは、ビジネス・メソッドとこの Bean との関連づけを記述します。
package com.service.customer.ejb; import com.service.customer.ejb.Customer; public interface ProcessCustomerSessionLocal { public java.util.List<Customer> findAllCustomers(); public Customer findCustomer(String key); }
Customer.java はデータベースにある Customer テーブルを表すエンティティ Bean です。@Entity、@Table(name = "customer")、@Id を利用することで、OpenEJB にこのクラスがエンティティ Bean であり、"customer" テーブルを表し、"customerId" というプライマリ・キーを持っていることを通知します。これらのアノテーションを利用することによって、openejb-jar.xml (ejb-jar.xml もそうですが)に他の構成が必要ありません。
package com.service.customer.ejb; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "customer") public class Customer implements Serializable { private String customerId; private String fullName; private String emailAddress; private String interests; public Customer() { } public Customer(String customerId, String fullName, String emailAddress, String interests) { this.customerId = customerId; this.fullName = fullName; this.emailAddress = emailAddress; this.interests = interests; } @Id public String getCustomerId() { return customerId; } public String getFullName() { return fullName; } public String getEmailAddress() { return emailAddress; } public String getInterests() { return interests; } public void setCustomerId(String customerId) { this.customerId = customerId; } public void setFullName(String fullName) { this.fullName = fullName; } public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } public void setInterests(String interests) { this.interests = interests; } } // end Customer
Customer Service Database
このアプリケーションのデモンストレーションが使うデータベースは、組み込みの Derby データベースです。 データベースの名前は CustomerDB で、一つのテーブルを持ちます。
Table Name |
Fields |
---|---|
CUSTOMER |
customerId (PRIMARY KEY) |
CUSTOMER テーブルはひとつの顧客の情報を持ちます。
ツールの利用
Customer Service アプリケーションの開発、ビルドは次のツールを利用しています。
Apache Derby
Apache Derby は Apache DB サブ・プロジェクトであり、Java で実装されたリレーショナル・データベースです。サイズが小さく、Java に基づくソリューションに簡単に組み込めるものです。組み込みフレームワークに加え、Derby は Derby ネットワーク・サーバを利用することで、よくあるクライアント/サーバ・フレームワークもサポートします。
http://db.apache.org/derby/index.html
Apache Maven 2
Maven はエンタープライズ Java プロジェクト向けの有名なオープンソースのビルド・ツールです。 ビルド作業の負荷を軽減できるように設計されました。Maven では Ant や他の伝統的な make ファイルなどで利用されるタスク・ベースの手法ではなく、宣言的手法を利用して、プロジェクトの構成や内容が定義されます。このことにより、企業全体で開発標準を適用することや、ビルド用スクリプトの記述やメンテナンスに必要な時間を削ることの助けとなります。宣言的で、ライフサイクルに基づく手法を使っ ていた Maven 1 は、伝統的なビルド方法よりも、多くの人にとって、根本的な発展となり、さらに Maven 2 はこの点を高めました。Maven 2 は次の URL からダウンロードできます。
http://maven.apache.org
サンプル・アプリケーションの構成、ビルド、デプロイ
以下のリンクから CustomerService アプリケーションをダウンロードしてください。
CustomerService
ファイルを解凍すると、CustomerService ディレクトリーが作られます。
ソース・コード
SVN からサンプルのソースコードをチェックアウトすることができます。
svn checkout http://svn.apache.org/repos/asf/geronimo/samples/trunk/samples/CustomerService
構成
アプリケーションの構成は、データベースの作成とデータベースへ接続するコネクション・プールの定義を含んでいます。
データベースの作成とデータ追加
Apache Geronimo サーバーを始動した後、 Geronimo コンソールへログインし、以下の手順により CustomerDB を作成してください。
create table customer ( customerid varchar(10) primary key, fullname varchar(30), emailaddress varchar(30), interests varchar(100) ); insert into customer values ('A100','John Doe10','Doe10@work.com','Java,Open Source, Computer Graphics'); insert into customer values ('b100','Jane Doe20','Doe20@home.net','Budget Travel, New Zealand, Martial Arts');
- 左側の Console Navigation から DB Manager リンクを選択してください。
- データベース名として CustomerDB を入力し、Create ボタンをクリックしてください。
- Use DB 欄で CustomerDB を選択してください。
- テキストエディタで CustomerService ディレクトリーから CustomerService.sql を開いてください。
- SQL Commands のテキストエリアに CustomerService.sql の内容を貼りつけ、Run SQL ボタンを押してください。
ビルド
コマンド・プロンプトを利用して CustomerService ディレクトリーへ移動し、mvn clean install site コマンドを入力するとビルドされます。CustomerService フォルダーの下に CustomerService-ear-2.0-SNAPSHOT.ear が作られます。これで Geronimo アプリケーション・サーバーへ CustomerService アプリケーションをデプロイする準備ができました。
アプリケーションのデプロイ
Geronimo コンソールの利用によって、サンプルアプリケーションのデプロイはかなり簡単です。
- Console Navigation パネルから Deploy New を選択してください。
- Archive 入力欄に CustomerService フォルダーの CustomerService-ear-2.0-SNAPSHOT.ear を読み込んでください。
- Install ボタンを押してアプリケーションをサーバーへデプロイしてください。
Customer Service ウェブ・アプリケーション
サンプル・ウェブ・アプリケーションをテストするには、ブラウザーを開いて http://localhost:8080/service を入力してください。 アプリケーションのインデックス・ページが表示され、そこには顧客を閲覧するためのリンクがあります。