■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 2009年10月18日 Java総合講座 - 初心者から達人へのパスポート vol.175 セルゲイ・ランダウ バックナンバー: http://www.flsi.co.jp/Java_text/ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ------------------------------------------------------- ・このメールマガジンは、画面を最大化して見てください。 小さな画面で見ていると、不適切な位置で行が切れてしまう など、問題を起すことがあります。 ・このメールマガジンに掲載されているソース・コード及び 文章は特に断らない限り、すべて筆者が著作権を所有してい ます。また、これらのソース・コードは学習用のためだけに 提供しているものです。 ------------------------------------------------------- ======================================================== ◆ 01.SOAPのアプリケーション(Webサービス) ======================================================== では、生成されたスタブを使って、Webサービスを呼び出すWebアプリケーション をこれから作っていきましょう。 このWebアプリケーションの処理の流れは、次のようなものとします。 (1) Webブラウザーに旅行検索のURLを入力することにより、旅行検索のため のWebページ(travel.html)が開く。 (2) 必要な項目を指定し、送信ボタンをクリックすることにより、サーブレット (TravelSearchServlet.java)が起動される。 (3) サーブレットはホテルの検索のために、ホテルのクラス(HotelBean.java) を呼び出し、JSP(travellist.jsp)を起動する。 このときHotelBean.javaは、H社のホテルを検索(H社のWebサービスを呼び出す) し、その結果のリストをtravellist.jspに渡す。 (4) JSP(travellist.jsp)はWebブラウザー上でWebページを表示し、 予約の要求を待つ。 (5) Webページで予約の要求(予約ボタンをクリック)を行うと、サーブレット (HotelServlet.java)が起動される。 (6) サーブレットはホテルの予約のために、ホテルのクラス(HotelBean.java) を呼び出し、JSP(reserveresult.jsp)を起動する。 このときHotelBean.javaは、H社のホテルの予約をし(H社のWebサービス を呼び出す)、その結果のリストをreserveresult.jspに渡す。 開発の手順等はvol.077以降に行ったWebアプリケーション開発とほとんど 同様になりますので、詳しい説明は省いていきます。 ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ なお、今回のWebアプリケーションでは、Log4jを使ってエラーのログなどを出力 できるようにしておきましょう。 本来ならば http://logging.apache.org/log4j/1.2/download.html などからLog4jをダウンロードしてインストールすべきですが、既にインストール 済みのAxisの中にLog4jのJARファイル(log4j-1.2.8.jar)が含まれているので、 ここではそれを利用しましょう。同時に、現在開発中のWebアプリケーションからも AxisのJARファイルにアクセスできるようにする必要がある(Webサービスのスタブ を使用しているため)ので、AxisのJARファイルをまるごとコピーして利用すること にします。 というわけで、 C:\Tomcat6.0\webapps\axis\WEB-INF\lib にあるAxisのJARファイル、すなわち axis-ant.jar axis.jar commons-discovery-0.2.jar commons-logging-1.0.4.jar jaxrpc.jar log4j-1.2.8.jar saaj.jar wsdl4j-1.5.1.jar をごっそりと C:\JavaWorks\JStudyRshaSoapClient\WEB-INF\lib にコピーして下さい。 (ここでは、TomcatのフォルダーではなくEclipseのワークスペース内の フォルダーにコピーしていますが、間違いではありません。 あとでEclipseからWARファイルを生成してTomcatにデプロイしますので、 結局はTomcatのほうに入ることになります。 なお、もし当Webアプリケーションだけでなく、すべてのTomcatのアプリ ケーションからJARファイルにアクセスできるようにしたい場合は、上の WEB-INF\libではなく、C:\Tomcat6.0\libにコピーする必要があります。) ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ では、まず最初に、HTMLファイル(travel.html)の作成から行っていきましょう。 下記のように作業を行って下さい。 (1) Eclipseのパッケージ・エクスプローラーの中のJStudyRshaSoapClientを 右クリックし、「新規」→「ファイル」を選択します。 (2) 「名前」に travel.html を入力し、「終了」ボタンをクリックします。 (3) パッケージ・エクスプローラーの中にできたtravel.htmlを右クリックし、 「アプリケーションから開く」→「テキスト・エディター」を選択し、 下記のようなソース・コードに編集します。 -------------------------------------------------------- <HTML> <HEAD> <TITLE>旅行検索のページ</TITLE> </HEAD> <BODY bgcolor="#77ffff" text="#fa5a00"> <H1>旅行(交通機関とホテル)検索</H1> <FORM action="http://localhost:8080/JStudyRshaSoapClient/servlet/travelsearch" method="POST"> <BR> 出発地: <BR> <SELECT NAME="departurePlace"> <OPTION selected>東京</OPTION> </SELECT> <BR> <BR> 行き先: <BR> <SELECT NAME="destination"> <OPTION selected>熱海</OPTION> <OPTION>箱根</OPTION> </SELECT> <BR> <BR> 旅行開始年月日: <BR> <SELECT NAME="startYYYY"> <OPTION selected>2010</OPTION> <OPTION>2011</OPTION> <OPTION>2012</OPTION> </SELECT> 年 <SELECT NAME="startMM"> <OPTION selected>1</OPTION> <OPTION>2</OPTION> <OPTION>3</OPTION> <OPTION>4</OPTION> <OPTION>5</OPTION> <OPTION>6</OPTION> <OPTION>7</OPTION> <OPTION>8</OPTION> <OPTION>9</OPTION> <OPTION>10</OPTION> <OPTION>11</OPTION> <OPTION>12</OPTION> </SELECT> 月 <SELECT NAME="startDD"> <OPTION selected>1</OPTION> <OPTION>2</OPTION> <OPTION>3</OPTION> <OPTION>4</OPTION> <OPTION>5</OPTION> <OPTION>6</OPTION> <OPTION>7</OPTION> <OPTION>8</OPTION> <OPTION>9</OPTION> <OPTION>10</OPTION> <OPTION>11</OPTION> <OPTION>12</OPTION> <OPTION>13</OPTION> <OPTION>14</OPTION> <OPTION>15</OPTION> <OPTION>16</OPTION> <OPTION>17</OPTION> <OPTION>18</OPTION> <OPTION>19</OPTION> <OPTION>20</OPTION> <OPTION>21</OPTION> <OPTION>22</OPTION> <OPTION>23</OPTION> <OPTION>24</OPTION> <OPTION>25</OPTION> <OPTION>26</OPTION> <OPTION>27</OPTION> <OPTION>28</OPTION> <OPTION>29</OPTION> <OPTION>30</OPTION> <OPTION>31</OPTION> </SELECT> 日 <BR> <BR> 旅行日数: <BR> <SELECT NAME="days"> <OPTION selected>1</OPTION> <OPTION>2</OPTION> <OPTION>3</OPTION> <OPTION>4</OPTION> <OPTION>5</OPTION> <OPTION>6</OPTION> <OPTION>7</OPTION> <OPTION>8</OPTION> <OPTION>9</OPTION> <OPTION>10</OPTION> <OPTION>11</OPTION> <OPTION>12</OPTION> <OPTION>13</OPTION> <OPTION>14</OPTION> <OPTION>15</OPTION> <OPTION>16</OPTION> <OPTION>17</OPTION> <OPTION>18</OPTION> <OPTION>19</OPTION> <OPTION>20</OPTION> <OPTION>21</OPTION> <OPTION>22</OPTION> <OPTION>23</OPTION> <OPTION>24</OPTION> <OPTION>25</OPTION> <OPTION>26</OPTION> <OPTION>27</OPTION> <OPTION>28</OPTION> <OPTION>29</OPTION> <OPTION>30</OPTION> </SELECT> <BR> <BR> 旅行者人数: <BR> <SELECT NAME="numOfTravelers"> <OPTION selected>1</OPTION> <OPTION>2</OPTION> <OPTION>3</OPTION> <OPTION>4</OPTION> <OPTION>5</OPTION> </SELECT> <BR> <BR> <INPUT TYPE="submit" NAME="submit" VALUE="送信"> </FORM> </BODY> </HTML> -------------------------------------------------------- 上に新しく出てきた<SELECT>というタグは、選択肢のリストを表示するプルダウン・ メニューを作るためのもので、その選択肢の一つ一つはその下に並んでいる<OPTION> というタグによって指定します。例えば、 <SELECT NAME="startYYYY"> <OPTION selected>2010</OPTION> <OPTION>2011</OPTION> <OPTION>2012</OPTION> </SELECT> という指定では、プルダウン・メニューで2010と2011と2012が選択項目として表示 されることになります。このうち<OPTION selected>というふうに<OPTION>タグに selected属性が指定されているものは、デフォルトで選択状態になる項目を指示す ることになります。 また、<SELECT>タグのNAME属性に指定した値は、vol.075で説明した<INPUT>タグの 場合と同様にパラメーターの名前としてサーブレットに渡されることになります。 また、<OPTION>タグで指定した選択項目のうち、実際にWebブラウザー上で選択 されたものは、パラメーターの値としてサーブレットに渡されることになります。 例えば、上記のstartYYYYというパラメーターの場合は、デフォルトでは2010が 選択状態になりますから、Webブラウザー上で選択状態を変えない限り2010が startYYYYというパラメーターの値としてサーブレットに渡されることになります。 なお、上記のHTMLでは、すべての入力項目をプルダウン・メニュー式にしていま すが、このようなやり方をすれば、入力できる値を制限できますし、ユーザーが 入力間違いを犯す(例えば半角で入力すべき数値を全角で入力してしまうなど) ことを防ぐことができ、入力しやすくなるという点でも望ましい方法です。 ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ 続いて、あとで作成するクラスが参照するプロパティー値を、プロパティー・ファイル から読み取るためのクラスを作成しましょう。 Eclipseを起動して、以下のような作業を行って下さい。 (1) Eclipseのパッケージ・エクスプローラーの中のJStudyRshaSoapClientの中の WEB-INF/srcを右クリックし、「新規」→「パッケージ」を選択します。 (2) 「名前」に jp.co.flsi.lecture.webapp.utility を入力し、「終了」ボタンをクリックします。 (3) パッケージ・エクスプローラーの中にできた jp.co.flsi.lecture.webapp.utilityを右クリックし、 「新規」→「クラス」を選択します。 (4) 「名前」に TravelServiceProperties と入力し、「終了」ボタンをクリックします。 (5) TravelServicePropertiesのエディターが開いたら、下記のようなソース・ コードに編集します。 -------------------------------------------------------- package jp.co.flsi.lecture.webapp.utility; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import org.apache.log4j.Logger; public class TravelServiceProperties extends Properties { private static TravelServiceProperties instance = null; private static Logger logger = Logger.getLogger(TravelServiceProperties.class); private TravelServiceProperties() { InputStream inputStream = getClass().getResourceAsStream("/travelservice.properties"); if(inputStream != null) { try { super.load(inputStream); } catch (IOException e1) { logger.error(e1); } } logger.info("インスタンスを生成しました。 ..............."); } public static TravelServiceProperties getInstance() { if (instance != null) { logger.info("インスタンスは既に存在します。 ..............."); } else { logger.info("インスタンスが存在しないので生成します。 ..............."); instance = new TravelServiceProperties(); } return instance; } } -------------------------------------------------------- もうお分かりだと思いますが、これはvol.145で作成したRunModePropertiesと 同様のものですね(実際にそのソースをコピーしてから編集し直したものです)。 したがって説明は省略します。このソース・コードの意味が分からない人は、 vol.145を復習して下さい。 ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ 続いて、H社のWebサービスを呼び出すクラス(HotelBean.java)を作成しま しょう。 Eclipseを起動して、以下のような作業を行って下さい。 (1) Eclipseのパッケージ・エクスプローラーの中のJStudyRshaSoapClientの中の WEB-INF/srcを右クリックし、「新規」→「パッケージ」を選択し ます。 (2) 「名前」に jp.co.flsi.lecture.webapp.bean を入力し、「終了」ボタンをクリックします。 (3) パッケージ・エクスプローラーの中にできた jp.co.flsi.lecture.webapp.beanを右クリックし、 「新規」→「クラス」を選択します。 (4) 「名前」に HotelBean と入力し、「終了」ボタンをクリックします。 (5) 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 { 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); } 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 { 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); } 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; } } } -------------------------------------------------------- このソース・コードのうち、 stayInfo.setMinRatePerNight(-1); stayInfo.setMaxRatePerNight(-1); という行は、アプリケーションを簡単にするために(検索条件としての) 最低料金と最高料金の指定を省略したものです。(vol.148で説明したよう にこれらに負の値(ここでは-1)を指定すると省略したことを意味します。 なお、こういったWebサービスの仕様は、H社が利用者にWSDLと一緒に説明 の文書を提供しておくべきものです。) 残りのコードは説明しなくても理解できますね。 なお、このソース・コードでは、先ほど作成したTravelServicePropertiesを使って、 WebサービスのURLを、プロパティー・ファイルの"WebService.URL"というプロパティー の値から読み出していますね。 したがって、プロパティー・ファイル(travelservice.properties)を作成しておく 必要があります。 C:\JavaWorks\JStudyRshaSoapClient\WEB-INF\classesフォルダーの配下に、 下記のような内容のtravelservice.propertiesを作成して下さい。 -------------------------------------------------------- WebService.URL=http://192.168.0.5:8080/axis/services/Hotel -------------------------------------------------------- ただし、上記の192.168.0.5の部分は筆者の環境におけるLinux(CentOS)のPC のIPアドレスですから、この部分は読者の環境に合わせて書き換えて下さい。 また、同じフォルダー配下にLog4jのプロパティー・ファイル(log4j.properties) も下記の内容で作成しておきましょう。 -------------------------------------------------------- log4j.rootLogger=INFO, A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=*%-5p [%d] %c.%M: %m%n -------------------------------------------------------- ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ (次回に続く) では、今日はここまでにします。 ====================================================== ◆ 02.演習問題 ====================================================== 上のHotelBeanのソース・コードでは、findHotels()メソッドと reserveHotel()メソッドの先頭の何行かのコードが重複してい ますね。 これを重複しないように、もう少しすっきりしたソース・コード に修正してみて下さい。 [ヒント:重複した部分を別のメソッドに切り出す。] ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ★ホームページ: 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. 不許無断複製 |