■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2009年10月25日

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

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


-------------------------------------------------------
・このメールマガジンは、画面を最大化して見てください。
小さな画面で見ていると、不適切な位置で行が切れてしまう
など、問題を起すことがあります。
・このメールマガジンに掲載されているソース・コード及び
文章は特に断らない限り、すべて筆者が著作権を所有してい
ます。また、これらのソース・コードは学習用のためだけに
提供しているものです。
-------------------------------------------------------


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


まず、前回の演習問題の回答例を挙げておきましょう。

----------------------------------
◇ 前回の演習問題の回答例
----------------------------------

これは、いわゆるリファクタリング(refactoring)と呼ばれる作業の一つです。
リファクタリングとは、ソース・コードを修正することにより、プログラムを読み
やすくし、保守(変更)しやすくする作業を意味します(vol.007参照)。
(リファクタリングの詳細は、後ほど特集号を作って詳しくお話しする予定です。)

Eclipseにはリファクタリングを支援する機能が含まれているので、これを使う
と作業が簡単になります。

前回の演習問題では、

--------------------------------------------------------
      HotelService locator = new HotelServiceLocator();

      Hotel hotel = null;
      TravelServiceProperties properties = TravelServiceProperties.getInstance();
      String url = properties.getProperty("WebService.URL");
      try {
         hotel = locator.getHotel(new URL(url));
      } catch (MalformedURLException e) {
         logger.error(e, e);
      }
--------------------------------------------------------

というコードがfindHotels()メソッドとreserveHotel()メソッドで重複しているので
これらを別のメソッドとして切り出せばいいので、まず、これら10行(ここではfindHotels()
メソッドのほうを選びましょう)を選択状態にして下さい。

これから、この選択状態にした10行を別のメソッドとして切り出すのです。
そのためには、メニュー・バーの「リファクタリング」→「メソッドの抽出」を選択し
ます。
「メソッドの抽出」ウインドウが表示されたら、メソッド名には、たとえば

getHotel

と入力し、アクセス修飾子はprivateを選択し、「OK」ボタンをクリックしましょう。
(なお、「OK」ボタンをクリックする前に「プレビュー」ボタンをクリックして、
どのようにソース・コードが変わるのかをプレビュー(前もって確認)してから
「OK」ボタンをクリックするという手順を踏むと、安心して作業できます。)

すると、先ほど選択状態にしていたコードがgetHotel()というメソッドとして
切り出されますね。そして元の位置のコードは、

      Hotel hotel = getHotel();

というように、切り出したメソッドを呼び出すだけのコードに置き換わります。

あとは、reserveHotel()メソッドのほうの先頭10行もfindHotels()メソッドと同様に

      Hotel hotel = getHotel();

に書き換わっていることを確認しましょう。

これでリファクタリングの作業が終わりました。

念のために、このリファクタリング作業後のHotelBeanの全ソース・コードを下に
提示しておきます。

--------------------------------------------------------
package jp.co.flsi.lecture.webapp.bean;

import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;

import org.apache.log4j.Logger;

import jp.co.flsi.lecture.webapp.utility.TravelServiceProperties;
import jp.co.flsi.lecture.webservice.hotel.Hotel;
import jp.co.flsi.lecture.webservice.hotel.HotelService;
import jp.co.flsi.lecture.webservice.hotel.HotelServiceLocator;
import jp.co.flsi.lecture.webservice.hotel.RoomInfo;
import jp.co.flsi.lecture.webservice.hotel.RoomReserveInfo;
import jp.co.flsi.lecture.webservice.hotel.StayInfoInput;

public class HotelBean {

   private static Logger logger = Logger.getLogger(HotelBean.class);

   private RoomInfo[] roomInfos;

   public void setRoomInfos(RoomInfo[] roomInfos) {
      this.roomInfos = roomInfos;
   }

   public RoomInfo[] getRoomInfos() {
      return roomInfos;
   }

   public void findHotels(String startDate, int numOfNights, int numOfLodgers) throws RemoteException, ServiceException {
      Hotel hotel = getHotel();
      StayInfoInput stayInfo = new StayInfoInput();
      stayInfo.setStartDate(startDate);
      stayInfo.setNumOfLodgers(numOfLodgers);
      stayInfo.setNumOfNights(numOfNights);
      stayInfo.setMinRatePerNight(-1);
      stayInfo.setMaxRatePerNight(-1);
      setRoomInfos(hotel.findRooms(stayInfo));
   }

   private Hotel getHotel() throws ServiceException {
      HotelService locator = new HotelServiceLocator();

      Hotel hotel = null;
      TravelServiceProperties properties = TravelServiceProperties.getInstance();
      String url = properties.getProperty("WebService.URL");
      try {
         hotel = locator.getHotel(new URL(url));
      } catch (MalformedURLException e) {
         logger.error(e, e);
      }
      return hotel;
   }

   public boolean reserveHotel(int roomNum, String startDate, int numOfNights, int numOfLodgers,
         String name, String address, String telNo) throws RemoteException, ServiceException {
      Hotel hotel = getHotel();

      RoomReserveInfo roomReserve = new RoomReserveInfo();
      roomReserve.setAddress(address);
      roomReserve.setName(name);
      roomReserve.setNumOfLodgers(numOfLodgers);
      roomReserve.setNumOfNights(numOfNights);
      roomReserve.setRoomNum(roomNum);
      roomReserve.setStartDate(startDate);
      roomReserve.setTelNo(telNo);
      if (hotel.reserveRoom(roomReserve)) {
         return true;
      }
      else {
         return false;
      }
   }
}
--------------------------------------------------------

ただし、これだと、getHotel()メソッドの位置がすっきりしないですね。
publicなfindHotels()メソッドとreserveHotel()メソッドの間にprivateなgetHotel()
メソッドが割り込んでいるのは居心地が悪いですから、getHotel()メソッドを
findHotels()メソッドの上に移動し、下記のようにソース・コードを整理しま
しょう。

--------------------------------------------------------
package jp.co.flsi.lecture.webapp.bean;

import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;

import org.apache.log4j.Logger;

import jp.co.flsi.lecture.webapp.utility.TravelServiceProperties;
import jp.co.flsi.lecture.webservice.hotel.Hotel;
import jp.co.flsi.lecture.webservice.hotel.HotelService;
import jp.co.flsi.lecture.webservice.hotel.HotelServiceLocator;
import jp.co.flsi.lecture.webservice.hotel.RoomInfo;
import jp.co.flsi.lecture.webservice.hotel.RoomReserveInfo;
import jp.co.flsi.lecture.webservice.hotel.StayInfoInput;

public class HotelBean {

   private static Logger logger = Logger.getLogger(HotelBean.class);

   private RoomInfo[] roomInfos;

   public void setRoomInfos(RoomInfo[] roomInfos) {
      this.roomInfos = roomInfos;
   }

   public RoomInfo[] getRoomInfos() {
      return roomInfos;
   }

   private Hotel getHotel() throws ServiceException {
      HotelService locator = new HotelServiceLocator();
      Hotel hotel = null;
      TravelServiceProperties properties = TravelServiceProperties.getInstance();
      String url = properties.getProperty("WebService.URL");
      try {
         hotel = locator.getHotel(new URL(url));
      } catch (MalformedURLException e) {
         logger.error(e, e);
      }
      return hotel;
   }

   public void findHotels(String startDate, int numOfNights, int numOfLodgers) throws RemoteException, ServiceException {
      Hotel hotel = getHotel();
      StayInfoInput stayInfo = new StayInfoInput();
      stayInfo.setStartDate(startDate);
      stayInfo.setNumOfLodgers(numOfLodgers);
      stayInfo.setNumOfNights(numOfNights);
      stayInfo.setMinRatePerNight(-1);
      stayInfo.setMaxRatePerNight(-1);
      setRoomInfos(hotel.findRooms(stayInfo));
   }

   public boolean reserveHotel(int roomNum, String startDate, int numOfNights, int numOfLodgers,
         String name, String address, String telNo) throws RemoteException, ServiceException {
      Hotel hotel = getHotel();
      RoomReserveInfo roomReserve = new RoomReserveInfo();
      roomReserve.setAddress(address);
      roomReserve.setName(name);
      roomReserve.setNumOfLodgers(numOfLodgers);
      roomReserve.setNumOfNights(numOfNights);
      roomReserve.setRoomNum(roomNum);
      roomReserve.setStartDate(startDate);
      roomReserve.setTelNo(telNo);
      if (hotel.reserveRoom(roomReserve)) {
         return true;
      }
      else {
         return false;
      }
   }
}
--------------------------------------------------------

このほうがすっきりしますね。


このように重複したコードを別のメソッドに切り出してもアプリケーションの機能が
変わるわけではなく、ユーザーから見れば何も変わりはないのですが、開発者や保守
をする人から見れば、大きな違いがあります。

一つ(もっとも重要なこと)は、重複した箇所を残していると、そこに保守が必要
になったとき(何らかの理由でその部分に修正が必要になったとき)に修正すべき
箇所が複数あるので、修正し間違いや修正し忘れの原因になる可能性があること
です。また、修正作業の時間も重複している回数分余計にかかることになります。

もう一つは、このようにリファクタリングしたほうが、各メソッドが簡潔になって
読みやすくなることです。

読みやすくするという点では、変数名やメソッド名をできるだけわかりやすくする
ということも重要で、その点、上のgetHotel()というメソッド名やhotelという変数名は
まだまだわかりにくいかも知れません。getHotelWebService()やhotelWebServiceのよう
にしたほうがいいかも知れませんが、これは読者の自由課題としておきましょう。
Eclipseでは、メニューの「リファクタリング」→「名前変更」という機能を使えば
その名前を宣言しているところから参照(呼び出し)をしているところまで、すべて
いっきょに名前を変更することができます。

┌補足─────────────────────────┐
ちなみに昔は、コンピューターの記憶容量がかなり小さかった
せいもあって、名前の文字数がかなり制限されていた時代があっ
たのですが、そういった時代では名前は短く短縮される(たと
えばhotelをhtに短縮するといったように)とか、あるいはもっ
と極端な場合には A123 といった意味不明の番号を割り振った
名前が使われていたことがありました。
こうなると、変数名やメソッド名を見ても意味がよくわからなく
てプログラムを解読するのに随分苦労するのですね。(ごく一部
の天才的な記憶力の持ち主なら別ですが。)

今は(特にJavaは)こういった記憶容量の問題はないし、変数名
やメソッド名の長さはプログラムの処理性能とも関係ないので、
名前は長くてもいいからわかりやすいものにすべきだ、という
考え方に変わっています。
今は、名前の入力もコンテンツ・アシストなどの機能を使って
半自動化して行うから、名前が長いと入力に時間がかかるという
こともないんですね。(ただしPCの性能が悪いとコンテンツ・ア
シストの処理に時間がかかり生産性が落ちる可能性はある。)

短縮した名前を使って読みにくいプログラムにしていると、か
えって開発者の生産性が落ちて、以後の開発や保守にコストが
かかってしまうので、長くてもいいからわかりやすい名前にし
ようというのが現代的な考え方なのですが、いまだに昔からの
わかりにくい名前を伝統的に(?)使い続けている会社もたくさ
ん残っています。
実は、名前を直したくてもそれらを参照(呼び出し)している
所が多すぎて修正するのも大変なんですね(名前が同じでも別
の変数を参照している場合もあるため、単純に名前変更をする
ことはできない)。
その点、Javaの場合はEclipseを使えばこういったリファクタリ
ングも簡単に行えてしまうのです。
└───────────────────────────┘

これで前回の演習問題の回答のお話は終わりにします。



◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆


では、続いて、サーブレット(TravelSearchServlet.java)を下記のように
作成しましょう。

(1) Eclipseのパッケージ・エクスプローラーの中のJStudyRshaSoapClientの中の
WEB-INF/srcを右クリックし、「新規」→「パッケージ」を選択します。

(2) 「名前」に
jp.co.flsi.lecture.webapp.servlet
を入力し、「終了」ボタンをクリックします。

(3) パッケージ・エクスプローラーの中にできた
jp.co.flsi.lecture.webapp.servletを右クリックし、
「新規」→「クラス」を選択します。

(4) 「名前」に
TravelSearchServlet
と入力し、「スーパークラス」に
javax.servlet.http.HttpServlet
と入力し、「終了」ボタンをクリックします。

(5) TravelSearchServletのエディターが開いたら、下記のようなソース・コード
に編集します。

--------------------------------------------------------
package jp.co.flsi.lecture.webapp.servlet;

import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.rpc.ServiceException;

import org.apache.log4j.Logger;

import jp.co.flsi.lecture.webapp.bean.HotelBean;

public class TravelSearchServlet extends HttpServlet {
  
   private static Logger logger = Logger.getLogger(TravelSearchServlet.class);

   public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
      req.setCharacterEncoding("Shift_JIS");
      HttpSession session = req.getSession();

      String departurePlace = req.getParameter("departurePlace");
      String destination = req.getParameter("destination");

      NumberFormat formatter = new DecimalFormat("00");
      String startDD =null;
      String startMM = null;
      String startYYYY = null;
      String startDate = null;
      try {
         startDD = formatter.format(formatter.parse(req.getParameter("startDD")));
         startMM = formatter.format(formatter.parse(req.getParameter("startMM")));
         startYYYY = req.getParameter("startYYYY");
         startDate = startYYYY + startMM + startDD;
      } catch (ParseException e) {
         logger.error(e, e);
      }
      
      int days = Integer.parseInt(req.getParameter("days"));
      String strNumOfTravelers = req.getParameter("numOfTravelers");
      int numOfTravelers = Integer.parseInt(strNumOfTravelers);

      HotelBean hotel = new HotelBean();
      try {
         hotel.findHotels(startDate, days - 1, numOfTravelers);
      } catch (ServiceException e) {
         logger.error(e, e);
      }
      session.setAttribute("STARTYYYY", startYYYY);
      session.setAttribute("STARTMM", startMM);
      session.setAttribute("STARTDD", startDD);
      session.setAttribute("DAYS", Integer.toString(days));
      session.setAttribute("NUMOFLODGER", strNumOfTravelers);
      session.setAttribute("DEPARTUREPLACE", departurePlace);
      session.setAttribute("DESTINATION", destination);
      session.setAttribute("HOTEL",hotel);
      getServletContext().getRequestDispatcher("/travellist.jsp").forward(req,res);
   }

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

ここで出てきたNumberFormatやDecimalFormatは、以前出てきたSimpleDateFormatの
親戚のクラスで、文字通り、数(Number)の表記形式を処理する機能を持つものです。

DecimalFormatのコンストラクターに上記のように"00"を指定してインスタンス生成
したNumberFormatオブジェクトは、数を10進数表示で2桁に整形する能力を持ち、
1桁の数の場合には先頭を0で埋めてくれます。
(たとえば、1は01に、7は07にしてくれる。)

また、NumberFormatのparse()メソッドは、引数に指定した数の文字列をNumber型の
数に変換し、NumberFormatのformat()メソッドは引数に指定したNumber型の数を
整形して文字列に変換してくれます。
したがって、これらを上のソース・コードのように
String startDD = formatter.format(formatter.parse(req.getParameter("startDD")));
String startMM = formatter.format(formatter.parse(req.getParameter("startMM")));
のように組み合わせて使用すると、日や月の数が1桁のときには先頭に0を付けて2桁に
整形してくれるし、日や月の数が2桁のときはそのまま2桁になります。


また、
         hotel.findHotels(startDate, days - 1, numOfTravelers);
というコードでは、宿泊日数を旅行日数より1少ないと考えて、daysから1を引い
ています。単純化したアプリケーションなのでこのようにしていますが、現実の
旅行会社のアプリケーションでは、宿泊日数自体をユーザーに指定してもらうの
が普通のようです。


なお、今回のアプリケーション開発はWebアプリケーションの中からWebサービスを
呼び出す方法を学ぶことが目的であり、Webアプリケーションの細かい枝葉の部分は
端折っております。したがって、細かいエラー処理や標準的でない操作に対する対処
の部分は作っておらず、vol.095で述べたようなdoGet()メソッドは省略しています。
ここら辺の処理もきちんとしておきたい人は、vol.095などを参照して自分でコーディ
ングして下さい。

(Webアプリケーションのプログラミングの細かい話を忘れた人は、vol.072〜vol.102
あたりを復習して下さい。)



◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆


サーブレット(TravelSearchServlet)を作成したので、これをweb.xmlファイル
(vol.072参照)に登録する必要があります。

そのためには、

(1)パッケージ・エクスプローラー内でJStudyRshaSoapClientの中のWEB-INFを
右クリック(WEB-INF/srcではなくWEB-INFを右クリックします。間違えない
ようにしてください)し、「新規」→「ファイル」を選択します。

(2)「ファイル名」に
web.xml
を入力し、「終了」ボタンをクリックします。

(3)web.xmlのエディターが開きますので、次のようにソース・コードを編集
してみてください。

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

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">

    <servlet>
        <servlet-name>TravelSearchServlet</servlet-name>
        <servlet-class>jp.co.flsi.lecture.webapp.servlet.TravelSearchServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>TravelSearchServlet</servlet-name>
        <url-pattern>/servlet/travelsearch</url-pattern>
    </servlet-mapping>
   
</web-app>
--------------------------------------------------------



◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆


では、続いて、JSP(travellist.jsp)の作成を行います。
以下のようにして、travellist.jspという名前のファイルを作成
しましょう。

(1) Eclipseのパッケージ・エクスプローラーの中のJStudyRshaSoapClientを右クリックし、
「新規」→「ファイル」を選択します。

(2) 「名前」に
travellist.jsp
を入力し、「終了」ボタンをクリックします。

(3) travellist.jspのエディターが開いたら、下記のようなソース・コードに
編集します。

--------------------------------------------------------
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="Shift_JIS" %>

<%@page import="jp.co.flsi.lecture.webservice.hotel.RoomInfo"%>
<HTML>
<HEAD>
<TITLE>旅行検索結果</TITLE>
</HEAD>
<BODY bgcolor="#77ffff" text="#fa5a00">
<H1>検索結果の交通機関のリスト</H1>
<BR>
<jsp:useBean class="java.lang.String" id="STARTYYYY" scope="session" />
<jsp:useBean class="java.lang.String" id="STARTMM" scope="session" />
<jsp:useBean class="java.lang.String" id="STARTDD" scope="session" />
<jsp:useBean class="java.lang.String" id="DAYS" scope="session" />
<jsp:useBean class="java.lang.String" id="NUMOFLODGER" scope="session" />
<jsp:useBean class="java.lang.String" id="DEPARTUREPLACE" scope="session" />
<jsp:useBean class="java.lang.String" id="DESTINATION" scope="session" />
旅行期間:<%= STARTYYYY %>年<%= STARTMM %>月<%= STARTDD %>日から<%= DAYS %>日間
<BR>
旅行者数:<%= NUMOFLODGER %>名
<BR>
<FORM action="orderdummy" method="POST">
<TABLE border="1" width="100%">
  <TBODY>
    <TR>
      <TH>出発駅</TH>
      <TH>発車時刻</TH>
      <TH>到着駅</TH>
      <TH>到着時刻</TH>
      <TH>路線名</TH>
    </TR>
    <TR>
      <TD><%= DEPARTUREPLACE %></TD>
      <TD>08:10</TD>
      <TD><%= DESTINATION %></TD>
      <TD>18:20</TD>
      <TD>どこかの線</TD>
    </TR>
  </TBODY>
</TABLE>
<BR>
<INPUT TYPE="submit" NAME="dummy" VALUE="交通機関を予約する">
</FORM>
<BR>
<BR>
<H1>検索結果のホテルのリスト</H1>
<BR>
ドコニデモアリソナホテル
<BR>
<FORM action="orderhotel" method="POST">
<TABLE border="1" width="100%">
  <TBODY>
    <TR>
      <TH>部屋番号</TH>
      <TH>部屋タイプ</TH>
      <TH>1泊料金</TH>
      <TH>定員人数</TH>
      <TH>選択</TH>
    </TR>

<jsp:useBean class="jp.co.flsi.lecture.webapp.bean.HotelBean" id="HOTEL" scope="session" />
<%      RoomInfo  anItem;
       RoomInfo[] roomInfos = HOTEL.getRoomInfos();
       StringBuffer sb = request.getRequestURL();
      for (int i = 0; i < roomInfos.length; i++) {
         anItem = roomInfos[i]; %>
          <TR>
            <TD><%= anItem.getRoomNum() %></TD>
            <TD><%= anItem.getRoomType() %></TD>
            <TD><%= anItem.getRatePerNight() %>円</TD>
            <TD><%= anItem.getCapacity() %>名</TD>
            <TD><INPUT TYPE="checkbox" NAME="<%= anItem.getRoomNum() %>"></TD>
          </TR>
<%      } %>

  </TBODY>
</TABLE>
<BR>
<TABLE border="1" width="100%">
  <TBODY>
    <TR>
      <TH>予約者芳名</TH>
      <TD><INPUT TYPE="text" NAME="reserveName" VALUE="" SIZE=20></TD>
    </TR>
    <TR>
      <TH>予約者住所</TH>
      <TD><INPUT TYPE="text" NAME="reserveAddress" VALUE="" SIZE=50></TD>
    </TR>
    <TR>
      <TH>予約者電話番号</TH>
      <TD><INPUT TYPE="text" NAME="reserveTel" VALUE="" SIZE=12></TD>
    </TR>
  </TBODY>
</TABLE>
<BR>
<INPUT TYPE="submit" NAME="putIntoCart" VALUE="選択した部屋を予約する">
</FORM>
</BODY>
</HTML>
--------------------------------------------------------

このJSPはvol.089のitemList.jspと同様のパターンですので、意味が分からない人は
vol.089付近を復習して下さい。


では、このあたりで一度アプリケーションの動きをテストしてみることにして、
編集したファイルをすべて保管したあと、EclipseでWARファイルを作成して
みましょう(WARファイルが何だったか忘れた人はvol.102を復習のこと)。

まず、準備として、対象とするプロジェクト(ここではJStudyRshaSoapClient)
に対し、以下のようにしてWARのファイル名を設定しておきます。

(1) パッケージ・エクスプローラーにおいて、プロジェクト(JStudyRshaSoapClient)
を右クリックし、「プロパティー」を選択します。
(2) 「プロパティー」ウインドウの左側で「Tomcat」を選択し、右側の
「WARエクスポート設定」タブをクリックします。
(3) 「エクスポートするWARファイル」の欄に(たとえばJavaWorksフォルダー
の中にWARファイルを作成したい場合は)
C:\JavaWorks\JStudyRshaSoapClient.war
のようにWARのファイル名を指定して下さい(プロジェクトの名前をファイル名にし、
拡張子は.warにして下さい)。
なお、「.javaファイルをエクスポート」という選択項目がありますが、これ
はWARファイルの中にソース・ファイルを書き込みたいときに選択(チェック
マークを入れる)するもので、通常は選択しません。
(4) 「OK」ボタンをクリックします。


WARファイルを作成するには、下記のように操作します。

(1) パッケージ・エクスプローラーにおいて、プロジェクト(JStudyRshaSoapClient)
を右クリックし、「Tomcatプロジェクト」→「プロジェクト設定に従いWARファイル
を作成」を選択します。
(2) 「操作が成功しました」のメッセージが表示されたら、「OK」ボタンをクリック
します。
(3) 準備で指定したフォルダーに、WARファイルが作成されていますので、確認
します。

そして最後に、作成されたWARファイルをTomcatのwebappsディレクトリー配下に置き
ます。
これで、Webアプリケーションのデプロイが完了です。



以上の作業が終わったら、Tomcatを起動した後、以下のように動作をテストをしてみま
しょう。(予めLinuxのPCを起動して、Axisが稼動状態になっていることが前提です。)

(1) Webブラウザーを起動し、下記URLを入力してください。
http://localhost:8080/JStudyRshaSoapClient/travel.html

(2) 旅行日数を3に、旅行者人数を2にして(他にも変更したい項目があれば変更して)、
「送信」ボタンをクリックします。

(3) 正常な検索結果(ホテルのリスト)が返ってくることを確認してください。

なお、データベース上の部屋の定員人数が(2)で指定した旅行者人数よりも1以上多い
部屋しかリストされませんので注意して下さい。(筆者も今テストしてみて気がつき
ました。)これはなぜかというと、RoomDbManager(vol.157参照)の各SQL文に
おいて

WHERE CAPACITY >= ?

とすべき所を

WHERE CAPACITY > ?

というようにミスしていたためです。これを修正してデプロイまでやり直すこと
は読者の自由課題としておきます。(今までの記事を読めばやり方は分かると
思いますが、もし、やり方が分からない人がいましたら、質問をお寄せ下さい。)



これで、取り合えず、Webアプリケーション(R社)からネットワークで隔てられた
コンピューター上のWebサービス(H社)がちゃんと呼び出されたことが分かりまし
たね。



◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆


(次回に続く)


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



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      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. 不許無断複製