JavaアプリケーションサーバとJMSプロバイダを接続する
前回は、Java EEプラットフォームと他のエンタープライズシステムとの相互接続をサポートするJava EE Connector Architecture(JCA)の次期バージョンとなる、JSR 322について紹介した。それに関連して、今回はJCAを使ったシステム間接続の方法を、Javaアプリケーションサーバ製品のひとつであるSun Java System Application Server(以下、SJSAS)を例にとって紹介しようと思う。
SJSASはJava EE 5準拠のアプリケーションサーバなのでJCA 1.5(JSR 112) の実装を含んでいる。今回はこれにJava Message Service(JMS)向けの汎用リソースアダプタであるGeneric Resource Adapter for JMS(以下、genericra)を追加し、JMSによるメッセージングを利用できるようにする。なお、JMS実装にはSJSASにバンドルされているSun Java System Message Queueを利用する。
ここではすでにSJSAS 9.1(またはそれを含むJava EE 5 SDK)がインストールされているものとして、管理コンソールを用いて各種設定を行う。SJSAS 9.1はこのサイトよりダウンロードできる。
SJSASへのリソースアダプタの追加
genericraはこのページで公開されている、今回は安定版である1.7-finalのRAR形式のバイナリを利用する。RAR形式はリソースアダプタをパッケージングする際に使うファイル形式で、WARファイルなどと同様にjarコマンドによって作成されている。
リソースアダプタをSJSASにデプロイするには、管理コンソールより[Applications]-[Connector Modules]と選択し、図1の画面の[Deploy]をクリックする。そして追加したいリソースアダプタのRARファイルとアプリケーション名、その他のオプション情報を入力し、[OK]をクリックする (図2)。genericraの場合には次に図3のようにJMSを利用するための各種プロパティを設定するページが表示されるので、このページにあるプロパティ表を参考にして適切な値を設定する。
以上でリソースアダプタがデプロイできた。続いてアプリケーションから利用するためのコネクションプールとコネクターリソースを設定する。まずコネクションプールは[Resources]-[Connectors]-[Connector Resource Pools]と選択し、図4の画面で[New]をクリックする。そして図5のように任意の名前と、リソースアダプタとしてgenericraを指定する。Connection Definitionには利用可能なファクトリクラスが表示されるので、今回はQueueConnectionFactoryを指定しておく。設定の2ページ目(図6)はとりあえずデフォルトのままでもよい。
外部システムとアプリケーションサーバとの相互接続はリソースアダプタによって実現されるが、実際にそれをアプリケーションで利用するにはコネクターリソースを用意する必要がある。コネクターリソースはJNDI(Java Naming and Directory Interface)を介してプログラムからアクセスできるようになっている。
SJSASの場合、コネクターリソースの設定は管理コンソールの[Resources]-[Connectors]-[Connector Resources]を選択して図7の画面の[New]をクリックする。そして任意のJNDI名と、先程作成したコネクションプール名を指定すればよい (図8)。
続いてJMSのためのリソースの設定を行う。今回はJMSのメッセージキューを利用したPoint-to-Pointのメッセージングを行うつもりなので、そのためのメッセージキューを設定しておく必要がある。そこで管理コンソールから[Resources]-[Connectors]-[Admin Object Resources]を選択し、図9の画面の[New]をクリックする。そして図10のように任意のJNDI名、リソースタイプ、リソースアダプタを設定する。設定の2ページ目(図11)はデフォルトのままでもよい。
以上ですべての設定は完了だ。続いて、これをアプリケーションから利用してみよう。
リソースアダプタ経由でJMSを利用する
今回は話を簡潔にするためメッセージの送信用、受信用それぞれのプログラムをJSPを利用したWebページとして記述する。ポイントは先ほど設定したコネクターリソースを利用して、JNDI経由でJMSのサービスを利用するということである。すなわリスト1のようにInitialContextクラスのlookupメソッドで「GenericraConnector」をルックアップすればよい。ルックアップに成功すれば、コネクションのファクトリクラスであるQueueConnectionFactoryのインスタンスが返ってくる (図5のConnection Definitionで設定)。
リスト1 ConnectionFactoryをJNDI経由で取得
InitialContext context = new InitialContext();
QueueConnectionFactory connFactory = (QueueConnectionFactory)context.lookup("GenericraConnector");
また、メッセージングのためのメッセージキューもJNDI経由で取得する (リスト2)。
リスト2 メッセージキューをJNDI経由で取得
Queue queue = (Queue)context.lookup("MyQueue");
あとはQueueConnectionFactoryからコネクションを作成し、セッションを使ってメッセージの送信を行えばよい。全体としてはリスト3のようになる。
リスト3 sender.jsp - メッセージ送信用のJSP
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Connector Example: MessageSender</title>
</head>
<body>
<h2>Connector Example: MessageSender</h2>
<%@ page import="javax.naming.*, javax.jms.*" %>
<%
try {
// InitialContextを作成
InitialContext context = new InitialContext();
// ConnectionFactoryをlookup
QueueConnectionFactory connFactory = (QueueConnectionFactory)context.lookup("GenericraConnector");
// Queueをlookup
Queue queue = (Queue)context.lookup("MyQueue");
// コネクションを作成
QueueConnection connection = connFactory.createQueueConnection("USERNAME", "PASSWORD");
// セッションを作成
QueueSession qSession = connection.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
// キューセンダーを作成
QueueSender qSender = qSession.createSender(queue);
// メッセージを作成
TextMessage message = qSession.createTextMessage();
message.setText("Hello World!");
// メッセージを送信
connection.start();
qSender.send(message);
System.out.println("Sender: Send message \"" + message.getText() + "\".");
// 接続を切断
qSender.close();
qSession.close();
connection.close();
} catch(NamingException ex) {
ex.printStackTrace();
}
%>
</body>
</html>
受信側もまったく同様で、リスト4のようにすればよい。ここではメッセージが送信される度にそれを受信するようになっており、受信内容はコンソールに出力している。したがってページはロード状態のまま何も出力されない。
リスト4 receiver.jsp - メッセージ受信用のJSP
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Connector Example: MessageReceiver</title>
</head>
<body>
<h2>Connector Example: MessageReceiver</h2>
<%@ page import="javax.naming.*, javax.jms.*" %>
<%
try {
// InitialContextを作成
InitialContext context = new InitialContext();
// ConnectionFactoryをlookup
QueueConnectionFactory connFactory = (QueueConnectionFactory)context.lookup("GenericraConnector");
// Queueをlookup
Queue queue = (Queue)context.lookup("MyQueue");
// コネクションを作成
QueueConnection connection = connFactory.createQueueConnection("USERNAME", "PASSWORD");
// セッションを作成
QueueSession qSession = connection.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
// キューレシーバーを作成
QueueReceiver qReceiver = qSession.createReceiver(queue);
// メッセージを受信
connection.start();
while (true) {
Message message = qReceiver.receive();
if (message != null) {
if (message instanceof TextMessage) {
TextMessage msg = (TextMessage)message;
System.out.println("Receiver: Receive message \"" + msg.getText() + "\".");
} else {
break;
}
}
}
// 接続を切断
qReceiver.close();
qSession.close();
connection.close();
} catch(NamingException ex) {
ex.printStackTrace();
}
%>
</body>
</html>
ちなみに、SJSASの場合はSun Java System Message Queueのためのリソースアダプタがバンドルされているため、genericraを利用しなくてもJMSを使うことができるようになっている。今回はリソースアダプタをデプロイする一例としてgenericraを取り上げたが、他のアダプタも同様の方法で利用することが可能である。