HomeDocumentation > 9. サンプル・アプリケーション > 9.h. とても簡単なエンティティ EJB の例

Phone Book Bean の例

アノテーションを利用してエンティティ Bean を呼び出す JSP ページ の例です。実行結果として次のように表示されます。






アプリケーションの内容

まず、データベース内のテーブルを表す PhoneBook エンティティ Bean を見てみましょう。PhoneBook のどのインスタンスもテーブルの1レコードです。
PhoneBook.java は次の記述を利用しています。

  1. @Entity アノテーションは、このクラスがエンティティ Bean という記述です
  2. @Table アノテーションは、エンティティ Bean が表すテーブルの名前の記述です
  3. @Id アノテーションは、テーブルのプライマリ・キーの記述です

なお通常は、エンティティ Bean には空のコンストラクターがあります。

PhoneBook.java
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 への受け渡しをするビジネス・インターフェースです。

MyPhonebookLocal.java
package org.apache.geronimo.samples.myphonebookpak;

import org.apache.geronimo.samples.myphonebookpak.PhoneBook;

public interface MyPhonebookLocal {
	public PhoneBook findByPrimaryKey(String name);
}

MyPhonebookBean.java は、ローカル・インターフェース(またはリモート・インターフェース)を実装したものです。このステートレス・セッション Bean にあるアノテーションの意味の説明は次のとおりです。

  1. @Stateless - Geronimo にこのクラスがステートレス・セッション Bean であることを通知します
  2. @PersistenceUnit - Geronimo に、persistence.xml に定義された永続化ユニット(persistence unit)を取得し、これを EntityManagerFactory とするように通知します

    直接 EntityManager を取得しようとするときは、PersistenceContext を利用します。EntityManagerFactory には PersistenceUnit を利用します。



    MyPhonebookBean.java
    package 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 ページです。

index.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 へはモジュール情報を記述します。

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 を加えました。

以下は一つの方法です

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>
		<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 が参照されます。

web.xml
<?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 のコンテキスト・ルートを記述します。

geronimo-web.xml
<?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 ファイル内の最上位階層に置きます。

geronimo-application.xml
<?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 を作成してください。

PhoneBook.sql
CREATE TABLE phonebook ( name VARCHAR(255) PRIMARY KEY, number VARCHAR(255) );
INSERT INTO phonebook VALUES ('John', '1234');
INSERT INTO phonebook VALUES ('Joe', '5678');
  1. 左側の Console Navigation から DB Manager リンクを選択してください。
  2. データベース名として PhoneBookDB を入力し、Create ボタンをクリックしてください。
  3. Use DB 欄で PhoneBookDB を選択してください。
  4. テキストエディタで myphonebook/myphonebook-ear/src/main/resources ディレクトリーから、PhoneBookDB.sql を開いてください。
  5. SQL Commands のテキストエリアに PhoneBookDB.sql の内容を貼りつけ、Run SQL ボタンを押してください。

ビルド

コマンドプロンプトを利用して myphonebook ディレクトリーへ移動し、mvn installmvn site の順にコマンドを入力するとビルドされます。myphonebook フォルダーの下に myphonebook-ear-2.0-SNAPSHOT.ear が作られます。これで Geronimo アプリケーション・サーバーへ myphonebook アプリケーションをデプロイする準備ができました。

アプリケーションのデプロイ

Geronimo Console の利用によって、サンプルアプリケーションのデプロイはかなり簡単です。

  1. Console Navigation パネルから Deploy New を選択してください。
  2. Archive 入力欄に myphonebook フォルダーの myphone-ear-2.0-SNAPSHOT.ear を読み込んでください。
  3. 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 は例えば以下のようになります。

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 に、例えば以下のようにデータソース名を記述してください。

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>