6. WebOTX UDDI Registryアプリケーション開発ガイド

6.1. 概要

本章では、UDDIクライアントAPIを使用した、 クライアントアプリケーションの実装方法について説明します。

クライアントアプリケーションを作成するための参考例として、 次の五つのサンプルプログラムを紹介します。

これらのプログラムを実際に実行するには、 環境に合わせてプログラムの変更が必要になります。 詳しくは6.7. 実行方法をご覧ください。


6.2. 照会APIのサンプル: FindExample

FindExampleは、照会APIを利用したサンプルで、以下のAPIを使用しています。


6.2.1. 前処理

実際に、FindExampleのソースの中を見てみます。

FindExampleで、主な処理を行っているのは、doFindメソッ ドです。



24:   public void doFind() {
25:
26:     // クライアントマネージャの作成を行う
27:     UDDIClientManager manager = new UDDIClientManager();
28:


メソッドの定義の先頭で、UDDIClientManagerオブ ジェクトを生成(27行目)しています。UDDIClientManagerクラスは、UDDI クライアントにおいて、クライアントアプリケーションとサーバであるUDDI Registryとの通信を管理するクラスです。

UDDIレジストリに対する検索/発行の操作、このクラスを通して行われる ことになりますが、 クライアントAPIはUDDIClientManagerクラ スのメソッドとして実装されているため、UDDIClientManagerク ラスのメソッド呼び出しがUDDIクライアントAPIの呼び出しに他なりません。



21:    public static final String targetURL = "http://mycompany.co.jp/uddi/services/UDDIService";

:

31:       // メッセージの発行先URLを指定する。
32:       // 照会メッセージ送信URL
33:       URL inquiryURL = new URL(targetURL);
34:       // 更新系メッセージ送信URL
35:       URL publishURL = new URL(targetURL);
36:
37:       manager.setInquiryURL(inquiryURL);
38:       manager.setPublishURL(publishURL);


次に、UDDIレジストリへメッセージを送信するための送信先URLを設定して います。

メッセージ送信先のURLは、照会APIと発行APIで別々に設定することが できます。

照会メッセージの送信先URLは、setInquiryURLメソッドを 使用して設定(36行目)し、 発行メッセージの送信先URLは、 setPublishURLメソッドを使用して設定(37行目)します。


6.2.2. find_business APIの利用

ここからは、検索のための各APIを実行するための前段階として、検索条件 を表すオブジェクトの作成方法を説明します。

find_business APIの仕様は、以下のようになっています。



public BusinessList find_business(int maxRows,
                                  int listHead,
                                  AuthInfo authInfo,
                                  FindQualifiers findQualifiers,
                                  Vector names,
                                  IdentifierBag identifierBag,
                                  CategoryBag categoryBag,
                                  TModelBag tModelBag,
                                  Find_tModel find_tModel,
                                  DiscoveryURLs discoveryURLs,
                                  Find_relatedBusinesses find_relatedBusinesses
                                 )
                              throws UDDIClientException


UDDIクライアントAPIでは、検索条件をオブジェクトとして組み立てた後、 (照会)APIに引数として渡すことによって検索を行います。 このサンプルで は検索条件として、会社名(複数指定できますが、ここでは1個だけ指定しま す)を指定するVectorのnamesと、 デフォルト検索動作を変 更を指示(例えば、「大文字小文字を区別する」といった指定)するための FindQualifiersオブジェクトを生成し、 これを引数としてAPI 呼び出しを行うことで検索を行います。



40:         // 検索キーとして、nameを指定する。"NEC"を検索する。
41:         Vector names = new Vector();
42:
43:         names.add(new Name("NEC sample", "en"));
44:
45:         FindQualifiers qualifiers = new FindQualifiers();
46:
47:         qualifiers.addFindQualifier(FindQualifier.APPROXIMATE_MATCH);


41行目のVectorオブジェクトnamesは、 検索条件としての名前を表すNameオブジェクトを複数まとめたものを表しています。 このサンプルでは、検索条件は1個だけなので、 "NEC sample"という名前のNameオブジェクトを生成、 ベクターに追加しています。 find_business APIは、 複数のNameによる検索も実行できるので、 さらに検索キーとなるNameオブジェクトをVectorに追加することも可能です。

次に、45行目でFindQualifiersオブジェクトを生成しています。 これを用いて、細かい検索動作を指定することが可能です。 変更可能な検索動作の例としては、 大文字小文字を無視するかしないか、 検索結果ソートする際の順序などがあります(詳しくは、 UDDI Version 3.0仕様の5.1.4 "Find Qualifiers"をご覧ください)。 このサンプルでは、 APPROXIMATE_MATCH (Nameで指定した名前をもとにあいまい検索をする)という条件を設定しています。



49:         // 最大応答結果を10件に設定し、namesにより検索を行う。
50:         // その他の指定しない項目は、nullを設定する。
51:         BusinessList list = manager.find_business(10, 1, null, qualifiers, names,
52:                 null, null, null, null, null, null);


最後に、find_businessメソッドを実行します。 先ほど作成したオブジェクトを、引数として設定します。 第1引数に指定されている"10"は、最大応答結果数です。 これにより、応答結果の数を最大で10件に限定することができます。 検索キーとして使用しない引数にはnull(オブジェクトの場合)または-1(整数の場合)を設定します。 このAPIの実行が成功すると、BusinessListオブジェクトが返されます。 逆に失敗すると、UDDIClientException例外が発生します。 例外処理については、6.3.4. 例外処理で説明します。


6.2.3. find_service APIの利用

find_service APIの仕様は以下のようになっています。



public ServiceList find_service(int maxRows,
                                String businessKey,
                                int listHead,
                                AuthInfo authInfo,
                                FindQualifiers findQualifiers,
                                Vector names,
                                CategoryBag categoryBag,
                                TModelBag tModelBag,
                                Find_tModel find_tModel
                                ) throws UDDIClientException {


find_businessと同様に、 検索キーとして使用するオブジェクトを引数に設定します。



65:       Vector serviceNames = new Vector();
66:       serviceNames.add(new Name("Web Service", "en"));
67:


検索キーとして、言語コード"en" (英語)を指定した"Web sample"という 名前のNameオブジェクトを生成します。これにより、英語の名称 が"Web sample"というサービスを検索します。



68:       // businessEntity配下にあり、name値を持つserviceを検索する
69:       // 指定しないその他の項目は、nullを設定する。
70:       ServiceList serviceList = manager.find_service(0, businessKey.getBusinessKey(),
71:               0, null, null, serviceNames, null, null, null);


find_businessで取得したbusinessKeyと、 65行目で生成した検索キーのNamesオブジェクトを引数に設定し ます。find_serviceの呼び出しが成功すると、 ServiceListオブジェクトが返されます。失敗すると、 UDDIClientException例外が発生します。

ServiceListオブジェクトは、buinessServiceを表す BusinessServiceオブジェクトのリストになっています。


6.2.4. get_serviceDetailの利用

get_serviceDetail APIの仕様は、以下のようになっていま す。



    public ServiceDetail get_serviceDetail(AuthInfo authInfo,
                                           Vector serviceKeys
                                          )
          throws UDDIClientException


serviceKeyのベクターを指定することにより、複数のBusinessServiceの詳細 な情報を取得することができます。



73:       // find_serviceの結果から、serviceKeyを取得する
74:       ServiceInfo serviceInfo = serviceList.getServiceInfos().elementAt(0);
75:       ServiceKey serviceKey = new ServiceKey(serviceInfo.getServiceKey());
76:
77:       // 結果表示
78:       System.out.println("find_service RESULT :");
79:       System.out.println("serviceKey = " + serviceKey.getServiceKey());
80:
81:       Vector serviceKeys = new Vector();
82:
83:       serviceKeys.add(serviceKey);


find_serviceにより取得できたserviceKeyを、 新たにServiceKeys(ServiceKeyのベクター)に設定 します。取得したいBusinessServiceが複数存在する場合は、 ここで、 addServiceKeyメソッドを用いて、 別の ServiceKeyを追加することも可能です。



85:       // serviceKey値により、businessServiceの詳細情報を取得する。
86:       ServiceDetail serviceDetail = manager.get_serviceDetail(null, serviceKeys);
87:       BusinessService businessService = (BusinessService) serviceDetail.getBusinessServices().elementAt(0);


83行目で得られたserviceKeysを引数として、 get_serviceDetail APIを実行します。 処理が成功すると、 ServiceDetailオブジェクトが返されます。 失敗すると、UDDIClientException例外が発生します。


6.2.5. 例外処理

UDDIクライアントAPIは処理に失敗した場合、 UDDIClientExceptionを発生します。 このオブジェクトの中には、 DispositionReportという、 エラーの詳細な情報を保持しているオブジェクトがあります。 エラーの原因を追求するための参考にすることができます。



 96:     } catch (UDDIClientException uddie) {
 97:       ErrInfo info = uddie.getDispositionReport().getResult().getErrInfo(0);
 98:
 99:       System.out.println("code = " + info.getErrorCode());
100:       System.out.println("message = " + info.getErrorMessage());


このサンプルでは、Exceptionをcatchしたあと、エラー内容を表示しています。


6.3. 発行APIのサンプル: SaveBusinessExample

SaveBusinessExampleでは、 save_business APIを使用して、 BusinessEntity, BusinessService, BindingTemplateを新規に追加する方法を示しています。 save_***APIを使用して、新規にデータを登録する際は、 そのデータを一意に決定するためのキー情報の設定は不要ですが、 データの更新を行う時には、キー情報の設定は必須となります。


6.3.1. 前準備

SaveBusinessExample内でメインの処理を行っているのは、 doSaveメソッドです。



26:    public static final String targetURL = "http://mycompany.co.jp/uddi/services/UDDIService";




38:   public void doSave() {
39:
40:     // クライアントマネージャの作成を行う
41:     UDDIClientManager manager = new UDDIClientManager();
42:
43:     try {
44:       // メッセージの発行先URLを指定する。
45:       // 照会メッセージ送信URL
46:       URL inquiryURL = new URL(targetURL);
47:       // 更新系メッセージ送信URL
48:       URL publishURL = new URL(targetURL);
49:
50:       manager.setInquiryURL(inquiryURL);
51:       manager.setPublishURL(publishURL);


UDDIClientManagerの生成、送信先URLの設定は、FindExampleの時と同じです。



53:       // メッセージを発行するための認証情報を取得する。
54:       AuthToken authToken = manager.get_authToken(user, pass);
55:       AuthInfo authInfo = authToken.getAuthInfo();


照会APIと異なり、発行APIでは、通常UDDIレジストリのデータを変更する際に認証を受け、 認証トークンを取得しなければいけません。 上の例では、get_authToken APIを使用し、 AuthTokenを取得しています。 54行目のuserpassはユーザー名とパスワードを文字列として与えています。


6.3.2. save_business APIの利用

save_business APIの仕様は以下のようになっています。



public BusinessDetail save_business(AuthInfo authInfo,
                                    Vector businessEntities)
                                    throws UDDIClientException


55行目で取得したAuthInfoオブジェクトと、 登録するBusinessEntityのベクター businessEntitiesを引数として設定します。 このAPIを使用することで、 BusinessEntityとその子供のBusinessService、BindingTemplateを登録することができます。 これから、それぞれのオブジェクトの作成方法を説明します。

・BusinessEntityの作成



57:         // businessEntityを新規登録するメッセージの作成を行う。
58:         // businessEntityを作成する。
59:         BusinessEntity businessEntity = new BusinessEntity();
60:
61:         // 必須項目name要素を作成し、nameリストへ追加
62:         Vector names = new Vector();
63:
64:         names.add(new Name("NEC sample", "en"));
65:         businessEntity.setNames(names);


まず、BusinessEntityオブジェクトを生成します(59行目)。 そして、"NEC sample"という名前をもったNameを ベクターnamesに追加し(64行目)、 そのnamesBusinessEntityのメンバとして設定します(65行目)。

BusinessEntityが持つその他の属性・要素も同様な方法によっ て、設定することができます。

・BusinessServiceの作成



67:         // 新規businessService を作成する。
68:         BusinessService service = new BusinessService();
69:         Vector serviceNames = new Vector();
70:
71:         serviceNames.add(new Name("Web Service", "en"));
72:         service.setNames(serviceNames);
73:         BusinessServices services = new BusinessServices();
74:
75:         services.addBusinessService(service);
76:         businessEntity.setBusinessServices(services);


BusinessEntityと同様な方法で、 BusinessServiceを生成し、"Web Service"という名前をもった NameをベクターserviceNamesに追加し、 BusinessServiceのメンバとして設定します。最後に、 BusinessEntityBusinessService自身を設定します。

BusinessServiceが持つその他の属性、要素も同様な方法に よって、設定することができます。

・BindingTemplateの作成



78:         // 新規bindingTemplate を作成する。
79:         BindingTemplate binding = new BindingTemplate();
80:
81:         binding.setAccessPoint(new AccessPoint("http://www.mycompany.jp",
82:                 "http"));
83:         BindingTemplates bindings = new BindingTemplates();
84:
85:         bindings.addBindingTemplate(binding);
86:         service.setBindingTemplates(bindings);


ここでも同様に、BindingTemplateを生成し、 アクセスポイント"http://www.mycompany.co.jp"をもつAccessPointBindingTemplateオブジェクトのメンバに設定します。最後に、 BusinessServiceオブジェクトへ、 BindingTemplateオブジェクト自身を設定します。

BindingTemplateが持つその他の属性、要素も同様な方法によって、 設定することができます。


6.3.3. save_business APIの実行


88:         // businessEntity を、businessEntityリストへ追加する。
89:         Vector entities = new Vector();
90:
91:         entities.add(businessEntity);
92:
93:         // save_businessAPI を実行する。
94:         BusinessDetail detail = manager.save_business(authInfo, entities);


最後に、先ほど作成したBusinessEntityをベクターentitiesに追加します(89、91行目)。 そして、 save_businessを実行します(94行目)。 処理が成功すると、登録したBusiness情報が返されます。 失敗すると、UDDIClientExceptionが発生します。


6.3.4. 例外処理

UDDIクライアントAPIは処理に失敗した場合、 UDDIClientExceptionを発生します。このオブジェクトの中には、 DispositionReportという、エラーの詳細な情報を保持しているオブジェクトがあります。 エラーの原因を追求するための参考にすることができます。



 99:     } catch (UDDIClientException uddie) {
100:         ErrInfo info = uddie.getDispositionReport().getFirstResult().getErrInfo();
101:
102:         System.out.println("code = " + info.getErrorCode());
103:         System.out.println("message = " + info.getErrorMessage());


このサンプルでは、Exceptionをcatchしたあと、 DispositionReportオブジェクトからエラー情報を取り出して(100行目)、 エラーコードとエラーメッセージを表示しています。


6.4. サブスクリプションAPIのサンプル: SubscriptionExample

6.4.1. サブスクリプションAPIの概要

サブスクリプションAPIは、大きく二つの種類に分けることができます。

一つ目は、save_subscription、delete_subscription、get_subscriptions、get_subscriptionResultsです。 これらのAPIは、それぞれ、サブスクリプション情報の保存、削除、取得、更新情報の同期的取得を行いますが、 いづれもサーバ(レジストリ)側で動作します。

二つ目は、notify_subscriptionListenerで、保存したサブスクリプション情報に基づいて、 レジストリが更新情報の通知を行う際に、 サーバ(レジストリ)側からクライアント側を呼び出すAPIです。 そのため、これをクライアントサイドAPIと呼ぶことにします。 (本UDDIクライアントライブラリではクライアントサイドAPIはサポートしていません。)

さて、サブスクリプション情報を登録すると、 その条件に合致する更新情報が取得できますが、 この取得方法には、以下の三つの方法があります。

  • サーバ側からのSOAP呼び出し
    notify_subscriptionListenerクライアントサイドAPIを用いてSOAPによる更新情報の通知を行います。 通知先のURLは、サブスクリプション情報中のbindingKeyにより指示されるbindingTemplate中のaccessPointで指定され(http:かhttps:である必要があります)、 notify_subscriptionListenerクライアントサイドAPIを実装したSOAPサービスである必要があります。
  • サーバ側からのメール送信
    電子メールを用いて更新情報の通知を行います。 通知先の電子メールアドレスは、 通知先のURLは、サブスクリプション情報中のbindingKeyにより指示されるbindingTemplate中のaccessPointで指定され(mailto:である必要があります)、 電子メールの本体は、notify_subscriptionListenerクライアントサイドAPIで通知されるSOAP Bodyになります。
  • get_subscriptionResults APIを用いた更新情報の同期的取得
    get_subscriptionResulst APIを用いてクライアントが、 自分の都合の良いタイミングで更新情報の取得を行います。 更新情報は、このAPIの呼び出しの返値として返されます。
  • notify_subscriptionListener APIは、 この一つ目の通知方法を行う際にサーバ(レジストリ)側がクライアント側を呼び出す際のAPIになります。 そのため、この通知方法を利用する場合には、 クライアント側でこのSOAP呼び出しを処理するためのアプリケーションを作成する必要があります。

    notify_subscriptionListener APIはサーバ(レジストリ)側からクライアント側への、 通常とは逆方向のアクセスとなります。そのため、ファイヤーウォールとの相性もあまりよくありません。

    また、SOAP呼び出しではなく電子メールによる通知も利用することができます。 しかし、電子メールによる通知はSOAP呼び出しのデータがそのまま送信される ように規定されているために、人間には読みにくいものとなっています。これ を電子的に処理する場合には、SOAP呼び出しの場合と同様に、アプリケーショ ンを作成する必要があります。

    そのため、通常は、get_subscriptionResult APIによる同期的な更新情報の取 得を用いるのが便利でしょう。このAPIは、もちろん、本UDDIクライアントAPI でサポートされています。


    6.4.2. サンプルプログラムの構成

    このサンプルは主に以下の四つのメソッドから構成されており、 それぞれ以下のサブスクリプションAPIを呼び出しています。

    サンプルプログラムのメソッド 使用しているサブスクリプションAPI
    doSave() save_subscription API
    doGet() get_subscriptionResults API
    doList() get_subscriptions API
    doDelete() delete_subscpription API

    以下では、 これらのメソッドを順に見ながらサブスクリプションAPIの使用方法を見ていきますが、 まずは、これらのメソッドを呼び出すmain()メソッドを見てみます。 main()は引数を解析してdoSave()/doGet()/doList()/doDelete()を呼び出します。

    
    
       91       public static void main(String[] args) {
       92           SubscriptionExample subscription = new SubscriptionExample();
       93   
       94           if (args.length >= 1) {
       95               if (args[0].equals("save")) {
       96                   subscription.doSave();
       97               } else if (args[0].equals("get")) {
       98                   if (args.length == 2) {
       99                       subscription.doGet(args[1]);
      100                   } else {
      101                       usage();
      102                   }
      103               } else if (args[0].equals("list")) {
      104                   subscription.doList();          
      105               } else if (args[0].equals("delete")) {
      106                   subscription.doDelete(args);
      107               } else {
      108                   usage();
      109               }
      110           } else {
      111               usage();
      112           }
      113       }
    
    
    

    コマンドライン引数でsavegetlistdeleteを指定することで、それぞれ doSave()、doGet()、doList()、doDelete()メソッドを呼び出します。


    6.4.3. サブスクリプションの保存

    まず最初に、save_subscription APIを用いてサブスクリプション情報をレジストリに保存します。

    save_subscription APIの仕様は以下のようになっています。

    
    
    public Subscriptions save_subscription(AuthInfo authInfo,
                                           java.util.Vector subscriptions)
                                    throws UDDIClientException
    
      
    

    一つめの引数は認証情報、 二つ目の引数は保存するSubscriptionクラスのインスタンスのベクターです。

    
    
      133               // メッセージを発行するための認証情報を取得する。
      134               AuthToken authToken = manager.get_authToken(user, pass);
      135               AuthInfo authInfo = authToken.getAuthInfo();
    
    
    

    認証情報は、get_authToken APIを用いて取得できます。

    次に、取得する更新情報に関する条件を指定しながら、 保存するサブスクリプション情報を作成します。

    
    
      138               // 検索キーとして、nameを指定する。"NEC"を検索する。
      139               Vector names = new Vector();
      140   
      141               names.add(new Name("NEC sample", "en"));
      142   
      143               FindQualifiers qualifiers = new FindQualifiers();
      144   
      145               qualifiers.addFindQualifier(FindQualifier.APPROXIMATE_MATCH);
      146   
      147               FindBusiness fb = new FindBusiness();
      148               fb.setNames(names);
      149               fb.setFindQualifiers(qualifiers);
      150   
      151               // 検索条件をもとにサブスクリプション情報を作成。
      152               Subscription subscription  = new Subscription();
      153               SubscriptionFilter sf = new SubscriptionFilter(fb);
      154               subscription.setSubscriptionFilter(sf);
      155               Vector subscriptions = new Vector();
      156               subscriptions.addElement(subscription);
    
    
    

    138行目から149行目では、 取得したい更新情報を選択する条件として照会APIを指定しています。 この照会APIの指定部分は、 照会APIのサンプルと類似しています。 例えば、この例では(照会APIのサンプルと同様に) find_businessを用いて特定の名称("NEC sample")を持つビジネスの更新情報だけを取得するように指定しています。 これらの情報を元にサブスクリプション情報を作成(151行目から154行目)し、 さらにこれをベクターへ追加(155行目、156行目)します。

    
    
      158               // サブスクリプション情報をサーバに保存。
      159               Subscriptions result = manager.save_subscription(authInfo, subscriptions);
      160               Subscription s = result.elementAt(0);
    
    
    

    最後に、認証情報とSubscriptionのベクターを引数として、 save_subscriptionを実行します(159行目)。 処理が成功すると、登録したサブスクリプション情報が返されます。 失敗すると、UDDIClientExceptionが発生します。


    6.4.4. サブスクリプション情報の一覧

    次に保存してあるサブスクリプション情報を一覧してみましょう。

    ある発行者の保存してある全てのサブスクリプション情報を取得するには get_subscriptions APIを用います。

    get_subscriptions APIの仕様は以下のようになっています。

    
    
    public Subscriptions get_subscriptionResults(AuthInfo authInfo)
                                                 throws UDDIClientException
    
      
    

    引数は認証情報authInfoのみで、 この認証情報により特定される発行者が保持する全てのサブスクリプション情報が本APIの実行結果として返されます。

    
    
      238               // メッセージを発行するための認証情報を取得する。
      239               AuthToken authToken = manager.get_authToken(user, pass);
      240               AuthInfo authInfo = authToken.getAuthInfo();
      241   
      242               Subscriptions subscriptions = manager.get_subscriptions(authInfo);
    
    
    

    240行目で取得した認証情報を指定してget_subscriptions APIを呼び出します(242行目)。

    
    
      247               Vector ss = subscriptions.getSubscriptions();
      248               for (int i = 0; i < ss.size(); i++) {
      249                   Subscription s = (Subscription) ss.elementAt(i);
      250                   System.out.println("  Subscription[" + i + "]");
      251                   System.out.println("         brief = " + s.getBrief());
      252                   System.out.println("           key = " + s.getSubscriptionKey().getKey());
      253                   System.out.println("        filter = " + s.getSubscriptionFilter());
      254                   System.out.println("    bindingKey = " + s.getBindingKey());
      255                   System.out.println("      interval = " + s.getNotificationInterval());
      256                   System.out.println("   maxEntities = " + s.getMaxEntities().getMaxEntities());
      257                   System.out.println("        expire = " + s.getExpiresAfter().getExpiresAfter());
      258                   System.out.println("");
      259               }
    
    
    

    ここでは取得したサブスクリプション情報を表示しています。 249行目でSubscrtiponクラスのインスタンスsを取得していますが、 これはsubscrtipon要素の情報を保持するbeanなので、get*()メソッドを用いて設定されている、 サブスクリプション情報を取得することがきます。


    6.4.5. 更新情報の取得

    保存したサブスクリプション情報をもとに、 get_subscriptionResults APIを用いて同期的に更新情報を取得します。

    get_subscriptionResults APIの仕様は以下のようになっています。

    
    
    public SubscriptionResultsList get_subscriptionResults(AuthInfo authInfo,
                                                           SubscriptionKey subscriptionKey,
                                                           CoveragePeriod coveragePeriod,
                                                           ChunkToken chunkToken)
                                                    throws UDDIClientException
    
      
    

    他のUDDIクライアントAPIと同様、 取得すべき更新情報に関する条件をオブジェクトとして作成し、 get_subscriptionResultsに渡します。 引数の意味は以下の通りです。

    
    
      197               // メッセージを発行するための認証情報を取得する。
      198               AuthToken authToken = manager.get_authToken(user, pass);
      199               AuthInfo authInfo = authToken.getAuthInfo();
    
    
    

    まず、認証情報を取得します。

    
    
      202               SubscriptionKey subscriptionKey = new SubscriptionKey(subKey);
      203               CoveragePeriod coveragePeriod = new CoveragePeriod();
      204
      205               SubscriptionResultsList srl = manager.get_subscriptionResults(authInfo, subscriptionKey, coveragePeriod, null);
    
    
    

    次に、サブスクリプション・キー(202行目)と更新情報の取得期間(203行目)を指定して、 get_subscriptionResultsを呼び出します(205行目)。 202行目のサブスクリプション・キーは、 コマンドライン引数で指定されたものがmain()メソッドを経由して、 このメソッドに引数(subKey)として渡されたものです。 また、更新情報の取得期間は指定なし(レジストリの最初の時点から、現在まで)のため、 CoveragePeriodクラスのコンストラクタには何も引数を与えません。

    
    
      207               // 応答結果の表示
      208               makeResponse(srl);
    
    
    

    最後に、get_subscriptionResultsの呼び出しにより取得できたSubscriptionResultsListから、 更新/変更された方法と削除された情報を表示します。


    6.4.6. サブスクリプション情報の削除

    最後に、保存したサブスクリプション情報をdelete_subscription APIを用いて削除してみましょう。

    
    
      293               // メッセージを発行するための認証情報を取得する。
      294               AuthToken authToken = manager.get_authToken(user, pass);
      295               AuthInfo authInfo = authToken.getAuthInfo();
    
    
    

    まず、認証情報を取得します。

    
    
      297               Vector keys = new Vector();
      298               // args[0]は無視する。
      299               for (int i = 1; i < args.length; i++) {
      300                   SubscriptionKey sk = new SubscriptionKey(args[i]);
      301                   keys.addElement(sk);
      302               }
    
    
    

    次に、削除するサブスクリプション情報を指示するサブスクリプション・ キーのためのSubscriptionKeyクラスのインスタンスのベクターを作ります。 これは、サンプルプログラムのコマンドライン引数で指定されたサブスクリプション・キーを引数として、 doDelete()メソッドに渡されたものを元にしています。

    
    
      304               manager.delete_subscription(authInfo, keys);
    
    
    

    最後に、 認証情報とサブスクリプション情報を指示するSubscriptionKeyクラスのインスタンスのベクターを引数として、 delete_subscription APIを呼び出します。


    6.4.7. 実行

    ここで、実際に実行してみましょう。 (実行に先立ってサンプルプログラムの一部を変更する必要があります。 変更/コンパイルの方法は、 「実行方法」を参照してください。)

    まず、コマンドラインの引数にsaveを指定して、 サブスクリプション情報の保存を行います。

    >java SubscriptionExample save
    SubscriptionKey = uddi:3fd52363-4f1c-4a43-01e9-454e414b433e
    

    成功すると、保存されたサブスクリプション情報のキーが表示されます。

    次に、保存されているサブスクリプション情報の一覧を得るために、 コマンドラインの引数にlistを指定して実行してみます。

    >java SubscriptionExample list
      Subscription[0]
             breif = false
               key = uddi:3fd52363-4f1c-4a43-01e9-454e414b433e
            filter = com.nec.jp.uddi.v3.client.datatype.subscription.SubscriptionFilter@1cb52ae
        bindingKey = null
          interval = null
       maxEntities = 0
            expire = 2005-04-20T19:35:05+09:00
    
    

    すると、最初に登録したサブスクリプション情報(ここでは、キーは uddi:3fd52363-4f1c-4a43-01e9-454e414b433e)が表示されました。

    ここで、 コマンドラインの引数にgetと、 サブスクリプション・キー (ここではuddi:3fd52363-4f1c-4a43-01e9-454e414b433e) を指定して、更新情報を取得してみましょう。

    >java SubscriptionExample get uddi:3fd52363-4f1c-4a43-01e9-454e414b433e
    <?xml version="1.0" encoding="UTF-8"?>
    <subscriptionResultsList someResultsUnavailable="true">
    ...
    </subscriptionResultsList>
    
    

    すると、このように更新情報が取得出来ます。

    最後に更新情報の取得が不要になった場合には、 コマンドラインの引数にlistと サブスクリプション・キー (ここではuddi:3fd52363-4f1c-4a43-01e9-454e414b433e) を指定して、実行してみます。

    >java SubscriptionExample delete uddi:3fd52363-4f1c-4a43-01e9-454e414b433e
    Deleted.
    

    削除に成功すると"Deleted."と表示されます


    6.5. 署名機能のサンプル: SigBESaveExample/SigBEGetExample

    本節では、UDDIクライアントAPIを用いてXML署名機能を利用する方法を説明します。


    6.5.1. 電子署名機能の概要

    UDDI Version 3.0仕様では、UDDIのデータ構造に対して電子署名を付加するための仕様が規定されています。 WebOTX UDDI Registryは、UDDI Version 3.0仕様に基づいた、 XML署名の付加と検証を行う機能をUDDIクライアントAPIに追加しました。 これにより、以下のUDDIデータに対して署名の付加を行い、また、検証を行うことができます。

    本UDDIクライアントAPIで、 署名モードをtrueにして、 以下のAPIを使用することでUDDIデータに署名が付加されます。 また、 検証モードをtrueにして、 以下のAPIを使用することでUDDIデータに付加された署名の検証を行うことができます。 署名モード/検証モードを設定するには、それぞれ UDDIClientManagerクラスの setSignMode(boolean)/setVerifyMode(boolean)を呼び出します。 署名/検証を行うにはこれらのメソッドにtrueを与えてください。

    実際に署名の生成と検証を行うにはプログラムでの指定と合わせて、 署名のための秘密鍵/公開鍵や認証のための証明書を保存するキーストアを、 適切に設定する必要があります。

    実際には、署名の付加・検証を行う場合に事前の準備としてキーストアに関連した以下の作業を行います。 UDDIクライアントライブラリでは、Javaのデフォルトの実装であるキーストアを使用し、 このキーストアの管理にはJDKのkeytoolコマンドを使用します。

    署名を付加する場合、署名者は通常以下のステップの作業を行います。
    1. 署名のための鍵ペア(秘密鍵と公開鍵)の生成…既にある秘密鍵を利用する場合は省略可能です。
    2. 証明書署名要求の生成…証明書発行局に公開鍵を署名してもらう場合にのみ必要となるオプションのステップです。
    3. 公開鍵のエクスポート…検証者が署名の検証を行うために必要な公開鍵を用意します。
    4. 公開鍵の配布…エクスポートした公開鍵を検証者に配布します。
    5. UDDIクライアントライブラリを用いた署名の付加…上の秘密鍵を用いて署名を付加したUDDIエンティティの情報をレジストリに保存します。
    署名を検証する場合、検証者は通常以下のステップの作業を行います。
    1. 証明書のインポート…署名者の公開鍵を、検証のために自己のキーストアに保存します。
    2. UDDIクライアントライブラリを用いた署名の検証…上の公開鍵を用いて署名を検証しながらUDDIエンティティの情報をレジストリから取得します。

    キーストアやkeytoolコマンドの詳細な説明は、Sunマイクロシステムズ社の ページを参照してください。また、署名処理の ためのキーストアに対する操作の概要についてはSunマイクロシステムズ社の チュートリアルページもご参照下さい。以下では、各ステップでの keystoreコマンドの使用方法の概略を述べるにとどめます。


    6.5.2. 署名の付加

    電子署名を生成するには、 UDDIClientManagerクラスのsetSignModeメソッドでtrueを設定することで、 save_binding, save_business, save_service, save_tModel, add_publisherAssertions, set_publisherAssertionsの各APIを用いて、 businessEntity/businessService/bindingTemplate/tModel/publisherAssertionの各データを保存する際に電子署名を生成/付加した上で保存することができます。

    さらに、電子署名を付加する場合には、 UDDIClientManagerクラスのsetParametersメソッドを用いて、 以下の「パラメタ」を適切に設定してください。

    パラメタ名 説明
    "StoreType" キーストアの種別。"JKS", "JCEKS"。
    "StorePassword" キーストアにアクセスするためのパスワード。
    "KeyAlias" 秘密鍵の名前。
    "KeyPassword" 秘密鍵を取得するためのパスワード。
    "SignatureAlgorithm" シグネチャ値を計算するためのアルゴリズム。"RSA", "DSA"。
    "KeyInfoType" 公開鍵の書式を定める方式。"RSA", "DSA", "X509"。

    6.5.3. 署名の検証

    署名付きのデータを検証するにはUDDIClientManagerクラスのsetVerifyModeメソッドでtrueを設定することで、 get_bindingDetail, get_businessDetail, get_serviceDetail, get_tModelDetail, find_relatedBusinesses の各APIを呼び出した際に businessEntity/businessService/bindingTemplate/tModel/publisherAssertionの各データに 付加された電子署名の検証を行うことができます。

    署名の検証に成功した場合、 get_bindingDetail, get_businessDetail, get_serviceDetail, get_tModelDetail, find_relatedBusinessesの各APIは、 通常の(署名モードオフの)場合と同じ動作をします。 ですから、この場合には(setVerifyModeメソッドを呼び出す以外の)署名検証を行わない場合のプログラミングと同様です。

    逆に、 署名の検証に失敗した場合、 get_bindingDetail, get_businessDetail, get_serviceDetail, get_tModelDetail, find_relatedBusinessesの各APIは、 署名検証失敗を示す例外が発生します。 例外ハンドラに署名検証失敗時の処理を追加することで、容易に署名対応することができます。

    署名検証の失敗した際に発生する例外はUDDIClientExceptionで、 失敗の具体的な内容はエラーコードで判定することが出来ます。 署名検証の失敗に関連するエラーコードは以下の通りです。

    エラーコード 説明
    E_clientInvalidNode ノードがnullの場合や、ツリー構造が不正な場合
    E_clientTransform XML変換に失敗した場合
    E_clientNoSuchAlgorithm この例外は、ある暗号アルゴリズムが要求されたにもかかわらず、現在の環境では使用できない場合
    E_clientNoSuchProvider この例外は、特定のセキュリティプロバイダが要求されたものの、現在の環境では使用可能でない場合
    E_clientInvalidKey これは無効な鍵 (無効な符号化、長さの誤り、未初期化など) である場合
    E_clientSignature JavaのSignatureオブジェクトで適切に署名生成が行えなかった場合
    E_clientKeyStoreUninitialize キーストアが初期化されていない場合
    E_clientUnrecoverKey この例外は、キーストア内のキーを復元できない場合
    E_clientGeneralIOError 署名対象の入力に失敗した場合
    E_clientDereference 署名対象文書が取得できない場合
    E_clientKeyinfo SignerInfoオブジェクト(keystore)から鍵が取得できなかった場合, 該当するKeyStoreが見つからない場合(DefaultJKS, DefaultJCEKS、ユーザ定義)
    E_clientAccessInvalid セキュリティ違反があった場合
    E_clientProperty CanonicalMethod要素が存在しない場合や、SignatureMethod, Transform DigestMethod要素を追加、設定できない場合

    6.5.4. 事前準備

    署名の付加/検証のサンプルを実行する前に、 前節での内容をふまえて事前の準備、すなわち、 以下のようなキーストアの設定を行います。

    1. 鍵ペアの生成
    2. xmlsec.propertiesファイルの配置
    3. サンプルファイルの一部変更

    サンプル実行のために、 ここでは「証明書署名要求(の生成)」と「証明書のインポート」は行いません。

    鍵ペアを生成するにはkeytoolコマンドを使用します。 サンプルプログラム (SigBESaveExample.javaSigBEGetExample.java) の設定に合わせて以下のような設定で行います。

    以上の設定でホームディレクトリにキーストアファイル.keystoreを作成します。 (パスワードやキーの名称等を変更した場合、サンプルプログラムも同様に変更してください。)

    以下は、Windows環境での実行例です。

    C:\> cd %HOME%
    C:\> keytool.exe -genkey -alias dsakey
    Enter keystore password: changeit
    What is your first and last name?
    [Unknown]: MyName
    What is the name of your organizational unit?
    [Unknown]: MyOU
    What is the name of your organization?
    [Unknown]: MyCompany
    What is the name of your City or Locality?
    [Unknown]: MyCity
    What is the name of your State or Province?
    [Unknown]: MyState
    What is the two-letter country code for this unit?
    [Unknown]: JP
    Is >CN=MyName, OU=MyOU, O=MyCompany, L=MyCity, ST=MyState, C=JP< correct?
    [no]: y
    Enter key password for <dsakey>
    (RETURN if same as keystore password): changeit
    C:\>
    

    以上の操作で、 ホームディレクトリにJKS形式のキーストアファイル.keystoreが作成されました。

    このキーストアの情報を元に以下のサンプルを実行します。 上の入力データを変更した場合は、それに合わせてサンプルプログラムも変更します。 「6.5.5. SigBESaveExample」も参照してください。

    次に、xmlsec.propertiesファイルの配置を行います。

    xmlsec.propertiesファイルは、 署名機能の実装として使用している 「SecureWare/XML署名・暗号開発キット(NEC製)」が必要とするファイルです。
    以下の内容(2行)のファイルをxmlsec.propertiesという名 前で保存し、(.keystoreファイル同様)ホームディレクトリに配 置してください。
    
    
    dom.implementation=PSVI
    casefold.status=SIMPLE
    
    
    

    署名の検証を行う場合は、 検証対象を署名している証明書のインポートを行う必要がありますが、 サンプルの実行では、 証明者が検証するという設定で鍵ペア生成時の(自己証明した)公開鍵を使用するので、 インポートする必要はありません。

    最後に、サンプルファイルを一部変更します( 6.7. 実行方法の変更も合わせて行ってください)。


    6.5.5. SigBESaveExample

    まずは、署名の付加のサンプルから見てみましょう。

    署名を付加してUDDIデータを登録する際の注意事項は以下の二点です。

    1. UDDIClientManager#setSignMode(true)を呼び出すとともに、 UDDIClientManager#setParameters(Properties)で適切なパラメタを設定する。
    2. 署名の有効性を保持するため以下の点に留意する
      1. UDDIデータのキーは全て設定する。
      2. UDDIデータの変更を行う場合は、 一部だけを変更せずに、 変更したいデータを含むbusinessEntity全体を変更/保存する。

    この点に注意してサンプルを見てみましょう。

    
    
       66       /**
       67        * サンプル本体のメソッド。
       68        *
       69        *
       70        */
       71       public void doSave() {
       72           // クライアントマネージャの作成を行う
       73           UDDIClientManager manager = new UDDIClientManager();
       74   
       75           // 署名モードをonにします。
       76           manager.setSignMode(true);
       77   
       78           // 署名付加時に必要になるパラメータを設定します。
       79           Properties p = new Properties();
       80           p.put("StoreType", "JKS"); // キーストアのタイプ: "JCEKS"
       81           p.put("StorePassword", "changeit"); // キーストアにアクセスするためのパスワード
       82           p.put("KeyAlias", "dsakey"); // 秘密鍵の名称
       83           p.put("KeyPassword", "changeit"); // 秘密鍵にアクセスするためのパスワード
       84           p.put("SignatureAlgorithm", "DSA"); // 電子署名に用いるアルゴリズム
       85           p.put("KeyInfoType", "DSA"); // 電子署名に用いるアルゴリズム
       86           manager.setParameters(p);
    
    
    

    76行目で署名モードをonにし、79行目から86行目で署名のためのパラメタを設定しています。

    
    
      105               // 署名付のbusinessEntityを作成する際には、businessKeyを指
      106               // 定する必要があります。businessKeyを指定しないとサーバ側
      107               // がbusinessKeyを割り当てますが、それによって署名が不正に
      108               // なってしまうためです。
      109               BusinessEntity businessEntity = new BusinessEntity();
      110               businessEntity.setBusinessKey("uddi:mycompany.co.jp:test-be");
    
    
    

    businessEntityを保存する場合は、 電子署名の正当性を保持するためbusinessKeyを指定する必要があります(110行目)。 また、同様の理由で、以下のようにbusinessEntityだけでなく、 businessService(とその親businessEntity)とbindingTemplate(とその親businessService)のキーを明示的に指定します。 これ以外については、通常のsave_* APIとほぼ同様です。

    
    
      118               // 新規 businessService を作成する際には、businessEntityと
      119               // 同様、署名の有効性を保つためにserviceKeyを指定する必要
      120               // があります。
      121               // また、(businessServiceの)親のbusinessKeyは、この例の
      122               // save_businessのようにbusinessServiceをbusinessEntityの
      123               // 入れ子として保存する場合には、省略可能ですが、これも署
      124               // 名の有効性を保つために指定する必要があります。
      125               BusinessService service = new BusinessService();
      126               service.setServiceKey("uddi:mycompany.co.jp:test-bs");
      127               service.setBusinessKey("uddi:mycompany.co.jp:test-be");
       :
      140               // 新規 bindingTemplate を作成します。これも上と同様に、自
      141               // 身のbidindingKeyと親のserviceKeyを指定する必要がありま
      142               // す。
      143               BindingTemplate binding = new BindingTemplate();
      144               binding.setServiceKey("uddi:mycompany.co.jp:test-bs");
      145               binding.setBindingKey("uddi:mycompany.co.jp:test-bt");
    
    
    

    このように、 既存のプログラムに対してわずかな変更を加えるだけで、 XML署名の機能を使うことができます。


    6.5.6. SigBEGetExample

    次に、署名の付加のサンプルを見てみましょう。

    
    
       67       /**
       68        * サンプル本体のメソッド。
       69        *
       70        *
       71        */
       72       public void doGet() {
       73           // クライアントマネージャの作成を行う
       74           UDDIClientManager manager = new UDDIClientManager();
       75   
       76           // 検証モードをonにします。
       77           manager.setVerifyMode(true);
       78   
       79           try {
       80               // メッセージの発行先URLを指定する。
       81               // 照会メッセージ送信URL
       82               URL inquiryURL = new URL(targetURL);
       83               manager.setInquiryURL(inquiryURL);
       :
    
    
    

    77行目で署名検証モードをonにしています。 これ以外は、通常のget_* APIの使用と変りはありません。 このように、 既存のプログラムに対してわずかな変更を加えるだけで、 XML署名の機能を使うことができます。

    通常のget_* APIとの違いは発生する例外の種類です。

    署名の生成や検証に失敗した場合は、UDDIクライアントAPIはUDDIClientExceptionを発生させます。

    エラーコードの詳細は、 こちらを参照してください。


    6.6. マルチバージョンクライアント機能のサンプル: MVCExample

    本節では、UDDIクライアントAPIのマルチバージョン機能を利用する方法を説明します。


    6.6.1. クライアントライブラリのマルチバージョン機能の概要

    UDDI Version 3.0仕様は、 「概ね」UDDI Version 2.0仕様に対する機能追加という形になっていますが、 そもそも使用しているXML表現の名前空間が違うために、 完全な「上位互換」にはなっていません。 そのため、例えば、 UDDI Version 2.0仕様に準拠したUDDI4JでUDDI Version 3.0仕様のレジストリにアクセスすることはできません。

    幸い、XMLの表現形式には違いがあるものの、 UDDIのデータの「モデル」には大きな違いがありません。 これを利用して、 一つのデータモデルからUDDI Version 2.0仕様とUDDI Version 3.0仕様、 双方のメッセージ形式でメッセージの送受信を可能にしたのがUDDIクライアントAPIのマルチバージョン機能です。 UDDIクライアントAPIのマルチバージョン機能を用いますと、 単一のプログラムからUDDI Version 2.0仕様とUDDI Version 3.0仕様、 双方の形式でUDDIメッセージを出力するようなプログラムの作成が可能になります。

    UDDIクライアントAPIは以下の機能を持っています。

    1. バージョンを指定してAPIを発行する機能
    2. レジストリの対応バージョンに合わせて送信するメッセージのバージョンを、 Version 3.0仕様からVersion 2.0仕様に落とすことが出来る自動選択機能
    これらの機能は、先のバージョンのUDDIクライアントAPIに統合されています。 また、通常の動作ではVersion 3でメッセージの送受信を行います。このため、 これまでのプログラムはUDDI Version 3.0仕様対応のプログラムとして、そのまま動作します。

    ただし、どのようなプログラム/UDDIデータでもUDDI Version 2.0仕様とUDDI Version 3.0仕様の双方で出力可能なわけではありません。 UDDI Version 2.0仕様とUDDI Version 3.0仕様双方で動作するプログラムを作成するには、 以下の点を守る必要があります。

    1. UDDI Version 2.0仕様とUDDI Version 3.0仕様で共通のデータ構造とAPIのみを使用していること。
    2. UDDI Version 2.0仕様とUDDI Version 3.0仕様で、UDDIのデータを識別する「キー」の表現形式が異なるため、双方の形式で指定していること。
    つまり、UDDI Version 3.0仕様でのみ定義されるデータを用いたりした場合には、「マルチバージョン」としては動作しません。

    マルチバージョン機能を使用するための全く新規なAPIは、 UDDIClientManagerクラスのsetVersion()だけで、 これに以下の値を引数として指定します。

    1. UDDIClientManager.VERSION3: Version 3としてAPIを発行 (デフォルト。データはV2形式で生成出来る必要があります。)
    2. UDDIClientManager.VERSION2: Version 2としてAPIを発行 (データはV2形式で生成出来る必要があります。)
    3. UDDIClientManager.AUTO: 送信先のレジストリがVersion 3で無ければ、Version 2でAPIを発行。ただし。データがV3形式でもV2形式でも生成できる必要があります。
    ただし、この他に、 Version 2でメッセージを送受信するためにVersion 2(でVersion 3とは異なる)固有の形式の情報が必要となる場合に、 それらを適切に設定する必要があります。


    6.6.2. マルチバージョン機能によるデータ生成の概要

    本節では、マルチバージョン機能による行われるデータ生成の概要について説明します。

    前節で説明したように、 UDDIClientManagerクラスのsetVersion()UDDIClientManager.VERSION2を指定したり、 UDDIClientManager.AUTOを指定した結果としてV2形式で送信する場合には、 V2形式でデータの生成が行われます。


    6.6.2.1. データ

    UDDIのAPI発行時に送信されるXML形式のデータは以下のように生成されます。

    1. XMLの名前空間は送信するUDDIのバージョンによって適切なものが設定されます。
    2. UDDI Version 3.0でのみ定義されるXML要素(keyedReferenceGroup要素)が使用されている場合、 例外UDDIClientExceptionが、エラーコードE_versionModeMismatchを伴って、発生します。 (プログラム中ではUDDIClientException.getErrorCode()メソッドUDDIErrorConst.E_versionModeMismatchが返ります。)
    3. それ以外の、UDDI Version 3.0とUDDI Version 2で要素の使用形態(必須要素の有無 等)に違いがある場合などには、 メッセージはV2の形式に変換されレジストリに送信されますが、レジストリがエラーを返す場合があります。 例えば、personName要素は、UDDI Version 3.0仕様では複数指定できますが、UDDI Version 2では一つしか指定できませんが、 personNameを複数指定したデータをUDDI Version 2形式で送信する場合には、 クライアントライブラリからはそのまま送信され、 UDDI Version 2のレジストリがエラーを返すことになります。
    4. V2に固有の属性であるgeneric属性とoperator属性は、 レジストリからの返答にあっても、無視されます。
    5. 検索修飾子については次節を参照してください。

    6.6.2.2. 検索修飾子

    検索修飾子は以下のように生成されます。

    プログラム上で指定した検索修飾子(FindQualifierクラスの 定数…(下図左端))に対して、対応するV2形式の検索修飾子が定義されている場合、 そのV2形式の修飾子に変換します。 V2形式の検索修飾子が定義されていない場合、 その検索修飾子は無視します。

    FindQualifierクラスの定数 V3形式の検索修飾子
    (上:短名形式、下:URI形式)
    V2形式の検索修飾子
    EXACT_MATCH exactMatch
    uddi-org:exactMatch
    exactNameMatch
    CASE_SENSITIVE_MATCH caseSensitiveMatch
    uddi-org:caseSensitiveMatch
    caseSensitiveMatch
    SORT_BY_NAME_ASC sortByNameAsc
    uddi-org:sortByNameAsc
    sortByNameAsc
    SORT_BY_NAME_DESC sortByNameDesc
    uddi-org:sortByNameDesc
    sortByNameDesc
    SORT_BY_DATE_ASC sortByDateAsc
    uddi-org:sortByDateAsc
    sortByDateAsc
    SORT_BY_DATE_DESC sortByDateDesc
    uddi-org:sortByDateDesc
    sortByDateDesc
    OR_LIKE_KEYS orLikeKeys
    uddi-org:orLikeKeys
    orLikeKeys
    OR_ALL_KEYS orAllKeys
    uddi-org:orAllKeys
    orAllKeys
    COMBINE_CATEGORY_BAGS combineCategoryBags
    uddi-org:combineCategoryBags
    combineCategoryBags
    SERVICE_SUBSET serviceSubset
    uddi-org:serviceSubset
    serviceSubset
    AND_ALL_KEYS andAllKeys
    uddi-org:andAllKeys
    andAllKeys
    (なし) (なし) soundex
    APPROXIMATE_MATCH approximateMatch
    uddi-org:approximateMatch:SQL99
    (なし)
    BINARY_SORT binarySort
    uddi-org:binarySort
    (なし)
    BINDING_SUBSET bindingSubset
    uddi-org:bindingSubset
    (なし)
    CASE_INSENSITIVE_SORT caseInsensitiveSort
    uddi-org:caseInsensitiveSort
    (なし)
    CASE_INSENSITIVE_MATCH caseInsensitiveMatch
    uddi-org:caseInsensitiveMatch
    (なし)
    CASE_SENSITIVE_SORT caseSensitiveSort
    uddi-org:caseSensitiveSort
    (なし)
    DIACRITIC_INSENSITIVE_MATCH diacriticInsensitiveMatch
    uddi-org:diacriticInsensitiveMatch
    (なし)
    DIACRITIC_SENSITIVE_MATCH diacriticSensitiveMatch
    uddi-org:diacriticSensitiveMatch
    (なし)
    SIGNATURE_PRESENT signaturePresent
    uddi-org:signaturePresent
    (なし)
    SUPPRESS_PROJECTED_SERVICES suppressProjectedServices
    uddi-org:suppressProjectedServices
    (なし)
    UTS_10 UTS-10
    uddi-org:UTS-10
    (なし)

    6.6.3. MVCExampleサンプルの概要

    では、実際にマルチバージョン対応のアプリケーションのサンプル MVCExample を見てみます。 MVCExampleは、FindExampleを、 マルチバージョン化した例になっています。

    この例を見ると、既存のクライアントプログラムをマルチバージョン化するのが難しくはないことがご理解いただけると思います。


    6.6.4. main()メソッド

    まず、main()メソッドを見てみます。 main()メソッドは、 FindExampleに対して、 サンプルプログラムの動作をコマンドライン引数を通して制御できるようにで変更されています。

    
    
      113           if (args.length == 1) {
      114               if (args[0].equals("2")) {
      115                   v = UDDIClientManager.VERSION2;
      116               } else if (args[0].equals("3")) {
      117                   v = UDDIClientManager.VERSION3;
      118               } else if (args[0].equals("A")) {
      119                   v = UDDIClientManager.AUTO;
      120               } else {
      121                   System.err.println("usage: MVCExample [2|3|A]");
      122                   System.exit(1);
      123               }
      124           }
      125           example.doFind(v);
    
    
    

    コマンドライン第一引数が 2/3/Aかによって、 クライアントライブラリの動作をVersion 2/Version 3/自動モード、 と切り替えてこの指定をdoFind()メソッドに引数として渡すようになっています。


    6.6.5. setVersion() APIの呼び出し

    FindExampleとの違いはsetVersion()メソッドを呼び出している点です。 これによりクライアントライブラリが動作するバージョンを指定することができます。 setVersion()メソッドを呼び出さない場合には、 setVersion(UDDIClientManager.VERSION3)を指定したのと同じになります。

    
    
       27           // クライアントマネージャの作成を行う
       28           UDDIClientManager manager = new UDDIClientManager();
       29           manager.setVersion(v);
    
    
    

    このサンプルでは、前節のコマンドライン引数から得たバージョンの値を引数として受取り、 その値を元にsetVersion()メソッドを呼び出しています。

    この他の違いは、 取得した情報の中から「キー」を得る場合に、 get*KeyV2()メソッド/set*KeyV2()メソッドを用いて、 V2用のキーを取得/設定する点です。

    
    
       51               // 最大応答結果を10件に設定し、namesにより検索を行う。
       52               // その他の指定しない項目は、nullを設定する。
       53               BusinessList list = manager.find_business(10, 1, null, qualifiers, names,
       54                       null, null, null, null, null, null);
       55   
       56               BusinessInfo businessInfo = list.getBusinessInfos().elementAt(0);
       57               BusinessKey businessKey = new BusinessKey(businessInfo.getBusinessKey());
       58               businessKey.setBusinessKeyV2(businessInfo.getBusinessKeyV2());
    
    
    

    FindExampleのコードに加えて、BusinessKey#setBusinessKeyV2()メソッドを呼び出し、 その値をBusinessKey#setBusinessKeyV2()メソッドで明示的に指定しています(58行目)。

    
    
       72               // businessEntity配下にあり、name値を持つserviceを検索する。
       73               // 指定しないその他の項目は、nullを設定する。
       74               ServiceList serviceList = manager.find_service(0, businessKey,
       75                       0, null, null, serviceNames, null, null, null);
       76   
       77               // find_serviceの結果から、serviceKeyを取得する
       78               ServiceInfo serviceInfo = serviceList.getServiceInfos().elementAt(0);
       79               ServiceKey serviceKey = new ServiceKey(serviceInfo.getServiceKey());
       80               serviceKey.setServiceKeyV2(serviceInfo.getServiceKeyV2());
    
    
    

    先の例と同様に、FindExampleとの違いはServiceKey#setServiceKeyV2()メソッドを呼び出している点です。 ServiceKeyオブジェクトを生成する場合に指定するのはV3形式のビジネスキーです。 V2形式のサービスキーはServiceKey#setServiceKeyV2()メソッドで明示的に指定する必要があります。

    このように、 既存のクライアント・アプリケーションをマルチバージョン化するには以下の作業を行うだけです。

    1. UDDIClientManager#setVersion()の呼び出しによるバージョン指定
    2. set*KeyV2()メソッドによるV2キーの設定


    6.6.6. 実行

    では実際に実行してみます。 「6.6.4. main()メソッド」で見たように、引数として 23Aのいずれかを与えます。


    >java MVCExample A
    

    自動モードで実行する場合です。

    >java MVCExample 3
    

    Version 3モードで実行する場合です。

    >java MVCExample 2
    

    Version 2モードで実行する場合です。

    このようにUDDIクライアントライブラリを用いたプログラムに簡単な修正 を施すことによってV2レジストリに対してもV3レジストリに対しても動作する プログラムを簡単に作成することができます。


    6.7. 実行方法

    ここでは、これまでにご紹介したサンプルプログラムを実行する方法について説明します。

    1. ソースの書き換え
    2. プログラムサンプルは、URLや認証のためのアカウント名やそのパスワードなど、 ソースコードの一部を書き換える必要があります。書き換える部分を以下に示します。

      各サンプルプログラム先頭のURLを動作環境に合わせて変更してください。 例えば、FindExample.javaでは、 21行目の太字で示される照会メッセージ送信URLの値を、自分の環境に合わせて書き換えます。 WebOTX UDDI Registry は、標準的なインストールの場合メッセージ送信URLに、 "http://Webサーバ名/uddi/services/UDDIService"を使用しますので、サンプルプルプログラム、 21行目のホスト名の部分(mycomapny.co.jp)をWebOTX UDDI Registryが動作しているホスト名で置き換えてください。 (WebOTX UDDI Registry以外のUDDIレジストリでお試しの場合は、 お使いになるUDDIレジストリのURLで置き換えてください。)

      
      21:    public static final String targetURL = "http://mycompany.co.jp/uddi/services/UDDIService";
      
      
      他のサンプルプログラムでも同様です。

      SaveBusinessExample.java等、認証情報を必要とするサンプルでは、 認証情報を取得するための、ユーザ名とパスワードの文字列を指定していますので、これを変更します。 SaveBusinessExample.javaでは、 28,29行目の太字部分で示されるユーザ名とパスワードを、(必要に応じて)自分の環境で登録済のユーザとそのパスワードに書き換えます。

      
      28:    public static final String user = "admin";
      29:    public static final String pass = "adminadmin";
      
      

    3. コンパイル
    4. 続いて、書き換えを行なったサンプルプログラムをコンパイルします。 コンパイルするためには、以下の表の保存場所にインストールされている jarファイルを環境変数CLASSPATH に追加してください。

      ファイル名 保存場所
      uddirt3.jar (Windows系) : ${WebOTXインストール先ディレクトリ}\lib\
      (UNIX系) : /opt/WebOTX/lib/
      dsig.jar (Windows系) : ${WebOTXインストール先ディレクトリ}\lib\
      (UNIX系) : /opt/WebOTX/lib/
      xsutil.jar (Windows系) : ${WebOTXインストール先ディレクトリ}\lib\
      (UNIX系) : /opt/WebOTX/lib/
      axis.jar 左記リンクから取得できます。
      jaxrpc.jar 左記リンクから取得できます。
      saaj.jar 左記リンクから取得できます。
      wsdl4j.jar (Windows系) : ${WebOTXインストール先ディレクトリ}\lib\
      (UNIX系) : /opt/WebOTX/lib/
      commons-pack.jar (Windows系) : ${WebOTXインストール先ディレクトリ}\lib\
      (UNIX系) : /opt/WebOTX/lib/
      log4j.jar (Windows系) : ${WebOTXインストール先ディレクトリ}\lib\
      (UNIX系) : /opt/WebOTX/lib/
      xercesImpl.jar (Windows系) : ${WebOTXインストール先ディレクトリ}\lib\endorsed
      (UNIX系) : /opt/WebOTX/lib/endorsed/
      xml-apis.jar (Windows系) : ${WebOTXインストール先ディレクトリ}\lib\endorsed
      (UNIX系) : /opt/WebOTX/lib/endorsed/
      xalan.jar (Windows系) : ${WebOTXインストール先ディレクトリ}\lib\endorsed
      (UNIX系) : /opt/WebOTX/lib/endorsed/

    5. 実行
    6. 実行するには、前項「コンパイル」で挙げたjarファイルをCLASSPATHに設定した上で、 コマンドプロンプトから、以下のようなコマンドを実行します。

      %> java サンプルプログラムのクラス名

      実行結果についての説明は、各サンプルプログラムの節を参照してください。


    6.8. HTTPSでの実行方法

    UDDI Version 3.0仕様では、発行APIを用いる際には、 HTTPSプロトコルの使用を推奨しています。

    WebOTX UDDI Registryは、 WebOTXの提供するSSL通信機能によりHTTPSを用いたアクセスが可能になります。

    WebOTXで、HTTPSによる接続を使用するためには、SSL機能をオンにして起動する必要があります。 SSL機能を利用するWebサーバの設定は、WebOTX 共通マニュアルの「運用編」-「 4. HTTPサーバに関する設定」を参照してください。

    UDDIクライアントライブラリで、 HTTPSを使用するには上記のプログラムの説明で"http"となっていたところを"https"に変更する他に、 以下の作業をする必要があります。 ただし、"https"への変更以外では通常プログラムの変更は不要です。


    6.8.1. サーバ側

    WebOTXの内蔵Webサーバを利用する場合は、サーバ側の設定は不要です。次のクライアント側の設定のみ行ってください。
    外部Webサーバを利用する場合は、秘密鍵の生成と、証明書の取得を行う必要があります。 これらの手順についての詳細は、利用されているWebサーバのマニュアルを参照してください。


    6.8.2. クライアント側

    通常、サーバ側ではクライアントのSSL認証を行わないため、クライアント側で行う必要のある作業は、以下の手順となります。なお、WebOTXでは1の作業まで完了したキーストアファイルのサンプル"cacert.jks""WebOTXインストールディレクトリ"/domains/domain1/config配下に用意してありますので、内蔵Webサーバを利用する場合は、これを使って1の手順を省略できます。

    1. サーバの証明書の読み込み

      サーバがエキスポートした証明書をクライアント側のキーストア読み込みます。 これには、JDKに付属のkeytoolコマンドを使用します。

      keytool -import -v -trustcacerts -file 証明書ファイル -keystore キーストア・ファイル

    2. クライアントプログラムへのシステムプロパティ設定

      キーストアファイルができれば、 このファイルをクライアントプログラムに指定する必要があります。 これには、システムプロパティjavax.net.ssl.trustStoreを使用します。 クライアントプログラム実行時に以下のように引数に追加すれば良いでしょう。

      -Djavax.net.ssl.trustStore=./client.keystore

      キーストアにパスワードが設定されている場合、これにあわせて、 システムプロパティjavax.net.ssl.trustStorePasswordを使用します。

      -Djavax.net.ssl.trustStorePassword=パスワード
      上記サンプルのキーストアファイル"cacert.jks"のパスワードはchangeitです。

    以上の設定により、HTTPSプロトコルを用いてレジストリにアクセスすることが可能になります。