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を利用するための各種プロパティを設定するページが表示されるので、このページにあるプロパティ表を参考にして適切な値を設定する。

図1

図2

図3

以上でリソースアダプタがデプロイできた。続いてアプリケーションから利用するためのコネクションプールとコネクターリソースを設定する。まずコネクションプールは[Resources]-[Connectors]-[Connector Resource Pools]と選択し、図4の画面で[New]をクリックする。そして図5のように任意の名前と、リソースアダプタとしてgenericraを指定する。Connection Definitionには利用可能なファクトリクラスが表示されるので、今回はQueueConnectionFactoryを指定しておく。設定の2ページ目(図6)はとりあえずデフォルトのままでもよい。

図4

図5

図6

外部システムとアプリケーションサーバとの相互接続はリソースアダプタによって実現されるが、実際にそれをアプリケーションで利用するにはコネクターリソースを用意する必要がある。コネクターリソースはJNDI(Java Naming and Directory Interface)を介してプログラムからアクセスできるようになっている。

SJSASの場合、コネクターリソースの設定は管理コンソールの[Resources]-[Connectors]-[Connector Resources]を選択して図7の画面の[New]をクリックする。そして任意のJNDI名と、先程作成したコネクションプール名を指定すればよい (図8)。

図7

図8

続いてJMSのためのリソースの設定を行う。今回はJMSのメッセージキューを利用したPoint-to-Pointのメッセージングを行うつもりなので、そのためのメッセージキューを設定しておく必要がある。そこで管理コンソールから[Resources]-[Connectors]-[Admin Object Resources]を選択し、図9の画面の[New]をクリックする。そして図10のように任意のJNDI名、リソースタイプ、リソースアダプタを設定する。設定の2ページ目(図11)はデフォルトのままでもよい。

図9

図10

図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を取り上げたが、他のアダプタも同様の方法で利用することが可能である。