目次


LinuxへのApache+Tomcat+DB2インストール

Comments
技術情報イメージIBMの情報管理テクノロジーを学ぶための100の情報
技術情報の検索はこちらから

1.はじめに

TomcatはThe Jakarta Projectによってリリースされているオープンソースのサーブレット・コンテナーであり、サーブレットとJava Server Pages(JSP)のリファレンス・インプリメンテーションです。無償で提供されるリファレンス・インプリメンテーションということでテスト環境や開発環境では広く利用されています。実際の大規模なシステム構築には、スケーラビリティやパフォーマンスが重要になりますので、商用のアプリケーション・サーバーであるWebSphere Application Server(WAS)などをお使いいただくことも多いかと思いますが、Tomcatも日々改良が重ねられており、現在では比較的小さな規模のシステムなどでは実環境として採用されるケースも増えています。 今回はこのTomcatとDB2 Universal DatabaseV8.1、さらにWebサーバーにApacheを使い、より実践的な環境の構築を解説していきます。

DB2 V8.1が現在お手元にないという方は、以下のサイトから90日評価版が無料でダウンロードできますので、こちらをご活用ください。

http://www.ibm.com/jp/software/data/download/

今回使用するソフトウェアは、すべてWebからダウンロードが可能ですので、どなたでもお試しいただけます。ぜひこの機会に実際に触れてみてください。各ソフトウェアのダウンロードに関しては、Chapter2「構成」の表にあります備考/情報源欄に記載されたURLをご参照ください。

2.構成

今回使用したソフトウェアは以下の通りです。

 名前、バージョン備考/情報源
OSRedhat 8.0http://www.jp.redhat.com
DB2DB2 Universal Database Enterprise Server Edition Ver. 8.1 for Linux
+ FixPak 1
+ 修正JDBCドライバー
http://www.ibm.com/jp/software/data ※ FixPakと 修正JDBCドライバー については、Chapter4「インストール」のURLを参照してください。
JDKIBM JDK 1.3.1 SR3N/A
TomcatTomcat Ver. 4.1.18http://jakarta.apache.org/tomcat/
ApacheApache Ver. 2.0.44http://httpd.apache.org
modulemod_jk2 for Tomcat Ver. 4.1.18N/A

使用したハードウェアは以下の通りです。(一台のみ)

CPU Intel Celeron 400 MHz
RAM 192 MByte
HDD IDE 8GByte

3.ApacheとTomcatの連携方法

ApacheとTomcatを連携させて動作させる場合、二つをつなぐコネクタが必要になります。このコネクタにはいくつか種類があるのですが、主なものを下表にまとめました。今回はApache2.0.44を使用するので、Apache2.0.x対応のmod_jk2を使用します。

Apache/Tomcat連携の主なコネクタ(2003/02/14時点)
名前Apacheの対応Ver.Tomcatの対応Ver.Protocol備考
mod_jk主に1.3.x3.2.x/3.3.x/4.0.x/4.1.x/5.xajp1.3
mod_jk2主に2.0.x3.2.x/3.3.x/4.0.x/4.1.x/5.xajp1.3/1.4
mod_webapp1.3.x 2.x 対応予定4.x系のみ対応WARPWindowsはサポート 対象外

4.インストール

Linux、DB2、Apache、Tomcat、mod_jk2の順番でそれぞれのインストール方法、その他設定などについてご説明します。

4.1 Linux(RedHat 8.0)のインストール

今回はDB2とTomcat+Apacheの連携がメインなので、RedHat 8.0のインストールについては、必要なオプション設定のみの言及とさせていただきます。

  1. インストールは「カスタム」インストールにしてください。
  2. 「パッケージグループの選択」の「開発」カテゴリで「開発ツール」を選択してください。この中には、Apacheのコンパイル時に必要になるgcc(GNU Cコンパイラ)等が含まれています。
  3. 「パッケージグループの選択」の「サーバー」カテゴリで「Webサーバー」は選択しないでください。今回使用する環境と異なるApacheが導入されてしまいます。もし入れてしまった、またはすでに導入されているという場合は、今回のApache(Ver.2.0.44)を導入する前に、必ず既存のApacheを削除しておいてください。

4.2 DB2 UDB ESE V8.1 for Linux + FP 1のインストール

DB2のインストールは、別ドキュメントにて詳細が説明されていますので、そちらを参照の上インストールを行ってください。その際、こちらの環境に合わせるための要件のみご説明します。

  1. ユーザー/パスワード
    以下の表に従って設定を行ってください。
     名前パスワードグループ名ホームディレクトリーポート番号
    インスタンスdb2inst1instpassdb2grp1/home/db2inst150000
    隔離ユーザーdb2fenc1fencpassdb2fgrp1/home/db2fenc1?
    管理ユーザーdasusr1dasupassdb2adm1/home/dasusr1?
  2. 必要なオプション
    後述するSampleDB作成のために、「インストールする機能の選択」で「入門」の選択をはずさないようにしてください。オプション(機能)を任意で選択するには、「インストール・タイプの選択」で「カスタム」を選択し、「インストールする機能の選択」で任意のオプションを選択します。
  3. CDROMやダウンロードしたアーカイブに含まれるinstall.txt(doc/ja_JPの下にあります。)、マニュアルの「サーバー機能 概説およびインストール」、下記URL等を参照の上、DB2 UDBのインストールを行ってください。

    マニュアル"サーバー機能 概説およびインストール"
          PDF版(2.61MB)

    "DB2 UDB for Linuxクイックインストール PDF版"(DB2 UDB V7.2) (420KB)
  4. FixPak1
    下記URLから、DB2 UDB ESE V8.1 for LinuxのFixPak1を入手し、中に含まれているFixpakReadme.jp等をご参照の上、FixPak1を導入してください。
    http://www-01.ibm.com/support/docview.wss?rs=71&uid=swg21256235

    ※ FixpakReadme.jpが文字化けする場合、以下のように文字コードを変換してご覧ください。
       nkf FixpakReadme.jp|less
  5. 修正JDBCドライバー
    DB2 V8.1 FixPak1には、適切でないバージョンのJDBCが含まれていますので、JDBCドライバーをアップデートする必要があります。FixPak2以降で修正済です。
  6. SampleDBの作成
    後述する動作確認の際にSampleDBを必要としますので、下記のDB2コマンドを実行してSampleDBの作成を行ってください。

       $ db2sampl

    ※ DB2インスタンスが起動していない場合は、db2startコマンドを実行して、DB2インスタンスを起動させてからSampleDBの作成を行ってください。
  7. JDKのアップデート
    上記インストール手順で導入されるIBM JDK 1.3.1は、より新しいバージョンのIBM JDKがリリースされておりますので、こちらをダウンロードしてバージョンアップすることをお勧めします。このドキュメントでは、以降、IBM JDK 1.3.1 SR3を導入したとして設定等を行いますので、ご注意ください。

    以下のURLからアクセスして無償でダウンロードできます(要ユーザー登録)。rpmファイルとバイナリファイルの二種類がありますが、アップデートの保守が簡単に行えるrpmファイルをお勧めします。

    https://www6.software.ibm.com/dl/lxdk/lxdk-p (N/A)

    rpmコマンドの -Uオプションで簡単にアップデートできます。

       $ su‐
       # rpm -Uvh IBMJava2-SDK-1.3.1-3.0.i386.rpm

    ※ IBM JDK 1.4.0もリリースされていますが、DB2 UDB V8.1 for Linuxでは未サポートですので、1.3.1 SR3が最新版となります。(2003/02/14時点)

4.3 Apacheのインストール

Apacheのインストールを行います。
今回はConfigureを行う際にオプション設定を行う必要があるので、バイナリーファイルではなく、ソースファイルを用意してください。Apacheのオフィシャルサイトからダウンロードできます。ここではソースファイルが入手できた前提でご説明いたします。

※ もしすでに別のApacheがインストールされている場合は、そちらを一度削除してから作業を行ってください。

まずrootでログインして、ソースファイルの置いてあるディレクトリに移動します。

$ su‐
# ls
httpd-2.0.44.tar.gz

※ Apache1.3.x系まではソースファイルがapache-1.3.xx.tar.gzというファイル名となっていますが、Apache2.0.x系からはhttpd-2.0.xx.tar.gzというファイル名になっています。今回使用するのはApache2.0.44なので、httpd-2.0.44.tar.gzになります。

Apacheのソースファイルを/usr/local/srcに展開して、コンパイル、インストールを行います。

# tar zxvf httpd-2.0.44.tar.gz -C /usr/local/src
# cd /usr/local/src/httpd-2.0.44
# ./configure --prefix=/usr/local/apache2 --enable-module=so

--prefix=/usr/local/apache2:/usr/local/apache2にApacheをインストールする。
--enable-module=so:DSO(Dynamic Shared Object)を有効にするために、 SOモジュールを組み込む。 ※後述のコネクタを利用するために必要。

# make
# make install

Apacheの設定ファイルを編集し、ServerNameにホスト名とポート番号を書きます(デフォルトでは291行目です)。

# cp -p /usr/local/apache2/conf/httpd.conf /usr/local/apache2/conf/httpd.conf.org
# vi /usr/local/apache2/conf/httpd.conf

#ServerName new.host.name:80 
ServerName <host名>:80

これでApacheのインストールは完了です。Apacheを起動させて、正しくインストールできたか確認しておきましょう。 次のコマンドでApacheを起動させます。

# /usr/local/apache2/bin/apachectl start

次のURLでApacheの画面が表示されれば成功です。
http://<host名>/

 
次のURLでApacheの画面が表示されれば成功です。   http://<host名>/
次のURLでApacheの画面が表示されれば成功です。 http://<host名>/

Apache単体での動作確認が完了したら、Apacheを終了させておきます。

# /usr/local/apache2/bin/apachectl stop

4.4 Tomcatのインストール

Tomcatのインストールを行います。TomcatではApacheのように、コンフィギュア時のオプション設定を行いませんので、ソースファイルではなくバイナリーファイルを用意します。
ユーザーはやはりrootで、ファイルを/usr/local/に展開します。

# tar zxvf jakarta-tomcat-4.1.18.tar.gz -C /usr/local/

これでTomcatのインストールは完了です。
ただし起動する前にいくつか設定をする必要があります。
まずTomcatのファイル権限をすべて、rootからTomcat実行ユーザーに変更します。ここではDB2インスタンスのオーナー(db2inst1:db2grp1)をTomcat実行ユーザーとします。これは後述のJDBC Type2 Driverを使用する際に、Tomcatを起動するユーザーが、データベースへ接続するユーザーである必要があるためです(セキュリティ等の観点から通常rootユーザーがDBに接続できるような設定は行いません)。

# cd /usr/local
# chown -R db2inst1:db2grp1 jakarta-tomcat-4.1.18

ユーザーをTomcat実行ユーザー(db2inst1)に変更し、Tomcatの起動で使用する二つの環境変数の設定を.bashrcに記述しておきます。二つの環境変数とは、Tomcatの起動シェルスクリプトに使用されるJavaのホームディレクトリを規定しておくJAVA_HOME環境変数と、Tomcatのホームディレクトリを規定しておくCATALINA_HOME環境変数のことです(CATALINAというのは、Tomcat4.0のコードネームです)。

# ln -s jakarta-tomcat-4.1.18 tomcat
# su - db2inst1
$ vi $HOME/.bashrc

export JAVA_HOME=/opt/IBMJava2-131
export CATALINA_HOME=/usr/local/tomcat
※ここではIBM JDKを指定します。Linuxプラットフォーム上のDB2 V8.1では、その他(IBM以外のSun等)のJDKは未サポートとなっています。 DB2 V8.1の各OSにおけるJDKサポートバージョン対応表:
http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/start/r0011932.htm

環境変数の設定を反映させるために、db2inst1で再ログインします。

$ exit
# su - db2inst1

これで設定が整いましたので、Tomcat単体の動作確認を行いましょう。  Tomcatのホームディレクトリに移動し、Tomcatを起動させます。

$ cd $CATALINA_HOME
$ bin/startup.sh

マシンのスペックにもよりますが、Tomcatの起動には少し時間がかかります(テスト機で1分程)。しかしstartup.shは非同期のコマンドですので、起動中であっても、何らかのエラーで起動に失敗していたとしても、プロンプトは戻ってきてしまいます。ですので起動の確認をするために、新しい端末エミュレータでログファイルの確認をすることをお勧めします。

ログファイルの確認は以下のコマンド等で行うことができます。

$ tail -f logs/catalina.out

下記のようなログが出力されていれば、起動が完了しています。

 
[INFO] Registry - -Loading registry information
[INFO] Registry - -Creating new Registry instance
[INFO] Registry - -Creating MBeanServer
[INFO] Http11Protocol - -Initializing Coyote HTTP/1.1 on port 8080
サービス Tomcat-Standalone を起動します
Apache Tomcat/4.1.18
[INFO] Http11Protocol - -Starting Coyote HTTP/1.1 on port 8080
[INFO] ChannelSocket - -JK2: ajp13 listening on 0.0.0.0/0.0.0.0:8009
[INFO] JkMain - -Jk running ID=0 time=13/47  config=/usr/local/jakarta-tomcat-4.1.18
/conf/jk2.properties

Tomcatの起動が確認できたら、ポート番号8080を指定した次のURLで、Tomcatに接続してみましょう。

http://<host名> :8080/

次の画面が表示されれば成功です。

 
成功。
成功。

Tomcat単体での動作確認が完了したら、Tomcatを終了させておきます。

$ bin/shutdown.sh

4.5 mod_jk2のインストール

この時点ではTomcatは単体で動作しています。ApacheへのリクエストをTomcatにディスパッチするためにApacheとTomcatを連携させるためのコネクタ(mod_jk2)をインストールします。 mod_jk2はApacheと同様コンパイルの際にオプション設定をする必要があるので、バイナリーファイルではなく、ソースファイルを用意します。
ユーザーrootで、ソースファイルのあるディレクトリに移動し、/usr/local/src/にそれを展開します。

$ su -
# tar zxvf jakarta-tomcat-connectors-4.1.18-src.tar.gz -C /usr/local/src

次にconfigureファイルを生成します。ファイルを生成するためのbuildconf.shスクリプトには、デフォルトでは実行権限が与えられていないので、実行権限を与えてから実行します。

# cd /usr/local/src/jakarta-tomcat-connectors-4.1.18-src/jk/native2
# chmod u+x buildconf.sh
# ./buildconf.sh

コンフィギュアをするときにJAVA_HOMEの値が必要になりますが、さきほど実行ユーザーで設定したJAVA_HOME環境変数はrootユーザーには有効ではありませんので、環境変数を設定してから、生成されたconfigureファイルを実行します。

# export JAVA_HOME=/opt/IBMJava2-131
# ./configure --with-PACKAGE=yes \
--with-apxs2=/usr/local/apache2/bin/apxs \
--with-tomcat41=/usr/local/jakarta-tomcat-4.1.18

※withオプションで指定するディレクトリはバージョンごとに異なりますので、自分の環境に合わせて適切な値を入力してください。

コンパイルします。

# make

コンパイルが完了すると、/usr/local/src/jakarta-tomcat-connectors-4.1.18-src/jk/build /jk2/apache2/の下にmod_jk2.soというモジュールができるので、それをApacheが使える場所にコピーします。

# cd ..
# cp build/jk2/apache2/mod_jk2.so /usr/local/apache2/modules/

コネクタの設定ファイルをデフォルトのまま、Apacheの下にコピーします。

# cp conf/workers2.properties /usr/local/apache2/conf/

続いてApacheにモジュールをLoadするために、httpd.confを修正します。デフォルトでは230行目あたりに、

LoadModule jk2_module modules/mod_jk2.so

という一行を追加します。

# vi /usr/local/apache2/conf/httpd.conf

 
	# Example:
# LoadModule foo_module modules/mod_foo.so
#
LoadModule jk2_module modules/mod_jk2.so
#

Apache側の設定が完了したら、つづいてTomcatの設定を確認します。 Tomcatの設定はrootではなく、Tomcat実行ユーザーで行います。

# su - db2inst1

Tomcatの設定ファイルである$CATALINA_HOME/conf/server.xmlで、jk2コネクタが有効になっていることを確認します。ファイルを開き以下の行を見つけ出して、コメントアウトされていなければコネクタは有効になっています。デフォルトでは112?118行目にあります。

$view $CATALINA_HOME/conf/server.xml

 
<!-- Define a Coyote/JK2 AJP 1.3 Connector on port 8009 -->
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
port="8009" minProcessors="5" maxProcessors="75"
enableLookups="true" redirectPort="8443"
acceptCount="10" debug="0" connectionTimeout="0"
useURIValidationHack="false"
protocolHandlerClassName="org.apache.jk.server.JkCoyoteHandler"/>

次に、この中のポート番号(8009)とApacheの下にコピーしたworkers2.propertiesファイルに記述されているポート番号が一致していることを確認します。デフォルトでは42?45行目にあります。

$ view /usr/local/apache2/conf/workers2.properties

 
[channel.socket:localhost:8009]
info=Ajp13 forwarding over socketdebug=0
tomcatId=localhost:8009

これでApacheとTomcatの連携モジュールのインストールが完了しました。  それでは、Sampleプログラムを実行して起動テストをしてみましょう。  Tomacat → Apacheの順に起動させます。

$ $CATALINA_HOME/bin/startup.sh
$ su -     ※Apacheはrootユーザーで起動。
# /usr/local/apache2/bin/apachectl start

次のURLで画面が表示されれば成功です。

http://<host名>/examples/servlets/index.html http://<host名>/examples/jsp/index.html

リンクが張られているJSPやServletのサンプルも動作するか試してみましょう。

 
画面イメージ
画面イメージ

動作確認ができたら、一旦ApacheとTomcatを停止します。このとき、Apacheの停止はrootで、Tomcatの停止はTomcat実行ユーザーで行います。

# /usr/local/apache2/bin/apachectl stop
# su - db2inst1
$ $CATALINA_HOME/bin/shutdown.sh

※デフォルトでは$CATALINA_HOME/webapps/examplesディレクトリの下のファイルしかブラウザから表示できません。修正方法は後述します。

5 Apache+Tomcat+DB2の起動テスト

Apache+TomcatからDB2への接続テストを行います。
Chapter4でのインストールおよび設定がすべて完了していることを確認してください。

5.1 アプリケーションの設定

TomcatでWebアプリケーションを実行するためには、Servlet APIの仕様で定義されたStandard Directory Layoutに従ってディレクトリーを作成しておく必要があります。

ここではアプリケーションの名前を"db2"とします。 Standard Directory Layoutとして定義されているデフォルトのディレクトリー構造になるように、以下のようにディレクトリーを作成します。

$ cd $CATALINA_HOME/webapps
$ mkdir db2
$ mkdir db2/WEB-INF
$ mkdir db2/WEB-INF/lib
$ mkdir db2/WEB-INF/classes

JavaのプログラムはStandard Directory Layoutに従って、このclassesディレクトリーの下に置きます。

次にTomcatの設定ファイルである$CATALINA_HOME/conf/server.xmlを修正し、db2コンテキストを追加します。 server.xmlの<Host>?</Host>の間に以下の文を追加してください(デフォルトで380行目)。

$ vi $CATALINA_HOME/conf/server.xml

 
<Context path="/db2" docBase="db2" debug="0" reloadable="true" >
</Context>

次に先ほど作成したdb2/WEB-INFの下に、Contextの設定ファイルとなるweb.xmlファイルを、以下の内容で作成し、サーブレットマッピングを有効にします。

$ vi $CATALINA_HOME/webapps/db2/WEB-INF/web.xml

 
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<servlet-mapping>
<servlet-name>invoker</servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>

</web-app>
※server.xmlはTomcat全体の設定ファイルです。server.xmlで設定したものは、どのアプリケーションにも有効となります。web.xmlは、各アプリケーションごとの設定ファイルです。

続いてコネクタの設定ファイルであるworkers2.propertiesの修正を行います。これを修正することで、Apacheが受けとったURLをTomcat内のContextと結びつけることができます。デフォルトではexamples(Context)しか有効でないので、db2(Context)をここに追加します。追加を行わずにリクエストをした場合ApacheはFileNotFoundエラーを返します。

以下の記述をworkers2.propertiesの最下行に書き加えてください。これはApacheの設定になりますので、rootユーザーで行います。

$ su -
# vi /usr/local/apache2/conf/workers2.properties

 
[uri:/db2/*]
info=Map the whole webapp

TomcatのWebアプリケーションでJDBCドライバーを使用するには、Tomcatのライブラリの中にJDBCドライバーをインストールしておく必要があります。ライブラリにインストールしておかないと、WebアプリケーションはJDBCドライバーを見つけることができません。インストール方法は、Tomcat専用のクラスライブラリ($CATALINA_HOME/common/lib/)に、JDBCドライバーのパッケージをコピーするだけで完了です。

5.2 Type2ドライバーのインストール

※ Tomcatのライブラリには、どのContextからも利用できる共有ライブラリ($CATALINA_HOME/common/lib/)と、Contextごとに設置する(Context名/WEB-INF/lib/)の二つがあります。JDBCドライバーは一般的に共有ライブラリに置きます。

JDBCドライバーが含まれているパッケージ(db2java.zip)を、ライブラリーにインストールします。ただし、TomcatではJARファイルしかライブラリーとして利用できないため、パッケージファイルの拡張子を.jarに変更する必要があります。JARファイルはZIPフォーマットに準拠しているので、拡張子を変更するだけで問題ありません。

# su - db2inst1
$ cp -p /opt/IBM/db2/V8.1/java/db2java.zip $CATALINA_HOME/common/lib/db2java.jar

※拡張子の変更を忘れないこと。ZIPファイルでは、ライブラリとして利用できません。

5.3 Java Servletの準備

JDBCドライバーの実行環境が整ったら、次にソースファイルを準備します。以下は、DB2 Type2ドライバーを使用してDB2のSample DBにあるstaff表から全データ行を取得し、それをブラウザーに表示するというJava Servletプログラムです。このソースファイルを適当な場所に保存します。

$ vi SampleDB2Srv.java

 
import java.io.IOException;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;
import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SampleDB2Srv extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
ServletOutputStream out = response.getOutputStream();
Connection conn = null;
Statement stmt = null;
ResultSet rset = null;

try{
// DB2 JDBCドライバー(Type2)の取得
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");
// Sample DBへ接続
String url = "jdbc:db2:sample";
conn= DriverManager.getConnection(url, "db2inst1", "instpass");
// ステートメントの生成
stmt = conn.createStatement();
// SQL文の実行
rset = stmt.executeQuery("SELECT id,name FROM staff");

// データを受け取る変数
int colId = 0;
String colName = null;

while(rset.next()){
colId = rset.getInt("id");
colName = rset.getString("name");
out.println(colId + " " + colName);
}

}
catch(ClassNotFoundException e){
out.println(e.getMessage());
e.printStackTrace();    }
catch(SQLException e){
out.println(e.getMessage());
e.printStackTrace();
}

finally{
// リソースの開放
if(rset != null){try{rset.close();}catch(SQLException e){}}
rset = null;
if(stmt != null){try{stmt.close();}catch(SQLException e){}}
stmt = null;
if(conn != null){try{conn.close();}catch(SQLException e){}}
conn = null;
}
out.close();
out = null;
}

}

ソースファイルが用意できたら、javacコマンドが使用できるようにPATHを通します。

$ export PATH=/opt/IBMJava2-131/bin:$PATH

PATHを通したら、IBM JDKがきちんと使われているか確認してください。

$ java -version

 
java version "1.3.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1)
Classic VM (build 1.3.1, J2RE 1.3.1 IBM build cxia32131-20021102 (JIT enabled: jitc))

次にコンパイルに必要なパッケージに、CLASSPATHを通します。 DB2をインストールした時点で、JDBCドライバーへのCLASSPATHは自動的に通されているので、ここではServletパッケージにだけCLASSPATHを通せば完了です。

$ export CLASSPATH=$CATALINA_HOME/common/lib/servlet.jar:$CLASSPATH

※PATHやCLASSPATHの設定も.bashrcに記述しておくと、ログインするたびに入力する必要がなくなるので便利です。

ソースファイルをコンパイルします。

$ javac SampleDB2Srv.java

生成された実行ファイルをTomcatが利用できる場所にコピーします。

$ cp SampleDB2Srv.class $CATALINA_HOME/webapps/db2/WEB-INF/classes

5.4 実行テスト
準備が整ったので、DB2インスタンス開始してTomcat+Apacheの実行テストを行います。
Tomcat → Apacheの順番で起動させます。

$ db2start
$ $CATALINA_HOME/bin/startup.sh
$ su -  ※Apacheはrootユーザーで起動。
# /usr/local/apache2/bin/apachectl start

Webブラウザから次のURLでSampleDB2Srv.classを呼び出します。

http://<host名>/db2/servlet/SampleDB2Srv

Sample DBからデータを読み出してきた結果が、以下のように画面に表示されれば成功です。

Sample DBからデータを読み出してきた結果が、以下のように画面に表示されれば成功です。
Sample DBからデータを読み出してきた結果が、以下のように画面に表示されれば成功です。
Sample DBからデータを読み出してきた結果が、以下のように画面に表示されれば成功です。

上のサンプルプログラムではJDBCドライバーにType2を使用していますが、DB2 V8.1ではType4もサポートされています。Type4を使用する場合は、SampleDB2Srv.javaの20%7E24行目を以下のように修正してください。

 
// DB2 JDBCドライバー(Type4)の取得
// Class.forName("COM.ibm.db2.jdbc.app.DB2Driver"); // Type2
Class.forName("com.ibm.db2.jcc.DB2Driver"); // Type4
// サンプルDBへ接続
// String url = "jdbc:db2:sample"; // Type2
String url = " jdbc:db2://localhost:50000/sample"; // Type4
conn= DriverManager.getConnection(url, "db2inst1", "instpass");

また、Type4ドライバーが含まれるパッケージdb2jcc.jarをTomcatから利用できる場所にコピーしておきます。

$ cp -p /opt/IBM/db2/V8.1/java/db2jcc.jar $CATALINA_HOME/common/lib/

これでType4ドライバーの利用も可能になります。

※ Javaアプレットに使用されてきたType3ドライバーは、V8.1でもサポートされていますが、将来的にサポートされない予定ですので、JavaアプレットにはType4ドライバーを使用するようにしてください。

なおDB2 のJDBCドライバーはJDBC2.1コアAPIをサポートしますが、仕様で定義されているすべての機能をサポートするわけではないのでご注意ください。
詳しくは以下のマニュアルを参考にしてください。

6.コネクション・プーリング

データベースの接続は負荷と時間がかかる処理です。特にWebシステムの場合、リクエストごとに接続が必要になりますので、この負荷は無視できないものとなります。コネクション・プーリングとは、その名の通りデータベースとのコネクション(接続)をアプリケーションサーバーでプールして、リクエストの際には以前のコネクションを再利用するというものです。商用WebアプリケーションサーバーであるWebSphere Application Serverなどでは以前より実装されている機能で、毎回新たな接続を確立する従来のコネクションの取り方に比べ、効率の良いリソースの利用が可能となります。
Tomcatでもこのコネクション・プーリング機能をサポートしておりますので、ここでそのコネクション・プーリング機能の利用方法についてご紹介しておきます。

Tocmatは、JNDIのサーバーになることができ、そこにJNDIリソースとしてDataSourceオブジェクトを登録することができます。デフォルトではJakatra CommonsのDBCPコンポーネントがリソース・ファクトリーとなり、アプリケーションからのDataSourceの要求にこたえます。アプリケーションはこのDataSourceのgetConnectionメソッドを実行することでデータベースへの接続を得ることができます。実際にはリソース・ファクトリーのDBCPがデータベースへの接続、その接続のプールを行っています。

それでは実際にDB2 JDBC Type2ドライバを使ってこれらの機能を実装する手順をご説明していきましょう。
まずJNDIのリソースとしてDataSourceオブジェクトを定義します。servlet.xmlに記述してあるdb2コンテキストの中にResource名/jdbc/db2として、以下のように記述します。FactoryのDBCP、JDBCドライバのクラス名、接続文字列などを定義します。

$ vi $CATALINA_HOME/conf/server.xml

<Context path="/db2" docBase="db2" debug="0" reloadable="true" >
↓ここから追加
<Resource name="jdbc/db2" auth="Container" type="javax.sql.DataSource"/> 
<ResourceParams name="jdbc/db2">
  <parameter>
    <name>factory</name>
    <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
  </parameter>
  <parameter>
    <name>driverClassName</name>
    <value>COM.ibm.db2.jdbc.app.DB2Driver</value>
  </parameter>
  <parameter>
    <name>url</name>
    <value>jdbc:db2:sample</value>
  </parameter>
  <parameter>
    <name>username</name>
    <value>db2inst1</value>
  </parameter>
  <parameter>
    <name>password</name>
    <value>instpass</value>
  </parameter>
  <parameter>
    <name>maxActive</name>
    <value>20</value>
  </parameter>
  <parameter>
    <name>maxIdle</name>
    <value>10lt;/value>
  </parameter>
  <parameter>
    <name>maxWaitlt;/name>
    <value>-1lt;/value>
  </parameter>
</ResourceParams>
↑ここまで
</Context>
※Type4ドライバを使用する場合はdriverClassNameとurlが以下のように変わります。
<parameter>
    <name>driverClassName</name>
    <value>com.ibm.db2.jcc.DB2Driver</value>
  </parameter>
  <parameter>
    <name>url</name>
    <value>jdbc:db2://localhost:50000/sample</value>
  </parameter>

次に、アプリケーションからオブジェクトを呼び出せるように、"/jdbc/db2"というリソースが存在することを宣言しておく必要があります。

web.xmlの<web-app >%7E </web-app >の間に以下の記述を加えてください。

# vi $CATALINA_HOME/webapps/db2/WEB-INF/web.xml

<resource-ref>
 <res-ref-name>jdbc/db2</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

server.xmlとweb.xmlの設定が終わったら、TomcatとApacheを一旦停止して再起動しておいてください。

プログラムの実行には、コネクション・プーリングのクラスが含まれるDBCPパッケージ(dbcp.jar)、DataSourceを利用するための名前解決のクラスが含まれるJNDIパッケージ(jndi.jar)、JDBC2.0の拡張パッケージ(jdbc2_0-stdext.jar)が必要になります。  
これらのパッケージは、標準のJDK1.3.1には含まれませんが、Tomcat専用の共有ライブラリ($CATALINA_HOME/common/lib/)にあらかじめ用意されているので特に追加する必要はありません。
確認だけ行っておきましょう。

$ ls $CATALINA_HOME/common/lib/

activation.jardb2java.jarjndi.jar
ant.jardb2jcc.jarmail.jar
commons-collections.jarjta.jarnaming-common.jar
commons-dbcp.jarjasper-compiler.jarnaming-factory.jar
commons-logging-api.jarjasper-runtime.jarnaming-resources.jar
commons-pool.jarjdbc2_0-stdext.jarservlet.jar

プログラムコンパイル時に必要となるライブラリに、CLASSPATHを通します。すでにCLASSPATHを通してあるservlet.var(通っていない方は通してください)に加えて、JNDIパッケージ(jndi.jar)と、JDBC2.0の拡張パッケージ(jdbc2_0-stdext.jar)へのパスをCLASSPATHに追加します。

$ export CLASSPATH=$CATALINA_HOME/common/lib/jndi.jar:$CLASSPATH
$ export CLASSPATH=$CATALINA_HOME/common/lib/jdbc2_0-stdext.jar:$CLASSPATH

以下のソースがコネクションプーリングを利用するServletプログラムになります。initContextのlookupメソッドを実行して取得したDataSourceオブジェクトからデータベース接続を得ています。ファイル名をDataSrcSrv.javaとして以下の内容を保存してください。

$ vi DataSrcSrv.java

import java.io.IOException;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;
import javax.sql.DataSource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DataSrcSrv extends HttpServlet{
  public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException{
    ServletOutputStream out = response.getOutputStream();
    Connection conn = null;
    Statement stmt = null;
    ResultSet rset = null;
    
    try{
      // Contextの初期化
      Context initContext = new InitialContext();
      // DataSourceの取得
      Context envContext = (Context)initContext.lookup("java:/comp/env");
      DataSource ds = (DataSource)envContext.lookup("jdbc/db2");
      // サンプルDBへ接続(PoolからConnectionの取得)
      conn= ds.getConnection();
      // ステートメントの生成
      stmt = conn.createStatement();
      // SQL文の実行
      rset = stmt.executeQuery("SELECT id,name FROM staff");
      
      // データを受け取る変数
      int colId = 0;
      String colName = null;
      
      while(rset.next()){
        colId = rset.getInt("id");
        colName = rset.getString("name");
        out.println(colId + " " + colName);
      }
    }
    catch(NamingException e){
      out.println(e.getMessage());
      e.printStackTrace();
    }
    catch(SQLException e){
      out.println(e.getMessage());
      e.printStackTrace();
    }
    finally{
      // リソースの開放
      if(rset != null){try{rset.close();}catch(SQLException e){}}
      rset = null;
      if(stmt != null){try{stmt.close();}catch(SQLException e){}}
      stmt = null;
      // ConnectionをPoolに戻す
      if(conn != null){try{conn.close();}catch(SQLException e){}}
      conn = null;
    }
    out.close();
    out = null;
  }
}
※PoolからConnectionを取得したときは、Close処理をしてもConnectionを閉じることはせず、再利用できるようPoolにConnectionを戻します。

コンパイルします。

$ javac DataSrcSrv.javas

コネクションプーリングの動作を確認してみましょう。まずlist applicationsを実行して、いずれの接続もないことを確認してください。

$ db2 list applications
SQL1611W データベース・システム・モニターからデータが戻されませんでした。
SQLSTATE=00000

次に5章で作成したサンプル・サーブレットを実行してください。

http://<host名>/db2/servlet/SampleDB2Srv

その後list applicationsを実行して接続を確認します。

$ db2 list applications
SQL1611W データベース・システム・モニターからデータが戻されませんでした。
SQLSTATE=00000

やはり何も返されないかと思います。5章でのサンプルでは、コネクション・プーリングが行われませんので、DBからデータを取得して結果を返すとすぐに接続は閉じてしまいます。そのためlist applicationsを実行しても、何もデータは返されないのです。
では以下のようにURLを指定してコネクションプーリング対応を行ったサンプルをWebブラウザから実行してください。5章のサンプルと同じように取得したデータが表示されていれば成功です。

http:// <host名> /db2/servlet/DataSrcSrv

以下のDB2コマンドを使って、コネクションがプーリングされていることを確認しましょう。

$ db2 list aplications

許可 ID   アプリケー     アプリケーション アプリケーション ID          DB名    エージェントの数
          ション名     ・ハンドル 
-------- -------------- ----------    ------------------------------ -------- -----
DB2INST1 java           379           *LOCAL.db2inst1.096DC6020639   SAMPLE   1 

上のようにアプリケーション名や接続DB名、接続ユーザー名などが表示されるはずです。

7.文字コード

Javaのアプリケーションでは文字コードをUNICODEで処理します。DB2のコードページやWebブラウザのエンコードがUNICODEではない場合、なんらかの文字コード変換が発生します。この際にUNICODE⇔他の文字コードの変換に使用されるコンバータが異なると文字化けが発生する可能性があります。
具体的には以下の文字やNEC特殊文字やIBM特殊文字などをはじめとする外字が化ける可能性があります。

\ YEN SIGN(小文字)
%7E OVERLINE(小文字)
? EM DASH
〜 WAVE DASH
‖ DOUBLE VERTICAL LINE
… HORIZONTAL ELLIPSIS
− MINUS SIGN
? CENT SIGN
? POUND SIGN
? NOT SIGN

問題になることが多いのはShift_JISとそのサブセット(Windows-31Jなど)とのUNICODEのコンバータです。これらのコンバータにはSJIS、MS932、Cp943Cなどの複数のコンバータが存在し、これらのコンバータ間で文字コードマッピングが異なるために一部の文字が文字化けを起こします。
DB2ではCp943Cのコンバータを使用すれば上記の文字について文字化けを回避することできます。しかしながらJava2SDK1.3.1でのShift_JIS、Windows-31Jのどちらのエイリアス(つまりデフォルトのコンバータ)もCp943Cではないため、setContentTypeでキャラクタセットを指定するだけでは文字化けが発生します。

response.setContentType("text/plain; charset= Windows-31J ");
PrintWriter out =response.getWriter();

そのため、以下のようにPrintWriterのエンコーダ(コンバータ)をCp943Cに指定することで文字化けを防ぐことができます。

response.setContentType("text/plain; charset= Windows-31J ");
PrintWriter out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(),"Cp943C"));
※なお、このようにPrintWriterをNewで作成した場合、かならずPrintWriterオブジェクトをclose()メソッドで明示的に閉じてください。そうしないとブラウザに書き出す前に処理が終了してしまい、何も表示されないことがあります。

requestのコンバータについてもCp943CをsetCharacterEncodingで指定します。

request.setCharacterEncoding("Cp943C");

また、丸数字丸付き数字1やローマ数字IなどのWindows固有のNEC特殊文字やIBM特殊文字など使用したい場合はDB自体にその文字を格納できる必要があります。その場合DBをShift_JIS のサブセットであるcodeset IBM-943で作成してください(LinuxでのCREATE DBのデフォルトcodesetはIBM-eucJPになります)。

create database IBM943 using codeset IBM-943 territory JP collate using IDENTITY

実際にデータを入れて確認してみましょう。なおWindows外字データの入力をLinuxから行うことはできませんので、WindowsのマシンでLinuxのDBをCATALOGしてそこから入力してください。ここではnihongoというテーブルを作成して文字化けの発生の可能性のある文字をINSERTしています。

 
実際にデータを入れて確認してみましょう
実際にデータを入れて確認してみましょう

このテーブルにSELECT、INSERTを行うサーブレットを作成します。いくつかのコンバーターでSELECTの結果を表示できるようにします。

$ vi SelNihongoSrv.java

import java.sql.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class SelNihongoSrv extends HttpServlet{
  public void doGet(HttpServletRequest request, 
      HttpServletResponse response)
      throws IOException{
    Connection con = null;
    Statement stmt = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    
    //request処理に使うコンバータ
    //request.setCharacterEncoding("JISAutoDetect");これでは文字化けが発生する。
    request.setCharacterEncoding("Cp943");
    
    //response処理に使うコンバータとそのキャラクタセット
    String conv = request.getParameter("conv");
    if (conv == null){conv="Cp943C";}
    String charset = null;
    if (conv.compareTo("ISO2022JP")==0){charset="ISO-2022-JP";}
    else if(conv.compareTo("UTF8")==0){charset="UTF-8";}
    else if(conv.compareTo("EUC_JP")==0){charset="EUC-JP";}
    else if(conv.compareTo("Cp33722")==0){charset="EUC-JP";}
    else if(conv.compareTo("SJIS")==0){charset="Shift_JIS";}
    else{charset="Windows-31J";}
    response.setContentType("text/html; charset="+charset);
    PrintWriter out = null;
    //out =response.getWriter();これでは文字化けが発生する。
    out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), conv));

    String act = request.getParameter("act");
    String dat = request.getParameter("dat");

    try{
      //JDBCドライバのセット
      Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");
      String url = new String("jdbc:db2:IBM943");
      con= DriverManager.getConnection(url, "db2inst1","instpass");

      
      //DBへINSERT
      if (act!=null && act.compareTo("INSERT")==0){
        pstmt = con.prepareStatement("INSERT INTO nihongo(nihongo) VALUES(?)");
        pstmt.setString(1,dat);
        pstmt.executeUpdate();
        pstmt.close();pstmt=null;
      }
      //DBをDEFAULTデータに戻す
      if (act!=null && act.compareTo("DEFAULT")==0){
        pstmt = con.prepareStatement("DELETE FROM nihongo WHERE def IS NULL");
        pstmt.executeUpdate();
        pstmt.close();pstmt=null;
      }
      
      out.println("<HTML>");
      out.println("<TITLE>DBCS</TITLE>");
      out.println("<BODY>");
      out.println("<FORM method=get >");
      out.println("利用したコンバータ"+conv+" ");
      out.println("次回コンバータ<SELECT name=conv>");
      out.println("<OPTION value=Cp943C>Cp943C Windows-31J</OPTION>");
      out.println("<OPTION value=MS932>MS932 Windows-31J</OPTION>");
      out.println("<OPTION value=SJIS>SJIS Shift_JIS</OPTION>");
      out.println("<OPTION value=ISO2022JP>ISO2022JP ISO-2022-JP</OPTION>");
      out.println("<OPTION value=UTF8>UTF8 UTF-8</OPTION>");
      out.println("<OPTION value=EUC_JP>EUC_JP EUC-JP</OPTION>");
      out.println("<OPTION value=Cp33722>Cp33722 EUC-JP</OPTION>");
      out.println("</SELECT><BR>");
      out.println("INSERT文字列<INPUT name=dat type=text size=20><BR>");
      out.println("<INPUT name=act type=submit value=SELECT>");
      out.println("<INPUT name=act type=submit value=INSERT>");
      out.println("<INPUT name=act type=submit value=DEFAULT>");
      out.println("</FORM>");
      out.println("<TABLE BORDER=1>");
      out.println("<TR><TH>col_nihongo</TH><TH>先頭文字キャラクタコード</TH></TR>");
      
      //DBから読み込み
      stmt = con.createStatement();
      rs = stmt.executeQuery("SELECT nihongo FROM nihongo");
      String col_nihongo = new String("");
      while(rs.next()){
        col_nihongo=rs.getString("nihongo");
        out.println("<TR>");
        out.println("<TD>"+col_nihongo+"</TD>");
        out.println("<TD>"+Integer.toString(col_nihongo.charAt(0), 16)+"</TD>");
        out.println("</TR>");
      }
      out.println("</TABLE>");
      out.println("</BODY>");
      out.println("</HTML>");
    }catch(Exception e){
      out.println(e.getMessage());
      e.printStackTrace();
    }finally {
      if (rs != null) { try { rs.close(); } catch (SQLException e) { ; } rs = null;}
      if (stmt != null) { try { stmt.close(); } catch (SQLException e) { ; } stmt = null;}
      if (pstmt != null) { try { pstmt.close(); } catch (SQLException e) { ; } pstmt = null;}
      if (con != null) { try { con.close(); } catch (SQLException e) { ; } con = null;}
      if (out != null) { out.close(); out = null;}//忘れると表示されないことがある。
    }
  }
}

コンパイルして、ブラウザで表示してください。

http://<host名>/db2/servlet/ SelNihongoSrv

 
文字化けなく表示イメージ
文字化けなく表示イメージ

上のように文字化けなく表示されます。
「次回のコンバーター」をMS932 Windows-31JとしてSELECTボタンをクリックすると、

 
文字化けを発生イメージ
文字化けを発生イメージ

上のように文字化けを発生します。コンバータを変更していろいろと試してみてください。コンバータによって化ける文字が異なることがわかります。

次に「次回のコンバータ」をCp943C Windows-31Jとし、INSERT文字列に「\ %7E ?〜‖…−???¦①」といった文字化けの発生する可能性のある文字列を入力して、INSERTボタンをクリックしてください。

 
INSERTボタンをクリックしてください。
INSERTボタンをクリックしてください。

上のように文字化けせずにDBにINSERTできたことがわかります。他にもINSERTをして文字化けが発生しないことを確認してください。なおDEFAULTボタンはブラウザからINSERTした行を消去します。

8.おわりに

Apache+Tomcat+DB2の環境構築についてご説明させていただきました。もし文章の間違い、ご意見等ありましたら、河田(HKWD@jp.ibm.com)までお知らせ下さい。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Information Management
ArticleID=326500
ArticleTitle=LinuxへのApache+Tomcat+DB2インストール
publish-date=03132006