■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2008年12月28日

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

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


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


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


さて、前回はAntを使って(Windows環境で)Webサービスのデプロイを行うためのビルド
・ファイルのサンプルを提示し、実際にデプロイを行ってみました。

このとき、下記のような4種類の作業を自動的に行っていましたね。

(a) ファイルのコピー
 Eclipseのワークスペースにあるファイルをディレクトリーごと
 作業用のディレクトリーにごっそりコピーした。

(b) JARファイルの生成
 (a)でコピーしたJavaのファイル(クラス・ファイル)からJARファイルを生成した。
 
(c) WSDLファイルの生成
 (a)でコピーしたJavaのファイル(クラス・ファイル)からWSDLファイルを生成した。

(d) JavaのファイルとWSDDファイルの生成
 (c)で生成したWSDLファイルからJavaのファイル(ソース・ファイル)とWSDDファイル
 を生成した。

(e) Axisのdeployの実行
 (d)で生成されたWSDDファイルを使ってAxisのdeployを実行した。


ここでは、WSDLファイルもWSDDファイルも自動的に生成されていることに注目してくだ
さい。
自分で作成したのは、Javaのファイル(WebService1クラス)だけですね。
(厳密に言えば、ビルド・ファイルとプロパティー・ファイルも自分で作成しています
が、これらは一度作れば、後は他のWebサービスを開発するときにも、ほとんど同様のもの
を作ればいいだけですから、大して手間はかかりません。)

このようにSOAP(というかAxis)を使うと、Webサービスのプログラミングさえすれば、
後はほとんど自動的に行えるので、(CORBAよりも)随分と開発が楽だということが
わかると思います。



では、前回作成したビルド・ファイルの中身を詳しく説明していきましょう。


まず最初に、ビルド・ファイルは拡張子を見てもわかるようにXML(eXtensible Markup
Language)という言語で書かれたファイルになっていますが、XML自体については、後ほど
詳しく説明します。

ちなみに1行目の

<?xml version="1.0" encoding="Shift_JIS"?>

もXMLであることを表していますね。なお、encoding="Shift_JIS"は、このファイルでは
文字コードとしてShift_JISを使っていることを示しています。(コメントにShift_JIS
の漢字やかなを使っています。)

さて、XMLは、HTMLのようなタグを使ってデータ構造を記述する形式をとっていますが、
Antのビルド・ファイルでは、そのファイル全体を<project>というタグで囲むことになっ
ています。つまり、<project>と</project>で全体を囲みます。

build_deploy.xmlファイルでは次のような<project>タグを設定していますね。

<project name="WebServices Deploy" basedir="." default="deploy">

ここには、name、basedir、defaultという3つの属性が指定されています。

このように<project>には、以下のような3つの属性があり、いずれも省略可能ですが、
指定しておくと便利だということで通常は指定しておきます。

name:
 プロジェクトの名前を指定します。何でもいいですが、ここではWebサービスのデプロイ
 を行うためのビルド・ファイルであることがわかるように、"WebServices Deploy"という
 名前にしています。あくまで個々のビルド・ファイルを識別するためのもので、ソフト
 ウエアの構築手順には関係しません。

basedir:
 相対パスの根元のディレクトリーとして使われるデフォルトのディレクトリーを設定
 します。ここでは"."すなわちカレント・ディレクトリーをデフォルトのディレクトリー
 として設定しています。basedirはこの属性だけでなく、プロパティーとして指定する
 こともできます。もし、属性とプロパティーのどちらにも指定しなかった場合は、この
 ビルド・ファイルが入っているディレクトリーがデフォルトのディレクトリーとなり
 ます。

default:
 ビルド・ファイルの中の実際に実行する部分は<target>(ターゲット)タグで記述され
 ますが、ターゲットを明示せずにAntを実行したときにデフォルトで実行したいターゲッ
 トをここに指定します。当サンプルでは、"deploy"を指定していますから、ターゲット
 を明示せずにAntを実行したときに"deploy"という名前のターゲットが実行されることに
 なります。


次の行に

   <property file="build.properties" />

という行がありますが、これは実際に参照するプロパティー・ファイルとして
"build.properties"という名前のファイルを指定しているものです。
こうしておけば、Antの実行時にこのファイルからプロパティーが読み込まれます。

なお、プロパティーはプロパティー・ファイルを使わなくても、この<property>タグで
直接設定することもできます。たとえば、

   <property name="pet.name" value="Tom" />

という<property>タグを書くと、pet.nameというプロパティーを宣言して、その値を
"Tom"にすることになります。

ちなみに、最後の/>はタグの締めくくりを意味し、

   <property name="pet.name" value="Tom">
   </property>

と書くのと同じ扱いになります。


続いて、<path>タグが書かれていますが、このタグは環境変数のPATHやCLASSPATHと同じ
ように、参照する(複数の)ファイルやディレクトリーを指定しておくためのものです。
ここでは、

   <path id="axis.classpath">
     <fileset dir="${axis.dir}/lib">
        <include name="**/*.jar" />
      </fileset>
   </path>

という設定になっていますが、まず、id="axis.classpath"によって、ここで設定する
pathに"axis.classpath"という名前をつけています。これは、あとで別のタグで参照
できるようにするためのものです。
そして、

     <fileset dir="${axis.dir}/lib">
        <include name="**/*.jar" />
      </fileset>

という記述によって、ファイルの組み合わせ(file set)を指定しています。
まず、<fileset>タグのdir属性(ここではdir="${axis.dir}/lib"という指定になっている)
によって、ベースにするディレクトリーを"${axis.dir}/lib"に指定していますが、この
${axis.dir}という表記は、axis.dirというプロパティーの値をそこに引用することを意味
します。
このaxis.dirプロパティーの値はどこで設定されているかというと、先ほどのプロパティー・
ファイルの中で設定されており、build.propertiesファイルの中を見ると、

axis.dir=C:/Tomcat6.0/webapps/axis/WEB-INF

という行があることがわかりますね。

この行は、axis.dirプロパティーの値として"C:/Tomcat6.0/webapps/axis/WEB-INF"を設定
しているものです。ここで"C:"はハードディスクのドライブ名ですが、ディレクトリー名の
区切りは、Windowsでの表記である"\"の代わりにUNIXと同じ"/"で表記することができます。
このように"/"で表記しておくとUNIXやLinuxと互換性があるので、UNIXやLinuxの環境に
ファイルを持ち込むときに作業が楽になりますが、"C:"のようなWindows特有の表記があ
ると、やはりUNIXやLinuxの環境ではそのまま使うことはできません。
つまり、このプロパティー・ファイルはUNIXやLinux用には別途用意してやる必要があり
ます。

さて、このaxis.dirプロパティーの値を実際に引用してやると、上のdir属性の値は
dir="C:/Tomcat6.0/webapps/axis/WEB-INF/lib"
と指定したのと同じことになります。これはAxisのlibフォルダーですね。

次に、この<fileset>タグの中に入れ子(nested)で入っている<include>タグ、すなわち

        <include name="**/*.jar" />

の部分は、このファイルの組み合わせに含める具体的なファイルを指定しています。
ここで"**/"はそのベースのディレクトリー配下のすべてのサブディレクトリーを意味し、
"*.jar"はそのディレクトリー(サブディレクトリー)にある、"なんとか.jar"という
ファイル名のファイルを意味します。つまり、この"*.jar"は.jarで終わる任意のファイ
ル名を意味します。
つまり、この<fileset>タグでは、Axisのlibフォルダー配下にある、すべてのJARファイル
を含めるようにファイルの組み合わせを設定しているわけです。


続いて、<taskdef>タグは、このプロジェクト内で使用する(Antの標準ではない)タスク
を定義するためのタグですが、このサンプルのビルド・ファイルでは、axis-tasks.properties
というファイルの中で定義されているタスクを使用することだけを指定しています。
すなわち、

   <taskdef resource="axis-tasks.properties" classpathref="axis.classpath" />

という指定をすると、実際にタスクを定義してあるaxis-tasks.propertiesというプロパティー・
ファイルからタスクの定義を取り出して使用することになります。このとき、
classpathref="axis.classpath"は、このファイルを"axis.classpath"という名前で設定さ
れている場所(CLASSPATH)から探してくるように指定しています。
そして、この"axis.classpath"は先ほどの<path>タグで設定された名前ですので、具体的
には、Axisのlibフォルダーの中にあるJARファイルから探し出すことになります。

で、axis-tasks.propertiesは実際にはどこに入っているかというとAxisのlibフォルダー
の中にあるaxis-ant.jarというJARファイルの中に入っています。

実際に入っていることを確認したい場合は、このJARファイルを解凍してみればいいのです
(JARファイルがZIP形式の圧縮ファイルであることは以前お話した通りです)が、解凍する
ためには、コマンド・プロンプトで次のようなコマンドを実行すればよろしい。

jar -xvf axis-ant.jar

解凍して出てきたaxis-tasks.propertiesをテキスト・エディター(NoEditorなど)で開い
て見ると、

axis-wsdl2java=org.apache.axis.tools.ant.wsdl.Wsdl2javaAntTask
axis-java2wsdl=org.apache.axis.tools.ant.wsdl.Java2WsdlAntTask
axis-admin=org.apache.axis.tools.ant.axis.AdminClientTask

という指定がされていることがわかりますね。これは、それぞれWsdl2javaAntTask、
Java2WsdlAntTask、AdminClientTaskというJavaのクラスに、axis-wsdl2java、axis-java2wsdl、
axis-adminというタスク名を付けていることを意味します。これがタスクの定義です。


では、続いて、

   <target name="copy2work">
     <copy todir="${work.dir}">
       <fileset dir="${classes.dir}">
         <include name="**/**"/>
         <exclude name="**/*.java"/>
       </fileset>
     </copy>
   </target>

の部分を見てみましょう。ここでは、"copy2work"という名前のターゲットを宣言して
います。1つのターゲットの中では複数のタスクを実行することができるのですが、
ここではcopyという1つのタスクしか指定していません。
このcopyは、ファイルやディレクトリー(フォルダー)をコピーするタスクで、Ant
に標準で定義されているものです。
タスクを実行するためには、このように<target>タグの入れ子としてタスク名のタグを
書いておきます。
copyタスクの場合には<copy>タグにtodirという属性を指定することができますが、この
属性は、コピー先のディレクトリーを指定するためのものです。
当サンプルの場合はtodir="${work.dir}"という指定になっていますが、これはコピー先
のディレクトリーを"${work.dir}"にするということを意味し、${work.dir}は、先ほどの
build.propertiesというプロパティー・ファイルの中で宣言されているwork.dirプロパティー
の値を引用することを意味します。
build.propertiesの中を見ると、
work.dir=./
と書かれていますから、実際には"./"すなわちカレント・ディレクトリー(このビルド・
ファイルが入っているディレクトリー)がコピー先として指定されることになります。
(ちなみに、work.dirというプロパティーの名前は作業用のディレクトリーという意味を
込めて付けました。)
そして、<copy>タグの入れ子になっている<fileset>タグはコピー元のファイルの組み合わせ
を指定するためのもので、先ほどの<path>タグのときに出てきた<fileset>タグと同じ
形式のものです。ただし、ここでは入れ子で<exclude name="**/*.java"/>という指定が
されていますが、この<exclude>タグは<include>の逆の意味を持つタグで、ファイルの
組み合わせから除外したいファイルを指定するものです。
つまり、

       <fileset dir="${classes.dir}">
         <include name="**/**"/>
         <exclude name="**/*.java"/>
       </fileset>

というように指定すると、「classes.dirプロパティーで指定されるディレクトリーの中の
すべてのサブディレクトリーの中のすべてのファイルをコピー対象とするが、ただし、
.javaで終わるファイル名のものは除外する。」ということを意味します。
("**/**"は、すべてのサブディレクトリーの中のすべてのファイルを意味します。)

.javaで終わるファイル名とは、Javaのソース・ファイルを意味しますから、上の指定では
ソース・ファイルが除外されることになります。

ここで、classes.dirプロパティーをbuild.propertiesの中から探すと、
classes.dir=C:/JavaWorks/JStudySOAP/bin
となっていますから、Eclipseのワークスペースの中のJStudySOAPプロジェクトのフォルダー
の中のbinフォルダーの中に入っている、すべてのサブディレクトリーの中の(ソース・ファ
イル以外の)すべてのファイルをコピー対象としていることになります。

実際には、ここにはWebService1.classというバイト・コードのファイルしか入っていま
せんね。ソース・ファイルは入っていません。というわけで、<exclude name="**/*.java"/>
という記述は実際には無意味です。あくまで学習のために(説明用に)入れておいただけなの
で、削除しても結構です。


続いて、

   <target name="jar" depends="copy2work">
     <jar destfile="${axis.dir}/lib/webservice1.jar"
       basedir="${work.dir}"
       includes="**/**"
       excludes="**/*.java"
     />
   </target>

の部分を見てみましょう。ここでは、"jar"という名前のターゲットを宣言しています。
(ちなみに、入れ子で指定しているタスクもjarという同じ名前ですが、タスクの名前と
ターゲットの名前は独立していますので、ターゲットに同じjarという名前を使っても
問題はありません。ただし、タスク名と同じだと紛らわしいかも知れませんね。
class2jarとかいうふうに別のターゲット名をつけたほうがよかったかも知れません。)

ここで、<target>タグにdependsという属性が指定されていることに注目してください。
このdepends="copy2work"という属性の指定は、このターゲットを実行する前に"copy2work"
というターゲットを実行しておくことを要求するものです。
このように<target>タグにdepends属性を指定することによって、ソフトウエア構築作業
の手順を設定することができます。

入れ子で指定している<jar>というタグは、JARファイルを処理するjarコマンドに対応する
タスクで、Antに標準で定義されているものです。
この<jar>タグでは、destfile、basedir、includes、excludesという属性を指定していま
すが、destfileという属性はJARファイルを出力するときの出力先のファイルを指定する
ものです。また、basedirはJARファイルを生成する元になるファイルを置いてある場所の
ベースのディレクトリーを指定するものです。
また、includesという属性は、含めたいファイルを指定するもので、excludesという属性は、
除外したいファイルを指定するものです。これらは、それぞれ、先ほどの<fileset>タグの
入れ子で指定した<include>タグや<exclude>タグと同じ働きを持ちます。
実際、これらのbasedir、includes、excludesの属性を指定する代わりに、入れ子で

       <fileset dir="${work.dir}">
         <include name="**/**"/>
         <exclude name="**/*.java"/>
       </fileset>

と指定することもできるのです。つまり、属性で指定しても、入れ子で指定しても、
どちらでも構わないということです。


続いて、

   <target name="java2wsdl" depends="jar">
     <axis-java2wsdl
      classname="jp.co.flsi.lecture.soap.WebService1"
      location="http://localhost:8080/axis/services/WebService1"
      namespace="http://webservice.flsi.co.jp/"
      output="${local.wsdl}" >
     </axis-java2wsdl>
   </target>

の部分を見てみましょう。

このターゲットでは、axis-java2wsdlというタスクを指定していますが、これは
先ほどのaxis-tasks.propertiesの中で定義されていたタスクですね。

このタスクはJavaのプログラムを読み取って、それに対応したWSDLファイルを生成
してくれるタスクです。

このとき読み取って欲しいプログラム(クラス)はclassnameという属性で指定し、生成さ
れたWSDLファイルの出力先はoutputという属性で指定します。サンプルでは、読み取る
クラスにはjp.co.flsi.lecture.soap.WebService1を指定し、出力先は(build.properties
の中にあるlocal.wsdlプロパティーの値を見ると)カレント・ディレクトリー上の
WebService1.wsdlという名前のファイルにしていることがわかりますね。
あと、locationという属性にはWebサービスのURLを指定し、namespaceという属性には
vol.127でdeploy.wsddの中の<namespace>に指定したのと同じものを指定します。



では、長くなったので、今回はここまでにして、続きは次回に回します。


(次回に続く)


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

何か、わからないところがありましたら、下記のWebページまで質問を
お寄せください。



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