Phone Book Bean の例
アノテーションを利用してエンティティ Bean を呼び出す JSP ページ の例です。実行結果として次のように表示されます。
アプリケーションの内容
まず、データベース内のテーブルを表す PhoneBook エンティティ Bean を見てみましょう。PhoneBook のどのインスタンスもテーブルの1レコードです。
PhoneBook.java は次の記述を利用しています。
- @Entity アノテーションは、このクラスがエンティティ Bean という記述です
- @Table アノテーションは、エンティティ Bean が表すテーブルの名前の記述です
- @Id アノテーションは、テーブルのプライマリ・キーの記述です
なお通常は、エンティティ Bean には空のコンストラクターがあります。
package org.apache.geronimo.samples.myphonebookpak; import java.io.Serializable; import javax.persistence.Id; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "phonebook") public class PhoneBook implements Serializable { private String number; private String name; public PhoneBook() { } public PhoneBook(String name, String number) { this.name = name; this.number = number; } @Id public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } }
MyPhonebookLocal.java は上記で触れたエンティティ Bean への受け渡しをするビジネス・インターフェースです。
package org.apache.geronimo.samples.myphonebookpak; import org.apache.geronimo.samples.myphonebookpak.PhoneBook; public interface MyPhonebookLocal { public PhoneBook findByPrimaryKey(String name); }
MyPhonebookBean.java は、ローカル・インターフェース(またはリモート・インターフェース)を実装したものです。このステートレス・セッション Bean にあるアノテーションの意味の説明は次のとおりです。
- @Stateless - Geronimo にこのクラスがステートレス・セッション Bean であることを通知します
- @PersistenceUnit - Geronimo に、persistence.xml に定義された永続化ユニット(persistence unit)を取得し、これを EntityManagerFactory とするように通知します
直接 EntityManager を取得しようとするときは、PersistenceContext を利用します。EntityManagerFactory には PersistenceUnit を利用します。
MyPhonebookBean.javapackage org.apache.geronimo.samples.myphonebookpak; import javax.ejb.Stateless; import javax.persistence.PersistenceUnit; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import org.apache.geronimo.samples.myphonebookpak.PhoneBook; @Stateless public class MyPhonebookBean implements MyPhonebookLocal { @PersistenceUnit(unitName="PhonePU") protected EntityManagerFactory emf; public MyPhonebookBean() { } public PhoneBook findByPrimaryKey(String name) { EntityManager em = emf.createEntityManager(); PhoneBook phonebook = (PhoneBook)em.find(PhoneBook.class, name); em.close(); return phonebook; } }
index.jsp は EJB を利用してデータベースへアクセスするための JSP ページです。
<%@ page contentType="text/html" import="org.apache.geronimo.samples.myphonebookpak.*, javax.naming.* " %> <% String searchName = ""; if (request.getParameter("searchname") != null) { searchName=request.getParameter("searchname"); } %> <html><head><title>Phonebook</title></head><body> <form action="index.jsp"> <b>Search number</b>:<br> Enter name: <input type="text" name="searchname" value="<%=searchName%>"> <input type="submit" value="Search"> (Test with <a href="index.jsp?searchname=Joe">Joe</a>) </form> <% if (! searchName.equals("")) { String number=""; try { Context context = new InitialContext(); MyPhonebookLocal myPhonebookLocal = (MyPhonebookLocal)context.lookup("java:comp/env/ejb/MyPhonebookBean"); PhoneBook phonebook = myPhonebookLocal.findByPrimaryKey(searchName); if(phonebook != null) { number = phonebook.getNumber(); } } catch (Exception e) { number=e.toString(); } out.println("This is the number returned from the EJB when searching for '"+searchName+"' : " + number); } %> </body></html>
EJB のデプロイメント・プラン
openejb-jar.xml へはモジュール情報を記述します。
<?xml version="1.0" encoding="UTF-8"?> <openejb-jar xmlns="http://www.openejb.org/xml/ns/openejb-jar-2.1" xmlns:nam="http://geronimo.apache.org/xml/ns/naming-1.1" xmlns:pkgen="http://www.openejb.org/xml/ns/pkgen-2.0" xmlns:sec="http://geronimo.apache.org/xml/ns/security-1.1" xmlns:sys="http://geronimo.apache.org/xml/ns/deployment-1.2"> <sys:environment> <sys:moduleId> <sys:groupId>org.apache.geronimo.samples</sys:groupId> <sys:artifactId>MyPhonebookBean</sys:artifactId> <sys:version>1.0</sys:version> <sys:type>car</sys:type> </sys:moduleId> </sys:environment> </openejb-jar>
persistence.xml へは永続化ユニットの名前を記述します。この名前は EntityManagerFactory を参照する時に利用されます。今回は PhonePU という名前を与えました。どういうわけか、私は jta-data-source の参照ができませんでした。そこで代替手段として、ConnectionURL、ConnectionDriverName、ConnectionUserName を明記しました。また、データベースにあるデータが上書きされないように、追加属性として SynchronizeMappings を加えました。
以下は一つの方法です
<?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="PhonePU"> <description>Phone Book</description> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <class>org.apache.geronimo.samples.myphonebookpak.PhoneBook</class> <properties> <property name="openjpa.ConnectionURL" value="jdbc:derby:PhoneBookDB" /> <property name="openjpa.ConnectionDriverName" value="org.apache.derby.jdbc.EmbeddedDriver" /> <property name="ConnectionUserName" value="app" /> <property name="openjpa.jdbc.SynchronizeMappings" value="false" /> </properties> </persistence-unit> <!-- <jta-data-source>PhoneBookPool</jta-data-source> <non-jta-data-source>PhoneBookPool</non-jta-data-source> --> </persistence>
Web-App のデプロイメント・プラン
web.xml には MyPhonebookLocal が所属するパッケージが記述されていて、ここから EJB が参照されます。
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" 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"> <display-name>MyPhonebookWeb</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <ejb-local-ref> <ejb-ref-name>ejb/MyPhonebookBean</ejb-ref-name> <ejb-ref-type>Entity</ejb-ref-type> <local>org.apache.geronimo.samples.myphonebookpak.MyPhonebookLocal</local> </ejb-local-ref> </web-app>
geronimo-web.xml へはモジュール情報と web-app のコンテキスト・ルートを記述します。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-1.1" xmlns:nam="http://geronimo.apache.org/xml/ns/naming-1.1" xmlns:sec="http://geronimo.apache.org/xml/ns/security-1.1" xmlns:sys="http://geronimo.apache.org/xml/ns/deployment-1.1"> <sys:environment> <sys:moduleId> <sys:groupId>${pom.groupId}</sys:groupId> <sys:artifactId>${pom.artifactId}</sys:artifactId> <sys:version>${version}</sys:version> <sys:type>war</sys:type> </sys:moduleId> </sys:environment> <context-root>/myphonebook</context-root> </web-app>
アプリケーションのデプロイメント・プラン
geronimo-application.xml はデプロイする必要のあるデータベース・プールをアプリケーションに通知します。データベース・プールは PhoneBookPool.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.1" xmlns:sec="http://geronimo.apache.org/xml/ns/security-1.1" xmlns:sys="http://geronimo.apache.org/xml/ns/deployment-1.1" application-name="t6"> <sys:environment> <sys:moduleId> <sys:groupId>${pom.groupId}</sys:groupId> <sys:artifactId>${pom.artifactId}</sys:artifactId> <sys:version>${version}</sys:version> <sys:type>ear</sys:type> </sys:moduleId> </sys:environment> <module> <connector>tranql-connector-ra-1.3.rar</connector> <alt-dd>PhoneBookPool.xml</alt-dd> </module> </application>
アプリケーションの構成、ビルド、デプロイ
以下のリンクから MyPhoneBook アプリケーションをダウンロードしてください。
MyPhoneBook
ファイルを解凍すると、myphonebook ディレクトリーが作られます。
ソースコード
SVN からサンプルのソースコードをチェックアウトすることができます。
svn checkout http://svn.apache.org/repos/asf/geronimo/samples/trunk/samples/myphonebook
データベースの作成とデータ追加
Apache Geronimo サーバーを始動した後、 Geronimo Console へログインし、以下の手順により PhoneBookDB を作成してください。
CREATE TABLE phonebook ( name VARCHAR(255) PRIMARY KEY, number VARCHAR(255) ); INSERT INTO phonebook VALUES ('John', '1234'); INSERT INTO phonebook VALUES ('Joe', '5678');
- 左側の Console Navigation から DB Manager リンクを選択してください。
- データベース名として PhoneBookDB を入力し、Create ボタンをクリックしてください。
- Use DB 欄で PhoneBookDB を選択してください。
- テキストエディタで myphonebook/myphonebook-ear/src/main/resources ディレクトリーから、PhoneBookDB.sql を開いてください。
- SQL Commands のテキストエリアに PhoneBookDB.sql の内容を貼りつけ、Run SQL ボタンを押してください。
ビルド
コマンドプロンプトを利用して myphonebook ディレクトリーへ移動し、mvn install 、mvn site の順にコマンドを入力するとビルドされます。myphonebook フォルダーの下に myphonebook-ear-2.0-SNAPSHOT.ear が作られます。これで Geronimo アプリケーション・サーバーへ myphonebook アプリケーションをデプロイする準備ができました。
アプリケーションのデプロイ
Geronimo Console の利用によって、サンプルアプリケーションのデプロイはかなり簡単です。
- Console Navigation パネルから Deploy New を選択してください。
- Archive 入力欄に myphonebook フォルダーの myphone-ear-2.0-SNAPSHOT.ear を読み込んでください。
- Install ボタンを押してアプリケーションをサーバへデプロイしてください。
MyPhoneBook ウェブ・アプリケーション
サンプル・ウェブ・アプリケーションをテストするには、ブラウザーを開いて http://localhost:8080/myphonebook を入力してください。
persistence.xml 内の jta-datasource を利用する方法の未テストの説明
このアプリケーションは openjpa のシーケンスを利用しないので、どうやら jta-datasource のみで利用できるようです。私の体験では、プライマリ・キーのために openjpa のシーケンスを利用するアプリケーションは、jta-datasource ではないものが必要です。このような jta-datasource ではないものをデプロイする時は、プランを確認し、<local-transaction/> や <xa-transaction/> ではなく <no-transaction/> を使うことを確認してください。
このアプリケーションのために、コンソールを利用して貴方が選択したデータベースが利用するデータソースをデプロイしてください。データソースに "MyDS" のような名前を与える必要があります。最終的に、console.dbpool/MyDS/1.0/rar のようなデータソースもジュールの名前を持つべきです。Geronimo が貴方のデータソースを使うために、2つのことが必要です。
1. Geronimo に新しいデータソース用のモジュールの探し方を知らせるために、アプリケーションの dependencies にモジュール名を含めてください。openejb-jar.xml は例えば以下のようになります。
<?xml version="1.0" encoding="UTF-8"?> <openejb-jar xmlns="http://www.openejb.org/xml/ns/openejb-jar-2.1" xmlns:nam="http://geronimo.apache.org/xml/ns/naming-1.1" xmlns:pkgen="http://www.openejb.org/xml/ns/pkgen-2.0" xmlns:sec="http://geronimo.apache.org/xml/ns/security-1.1" xmlns:sys="http://geronimo.apache.org/xml/ns/deployment-1.2"> <sys:environment> <sys:moduleId> <sys:groupId>org.apache.geronimo.samples</sys:groupId> <sys:artifactId>MyPhonebookBean</sys:artifactId> <sys:version>1.0</sys:version> <sys:type>car</sys:type> </sys:moduleId> <sys:dependencies> <sys:dependency> <sys:groupId>console.dbpool</sys:groupId> <sys:artifactId>MyDS</sys:artifactId> <sys:version>1.0</sys:version> <sys:type>rar</sys:type> </sys:dependency> </sys:dependencies> </sys:environment> </openejb-jar>
2. persistence.xml に、例えば以下のようにデータソース名を記述してください。
<?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="PhonePU"> <description>Phone Book</description> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <jta-datasource>MyDS</jta-datasource> <class>org.apache.geronimo.samples.myphonebookpak.PhoneBook</class> <properties> <property name="openjpa.jdbc.SynchronizeMappings" value="false" /> </properties> </persistence-unit> <!-- <jta-data-source>PhoneBookPool</jta-data-source> <non-jta-data-source>NoTXPhoneBookPool</non-jta-data-source> --> </persistence>