8. UDDI チュートリアル

8.1. はじめに

このチュートリアルでは、 架空の企業「日電PC」社と、 その関連工場における、 WebサービスによるSCM(サプライ・チェーン・マネージメント)システムを例にとり、 Webサービスによる実装と、 その情報をUDDIに登録/検索することを通して、 UDDIの利用方法の基礎を学びます。


8.1.1. 状況設定

このチュートリアルでは、 架空のパソコンメーカ「日電PC」社が、 SCM(サプライ・チェーン・マネージメント)をWebサービスを用いて実装する…という例題で、 簡単なWebサービスの実装とそれに関する情報をUDDIに登録し、 検索/実行するまでの過程を一通り学びます。

この例題では、 以下のようなURLやファイルが、 「日電PC」社で使用されるファイルやURLとして現れます。 このチュートリアルをもとに、 ご自分のサイトでWebサービス/UDDIレジストリを立ち上げてみる場合には、 下記のURLやファイル名を、適宜読み替えてください。

  1. 「日電PC」社 Webサービスサイト: www.nichiden-pc.co.jp
    本チュートリアルの例題で、Webサービスを提供するホスト名です。
  2. 「日電PC」社 SCM Webサービスアクセスポイント: http://www.nichiden-pc.co.jp/scm/services/GetStock
    本チュートリアルの例題で、Webサービスを提供するURLです。
  3. 日電PC SCM WebサービスWSDLファイル: http://www.nichiden-pc.co.jp/scm-ws.wsdl
    本例題で用いるWSDLの置場所を表すURLです。実際に配置する必要はありません。
  4. 日電PC SCM Webサービス説明文書: http://www.nichiden-pc.co.jp/scm-ws.pdf
    本例題でのWebサービスについて説明している文章です。 例題で現れるだけで実際に準備する必要はありません。
  5. 「日電PC」社 の 社内UDDIレジストリ アクセスポイント: http://uddi.nichiden-pc.co.jp/uddi/services/UDDIService
    本例題で、Webサービスが登録/検索されるUDDIレジストリです。

以下は、本チュートリアルで用いるサンプルファイルです。 サンプルの実行には以下のファイルをご使用ください。

  1. 日電PC SCM Webサービス用 WSDLファイル: scm-ws.wsdl
    日電PC社のSCM(サプライ・チェーン・マネージメント)システムを実装するWebサービスの、WSDLファイルです。 ただし、チュートリアル用のサンプルですので、定義されているのは「在庫量」の検索を行うダミーのメソッドだけです。
  2. 日電PC SCM Webサービス用tModel: nichiden-pc-tmodel.xml
    UDDIレジストリー内部で、日電PC社のSCMシステムのWebサービスの仕様を識別するためのtModelデータ構造を納めたXML形式のファイルです。 このXML形式のファイルは、WebOTX UDDI Registryにアップロードしてデータを登録することができます。
  3. 日電PC SCM Webサービス用businessEntity: nichiden-pc-be.xml
    UDDIレジストリー内部で、日電PC社に関する情報を表すbusinessEntityデータ構造を納めたXML形式のファイルです。 このXML形式のファイルは、WebOTX UDDI Registryにアップロードしてデータを登録することができます。
  4. 日電PC SCM Webサービス用businessService/bindingTemplate: nichiden-pc-bs.xml
    UDDIレジストリー内部で、日電PC社の提供するサービス、つまり、SCMシステムのWebサービスに関する情報が保持するbusinessServiceデータ構造を納めたXML形式のファイルです。 このXML形式のファイルは、WebOTX UDDI Registryにアップロードしてデータを登録することができます。

8.2. 手順の概要

WebサービスをUDDIに登録し公開するには、大まかに以下の作業を行うことになります。

  1. SOAPでサービスを準備する: 登録すべきサービスをSOAPでサービスを実装します。
  2. UDDIにサービスを登録する: 実装したサービスに関する情報をUDDIに登録します。
  3. UDDIでサービスを検索する: 登録したサービスを検索したり、さらに実際に呼び出してみます。

以降の節では、これに沿って順番にみていきましょう。


8.3. サービスを準備する

まずは登録すべきWebサービスがなければ、UDDIも意味がありません。

新たにサービスを実装するにしても、 あるいは、既存のサービスを利用するにしても、 登録すべきサービスを用意する必要があります。

本チュートリアルでは、 サービスの実装の準備として、 (ダミーの)在庫量検索サービスのWSDLを定義し、 実際に実装、利用可能にしてみます。


8.3.1. サービスの仕様を決める

Webサービスを新たに準備する場合には、 まず、WSDLファイルを用意するのが自然でしょう。 必ずしもWSDLファイルを先に準備する必要があるわけではありませんが、 本チュートリアルでは、 WSDL2Javaというツールを用いてWSDLファイルから一部のJavaコードを自動生成するので、 まずは、WSDLファイルを定義することにします。

さて、このチュートリアルはあくまでサンプルですので、SCMのごくごく一部として在庫量検索機能だけを実装します。 加えて、 この検索機能は、 文字列型の「商品ID」を与えると現在の在庫量が「整数」で返るだけのシンプルなサービスとします。 本物のSCMでは在庫量ひとつを求めるだけでも複雑な処理が必要になるでしょう。 本チュートリアルはUDDIへの登録と検索、さらにそのサービスの呼び出しを学習するのが目的ですので、 このサービスの実装は極めて簡単なものを用いますが、 WSDLの記述方法やUDDIへの登録方法という点では、 基本的に本物のSCMをWebサービスで実現する場合とそれほど変わらないでしょう。

在庫量検索サービスの実際のWSDLファイルを参照しながら、 その意味を簡単に説明します。

WSDLは、主に以下のようなXML要素を用いてWebサービスの「インターフェース仕様」を表現します。

  1. definitions要素
    WSDL文書の最上位要素です。子要素である以下の要素で具体的な情報を表現します。
    1. types要素
      メッセージのフォーマットを定義する際に使用するデータ型を抽象的に定義します。
    2. message要素
      伝送されるメッセージのフォーマットを抽象的に定義します。
    3. operation要素
      Webサービスで使用可能な「操作」を抽象的に定義します。
    4. portType要素
      関連する「操作」をひとつにまとめた抽象的な「ポート」を定義します。
    5. binding要素
      portType要素で定義された操作を具体的な通信プロトコル(HTTPなど)を「バインディング」として、関連づけます。
    6. port要素
      binding要素で定義されたバインディングに、 実際に通信するためのエンドポイント(HTTPの場合はURL)を関連づけます。
    7. service要素
      port要素で定義したポートのうち、関連するポートをひとまとめにして「サービス」を定義します。

さて、これを念頭に置きながら、 在庫量検索サービスの実際のWSDLファイルを参照してみます。 細かな記法に関する詳細までは説明しませんが、 このチュートリアルのサンプルのようなごく簡単なサービスであれば、 容易にご理解いただけると思います。

なお、WSDLについてはアプリケーション開発ガイド第4章をご覧ください。



    1   <?xml version="1.0" encoding="shift_jis"?>
    2   
    3   <!--  -->
    4   <definitions name="urn:GetStock" 
    5                targetNamespace="urn:scm.nichiden-pc.co.jp"
    6                xmlns:tns="urn:scm.nichiden-pc.co.jp"
    7                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    8                xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    9                xmlns="http://schemas.xmlsoap.org/wsdl/">


WSDLのトップレベルはdefinitionns要素です。name要素はサービス名を指定します。 このサンプルではurn:GetStockがサービス名となっています。



   11     <!-- メッセージ型宣言 -->
   12     <!-- SOAPで受け渡しするメッセージの形式を定義します。 -->
   13     <message name="GetStockRequest">
   14       <part name="product_id" type="xsd:string"/>
   15     </message>
   16     <message name="GetStockResponse">
   17       <part name="result" type="xsd:int"/>
   18     </message>


message要素は、SOAPで受け渡しするメッセージの形式を定義します。 本チュートリアルで実装するのは前述のように、 『文字列型の「商品ID」を与えると現在の在庫量が「整数」で返るだけのシンプルなサービス』だけですから、 メッセージの種類も引数(…商品ID…文字列…)と、返値(…在庫量…整数…)を表すために、 二つのメッセージ要素: GetStockRequestとGetStockResponseが定義されています。



   20     <!-- ポート型宣言 -->
   21     <!-- メッセージ型宣言で定義したメッセージ型を利用して、メッセージの
   22     フォーマット定義します。 -->
   23     <portType name="GetStock">
   24       <operation name="getStock" >
   25         <input  message="tns:GetStockRequest"/>
   26         <output message="tns:GetStockResponse"/>
   27       </operation>
   28     </portType>


port要素/operation要素は、 入力(引数)と出力(返値)のメッセージフォーマットをmessage要素での定義を参照しながら定義します。 ここでは、GetStockRequest/GetStockResponseを用いて在庫量検索のための操作getStockを定義しています。 関連する操作が集めてポート型を定義しますが、 このサンプルでは操作getStockひとつだけになっているので簡単です。



   30     <!-- バインディング宣言 -->
   31     <!-- ポート型宣言で定義したポートを実際のプロトコル(ここではHTTP)と
   32     結び付けます。 -->
   33     <binding name="GetStockBinding" type="tns:GetStock">
   34       <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
   35       <operation name="getStock">
   36         <soap:operation soapAction="getStock"/>
   37         <input>
   38           <soap:body use="encoded" 
   39                      namespace="urn:scm.nichiden-pc.co.jp" 
   40                      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   41         </input>
   42         <output>
   43           <soap:body use="encoded" 
   44                      namespace="urn:scm.nichiden-pc.co.jp"
   45                      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   46         </output>
   47       </operation>
   48     </binding>


binding要素は、 先に定義したポート型に属する操作それぞれに、 具体的なプロトコルを関連づけます。 このサンプルでは操作getStockに対して、 プロトコルとしてはSOAPを用いてRPC形式で呼び出すものとしてバインディングを定義しています。



   50     <!-- サービス宣言 -->
   51     <!-- バインディング宣言で定義したバインディングの実際のアクセス方法
   52     を定義します。ここでは、HTTPとしてアクセスするためのURLが指定されて
   53     います。 -->
   54     <service name="GetStockService">
   55       <port name="GetStock" binding="tns:GetStockBinding">
   56         <soap:address location="http://localhost/scm/services/GetStock"/>
   57       </port>
   58     </service>


service要素は、Webサービスを提供するURLを定義します。本チュートリアルではURLを http://www.nichiden-pc.co.jp/scm/services/GetStockと定義していますが、 この例では http://localhost/scm/service/GetStockに置き換えています。

※注意事項
 proxyサーバを利用している場合、"localhost"という名前を正しく解決できないので、 "localhost"の代わりに"(ローカルのマシン名)"を記述してください。


8.3.2. サービスを実装する

WSDLは、 Webサービスを利用するための「インターフェース」、つまり呼び出しかたを定義しているだけなので、 これだけで在庫量の検索ができるわけではありません。 本当に在庫量の検索をするためには、 実際に「在庫量の検索」を行うようなプログラムを記述する必要があります。

今回は、WSDLを先に作成し、この仕様を満たすJavaの実装をつくります。 このような場合にはWebOTXに付属するWSDL2Javaというツールを使うと、 クライアント側(Webサービス利用側)とサーバ側(Webサービスの提供側)のコードの「一部」(すべてではありません)を自動生成することができます。 本節ではWSDL2Javaを使いながら、 先ほど定義したWSDLファイルの実装をしてみましょう。


8.3.2.1. WSDL2Javaを用いたサーバコードの実装

WSDL2Javaを用いると、 クライアント側(Webサービス利用側)とサーバ側(Webサービスの提供側)のコードの一部を自動生成することができます。

自動生成されるのは、 WSDLファイルに記述された内容を元にして クライアント側でWebサービスを呼び出すための処理を行ったり、 サーバー側で受信したSOAP形式のXMLメッセージからそれを処理するJavaプログラムを呼び出す部分だけで、 当然ですがすべてのプログラムが自動的に生成されるわけではありません。 しかし、WSDL2Javaを用いれば、 SOAP呼び出しのための固有のコーディングを最小限にすることができ、 通常のJavaアプリケーションを作成するのに近い労力で、 SOAP呼び出しを行うWebサービスJavaアプリケーションを作成することができます。

本節では、WSDL2Javaを用いてWebサービスのサーバー側を実装をしてみます。

WSDL2Javaでサーバサイドのコードを生成するには、 オプション-sを指定してWSDL2Javaを起動します。

例えば、先ほど説明した本チュートリアルで用いているscm-ws.wsdlの場合は:
% java org.apache.axis.wsdl.WSDL2Java -s scm-ws.wsdl
のようになります。

WSDL2Javaは以下のようなファイルを生成します。 標準では、生成されるファイルのプレフィックス(GetStock)やパッケージ名はWSDLファイルの記述内容によって決定されます。

  1. GetStock.java
  2. GetStockBindingImpl.java
  3. GetStockBindingStub.java
  4. GetStockService.java
  5. GetStockServiceLocator.java
  6. deploy.wsdd

このうち斜体(italic)で表示したファイルはクライアント側で使用するコードです(後で説明します)。

以下がサーバ側で使用するコードです。

  1. GetStock.java:
    日電PC社のSCMにWebサービスクライアントからアクセスするためのJavaインターフェースが定義されたファイルです。
  2. GetStockBindingImpl.java:
    WSDLで定義したバインディング GetStockBinding を実際に処理するプログラムの、 「テンプレート」として利用することができるファイルです。 WSDL2Javaを用いてWSDLからJavaコードを生成する場合には、このファイルを編集すれば良いでしょう。
  3. deploy.wsdd:
    サービスを配備する時に必要になる情報を納めたファイルです。サービスを配備するときに使用します。

GetStockBindingImpl.javaというファイルには、 scm-ws.wsdlの記述に基づいて以下のようなコードが自動生成されますが、 このファイルには、 クラスGetStockBindingImplが定義されており、 ただひとつのメソッドgetStockがあります。 引数がproduct_idとなっていること、返り値がintであることから、 これが在庫量検索のためのメソッドであることがわかります。



    1   /**
    2    * GetStockBindingImpl.java
    3    *
    4    * This file was auto-generated from WSDL
    5    * by the Apache Axis WSDL2Java emitter.
    6    */
    7   
    8   package jp.co.nichiden_pc.scm;
    9   
   10   public class GetStockBindingImpl implements jp.co.nichiden_pc.scm.GetStock{
   11       public int getStock(java.lang.String product_id) throws java.rmi.RemoteException {
   12           return -3;
   13       }
   14   
   15   }


しかし、上記のコード(12行目)は単に定数値(-3)を返すだけのダミーです。 実際に在庫量検索を行うには、 この部分に、 在庫量検索を行うプログラムを記述する必要があります。

実際のSCMシステムでは単に在庫量の検索をするだけでも複雑な処理が行われますが、 このサンプルは、Webサービスについての説明行うためのチュートリアルの一部なので、 以下のように実装してみました。



    1   /**
    2    * GetStockBindingImpl.java
    3    *
    4    * This file was auto-generated from WSDL
    5    * by the Apache Axis WSDL2Java emitter.
    6    */
    7   
    8   package jp.co.nichiden_pc.scm;
    9   
   10   public class GetStockBindingImpl implements jp.co.nichiden_pc.scm.GetStock{
   11       public int getStock(java.lang.String product_Id) throws java.rmi.RemoteException {
   12           return (int) (100 * Math.random()); // 変更部分: 0-100までの乱数を返す
   13       }
   14   
   15   }


在庫量は、0から100までの整数を乱数で返します。

このサンプルでは、サービスの実装はこのファイル(GetStockBindingImpl.java)だけですのでコンパイルは以下のように簡単です。
% javac jp/co/nichiden_pc/scm/GetStockBindingImpl.java
ただし、 GetStockBindingImpl.javaは同じ生成されたファイルGetStock.javaを参照しており、 これも同時にコンパイルされます。


8.3.2.2. サービスの配備

次に、前節でコンパイルしたサービスの実装を実際にWebサービスとして呼び出し可能にしてみましょう。

本来ならば、前節でコンパイルして得られたクラスファイルを使用し、 Webサービスとして動作するWebアプリケーションを作成するのですが、 このチュートリアルでは作成済みのWebアプリケーション(WARファイル)を利用してサービスの配備を行います。 WebサービスをWebアプリケーションとして開発する方法の詳細については 「アプリケーション開発ガイド - 3.1.1 Webアプリケーションの開発」をご覧ください。

配備するWebアプリケーションは次のディレクトリにWARファイル形式で格納してあります。

{WebOTXインストールディレクトリ}/UDDIReg/samples/scm.war
このWARファイルを利用してサービスを配備しましょう。3.6 WARの配備に記述された手順に従って配備してください。


8.3.3. サービスを呼び出してみる

次に進む前に、正しく配備されたか確認するため、上記のサービスを呼び出してみましょう。 サービスのアクセスポイントはWSDLのサービス宣言で記述した次のURLを使用します。

http://localhost/scm/services/GetStock

※注意事項
 proxyサーバを利用している場合、"localhost"という名前を正しく解決できないので、 "localhost"の代わりに"(ローカルのマシン名)"を記述してください。

ブラウザからこのURLにアクセスしてください。サービスが正しく呼び出されると 次のような画面が表示されます。

動作確認


8.4. UDDIに登録する

前節では、 本チュートリアルでのサンプルとして、 在庫量を調べるWebサービスを実装し、配備しました。 本節では、 このサービスを利用可能にするために適切なUDDIデータを用意して、 WebOTX UDDI Registryに登録してみます。

UDDIレジストリに登録するデータは以下の5種類です。

  1. tModel
    Webサービスの技術情報/仕様を表すためのデータ構造です。 同じ仕様でサービスを行う異なるWebサービスは、 tModelを共有することで同一のサービスを提供することを表現します。
  2. businessEntity
    Webサービスを提供する企業などのビジネス主体を表すためのデータ構造です。
  3. businessService
    ある企業(businessEntity)によって提供されるサービスを表すためのデータ構造です。
  4. bindingTemplate
    Webサービスへの接続情報などを表すためのデータ構造です。
  5. publisherAssertion
    企業(businessEntity)間の関係、(親会社-子会社 など)を表すためのデータ構造です。 本チュートリアルでは使用しません。

詳細は、2.1. UDDIとはを参照してください。

WebOTX UDDI Registryでは、 UDDIの発行APIを用いてプログラムから上記のデータを登録することができるだけではなく、 上記のデータ構造をXML形式でファイルに保存し、 このファイルをGUIからアップロードすることでUDDIデータの登録を行うこともできます。 本チュートリアルでは、XMLファイル形式でこれらのデータを用意し、 GUIを通してWebOTX UDDI Registryに登録してみます。


8.4.1. tModelを用意する

まずは、WebOTX UDDI Registryに登録するtModelを用意します。

tModelは、UDDIにおいて、Webサービスの「仕様」を表すためのデータ構造です。 その意味ではWSDLと関連があります。 WSDLとの違いは、WSDLがWebサービスの仕様「そのもの」を表すのに対して、 tModelが、UDDIの内部においてWSDLを含む各種の仕様を一意に識別するためのデータ構造である、という点です。 このためtModelには、WSDLや仕様書へのポインタやUDDIの内部でtModelを検索するための情報が保持されているだけで、 WSDLのように直接Webサービスに関する情報が記載されているわけではありません。

先に作ったwsdlファイルをもとに、このWSDLファイルに対応するtModelを作成します。

以下が、日電PCのSCMシステムを表すtModel(サンプルのtModelはここ)です。



    1   <?xml version="1.0" encoding="shift_jis"?>
    2   <tModel tModelKey="">
    3       <name>Nichiden-PC SCM Web Service tModel</name>
    4       <description xml:lang="en">tModel for Nichiden-PC SCM system.</description>
    5       <description xml:lang="ja">日電PC サプライチェーンマネージメントシステムのためのtModel。</description>


この部分は、tModelの名称と、このtModelの簡単な説明を記述しています。



    6       <overviewDoc>
    7           <description xml:lang="en">Description of overviewDoc of this tModel</description>
    8           <description xml:lang="ja">このtModelについての概要文書。</description>
    9           <overviewURL useType="text">http://www.nichiden-pc.co.jp/scm-ws.pdf</overviewURL>
   10       </overviewDoc>
   11       <overviewDoc>
   12           <description xml:lang="en">WSDL for this tModel</description>
   13           <description xml:lang="ja">このtModelについてのWSDL文書</description>
   14           <overviewURL useType="wsdlInterface">http://www.nichiden-pc.co.jp/scm-ws.wsdl</overviewURL>
   15       </overviewDoc>


overviewDoc要素は、 このtModelについての説明を行う文書に関する情報を記述するための要素です。 description要素でこの文章についての説明が記述できます。 また、overviewURL要素を使って、 このtModelが示すWebサービスの仕様に関する文章やWSDLファイルのURLを指定することもできます。



   16       <categoryBag>
   17         <keyedReference keyName="uddi-org:types:wsdl"
   18   		      keyValue="wsdlSpec"
   19   		      tModelKey="uddi:uddi.org:categorization:types"/>
   20         <keyedReference keyName="uddi-org:types:soap"
   21   		      keyValue="soapSpec"
   22   		      tModelKey="uddi:uddi.org:categorization:types"/>
   23         <keyedReference keyName="uddi-org:types:xml"
   24   		      keyValue="xmlSpec"
   25   		      tModelKey="uddi:uddi.org:categorization:types"/>
   26         <keyedReference keyName="uddi-org:types:specification"
   27   		      keyValue="specification"
   28   		      tModelKey="uddi:uddi.org:categorization:types"/>
   29       </categoryBag>
   30   </tModel>


categoryBag要素は、 目的とするtModelを検索しやすくするような分類情報を付加します。 このtModelでは、wsdlファイルを公開していることと、SOAPインタフェースでサービスにアクセス可能 であることを分類情報として付加しています。


8.4.2. businessEntityを用意する

businessEntityは、UDDIにおいてビジネスの主体(企業)を表すためのデータ構造です。 このためbusinessEntityには、企業自体の記述や、連絡先などの情報が保持されています。 さらにbusinessEntityには、その内部に複数のbusinessServiceを持つことができます。

社内でWebサービスを運営する場合には、 必ずしもbusinessEntityを「会社」とする必要はないでしょう。

以下が、日電PCのSCMシステムを表すbusinessEntity(サンプルのBusinessEntity)です。



    1   <?xml version="1.0" encoding="shift_jis"?>
    2   <businessEntity businessKey="">
    3      <name xml:lang="en">Nichiden-PC Intranet WebService</name>
    4      <name xml:lang="en">日電PC Webサービス サイト</name>
    5      <description xml:lang="en">Nichiden PC Web Service site.</description>
    6      <description xml:lang="ja">日電PC Webサービスのサイトです。</description>


name要素はこのbusinessEntityの名称を、description要素はこのbusinessEntityに対する簡単な説明記述しています。



    7      <contacts>
    8         <contact useType="">
    9            <description xml:lang="en">Please contact us for questions.</description>
   10            <description xml:lang="ja">質問はこちらまでどうぞ。</description>
   11            <personName xml:lang="en">Taro Nichiden</personName>
   12            <personName xml:lang="ja">日電太郎</personName>
   13            <phone>123-4567</phone>
   14            <email>taro.nichiden@nichiden-pc.co.jp</email>
   15         </contact>
   16      </contacts>
   17   </businessEntity>


contact要素は、businessEntityの連絡先に関する情報を記述しています。

このサンプルでは、内部にbusinessServiceを保持していません。 UDDIレジストリでは、 既存のbusinessEntityに対して、 businessServiceを追加したり削除したりすることができますが、 WebOTX UDDI RegistryでXMLファイルをアップロードする場合にも、 あとからbusinessServiceを追加することができます。 次節で、businessServiceを追加してみましょう。


8.4.3. businessService/bindingTemplateを用意する

businessServiceは、ある企業(businessEntity)が提供するひとつのサービスを表すデータ構造です。 さらにbusinessServiceには、その内部に複数のbindingTemplateを持つことができます。

以下が、日電PCのSCMシステムを表すbusinessService(サンプルのBusinessService)です。



    1   <?xml version="1.0" encoding="shift_jis"?>
    2   <businessService serviceKey="" businessKey="uddi:607c7828-49b6-f2e7-1cc9-6b16fb34a28e">
    3                         <!-- このbusinessKeyを先に登録したnichiden-pc-be.xmlのbusinessEntityのbusinessKeyに変更してください。 -->
    4      <name xml:lang="en">SCM Service</name>
    5      <name xml:lang="ja">SCM サービス</name>
    6      <description xml:lang="en">Nichiden PC Supply Chain Management System Web Service.</description>
    7      <description xml:lang="ja">日電PC サプライ・チェーン・マネージメント システムのWebサービスです。</description> 

name要素はこのbusinessServiceの名称を、description要素はこのbusinessServiceに対する簡単な説明記述しています。



    9      <bindingTemplates>
   10         <bindingTemplate>
    :
   18         </bindingTemplate>
   19      </bindingTemplates>
   20   </businessService>


businessService要素の子要素として、 bindingTemplates要素を介して複数のbindingTemplate要素を持つことができます。 しかし、 このチュートリアルの例では、 簡単にするため、 ただひとつだけのbindingTemplateを定義しているだけです。

さて、そのbindingTemplateを見ていきます。



   10         <bindingTemplate>
   11            <description xml:lang="en">Nichiden PC SCM Web Service site.</description>
   12            <description xml:lang="ja">日電PC SCMサービス Webサービスのサイトです。</description>
   13            <accessPoint useType="endPoint">http://localhost/scm/services/GetStock</accessPoint>


description要素は、このbindingTemplateの簡単な説明です。 また、13行目のaccessPoint要素は、 useType="endPoint"が指定されている場合、 このWebサービスのアクセスポイントが、 URL(http://localhost/scm/services/GetStock)であることを表しています。

本チュートリアルでは、URLを

http://www.nichiden-pc.co.jp/scm/services/GetStock

と定義していますが、

UDDIクライアントアプリケーション動作させるために、この例では

http://localhost/scm/service/GetStock

に置き換えています。

※注意事項
 proxyサーバを利用している場合、"localhost"という名前を正しく解決できないので、 "localhost"の代わりに"(ローカルのマシン名)"を記述してください。



   14            <tModelInstanceDetails>
   15               <tModelInstanceInfo tModelKey="uddi:947d354f-696e-67b5-d13b-52f48f8dfc5c"/>
   16                          <!-- このtModelKeyを先に登録したnichiden-pc-tmodel.xmlのtModelのtModelKeyに変更してください。 -->
   17            </tModelInstanceDetails>
   18         </bindingTemplate>


tModelInstanceDetails要素は、 tModelInstanceInfoを複数保持するコンテナ要素です。 tModelInstanceInfoには、 このbindingTemplateに関連づけられたtModelを指定するために用いられます。 上の例では、このbindingTemplateが先に定義したtModelに関連づけられたbindingTemplateであることを表しています。


8.4.4. GUIを使ったUDDIデータの登録

以降の節では、 これまで説明したUDDIデータのXML形式ファイルを、 GUIから登録します。

管理者は「管理コンソール」もしくは「データ・マネージャ」から、 WebOTX UDDI Registryにアカウントを持つユーザーは「データ・マネージャ」から、 それぞれ、UDDIデータのXML形式ファイルをGUIから登録します。 管理コンソールとデータ・マネージャでは、 データのアップロード画面にいたる操作方法が異なりますが、 アップロードの方法自体は同じです。 以降では、データ・マネージャを用いてデータのアップロードを行います。

データ・マネージャは通常のインストール方法の場合、 以下のアドレスでアクセスすることができます。

http://(WebOTX UDDI Registryをインストールしたホスト)/uddi/publisher/

詳しくは5.3.4.4. UDDIデータのアップロードを ご覧ください。


8.4.5. GUIから上記tModelを登録

まず、アップロード画面を呼び出します。 遷移方法は、左メニューの「自ビジネス情報の管理」を押してから、 主画面左下の「アップロード」ボタンを押します。

すると、次のように「UDDIデータのアップロード」画面が現れます。

アップロード画面

次に「ファイルネーム」欄 右の「参照」ボタンを押します。 すると、「ファイルの選択」ダイアログが現れます。

アップロード画面 with ファイルダイアログ

ここで、アップロードするtModelのXMLファイルを指定してから、 「アップロード」ボタンを押してください。

成功画面

無事、アップロードが完了した場合、 上のような完了画面が表示されます。

さて、ここで指定したtModelのXMLファイルの内容が確かにアップデートされたか確認しましょう。 左メニューの「自ビジネス情報の管理」を押します。 すると、再び「自ビジネス情報の管理」画面が現れ、 tModelの欄が一行増え、確に登録されているのがわかります。

登録後画面

tModelの名称部分を押すと、 tModelの詳細情報が表示されますから、 tModelの内容を詳細に確認できます。

登録後画面

さて、この「tModel詳細」画面で表示されるtModelのキーを、 あとで使用しますのでどこかに保存しておいてください。


8.4.6. GUIから上記businessEntityを登録

さて、businessEntityの情報を登録するために、再び、アップロード画面を呼び出します。 画面左、メニューの「自ビジネス情報の管理」を押します。 さらに画面下左の「アップロードボタン」を押してください。

アップロード画面

次に「ファイル指定」ボタンを押します。 すると、「ファイル選択ダイアログ」が現れます。

アップロード画面 with ファイルダイアログ

ここで、アップロードするbusinessEntityのファイルを指定してから、 「アップロード」ボタンを押します。

成功画面

無事、アップロードが完了した場合、 上のような完了画面が表示されます。

たしかにアップデートされたか確認しましょう。 左メニューの「自ビジネス情報の管理」をします。 すると、いまアップロードされたbusinessEntityが表示されているのがわかります。

登録後画面

businessEntityの名称部分を押すと、businessEntityの詳細情報が表示されます。

登録後画面

ここで表示されるbusinessKeyの値を、 次節で使用しますのでどこかに保存しておいてください。


8.4.7. GUIから上記businessService/bindingTemplateを登録

businessServiceやbindingTemplateをアップロードする場合、 親のbusinessEntityとbusinessServiceをそれぞれ指定する必要があります。 businessServiceはその親としてbusinessEntityを、 bindingTemplateはその親としてbusinessServiceを必要とするからです。

これらのデータ構造の詳細は2.2. UDDIレジストリとそのデータ構造をご覧ください。

そのため、businessServiceをアップロードする前に、 まず、businessServiceの親のbusinessEntityを指定するために、 サンプルファイル、nichiden-pc-bs.xmlを変更します。 変更するのは、2行目です。



    1   <?xml version="1.0" encoding="shift_jis"?>
    2   <businessService serviceKey="" businessKey="uddi:607c7828-49b6-f2e7-1cc9-6b16fb34a28e">
    3                         <!-- このbusinessKeyを先に登録したnichiden-pc-be.xmlのbusinessEntityのbusinessKeyに変更してください。 -->
    4      <name xml:lang="en">SCM Service</name>
    5      <name xml:lang="ja">SCM サービス</name>
    6      <description xml:lang="en">Nichiden PC Supply Chain Management System Web Service.</description>
    7      <description xml:lang="ja">日電PC サプライ・チェーン・マネージメント システムのWebサービスです。</description>


上で、"uddi:607c7828-49b6-f2e7-1cc9-6b16fb34a28e"となっているところ、 前節の最後のbusinessKeyの値と置き換えてください。 これにより、このbusinessServiceが属する親businessEntityが指定されたことになります。

ただし、 businessService/bindingTemplteをその親のbusinessEntity/businssServiceの一部として一括して保存する場合には、 その親は自動的に判別されるのでキーを指定する必要はありません。

さらに、ここでアップロードするbindingTemplateが、 先にアップロードしたtModelに関連付けるため、 tModelIntanceInfo要素のtModelKey属性を書き換えます。



   14            <tModelInstanceDetails>
   15               <tModelInstanceInfo tModelKey="uddi:uddi.org:transport:http:get"/>
   16               <tModelInstanceInfo tModelKey="uddi:947d354f-696e-67b5-d13b-52f48f8dfc5c"/>
   17                          <!-- このtModelKeyを先に登録したnichiden-pc-tmodel.xmlのtModelのtModelKeyに変更してください。 -->
   18            </tModelInstanceDetails>
   19         </bindingTemplate>


上で、"uddi:947d354f-696e-67b5-d13b-52f48f8dfc5c"となっているところ、 前節の最後のtModelKeyの値と置き換えてください。

さて、この二つの書き換えを行ったら、 再び、アップロード画面を呼び出します。 画面左、メニューの「自ビジネス情報の管理」を押します。 さらに画面下左の「アップロードボタン」を押します。

アップロード画面

次に「ファイル指定」ボタンを押します。 すると、「ファイル選択ダイアログ」が現れます。

アップロード画面 with ファイルダイアログ

ここで、アップロードするbusinessService/bindingTemplateのファイルを指定してから、 「アップロード」ボタンを押します。

成功画面

無事、アップロードが完了した場合、 上のような完了画面が表示されます。

たしかにアップデートされたか確認しましょう。 左メニューの「自ビジネス情報の管理」を押し、businessEntityの名称部分を押します。 するとビジネス詳細画面のサービス一覧にbusinessServiceが表示されているのがわかります。

登録後画面

businessServiceの詳細を押すと、businessServiceの詳細情報が表示されます。

登録後画面


8.5. UDDIを検索する

本節では、実際にUDDIに登録したデータをもとに、 そのデータの検索と登録したサービスの呼び出しを行います。


8.5.1. GUIから検索する

サービスを検索する最も簡単な方法は、WebOTX UDDI Registryのレジストリ・ブラウザを使う方法です。 レジストリ・ブラウザは通常のインストール方法の場合、 以下のアドレスでアクセスすることができます。

http://(WebOTX UDDI Registryをインストールしたホスト)/uddi/browser/

日電PC社の場合、http://uddi.www.nichiden-pc.co.jp/uddi/browser/にアクセスすれば、 レジストリ・ブラウザのGUIで対話的に、 日電PC社のSCMシステムの情報を入手できるでしょう。

人手によってWebサービスの情報を入手する場合には、 GUIを用いるのが最も簡単です。


8.5.2. クライアントプログラムからサービスを検索して呼び出す。

前節ではGUIでWebサービスを検索する方法について述べました。 しかし、この検索をプログラムから行いたい場合もあります。 例えば、将来の「日電PC社」のSCMシステムを考えてみましょう。 今のところ、 「日電PC社」のSCMシステムのアクセスポイントは一カ所しかありませんから、 ここにアクセスするプログラムを書くことはできます。 しかし、近い将来、SCMシステムが各工場に設置された時にはどうでしょう? アクセスポイントは、複数になるかも知れませんし、変更されてしまうかも知れません。 その度にGUIから、SCMシステムのアクセスポイントをすべて列挙して、 それをもとにプログラムを変更するのは如何にも面倒です。

このような場合には、UDDI APIを用いて、サービスをプログラムで検索するのが良いでしょう。 UDDI自身もWebサービスなのでプログラムから検索することもできます。 この、UDDIレジストリにアクセスするためのライブラリが、 WebOTX UDDI Registry クライアントライブラリです。

本節では、 WebOTX UDDI Registry クライアントライブラリを用いて、 「日電PC社」のSCMシステムのアクセスポイントを検索し、 さらに、このアクセスポイントに対して、実際にSOAP呼び出しを行い、 先に実装したサービスを呼び出すクライアント・プログラムを作成します。 具体的には、以下のようなプログラムを作成します。

日電PC社の社内UDDIレジストリに登録されたSCMシステムのアクセスポイントをすべて列挙し、 そのアクセスポイントに対して先にWSDLファイル(scm-ws.wsdl)で定義した、 getStockを呼び出す。
これにより、社内の各地区における在庫量に関する情報が容易に入手できるようになります。 (実際のSCMシステムはこんなに単純ではありません。 これはあくまでチュートリアルのため極めて簡素化した例です。)

まず、サービスの呼び出し部分のコードを、WebOTXのWSDL2Javaツールを利用して生成します。 先ほど、サーバー側のコード生成にもWSDL2Javaを使用しました。クライアントサイドのコードは、 先ほどサーバサイドのコードを生成した際に同時に生成されているので、それを利用します。 また、以下のようにクライアントサイドのコードだけを生成してもかまいません。

% java org.apache.axis.wsdl.WSDL2Java scm-ws.wsdl

以下の2つのファイルがクライアントサイドのコードとして生成されます。

  1. GetStock.java
    日電PC社のSCMにWebサービスクライアントからアクセスするためのJavaインターフェースが定義されたファイルです。
  2. GetStockBindingStub.java
    WSDLに基づいてSOAP呼び出しを行うクラスで、 GetStock.javaで定義されるJavaインターフェースを実装(implements)しています。 このクラスの中に、Webサービスクライアントで日電PC社のSCMにアクセスするSOAP呼び出しのためのJavaコードがまとめられていますので、 GetStock.javaで定義されるJavaインターフェースを元にしたプログラムを記述するだけで、 日電PC社のSCMにアクセスすることができます。

上の二つをファイルを使用する主クラスとして、 以下のプログラムを作成します。

このプログラムは単一のクラスSCMClientからなり、以下の三つのメソッドをもちます。

  1. doFind()
    UDDIレジストリの検索を行うメソッドです。
  2. getStock(Vector,String)
    UDDIを検索して得られた(複数の)アクセスポイントに対して 実際のSOAP呼び出しを行うメソッドです。
  3. main()
    このプログラムのエントリポイントです。上の二つのメソッドを呼び出し、最終結果を表示します。

さて、このメソッドを順番にみていきましょう。

まず、クラスの先頭では、UDDIのアクセスポイントが定数として定義されています。



   25   public class SCMClient {
   26       
   27       /**
   28        * UDDIのアクセスポイント
   29        *
   30        */
   31       public static final String targetURL = "http://uddi.www.nichiden-pc.co.jp/uddi/services/UDDIService";
   32   


この値をdoFind()メソッドは利用します。 次がdoFind()メソッドの本体です。



   67       /**
   68        * 指定してたtModelKeyを持つ、検索キーとしてWebサービスを検索するメソッド
   69        *
   70        * @return 接続先URL文字列のベクター
   71        */
   72       public Vector doFind() {
   73           Vector accessPoints = new Vector();;
   74   
   75           // UDDIクライアントマネージャの作成を行う
   76           UDDIClientManager manager = new UDDIClientManager();
   77   
   78           try {
   79               // メッセージの発行先URLを指定する。
   80               URL inquiryURL = new URL(targetURL); // 参照系メッセージ送信URL
   81               URL publishURL = new URL(targetURL); // 更新系メッセージ送信URL
   82               manager.setInquiryURL(inquiryURL);
   83               manager.setPublishURL(publishURL);


まず、 UDDIクライアントライブラリの主クラスである、 UDDIClientManagerのインスタンスを生成します。 さらに、UDDIレジストリのアクセスポイント(31行目で定義した定数targetURL)を設定します。

さて、ここでUDDIに対する検索条件を考えてみます。 このプログラムでの検索条件は、 「日電PC社のSCMシステムの全アクセスポイント」ですから、

「日電PC社のSCMシステム」を表すtModelに関連付けられたbindingTemplateを検索し、そこからAccessPointを得る、
としましょう。



   85               //検索キーとなるtModelKeyを指定
   86               TModelBag tb = new TModelBag();
   87               tb.addTModelKey(new TModelKey("uddi:11216026-4f38-a70b-65d5-08a6677f2a05"));
   88   	    //                             ↑このtModelキーの値を変更してください。


まず、tModelを指定します。 uddi:11216026-4f38-a70b-65d5-08a6677f2a05の部分は、 先に保存した日電PC社のtModelの値に置き換えてください。 この指定は、bindingTemplateの検索対象として、 「日電PC社」のSCMシステムのアクセスポイントであるものを選ぶことになります。



   94               //bindingTemplateの検索を行い、指定されたtModelKeyを持つbindingTemplateの集合を取得
   95               BindingDetail bd = manager.find_binding(10, null, 1, null, qualifiers, tb, null, null);


次に、このtModelを持つbindingTemplateをUDDIClientManagerクラスのfind_bindingメソッドを呼び出すことで検索します。

WebOTX UDDI Registryクライアントライブラリは、 find_bindingメソッドは検索結果として、 BindingDetailクラスのインスタンスを返します。 BindingDetailクラスは、 UDDI Version 3.0 APIにおけるbindingDetail要素に対応しており、 bindingTemplateの検索結果集合を表しています。



   97               //Webサービスの接続先情報を取り出す
   98               for (int i = 0; i < bd.size(); i++) {
   99                   BindingTemplate bt = bd.elementAt(i);
  100                   AccessPoint ap = bt.getAccessPoint();
  101                   accessPoints.add(ap.getAccessPoint());
  102                   System.out.println("AccessPoint = " + ap.getAccessPoint());
  103               }


BindingDetailクラスは、 メソッドsize()を持ち、 いくつのbindingTemplateを持つのかを調べることができ、 さらにelementAt()メソッドを用いて、 i番目のbindingTemplateを取り出すことができるので、 これらを使ってbindingTemplateをひとつづつ取出します。 さらにこのbindingTemplateから、 接続先情報が記しているaccessPointを取出します。 このアクセス先情報は、Vectorに集められ、最後に本メソッドの結果として返されます。



  114           //接続先のベクターを返す
  115           return accessPoints;
  116       }


次に、 doFind()メソッドで得られた、 アクセス先に順番にアクセスしてSOAP呼び出しを行うメソッドgetStock() です。



   33       /**
   34        * 製品IDを検索キーとして在庫量を検索するWebサービスにアクセスするメソッド
   35        *
   36        * @param accessPoints	アクセス先のURL文字列のベクタ
   37        * @param Product_ID	在庫量検索対象の製品ID文字列(ただしダミーなので適当な文字列を指定) 
   38        * @return 接続先URL,製品ID,在庫量の三つの文字列を一組としたベクター。接続先がn個所ならこの長さはn*3。
   39        *
   40        */
   41       public Vector getStock(Vector accessPoints, String Product_ID){


getStock()メソッドは、2つの引数を持ちます。 ひとつ目の引数は、doFind()メソッドで求めたWebサービスのアクセス先URLのベクタ、 二つ目の引数は、在庫量を調べる製品の製品IDです(ただしこの値はダミーで実際には使われません。)。



   42           Vector stockValues = new Vector();
   43           for (int i = 0; i < accessPoints.size(); i++) {
   44               Vector valueSet = new Vector();


getStock()メソッドでは、引数で与えられたアクセスポイントのベクタそれぞれに対して、 SOAP呼び出しを行います。 以下が実際の呼び出し部分です。



   48                   GetStockBindingStub gsbs = new GetStockBindingStub(new URL((String) accessPoints.elementAt(i)), null);
   49   
   50                   //接続先を格納
   51                   valueSet.add((String) accessPoints.elementAt(i));
   52   
   53                   //製品IDを格納
   54                   valueSet.add(Product_ID);
   55   
   56                   //在庫量を格納
   57                   valueSet.add(new Integer(gsbs.getStock(Product_ID)));
   58                   stockValues.add(valueSet);


getStock()メソッドでは、引数で与えられたアクセスポイントのベクタの要素それぞれに対して、 SOAP呼び出しを行います(48行目)。 結果は、 ベクタvalueSetに保存されますが、 プログラムの簡便化のため、 (接続先、製品ID、在庫量)の三つを一組して保存することに注意してください。



   63           //検索結果の集合を返す
   64           return stockValues;
   65       }


最後に検索結果のベクタを返します。



  119       /**
  120        * サンプルプログラムのエントリーポイント
  121        *
  122        * @param args 未使用
  123        *
  124        */ 
  125       public static void main(String[] args) {


main()メソッドは、本プログラムのエントリーポイントです。



  126           SCMClient example = new SCMClient();
  127   
  128           //UDDIレジストリから接続先リストを取得
  129           Vector accessPoints = example.doFind();


まず、doFind()メソッドでUDDIから接続先のURLベクタを得ます。



  131           //検索キーとなる製品IDを指定
  132           String Product_ID = "Product_ID"; // 本サンプルでは製品ID文字列はダミーです。
  133           Vector stockValues = new Vector();
  134   
  135           //GetStockサービスに接続
  136           try {
  137               stockValues = example.getStock(accessPoints, Product_ID);
  138           } catch (Exception e) {
  139               e.printStackTrace();
  140           }


つぎに、この接続先情報を、(ダミーの)製品IDを指定して、在庫量を調査します。



  142           //結果表示
  143           System.out.println("==getStock RESULT==");
  144           for (int i = 0; i < stockValues.size(); i += 3) {
  145               Vector valueSet = (Vector) stockValues.elementAt(i);
  146               System.out.print(i + 1);
  147               //接続先を表示
  148               System.out.println(". " + (String) valueSet.elementAt(0));
  149               //製品IDを表示
  150               System.out.print("            "+(String) valueSet.elementAt(1) + "'s stock value =");
  151               //在庫数を表示
  152               System.out.println((Integer) valueSet.elementAt(2));
  153           }


最後に結果を表示します。 ベクタstockValuesには、 三つ一組で値が入っているのでこれを順に取り出して表示します。

実行結果

%java jp.co.nichiden_pc.scm.SCMClient

AccessPoint = http://localhost/scm/services/GetStock
==getStock RESULT==
1. http://localhost/scm/services/GetStock
            Product_ID's stock value =6
%

以上で、チュートリアルは終了です。