レベル: 中級 Dale de los Reyes (dreyes4@hotmail.com), Freelance writer
2007年 2月 13日 この連載ではこれまで、データ・ソース接続と JMS (Java Message Service) リソース・グループを作成し、それぞれが ApacheGeronimo および JNDI (Java™ Naming and Directory Interface) とどのように連動するかを説明してきました。4回連載の第 3 回目となるこの記事では、Apache Geronimo、JNDI、メール・セッションが相互に作用する仕組みについて取り上げます。単純なGeronimo アプリケーションで JNDI を使ってメール・セッションを作成する方法、そしてメール・セッションにアクセスする方法を紹介します。
はじめに
メール・セッションは JavaMail リソースの 1 つで、JavaMail とは E メール・システムをモデル化する API のことです。連載第2 回で説明した JMS API とは異なり、JavaMail が処理するメッセージは、人間が利用することを目的としています。JavaMailAPI は Sun などのサード・パーティーによって実装されていますが、Geronimo にも独自の実装があり、その完成度は E メール・メッセージを個別に送信するには十分です。
この記事では第 2 回の内容を引き継いで、ユーザーが特定関心事グループに属するカスタマーに E メールで連絡できるようにするための新しい JSP (JavaServerPages) コンポーネントを作成します。この E メールは、Geronimo アプリケーション・サーバーから Apache James MailServer 2.2 に送信されます。次に、James の E メール・メッセージを読み出すためのコンソール・ベースのクライアントを作成し、新しく追加した機能を検証します。
この連載に記載する Customer Service ユーティリティーは、ユーザーが基本カスタマー情報をデータベースに保存するために使用する単純なWeb アプリケーションです。ビルドには Ant 1.6.5 と Java 1.4.2_10 を使用し、Tomcat を備えた Geronimo1.1 にデプロイします。また、Geronimo には Apache Derby データベースと ActiveMQ JMS プロバイダーがバンドルされているため、この両方を使用します。
James をセットアップする
Apache James Mail Server はデフォルト構成で配布されます。単純なテストには、この構成で十分です。
- アプリケーションを適切な場所に解凍してインストールした後、JAMES_HOME という名前を付けます。
- コンソールで JAMES_HOME/bin/run.bat というスクリプトを実行して James を起動します。James が起動した後のコンソールは、図 1のようになります。
- コンソールで Ctrl+C を押して James を停止します。
- ディレクトリーを JAMES_HOME/work/james-<system generated id>/SAR-INF/libに変更します。このディレクトリーは、James が初めて起動されたときに作成されます。activation.jar ファイルと mail-1.3.1.jarファイルを JAMES_HOME/lib にコピーします。
- James を再起動し、ポート番号をメモします。Remote Manager Service のポート番号はとりわけ重要です。
-
telnet localhost 4555 (James がローカル・マシンにインストールされているという前提) と入力して Remote Manager Service に接続します。ログインとパスワードには、どちらもデフォルトのroot を使用してください。adduser [user] [password] を入力してユーザー・アカウントとパスワードを作成します。例えば、adduser smith smith と入力すると、ユーザー名 smith、パスワード smith のユーザーが作成されます。必要に応じてこのステップを繰り返してください。
- 最後に第 3 回の記事用として CustomerService/resource/build.properties ファイルを変更し、Geronimoおよび James に対応する場所を適用します。
図 1. Windows コンソールでの James の起動
これで、James Mail Server が Geronimo から E メールを受信するための準備が整いました。デフォルト構成ファイルはJAMES_HOME/apps/james/SAR-INF/config.xml にあります。このファイルはこの記事のために変更する必要はありませんが、Jamesの設定を詳しく調べたいという方のためにファイルの場所をお知らせしておきます。
次に必要なのは、テスト・カスタマーを Geronimo データベースで作成または編集することです。http://localhost:8080/serviceにある Customer Service ユーティリティーにアクセスし、Customer Processing Page に進んでください。このページで、localhostに E メール・アドレスを持つカスタマーを作成します。図 2 はその一例です。
図 2. John Smith の E メール・アドレス更新
上記では、John Smith という名前のカスタマーの E メール・アドレスを更新しています。ドメイン名が localhost となっていることに注意してください。このドメイン名は、Jamesのデフォルト構成では、このユーザー宛ての着信メールを受信するときに求められるドメイン名と同じです。次のステップは JNDI でメール・セッションを宣言することですが、詳細は次のセクションで説明します。
Geronimo デプロイメント記述子の作成方法
記述子ファイルの構成は重要です。なぜなら、記述子ファイルは、これらのコンポーネントを Geronimo で使用するための手段だからです。また、記述子ファイルを構成することによってJNDI 名を指定の Java オブジェクトに関連付けることにもなります。Geronimo にデプロイされるコンポーネントには通常、2 つのデプロイメント・ファイルがあります。1つは標準 J2EE (Java 2 Platform, Enterprise Edition) または Java EE (Java Platform,Enterprise Edition) デプロイメント記述子、そしてもう 1 つは Geronimo 固有のデプロイメント・プランです。
新しい JSP インターフェースでは、ユーザーが特定関心事グループのカスタマーに E メールを送信できます。この E メールは Web 層のCustomerServiceJavaBean 内から送信されます。リスト 1 に、標準 web.xml J2EE/Java EE デプロイメント記述子に JavaMail リソースを指定するために必要な追加タグを記載します。
リスト 1. web.xml のリスト抜粋
<resource-ref>
<res-ref-name>mail/CustomerServiceMailSession</res-ref-name>
<res-type>javax.mail.Session</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
|
上記の <resource-ref> タグは、JNDI 名をリソース・オブジェクトのタイプに関連付けます (この例では、javax.mail.Session)。このタグに見覚えがあると思うのなら、それはデータ・ソース (JDBC の場合) または接続ファクトリー (JMS の場合) など、他のリソースのオブジェクト・タイプを宣言するために使うタグと同じだからです。この2 つのリソース・タイプは、サンプル・アプリケーションの別の場所ですでに使用されています。リスト 2 に、対応する Geronimo 固有のデプロイメント・プランに必要なタグを記載します。
リスト 2. geronimo-web.xml のリスト抜粋
<resource-ref>
<ref-name>mail/CustomerServiceMailSession</ref-name>
<resource-link>mail/CustomerServiceMailGBean</resource-link>
</resource-ref>
|
<ref-name> は web.xml の <res-ref-name> に対応すると同時に、メール・セッション・リソースを呼び出すために使われる JNDI 名でもあります。<resource-link> は、JavaMail セッションの生成を行う MailGBean の名前を指定します。この名前はリスト 3 に記載するように、アプリケーション・レベルで宣言されます。
リスト 3. geronimo-appliction.xml のリスト
<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>default</dep:groupId>
<dep:artifactId>CustomerService</dep:artifactId>
<dep:version>1.0</dep:version>
<dep:type>ear</dep:type>
</dep:moduleId>
<dep:dependencies>
<dep:dependency>
<dep:groupId>geronimo</dep:groupId>
<dep:artifactId>geronimo-mail</dep:artifactId>
<dep:version>1.1</dep:version>
<dep:type>jar</dep:type>
</dep:dependency>
<dep:dependency>
<dep:groupId>geronimo</dep:groupId>
<dep:artifactId>geronimo-javamail-transport</dep:artifactId>
<dep:version>1.1</dep:version>
<dep:type>jar</dep:type>
</dep:dependency>
</dep:dependencies>
<dep:hidden-classes/>
<dep:non-overridable-classes/>
</dep:environment>
<module>
<connector>tranql-connector-1.2.rar</connector>
<alt-dd>CustomerServicePool-alt.xml</alt-dd>
</module>
<gbean name="mail/CustomerServiceMailGBean"
class="org.apache.geronimo.mail.MailGBean">
<attribute name="transportProtocol">smtp</attribute>
<attribute name="useDefault">false</attribute>
<attribute name="host">localhost</attribute>
<attribute name="properties">
mail.debug=true
mail.smtp.port=25
</attribute>
</gbean>
</application>
|
geronimo-mail-1.1.jar 用と geronimo-javamail-transport-1.1.jar 用の 2 つの <dependency> タグが必要な理由は、それぞれに MailGBean と Transport の実装が含まれるからです。<gbean> 宣言をサポートするには両方とも必要になります。この <gbean> の名前は、前にリストした geronimo-web.xml の <resource-link> に指定した名前と同じです。
transportProtocol 属性は E メールの送信プロトコル、smtp を指定します。host 属性が指定するのは、メール・サーバーが位置するドメインの名前または IP アドレスです。この記事の James は Geronimo 1.1と同じマシンにインストールされていますが、アクセス可能で正しく構成されたメール・サーバーであれば何を使っても構いません。その場合、localhostではなく実際の E メール・アドレスを使用できます。properties 属性では、名前と値のペアを使って追加属性を設定できます。この例では、デバッグ・メッセージが Geronimo 出力コンソールに表示されるように設定されています。smtp port は James Mail Server のポートと同じです。最後に、この <gbean> はアプリケーション・レベルの記述子に指定されているため、適用範囲はアプリケーション・レベルだけとなります。これで、関連コンポーネントは構成できました。今度はJNDI を使用するコードのオブジェクトを見てみましょう。
Customer Service ユーティリティーと JavaMail
拡張 Customer Service ユーティリティーの準備はもう少しで完了です。次のステップでは、JNDI でメール・セッションを呼び出し、JavaMailを使ってメッセージを送信します。完全な JNDI ストリングをリスト 4 に記載します。
リスト 4. customer.properties での JNDI 名のリスト
# Specify JNDI names here
jndi.customer.ejb=java:/comp/env/ejb/CustomerEntityBean
jndi.process.ejb=java:/comp/env/ejb/ProcessCustomerSessionBean
jndi.group.ejb=java:/comp/env/ejb/InterestGroupEntityBean
jndi.jms.connector=java:comp/env/jms/CustomerServiceConnectionFactory
jndi.jms.topic=java:comp/env/jms/CustomerServiceTopic
jndi.mail.session=java:comp/env/mail/CustomerServiceMailSession
|
前述の手順で Web アーカイブ記述子の <ref-name> タグで宣言した名前が、完全な JNDI 名のコンテキストでリストされました。すべての名前には、推奨される J2EE 命名規則に従って、名前の前に情報が挿入されています。リスト5 のコードに、完全な JNDI 名のコンテキストを使って CustomerServiceMailSession の検索を実行する方法を示します。
リスト 5. JNDI 検索を実行する CustomerServiceJavaBean.java のリスト抜粋
public CustomerServiceJavaBean()
{
InitialContext initial = null;
Object objref = null;
bundle = ResourceBundle.getBundle("customer", Locale.getDefault(),
CustomerServiceJavaBean.class.getClassLoader());
JNDI_PROCESS_EJB = bundle.getString("jndi.process.ejb");
JNDI_MAIL_SESSION = bundle.getString("jndi.mail.session");
try
{
initial = new InitialContext();
objref = initial.lookup(JNDI_PROCESS_EJB);
processHome = (ProcessCustomerHome)PortableRemoteObject.narrow(objref,
ProcessCustomerHome.class);
System.out.println("looking up: " + JNDI_PROCESS_EJB);
objref = initial.lookup(JNDI_MAIL_SESSION);
mailSession = (Session)PortableRemoteObject.narrow(objref,
javax.mail.Session.class);
System.out.println("looking up: " + JNDI_MAIL_SESSION);
} // end try
catch (Exception e)
{
e.printStackTrace();
} // end catch
} // end CustomerServiceJavaBean
|
上記で明らかなのは、メール・セッションを検索するためのコードは ProcessCustomerSessionBean を検索する場合のコードと同様で、変更が必要な箇所はメール・セッションを参照する箇所のみだということです。リスト 6 に、実際の E メールをGeronimo から送信するために必要なコードを記載します。
リスト 6. E メールを送信する CustomerServiceJavaBean.java のリスト抜粋
private boolean sendEmail(String toAddress, String fromAddress, String
subject, String content)
{
boolean status = false;
try
{
Date dateStamp = new Date();
MimeMessage email = new MimeMessage(mailSession);
email.setFrom(new InternetAddress(fromAddress));
email.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(toAddress, false));
email.setSubject(subject);
email.setText(content);
email.setHeader("X-Mailer", "JavaMailer");
email.setSentDate(dateStamp);
Transport.send(email);
status = true;
} // end try
catch (Exception e)
{
status = false;
e.printStackTrace();
} // end catch
return status;
} // end sendEmail
|
ここでも CustomerServiceJavaBean は Web 層の一部で、Geronimo はこのレベルから E メールを送信します。前のリストに示したJNDI 検索で取得した mailSession を使用して、E メール・メッセージを表す実際のオブジェクトである MimeMessage が作成されます。関連属性が設定された後、メッセージは Transport オブジェクトによってメール・サーバーに送信されます。
ここで必要となるのは、メール・サーバーがメッセージを正常に受信したかどうかを確認することです。それには、メール・サーバーに接続可能なコンソール・ベースのクライアントを使って、指定されたユーザーに関連するすべてのメッセージを抽出し、各メッセージの内容をコンソールに出力します。リスト7 に、このクライアントのリストを抜粋します。Reader という名前のこのクライアントが、メール・セッションを生成します。
リスト 7. JavaMail セッションを生成する Reader.java メソッド
private Session generateSession(String host, String user, String password)
{
authentication = new PasswordAuthentication(user, password);
Properties properties = new Properties();
properties.put("mail.host", host);
properties.put("mail.debug", "false");
properties.put("mail.user", user);
properties.put("mail.store.protocol", "pop3");
Session session = Session.getInstance(properties, this);
return session;
} // end generateSession
|
PasswordAuthentication が指定されたユーザーの名前とパスワードを検証します。このメソッドでは JNDI を利用していないことに注目してください。JNDI を利用する代わりに関連プロパティーを設定し、設定したプロパティーを使ってメール・セッションを作成しています。リスト8 は、E メール・メッセージを抽出する実際のコードです。
リスト 8. 特定ユーザー宛てのすべての着信 E メールを読み出す Reader.java メソッド
protected void readEmail(String host, String username, String password)
{
Store store = null;
Folder inbox = null;
try
{
Session mailSession = generateSession(host, username, password);
store = mailSession.getStore();
store.connect();
Folder folder = store.getDefaultFolder();
inbox = folder.getFolder("inbox");
inbox.open(Folder.READ_ONLY);
Message[] messages = inbox.getMessages();
System.out.println("Inbox for userID: " + username);
System.out.println("inbox size: " + messages.length);
System.out.println("*****");
for (int x = 0; x < messages.length; x++)
{
MimeMessage email = (MimeMessage)messages[x];
System.out.println("FROM: " + email.getFrom()[0].toString());
System.out.println("TO: " +
email.getRecipients(Message.RecipientType.TO)[0].toString());
System.out.println("DATE: " + email.getSentDate());
System.out.println("SUBJECT: " + email.getSubject());
System.out.println("CONTENT: " + email.getContent());
} // end for
System.out.println("*****");
} // end try
catch (Exception e)
{
e.printStackTrace();
} // end catch
finally
{
try
{
inbox.close(true);
store.close();
} // end try
catch (Exception e)
{
e.printStackTrace();
} // end catch
} // end finally
} // end readEmail
|
作成されたメール・セッションは、メール・サーバーに接続するメッセージ・ストアを取得するために使用されます。inbox がフォルダー名として予約されており、接続が確立するとこのフォルダーに含まれるすべてのメッセージを取得できるようになります。メッセージの取得が完了すれば、メッセージのコンテンツをコンソールに表示するのは簡単なことです。
これで、Customer Service ユーティリティーを Geronimo にデプロイする準備が整いました。以下の手順に従ってください。
- CustomerService/resources/build.properties ファイルを修正し、ディレクトリーの場所が正しく定義されていることを確認します。
- 次に、コンソールを開いてディレクトリーを CustomerService/build.xml がある場所に変更し、
ant と入力します。これによって、アプリケーションのビルドとデプロイメントが行われ、http://localhost:8080/service でアプリケーションにアクセスできるようになります。同時に、クライアントReader アプリケーションもパッケージ化されます。Groups Contact Page は図 3 のように表示されます。
図 3. Groups Contact Page によるカスタマーへの E メールの送信
このページでは、ユーザーが Java 特定関心事グループで取得したすべてのカスタマーのなかから、John Smith に 1 通の E メールを送信することにしています。必要な場合は、表示されたすべてのカスタマーを選択し、同じEメールをそれぞれのカスタマーに送信することもできます。この場合、ドメイン名 (localhost) が有効で、カスタマーのユーザー ID がメール・サーバーで作成済みであることが条件となります。Eメールが送信されると、図 4 に示すようなデバッグ・メッセージが Geronimo 出力コンソールに表示されます。
図 4. JavaMail デバッグ・メッセージが表示された Geronimo コンソール
上記の出力によると、John Smith 宛てのメッセージは正常に James Mail Server に送信されました。次のステップは、メール・サーバーを調べてE メールが James 内にあることを確認することです。client localhost smith smith と入力して、Reader を実行してください。出力結果は、図 5 のようになるはずです。
図 5. James からの受信 E メールに関するクライアントの出力
クライアントの出力には、Group Contacts Page から John Smith に送信されたすべてのメッセージが表示されます。Geronimoから送信された E メール・メッセージは、James Mail Server に正常に送信されています。JNDI で JavaMail リソースにアクセスする方法は、これですべてです。
まとめ
この記事では、JavaMail リソース・グループを構成して呼び出す方法を説明しました。Customer Service ユーティリティーでカスタマー宛てのE メールを Web インターフェースから Apache James Mail Server に送信し、JNDI からこのリソースにアクセスする方法を実演しました。さらに専用のコンソール・アプリケーションを実装して、着信E メールが受信されたことを確認しました。次の連載最終回では、Customer Service ユーティリティーを完成するために使用する、URI接続への JNDI アクセスについて説明します。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| Part 3 source code | CustomerService-part3.zip | 589KB | HTTP |
|---|
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | |  | Dale de los Reyes は 1996 年、California Polytechnic State University, San Luis Obispo でコンピューター・サイエンスの学位を取得し、J2EE、Microsoft® Windows® 対応 C++、メインフレーム対応 COBOL でのアプリケーション開発の経験を積んでいます。余暇は写真、武道、そして独自のプロジェクトの追及に費やしています。
|
記事の評価
|