■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2009年02月15日

    Java総合講座 - 初心者から達人へのパスポート
                  vol.140

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


[このメールマガジンは、画面を最大化して見てください。]


========================================================
◆ 01.SOAPのアプリケーション(Webサービス)
========================================================


それでは、DBViewerを使って、データベースHOTELDBにデータを入力しておき
ましょう。


まず、Eclipseを起動して、DBViewerのパースペクティブを開いておいて下さい。
(やり方を忘れた人は、vol.139を参照。)

そして、データベースHOTELDBに接続しておきましょう。
(「DBツリー・ビュー」の中のDBViewerPluginの配下にあるHOTELDBを右クリッ
クし、「接続」を選択します。)


続いて、「DBツリー・ビュー」の中のDBViewerPluginの配下にあるHOTELDBの
配下のTABLEの配下にあるroominfo(これはテーブル名ですね)を
ダブル・クリックしましょう。roominfoテーブルが表示されますね。


では、次のようにして新しいレコードを作ってみましょう。

(1) 表示されているroominfoテーブルの表を右クリックし、「新規レコード」
を選択(もしくはCtrl + Iキーを押す)します。

ROOMNUMカラムには

101

を入力し、タブ(Tab)・キー(または→キー)を押して、CAPACITYカラムには

2

を入力し、タブ・キー(または「→」キー)を押して、RATEカラムには

10000

を入力し、タブ・キー(または「→」キー)を押して、TYPEカラムには

SINGLE

を入力し、タブ・キー(または「→」キー)を押して、WEBカラムには

Y

を入力し、Enterキーを押します。

(2) この行の先頭(左端の1という数字が表示されているところ)をクリックし、
メニュー・バーの「編集」→「コピー」を選択(もしくはCtrl + Cキーを押す)
します。

(3) Ctrl + Vキーを繰り返し(20回)押すことにより、同じコピーした内容を
複数行貼り付けます。

(4) 2行目のROOMNUMカラムをクリックして(F2キーを押すと端にカーソルが入る)
数値を

102

に書き換え、下向きの矢印マーク(↓)のキー(カーソル・キー)を押します。

(5) (4)と同じ操作を繰り返して、それぞれの行のROOMNUMカラムを

103
105
106
107
108
201
202
203
205
206
207
208
301
302
303
305
306
307
308

に書き換えます。

(6) 同様にして、下記のように他のカラムも書き換えましょう。

ROOMNUMが201〜208の行は、RATEが20000でTYPEがDOUBLE
ROOMNUMが301〜308の行は、CAPACITYが3でRATEが30000でTYPEがSUITE

(このとき、入力した文字列を一回Ctrl + Cキーでコピーしてから、下向きの矢印
マーク(↓)のキーを押し、以下、Ctrl + Vキーで貼り付けてから下向きの矢印
マーク(↓)のキーを押すという操作を繰り返すと、楽に書き換え作業ができます。)

それから、ROOMNUMが偶数番号のもの(102,106,108,202など)は、WEBをNに書き換え
ましょう。

以上で、入力されたデータは、全体的には

--------------------------------------------------------
101   2   10000   SINGLE   Y
102   2   10000   SINGLE   N
103   2   10000   SINGLE   Y
105   2   10000   SINGLE   Y
106   2   10000   SINGLE   N
107   2   10000   SINGLE   Y
108   2   10000   SINGLE   N
201   2   20000   DOUBLE   Y
202   2   20000   DOUBLE   N
203   2   20000   DOUBLE   Y
205   2   20000   DOUBLE   Y
206   2   20000   DOUBLE   N
207   2   20000   DOUBLE   Y
208   2   20000   DOUBLE   N
301   3   30000   SUITE    Y
302   3   30000   SUITE    N
303   3   30000   SUITE    Y
305   3   30000   SUITE    Y
306   3   30000   SUITE    N
307   3   30000   SUITE    Y
308   3   30000   SUITE    N
--------------------------------------------------------

という構成になっているはずです。

(7) 最後に「SQL実行・ビュー」にあるコミット・ボタン(円筒形の上に黄色い
曲がった矢印が乗っかっているアイコンのボタン)をクリックすることによって、
COMMITを行っておきましょう。


これで、データベースの用意は完了です。
HOTELDBを切断(「DBツリー・ビュー」の中のHOTELDBを右クリックし、「切断」を選択)
した後、パースペクティブをJavaに戻しておきましょう。



ところで、前回、server.xmlに

--------------------------------------------------------
<Context path="/axis" reloadable="true">
  <Resource name="jdbc/HOTELDB" auth="Container"
    type="javax.sql.DataSource"
    driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://127.0.0.1:3306/HOTELDB"
    username="root"
    password="rootpass"
    maxActive="10"
    maxIdle="30"
    maxWait="10000"
    defaultAutoCommit="false" />
</Context>
--------------------------------------------------------

のような記述を行うことによって、リソース・ファクトリーを設定しました
が、この記述の中にはリソース・ファクトリーのクラス名などは出てきませ
んね。ここらへんがどうなっているのか、ちょっとお話しておきましょう。


実は、Tomcat 6.0はデフォルトとして

org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory

というクラス名のリソース・ファクトリーを使うようになっていま
す(もし明示的に指定したい場合は、factoryという属性でクラス名を
指定することができます)。そして、このデフォルトのファクトリーは

org.apache.tomcat.dbcp.dbcp.BasicDataSource

という(DataSourceを実装した)クラスのインスタンスを生成します。
これらのクラスは、C:\Tomcat6.0\libフォルダーの中のtomcat-dbcp.jar
というJARファイルの中に入っています。

実は、これらは、それぞれCommons DBCPというAPIの

org.apache.commons.dbcp.BasicDataSourceFactory
org.apache.commons.dbcp.BasicDataSource

と同じもの(これらをTomcat専用のパッケージに入れることによって
Tomcatの中に取り込まれた)なので、そのAPIの詳細はCommons DBCPの
リファレンス・マニュアルで調べられます。
(ちなみに、古いTomcatはorg.apache.commons.dbcpのものを使っていた。
このパッケージ変更はTomcat 5.5で行われた。)

というわけで、これらのAPIの詳細を知りたい人は、Commons DBCPのリファレンス・
マニュアル

http://commons.apache.org/dbcp/apidocs/index.html

を参照してください。


ちなみに、上のResourceタグについては

http://tomcat.apache.org/tomcat-6.0-doc/config/context.html

の「Resource Definitions」という項目で説明されていますが、そこにはその属性は、
auth、description(注釈なので省略可能)、name、scope(デフォルトがshareable
(接続は共有可能)なので省略可能)、typeの5つしかありませんね。
では、残りのdriverClassName、url、username、passwordなどの属性はどうなっ
ているかというと、リソース・ファクトリー
org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory

org.apache.tomcat.dbcp.dbcp.BasicDataSource
のインスタンス生成のときに、そのプロパティー(属性)値を設定するのに使ってい
るのです。つまり、残りのdriverClassName、url、username、passwordなどの属性は
org.apache.tomcat.dbcp.dbcp.BasicDataSource
のフィールド(プロパティー)なのです。したがって、これらのフィールドの詳細は、
http://commons.apache.org/dbcp/apidocs/org/apache/commons/dbcp/BasicDataSource.html
を参照してください。


なお、リソース・ファクトリーを自分で作ってみたいという上級者の方は、

http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html

の「Adding Custom Resource Factories」の項目を参照してください。




では、続いてプログラミングのほうに入っていきましょう。


Eclipseで、JStudySOAPプロジェクトのjp.co.flsi.lecture.webservice.hotelパッ
ケージのHotelSoapBindingImpl.javaを編集することにしましょう。

このクラスは現在

--------------------------------------------------------
/**
 * HotelSoapBindingImpl.java
 *
 * このファイルはWSDLから自動生成されました / [en]-(This file was auto-generated from WSDL)
 * Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java生成器によって / [en]-(by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.)
 */

package jp.co.flsi.lecture.webservice.hotel;

public class HotelSoapBindingImpl implements jp.co.flsi.lecture.webservice.hotel.Hotel{
    public jp.co.flsi.lecture.webservice.hotel.RoomInfo[] findRooms(jp.co.flsi.lecture.webservice.hotel.StayInfoInput in0) throws java.rmi.RemoteException {
        return null;
    }

    public boolean reserveRoom(jp.co.flsi.lecture.webservice.hotel.RoomReserveInfo in0) throws java.rmi.RemoteException {
        return false;
    }

}
--------------------------------------------------------

という内容になっていますね。

これを、下記の内容に書き換えて下さい。

--------------------------------------------------------
/**
 * HotelSoapBindingImpl.java
 *
 * このファイルはWSDLから自動生成されました / [en]-(This file was auto-generated from WSDL)
 * Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java生成器によって / [en]-(by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.)
 */

package jp.co.flsi.lecture.webservice.hotel;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Vector;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

public class HotelSoapBindingImpl implements jp.co.flsi.lecture.webservice.hotel.Hotel{
   public jp.co.flsi.lecture.webservice.hotel.RoomInfo[] findRooms(jp.co.flsi.lecture.webservice.hotel.StayInfoInput stayInfo) throws java.rmi.RemoteException {
      Vector<RoomInfo> roomInfoVector = new Vector<RoomInfo>();
      try{
         Context initCtx = new InitialContext();
         if(initCtx == null) throw new Exception("Error: InitialContext could not be generated!");
         DataSource ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/HOTELDB");
         if (ds != null) {
            Connection conn = ds.getConnection();
            if(conn != null)  {
               Statement selectSql = conn.createStatement();
               ResultSet rs = selectSql.executeQuery("SELECT * FROM ROOMINFO");
               while (rs.next()) {
                  RoomInfo roomInfo = new RoomInfo();
                  roomInfo.setRoomNum(rs.getInt("ROOMNUM"));
                  roomInfo.setCapacity(rs.getInt("CAPACITY"));
                  roomInfo.setRatePerNight(rs.getInt("RATE"));
                  roomInfo.setRoomType(rs.getString("TYPE"));
                  if ("Y".equals(rs.getString("WEB"))) {
                     roomInfo.setWebBrowsable(true);
                  }
                  else {
                     roomInfo.setWebBrowsable(false);
                  }
                  roomInfoVector.add(roomInfo);
               }
               selectSql.close();
               conn.close();
            }
         }
      }
      catch(Exception e) {
         e.printStackTrace();
      }
      return roomInfoVector.toArray(new RoomInfo[roomInfoVector.size()]);
   }

   public boolean reserveRoom(jp.co.flsi.lecture.webservice.hotel.RoomReserveInfo roomReserve) throws java.rmi.RemoteException {
      return false;
   }

}
--------------------------------------------------------

なお、これはデータベースのリソース(前回設定したリソース)へのアクセスを検証
するためのソース・コードであり、まだ、簡単なコードしか組んでいません。
アプリケーションとして必要な機能はあとで組み込みます。



(次回に続く)


では、今日はここまでにします。



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      http://www.flsi.co.jp/Java_text/
★このメールマガジンは
     「まぐまぐ(http://www.mag2.com)」
 を利用して発行しています。
★バックナンバーは
      http://www.flsi.co.jp/Java_text/
 にあります。
★このメールマガジンの登録/解除は下記Webページでできます。
      http://www.mag2.com/m/0000193915.html
★このメールマガジンへの質問は下記Webページにて受け付けて
 います。わからない所がありましたら、どしどしと質問をお寄
 せください。
      http://www.flsi.co.jp/Java_text/
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Copyright (C) 2009 Future Lifestyle Inc. 不許無断複製