| 6. WebOTX UDDI Registryアプリケーション開発ガイド |
| 6.1. 概要 |
本章では、UDDIクライアントAPIを使用した、 クライアントアプリケーションの実装方法について説明します。
クライアントアプリケーションを作成するための参考例として、 次の五つのサンプルプログラムを紹介します。
find_business、find_service、get_serviceDetailAPIを利用した照会APIのサンプルです。
save_business APIを利用した発行APIのサン
プルです。
save_subscription、get_subscriptionResultAPIを利用したサブスクリプショ ンAPIのサンプルです。
UDDIクライアントAPIの署名機能を用いてUDDIデータへの署 名の付加と、付加されている署名の検証を行うサンプルです。
UDDIクライアントAPIのマルチバージョン機能を用いた、単 一アプリケーションからV2/V3双方のレジストリに接続可能なプログラム を作成するサンプルです。
これらのプログラムを実際に実行するには、 環境に合わせてプログラムの変更が必要になります。 詳しくは6.7. 実行方法をご覧ください。
| 6.2. 照会APIのサンプル: FindExample |
FindExampleは、照会APIを利用したサンプルで、以下のAPIを使用しています。
find_business
find_service
get_serviceDetail
| 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行目のuserとpassはユーザー名とパスワードを文字列として与えています。
| 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行目)、
そのnamesをBusinessEntityのメンバとして設定します(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のメンバとして設定します。最後に、
BusinessEntityへBusinessService自身を設定します。
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"をもつAccessPointを
BindingTemplateオブジェクトのメンバに設定します。最後に、
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はサポートしていません。)
さて、サブスクリプション情報を登録すると、 その条件に合致する更新情報が取得できますが、 この取得方法には、以下の三つの方法があります。
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_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 }
コマンドライン引数でsave、get、
list、deleteを指定することで、それぞれ
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データに対して署名の付加を行い、また、検証を行うことができます。
UDDIClientManagerクラスの
setSignMode(boolean)/setVerifyMode(boolean)を呼び出します。
署名/検証を行うにはこれらのメソッドにtrueを与えてください。
実際に署名の生成と検証を行うにはプログラムでの指定と合わせて、 署名のための秘密鍵/公開鍵や認証のための証明書を保存するキーストアを、 適切に設定する必要があります。
実際には、署名の付加・検証を行う場合に事前の準備としてキーストアに関連した以下の作業を行います。 UDDIクライアントライブラリでは、Javaのデフォルトの実装であるキーストアを使用し、 このキーストアの管理にはJDKのkeytoolコマンドを使用します。
署名の生成と検証に必要な秘密鍵と公開鍵を生成します。
署名の検証を行う場合に必要となる公開鍵(を含む証明書)をエクスポートします。 署名検証者がこの公開鍵(を含む証明書)をインポートすることで、 データの発行者が正しくデータを発行し、そして署名しているかどうかを、検証することができます。
鍵ペアの生成時に生成される(公開鍵を含む)証明書は、 自分自身(の秘密鍵)で署名された自己署名証明書になっています。 証明書を証明書発行局 (CA : Certification Authority) に署名してもらうことにより、 第三者からの信用を得やすくなります。 証明書署名要求の生成は、証明書発行局に証明書への署名を依頼するための電子情報を生成するステップです。
署名の検証を行う場合には、署名者の証明書をインポートすることで、他人の付加した署名の検証を行うことができます。 また、「証明書署名要求の生成」を行った場合に証明書発行局が発行する電子情報をとりこむ場合にも証明書のインポートを行う必要があります。
キーストアやkeytoolコマンドの詳細な説明は、Sunマイクロシステムズ社の ページを参照してください。また、署名処理の ためのキーストアに対する操作の概要についてはSunマイクロシステムズ社の チュートリアルページもご参照下さい。以下では、各ステップでの keystoreコマンドの使用方法の概略を述べるにとどめます。
keytool -genkey -alias 鍵のalias名 -keystore キーストアファイル名
keytool -export 鍵のalias名 -keystore キーストアファイル名 -file エキスポートした証明書を出力するファイル名
keytool -certreq -alias 鍵のalias名 -keystore キーストアファイル名 -file 証明書署名要求を出力するファイル名
keytool -import -alias 鍵のalias名 -keystore キーストアファイル名 -file インポートする証明書のファイル名
| 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. 事前準備 |
署名の付加/検証のサンプルを実行する前に、 前節での内容をふまえて事前の準備、すなわち、 以下のようなキーストアの設定を行います。
xmlsec.propertiesファイルの配置サンプル実行のために、 ここでは「証明書署名要求(の生成)」と「証明書のインポート」は行いません。
鍵ペアを生成するにはkeytoolコマンドを使用します。 サンプルプログラム (SigBESaveExample.javaとSigBEGetExample.java) の設定に合わせて以下のような設定で行います。
JKS
changeit
dsakey
changeit
DSA
.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. 実行方法の変更も合わせて行ってください)。
サンプルプログラム中でUDDIキーを指定している部分を、 登録先(サンプルプログラムでtargetURLで指定したURLのUDDI)のノードIDを元に変更してください。 UDDIのノードIDは、WebOTX UDDI Registryの場合、管理者が事前に設定しています(3.3.1. server.properties参照)。 わからない場合は、管理者にお尋ね下さい。通常は、"uddi:"の右にノードのホスト名を付加したものになっているでしょう。 例えば、登録先UDDIのノードIDがuddi:hostname.nec.co.jpの場合には、サンプルで以下のようになっている部分を:以下のように変更します。businessEntity.setBusinessKey("uddi:mycompany.co.jp:test-be");これをビジネスキー(businessEntity.setBusinessKey("uddi:hostname.nec.co.jp:test-be");uddi:mycompany.co.jp:test-beだけでなく)、 サンプルで指定しているUDDIエンティティの全てのキー (uddi:mycompany.co.jp:test-bsやuddi:mycompany.co.jp:test-bt) についても変更してください。
| 6.5.5. SigBESaveExample |
まずは、署名の付加のサンプルから見てみましょう。
署名を付加してUDDIデータを登録する際の注意事項は以下の二点です。
この点に注意してサンプルを見てみましょう。
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は以下の機能を持っています。
ただし、どのようなプログラム/UDDIデータでもUDDI Version 2.0仕様とUDDI Version 3.0仕様の双方で出力可能なわけではありません。 UDDI Version 2.0仕様とUDDI Version 3.0仕様双方で動作するプログラムを作成するには、 以下の点を守る必要があります。
マルチバージョン機能を使用するための全く新規なAPIは、
UDDIClientManagerクラスのsetVersion()だけで、
これに以下の値を引数として指定します。
UDDIClientManager.VERSION3: Version 3としてAPIを発行 (デフォルト。データはV2形式で生成出来る必要があります。)UDDIClientManager.VERSION2: Version 2としてAPIを発行 (データはV2形式で生成出来る必要があります。)UDDIClientManager.AUTO: 送信先のレジストリがVersion 3で無ければ、Version 2でAPIを発行。ただし。データがV3形式でもV2形式でも生成できる必要があります。| 6.6.2. マルチバージョン機能によるデータ生成の概要 |
本節では、マルチバージョン機能による行われるデータ生成の概要について説明します。
前節で説明したように、
UDDIClientManagerクラスのsetVersion()で
UDDIClientManager.VERSION2を指定したり、
UDDIClientManager.AUTOを指定した結果としてV2形式で送信する場合には、
V2形式でデータの生成が行われます。
| 6.6.2.1. データ |
UDDIのAPI発行時に送信されるXML形式のデータは以下のように生成されます。
keyedReferenceGroup要素)が使用されている場合、
例外UDDIClientExceptionが、エラーコードE_versionModeMismatchを伴って、発生します。
(プログラム中ではUDDIClientException.getErrorCode()メソッドで
UDDIErrorConst.E_versionModeMismatchが返ります。)
| 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()メソッドで明示的に指定する必要があります。
このように、 既存のクライアント・アプリケーションをマルチバージョン化するには以下の作業を行うだけです。
| 6.6.6. 実行 |
では実際に実行してみます。
「6.6.4. main()メソッド」で見たように、引数として
2、3、Aのいずれかを与えます。
>java MVCExample A |
自動モードで実行する場合です。
>java MVCExample 3 |
Version 3モードで実行する場合です。
>java MVCExample 2 |
Version 2モードで実行する場合です。
このようにUDDIクライアントライブラリを用いたプログラムに簡単な修正 を施すことによってV2レジストリに対してもV3レジストリに対しても動作する プログラムを簡単に作成することができます。
| 6.7. 実行方法 |
ここでは、これまでにご紹介したサンプルプログラムを実行する方法について説明します。
プログラムサンプルは、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";
続いて、書き換えを行なったサンプルプログラムをコンパイルします。 コンパイルするためには、以下の表の保存場所にインストールされている 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/ |
実行するには、前項「コンパイル」で挙げた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の手順を省略できます。
サーバがエキスポートした証明書をクライアント側のキーストア読み込みます。 これには、JDKに付属のkeytoolコマンドを使用します。
keytool -import -v -trustcacerts -file 証明書ファイル -keystore キーストア・ファイル |
キーストアファイルができれば、
このファイルをクライアントプログラムに指定する必要があります。
これには、システムプロパティjavax.net.ssl.trustStoreを使用します。
クライアントプログラム実行時に以下のように引数に追加すれば良いでしょう。
-Djavax.net.ssl.trustStore=./client.keystore |
キーストアにパスワードが設定されている場合、これにあわせて、
システムプロパティjavax.net.ssl.trustStorePasswordを使用します。
-Djavax.net.ssl.trustStorePassword=パスワード |
以上の設定により、HTTPSプロトコルを用いてレジストリにアクセスすることが可能になります。