2008年3月20日木曜日

JavaEE 5 SDKを使ってみる

JMSのチュートリアルを読んでいたら、J2SE1.3のSDKをベースに書かれていたので、
それなら、とJavaEE 5 SDKを使ってみることにした。
だって、各アプリケーションサーバのJNDIのセッティング方法を調べるのが面倒なんだもん!
#実際、プラットフォームがごちゃごちゃな環境では、各APサーバごとに管理方法が異なるため、厄介な話なのだ。

(注意事項)
2008/3/21現在、JavaEE 5 SDK Update 4 は、英語版のみです。
日本語を含めた多言語をサポートした最新バージョンはJava EE 5 SDK Update 3です。
以下のインストール手順はJavaEE 5 SDK Update 4のスナップショットです。
ダウンロードするときは、くれぐれも間違えないように。

1.前提
・JDK 1.6がインストールされていること。
・Windows環境であること。


2.ダウンロード

JavaEEのSDKは以下のリンクからダウンロードする。
※ダウンロードには、SunDeveloperCenterのユーザアカウントが必要です。
http://sdc.sun.co.jp/java/javaee/downloads/index.html

日本語対応の多言語版は、ページの下のほうにあるので、注意してください。


3.インストール

2.でダウンロードした、「java_ee_sdk-5_04-windows-nojdk.exe」を起動する。

Step1. Welcome
「Next」を押す


















Step2. Agreement

「Yes」を選択して、「Next」を押す


















Step3.インストールディレクトリの指定

例ではC:\Sun\SDKとしている。お好きなところで。



















Step4.JDKインストールディレクトリの指定
JDKをインストールしたディレクトリを指定する




Step5. 管理用の設定

・管理者のユーザ名、パスワードを設定する。
・管理機能を呼び出すごとにユーザ名・パスワードを求められるのは面倒なので、
 「Don't Prompt for Admin User Name and Password」を選択する。
・ポートはデフォルトのままにしておく。

















Step6. インストールオプションの設定

  • 「Upgrade from Previous Version」
    • 前バージョンからの設定ファイルの移行は無いので、チェックを外す
  • 「Enable Updatechecker Client」
    • 勝手にバージョンチェックされるのも嫌なので、チェックを外す
  • 「Create Desktop Shortcut to Autodeploy Directory」
    • 便利だけど、これ以上デスクトップを汚したくないので、チェックを外す
  • 「Add bin directory to PATH」
    • パスは追加しておかないとね
  • 「Create Windows Service」
    • 手動でサーバ起動・停止を行うので、チェックは外しておく

















Step7. インストール内容の確認
「Next」を押す
















Step8. インストール中
しばし待たれよ
















Step9. ユーザ登録
登録しておくとパッチの情報とか貰えるらしいけど、
ちょこっと使うだけなので、「Skip Registration」を選択する。

















Step10. インストール完了
サーバの起動は別途手動で行うので、
ここでは「Finish」を押して、インストールを完了する。

















----------[インストール完了]-----------------

(おまけ)
3'. アンインストール
「プログラムの追加と削除」から「Java Platform, Enterprise Edition 5 SDK」を選択して、削除する。
一部のディレクトリは削除されないので、手動で削除。


4.サーバを起動する

JavaEE5SDKをインストールすると、漏れなく
  • Sun Java System Message Queue 4.1
  • Sun Java System Application Server 9.1
が付いてきます。
Sun Java System Application Serverは、GlassFishをベースとしたAPサーバです。
IBMがGeronimoをベースとしてWAS-CEを作っているのと似ている。
今回使ってみて思ったけど、やっぱり標準サポートのSDKであり、日本語対応がされているという点は大きい。学習用にはもってこい。何よりJNDIの設定が簡単!

話が逸れましたが、サーバを起動するためには、
[スタートメニュー]→[Sun Microsystems]→[JavaEE SDK]→[Start Default Server]をクリックするか、
コマンドプロンプトにて、以下のコマンドを実行する。

asadmin start-domain

サーバが起動するので、ブラウザを使って管理コンソールにアクセスする。
URLは以下のとおり。
(インストール時に管理用コンソールのポートを別の番号にした場合は、そのポート番号を指定する)

http://localhost:4848/login.jsf









ユーザ名、パスワードは、インストール中に指定したものを入力する。
ログインすると、ユーザ登録がどうたら、と聞かれるので、
「Never Register」をクリックする。
















  で、いろいろとメニュー項目を眺めたりするんだけど、全部英語だYO!
  まぁダウンロードするときにEnglishしか選べなかったので、わかっていたことですが。
  そういえばJ2EE 1.4のSDKを使っていたときは日本語だったなぁ、と思い出して、調べたら多言語版があったよorz
  というわけで、多言語版をインストールし直し・・・。
  でもでも、日本語でConnectionFactoryを接続ファクトリと言われてもピンと来なくて、微妙だったりする(笑)

5.JMSの設定を行う
普通ならここでHelloWorld的なWebアプリケーションを作って終わるところだけど、
そんなこたぁ、どうでもいいんです!ルックアップがしたいのですよ!

まずは接続ファクトリの設定から。
管理コンソール画面の、左側にある共通操作ペインから、[リソース]→[JMSリソース]→[接続ファクトリ]を選択して、「新しいJMS接続ファクトリ」作成画面を開く。
















「JNDI名」を「jms/QueueConnectionFactory」とする。
「リソースタイプ」を「javax.jms.QueueConnectionFactory」とする。
他の設定はデフォルトのまま、「了解」ボタンを押して登録する。
なんて簡単なんだ!

続いて、キューの設定を行う。
先ほどと同様に、管理画面左側のペインから、
[リソース]→[JMSリソース]→[接続リソース]を選択して、「新しい接続先リソース」作成画面を開く。

「JNDI名」は「jms/MyQueue」とする。
「物理送信先名」は「MyQueue」とする。(これは送信先リソースのNameプロパティの値になる)
「リソースタイプ」は「javax.jms.Queue」とする。

続いて、キューを作成する。
ここでの操作は、
Sun Java System Message Queue 4.1に反映される。
今度は[構成]→[Javaメッセージサービス]→[JMSホスト]→[物理送信先]を選択する。
「新規」ボタンを押して、以下の設定でキューを作成する。
名前:MyQueue
タイプ:javax.jms.Queue

6.ルックアップを行う

スタンドアロンのアプリからメッセージをputしたい。
やり方は2つ。
まず1つ目は、JMSプロバイダが提供する接続ファクトリとキューを生成して、
宛先名やらキュー名やらを設定する方法。
2つ目は、JNDIでConnectionFactoryとQueueをルックアップして取得する方法がある。

1つ目の方法だと、JMSプロバイダガ提供する独自のクラスを生成する必要があり、
ソースコードの移植性が落ちる。
そこで2つ目の方法を使う。

JNDIを使うためには、まずInitialContextに環境定義を渡す必要がある。

InitialContextのAPIを見ると分かるが、やり方は
  1. プロパティを渡す
  2. jndi.propertiesファイルに設定しておく
の2通りである。
APサーバ上で実行されるAP(Webアプリケーション等)は、APサーバが環境定義を把握しているので、勝手にプロパティを読み込まれる。そのため、AP実装時に、InitialContextのコンストラクタに引数を渡す必要がない。

では、APサーバ上で実行しないAPはどうなるのか。
この場合、自前でプロパティを渡すしかない。
つまり、ソースコードにプロパティを記述して、それをInitialContextのコンストラクタ引数に渡すか、
クラスパス上にjndi.propertiesファイルを作成するか、だ。

以下、Sun Java Application Server上で、先ほど設定したQueueConnectionFactoryをJNDIで取得するためのサンプルだ。

import java.util.Properties;

import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.naming.Context;
import javax.naming.InitialContext;

public class JmsSender {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory");
InitialContext context = new InitialContext(props);
System.out.println("context ok");
QueueConnectionFactory factory = (QueueConnectionFactory)context.lookup("jms/QueueConnectionFactory");
System.out.println("factory ok");
Queue queue = (Queue)context.lookup("jms/MyQueue");
System.out.println("queue ok");
}
}


Propertiesを生成して、値を自前で設定している。

put(Context.INITIAL_CONTEXT_FACTORY
,"com.sun.enterprise.naming.SerialInitContextFactory");

Context.INITIAL_CONTEXT_FACTORYは、実際には「java.naming.factory.initial」という値である。
したがって、jndi.propertiesファイルを用意する場合は、
 java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory
という定義を記述すればよい。これでソースファイルの環境依存性が無くなる。

ただし、厄介なのがこのプロパティ。今回は、「
com.sun.enterprise.naming.SerialInitContextFactory」というコンテキストファクトリを指定したが、
これは今回に限った話で、JNDIプロバイダが異なれば、設定が変わってくる。
しかも、どの値を設定していいのか、よく分からない。

実は、「
com.sun.enterprise.naming.SerialInitContextFactory」という値を取得するために、
一度、Webアプリケーションを作成して、その上でInitialContextを生成して、
そこから環境定義を取得している。
これによってInitialContextの実体クラスを把握できたのだ。

public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
Context context = null;
PrintWriter pw = res.getWriter();

context = new InitialContext();
pw.println("get InitialContext: ok");

Hashtable table = context.getEnvironment(); // コンテキストの環境定義を取得する
pw.println(table.toString());
}


今回はJMSプロバイダとAPは同じホスト上で実行した。
そのため、本来指定しなければならない、Context.PROVIDER_URLの値(JNDIプロバイダのURL)は指定せずに済んだ(※)。
(※指定せずに済んだのは、
コンテキストがSerialInitContextFactoryだったからというのもある)

このURLの指定も、APサーバの設定で異なる。
rmiregistryだったらrmi://localhostとか、
LDAPを使うなら、ldap://ldapserver:900/o=myObjectsとか、ファイルシステムだったら、file:///C:/tempとか、
ActiveMQが提供するファクトリクラスなら、tcp://localhostだってOKだし、
CosNamingならiiop://とか。
とにかくJNDIを使うのは骨が折れるのだ。

JNDIは自前でbindを行ってしまえば、それで使える。

Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
props.put(Context.PROVIDER_URL, "rmi://localhost");
InitialContext context = new InitialContext(props);
context.rebind(JNDI名,オブジェクト);

こうすればコンテキストの生成時に、自分で把握しているプロパティを渡せるので、
今回のようにいちいち調べなくてもよくなる。
ただし、こうなるとAPサーバの管理コンソールに頼れなくなり、管理を全て自前で行う必要がある。


7.まとめ
Sun Java System Application Serverは無償ながら、
多言語にも対応しており、リソースの設定が楽。だけど・・・

JNDIプロバイダ(大抵はAPサーバ)ごとに、以下の情報が異なる。
  • イニシャルコンテキストのファクトリークラス
  • プロバイダーURL
この値を調べるのが大変なので、APサーバには、管理コンソールから、JNDI名とこれらの情報を紐付けてみられるような機能があると嬉しい。
Sun Java System Application Serverにもメニュー項目からそれが見当たらなかったので、また旅に出ます。
とにかくスタンドアロンのJNDIクライアントには厳しい世界です。

0 件のコメント:

参加ユーザー

今月の本

  • 臆病者のための株入門
  • TSPガイドブック:リーダー編
  • 夜明けの街で
  • 詳解Oracleアーキテクチャ
  • Ajax イン・アクション
  • 実践Ajax
  • すごい「実行力」
  • More Effective C++
  • 母子関係の理論
  • コンピュータアーキテクチャのエッセンス