 | 级别: 初级 Alfredo da Silva (afdasilv@us.ibm.com), 软件顾问工程师
2001 年 11 月 01 日 为了给 Web 服务开发者提供附加的工具,本文讨论了一个新的 API ― 服务注册代理(Service Registry Proxy,SRP)― 它将提高应用程序开发中的抽象级别并能促成 UDDI 和 WSDL 元素间的无缝集成。
UDDI4J API 的发布(在
参考资料中查看它的链接地址及本文中其他的参考内容)让我们能够创建具有感知 UDDI 的应用程序,使从一开放源代码的 API 中进行
publish 、
unpublish 及
find 操作成为可能。
为了把 WSDL 文档(在
参考资料中查看其链接地址)加入本综合体,我们在 UDDI4J 的上部设计了一个名叫服务注册代理 API(SRP)的新层。
SRP API 元素把 UDDI4J API 的类和 WSDL4J API 所定义的部分类进行封装,进而提供了与 UDDI 注册中心接口连接的方法集。因其提升了抽象级别,所以这种模式简化了应用程序的开发,开发者就可以集中精力到与 Web 服务设计领域直接相关的实体上。
SRP 支持的类
SRP API 的结构围绕以下主要元素组成:服务提供者(Service Provider,SP)、服务定义(Service Definition,SD)、服务实现(Service Implementation,SIMP)及服务接口(Service Interface,SITF),如图 1 所示:
图 1:SRP API 主要元素
-
SP
服务提供者:代表能提供服务的实体。它封装了一个对 UDDI4J 中
BusinessEntity 类的引用。
-
SD
服务定义:将服务分为两部分进行描述:实现(SIMP)与一序列实现的接口(SITF)。
-
SIMP
服务实现:具有双重角色。它一方面呈现相关的 WSDL 实现文档(参见参考资料),同时也引用 UDDI4J 中的
BusinessService 类。
-
SINT
服务接口:同样封装了两个实体:一个 WSDL 接口文档(查看参考资料)和一个对 UDDI4J 中
TModel 类的引用。
由 SIMP 和 SINT 所提供 WSDL 的能力继承于他们的父类
WSDLServiceInfo 。
这样组织能够使 SRP 把 UDDI 和 WSDL 元素结合在一起,与此同时,抽象了它们的概念 ― 所以建立 Web 服务就成为一项更高效的任务了。
SRP 支持的类
在其内部,SRP 有其主要的属性。请参阅
表 1的描述。他们处理与 UDDI4J API 相接的接口并维护相关的 UDDI 注册中心连接信息。
表 1:SRP 属性
|
属性
|
描述
| | protected int maxRowsReturned = 100; | 返回的最大行数 | | protected int numRowsToSearch = 100; | 最大搜索行数 | | protected String inquiryURL; | Find 操作时使用的 URL | | protected String publishURL; | Publish 操作时使用的 URL | | protected String userId; | 连接 UDDI 注册中心的用户标识 | | protected String cred; | 连接 UDDI 注册中心的密码 | | protected UDDIProxy uddiProxy; | UDDI4J 代理对象 |
API 的功能性
SRP API 由下列功能组构成:Publish、Unpublish 及 Find,如
表 2所示。完整的 SRP API javadoc,请参阅
参考资料里面的链接地址。
表 2:SRP 功能组
|
API
|
Sub-API
|
调用方法
|
描述
| | Publish | ? | ? | 发布 ServiceProviders、ServiceDefinition 及 ServiceInterface 对象 | | ? | ? | | ? | | ? | ? | publish (ServiceProvider) : ServiceProvider | ? | | ? | ? | publish (ServiceProvider, ServiceDefinition) : ServiceDefinition | ? | | ? | ? | publish (ServiceInterface) : ServiceInterface | ? | | ? | ? | ? | ? | | Unpublish | ? | ? | 取消发布 ServiceProviders、ServiceDefinition 及 ServiceInterface 对象 | | ? | ? | ? | ? | | ? | ? | unpublish (ServiceProvider) : void | ? | | ? | ? | unpublish (ServiceInterface) : void | ? | | ? | ? | unpublish (ServiceProvider, ServiceDefinition) : void | ? | | ? | ? | ? | ? | | Find | ? | ? | ? | | ? | Service Provider | ? | 给出搜索条件查找 ServiceProvider 对象 | | ? | ? | ? | ? | | ? | ? | findAllServiceProviders (FindQualifiers, boolean) : ServiceProvider[] | ? | | ? | ? | findServiceProvider (ServiceDefinition) : ServiceProvider | ? | | ? | ? | findServiceProvider (String) : ServiceProvider | ? | | ? | ? | findServiceProviders (FindQualifiers, DiscoveryURLs) : ServiceProvider[] | ? | | ? | ? | findServiceProviders (FindQualifiers, TModelBag) : ServiceProvider[] | ? | | ? | ? | findServiceProviders (String, boolean) : ServiceProvider[] | ? | | ? | ? | findServiceProviders (CategoryList) : ServiceProvider[] | ? | | ? | ? | findServiceProviders (IdentifierList) : ServiceProvider[] | ? | | ? | ? | ? | ? | | ? | Service Definition | ? | 给出搜索条件查找 ServiceDefinition 对象 | | ? | ? | ? | ? | | ? | ? | findAllServices (FindQualifiers, boolean) : ServiceDefinition[] | ? | | ? | ? | findService (String) : ServiceDefinition | ? | | ? | ? | findService (FindQualifiers, ServiceProvider, ServiceImplementation) : ServiceDefinition | ? | | ? | ? | findServices (FindQualifiers, TModelBag) : ServiceDefinition[] | ? | | ? | ? | findServices (String, boolean) : ServiceDefinition[] | ? | | ? | ? | findServices (FindQualifiers, ServiceInterface) : ServiceDefinition[] | ? | | ? | ? | findServices (ServiceInterface, String) : ServiceDefinition[] | ? | | ? | ? | findServices (ServiceInterface, CategoryList) : ServiceDefinition[] | ? | | ? | ? | findServices (ServiceProvider, String) : ServiceDefinition[] | ? | | ? | ? | findServices (FindQualifiers, ServiceProvider) : ServiceDefinition[] | ? | | ? | ? | findServices (FindQualifiers, ServiceProvider, CategoryList) : ServiceDefinition[] | ? | | ? | ? | findServices (FindQualifiers, CategoryList) : ServiceDefinition[] | ? | | ? | ? | findServices (ServiceList) : ServiceDefinition[] | ? | | ? | ? | ? | ? | | ? | Service Interface | ? | 给出搜索条件查找 ServiceInterface 对象 | | ? | ? | ? | ? | | ? | ? | findAllServiceInterfaces (FindQualifiers, boolean) : ServiceInterface[] | ? | | ? | ? | findServiceInterface (String) : ServiceInterface | ? | | ? | ? | findServiceInterfaces (String, boolean) : ServiceInterface[] | ? | | ? | ? | findServiceInterfaces (FindQualifiers, IdentifierList) : ServiceInterface[] | ? | | ? | ? | findServiceInterfaces (FindQualifiers, CategoryList) : ServiceInterface[] | ? | | ? | ? | findServiceInterfaces (ServiceImplementation) : ServiceInterface[] | ? | | ? | ? | findServiceInterfaces (ServiceImplementation, String) : ServiceInterface[] | ? | | ? | ? | findServiceInterfaces (ServiceImplementation, IdentifierList) : ServiceInterface[] | ? | | ? | ? | findServiceInterfaces (ServiceImplementation, CategoryList) : ServiceInterface[] | ? |

 |

|
让它发挥作用
本文通过一个“服务提供者”元素的发布、查找和最后取消发布的演示来阐述 SRP API 的能力。本演示的源代码在清单
1、
2及
3中列出。欢迎在您自己的项目中使用和改编这些代码。
该
ServiceProviderPublishDemo 在它初始化阶段,用指定的发布和查询 URL,还有已向目标 UDDI 注册中心预注册的用户标识和密码,创建一个 SRP 对象。
CategoryList 被实例化来支持 ServiceProvider 的创建,这个“服务提供者”还需要一个名称和描述。
当 ServiceProvider 一被成功的创建,SRP 的 publish 方法就立刻被调用 ― 接收该对象作为其唯一的参数。这段代码在其执行期间检查可能的出错条件并发出适当的消息。
清单 1:服务提供者发布演示
import com.ibm.wstk.service.provider.*;
import com.ibm.wstk.service.registry.*;
import com.ibm.wstk.service.util.*;
import com.ibm.wstk.uddi.*;
public class ServiceProviderPublishDemo
{
public static String UDDI_TEST_REGISTRY_INQUIRY
= "http://www-3.ibm.com/services/uddi/testregistry/inquiryapi";
public static String UDDI_TEST_REGISTRY_PUBLISH
= "https://www-3.ibm.com/services/uddi/testregistry/protect/publishapi";
public static String UDDI_USER = "srpuser";
public static String UDDI_PASSWD = "srppwd";
public static String SERVICE_PROVIDER_NAME = "demo provider";
public static String SERVICE_PROVIDER_DESC = "SRP provider demo";
public static String TMODEL_KEY = "NAICS";
public static String KEY_NAME = "Greeting Card Publishers";
public static String KEY_VALUE = "511191";
public static void main(String args[])
{
try
{
//////////////////// INITIALIZATION
/////////////////////////////////
// Create Service Registry Proxy
ServiceRegistryProxy srp =
new ServiceRegistryProxy(UDDI_TEST_REGISTRY_INQUIRY,
UDDI_TEST_REGISTRY_PUBLISH,
UDDI_USER, UDDI_PASSWD);
// Create category list
CategoryList categoryList =
new CategoryList(TModelKeyTable.getTModelKey(TMODEL_KEY),
KEY_NAME, KEY_VALUE);
// Create service provider
ServiceProvider serviceProvider =
new ServiceProvider(SERVICE_PROVIDER_NAME,
SERVICE_PROVIDER_DESC,
categoryList);
//////////////////// PUBLISH
////////////////////////////////////////
// Publish the service provider
srp.publish(serviceProvider);
// Display publish completed message
System.out.println("Service provider " + "\"" +
SERVICE_PROVIDER_NAME + "\"" + " was published.");
}
catch (ServiceRegistryProxyException e)
{
System.out.println("ServiceRegistryProxyException: " + e.getMessage());
}
catch (InvalidCategoryException e)
{
System.out.println("InvalidCategoryException: " + e.getMessage());
}
}
}
|
这个查找一个“服务提供者”(ServiceProvider)的演示使用和前面演示中用到的相同参数来创建一个 SRP 实例。
然后通过使用查找 SRP 方法中的其中一个找到前面发布的“服务提供者”,并在执行中产生适当的消息。
表 2:服务提供者查找演示
import com.ibm.wstk.service.provider.*;
import com.ibm.wstk.service.registry.*;
import com.ibm.wstk.service.util.*;
import com.ibm.wstk.uddi.*;
public class ServiceProviderFindDemo
{
public static String UDDI_TEST_REGISTRY_INQUIRY
= "http://www-3.ibm.com/services/uddi/testregistry/inquiryapi";
public static String UDDI_TEST_REGISTRY_PUBLISH
= "https://www-3.ibm.com/services/uddi/testregistry/protect/publishapi";
public static String UDDI_USER = "srpuser";
public static String UDDI_PASSWD = "srppwd";
public static String SERVICE_PROVIDER_NAME = "demo provider";
public static void main(String args[])
{
try
{
//////////////////// INITIALIZATION
/////////////////////////////////
// Create Service Registry Proxy
ServiceRegistryProxy srp =
new ServiceRegistryProxy(UDDI_TEST_REGISTRY_INQUIRY,
UDDI_TEST_REGISTRY_PUBLISH,
UDDI_USER, UDDI_PASSWD);
//////////////////// FIND
///////////////////////////////////////////
// Find the published service provider
ServiceProvider[] serviceProviderList =
srp.findServiceProviders(SERVICE_PROVIDER_NAME, true);
// Display find completed message
if (serviceProviderList == null)
System.out.println("Service provider " + "\"" +
SERVICE_PROVIDER_NAME
+ "\"" + " was not found.");
else
{
System.out.println("Service Provider Name: " +
serviceProviderList[0].getBusinessEntity
().getNameString());
System.out.println(" Description: " +
serviceProviderList[0].getBusinessEntity
().getDefaultDescriptionString());
}
}
catch (ServiceRegistryProxyException e)
{
System.out.println("ServiceRegistryProxyException: " + e.getMessage());
}
}
}
|
最后就是取消发布的时候了。初始化还和前面一样。然后,找到的目标 ServiceProvider 通过适当的 SRP unpublish 方法使它取消发布。同样,错误会被监视并汇报。
清单 3:服务提供者取消发布演示
import com.ibm.wstk.service.provider.*;
import com.ibm.wstk.service.registry.*;
import com.ibm.wstk.service.util.*;
import com.ibm.wstk.uddi.*;
public class ServiceProviderUnpublishDemo
{
public static String UDDI_TEST_REGISTRY_INQUIRY
= "http://www-3.ibm.com/services/uddi/testregistry/inquiryapi";
public static String UDDI_TEST_REGISTRY_PUBLISH
= "https://www-3.ibm.com/services/uddi/testregistry/protect/publishapi";
public static String UDDI_USER = "srpuser";
public static String UDDI_PASSWD = "srppwd";
public static String SERVICE_PROVIDER_NAME = "demo provider";
public static void main(String args[])
{
try
{
//////////////////// INITIALIZATION
/////////////////////////////////
// Create Service Registry Proxy
ServiceRegistryProxy srp =
new ServiceRegistryProxy(UDDI_TEST_REGISTRY_INQUIRY,
UDDI_TEST_REGISTRY_PUBLISH,
UDDI_USER, UDDI_PASSWD);
//////////////////// UNPUBLISH
//////////////////////////////////////
// Find the published service provider
ServiceProvider[] serviceProviderList =
srp.findServiceProviders(SERVICE_PROVIDER_NAME, true);
if (serviceProviderList != null)
{
// Unpublish the service provider
srp.unpublish(serviceProviderList[0]);
// Display unpublish completed message
System.out.println("Service provider " + "\"" +
SERVICE_PROVIDER_NAME + "\"" + " was unpublished.");
}
else
// Display error message
System.out.println("Service provider " + "\"" +
SERVICE_PROVIDER_NAME + "\"" + " not found.");
}
catch (ServiceRegistryProxyException e)
{
System.out.println("ServiceRegistryProxyException: " + e.getMessage());
}
}
}
|
这些演示使用 IBM UDDI 测试注册中心(IBM UDDI Test Registry)进行交互;在测试注册中心中已经注册了预先定义的登录名和密码。
SRP、UDDI4J 和 WSDL4J 也在 IBM Web Services Toolkit (WSTK) 中作为其组成部分提供(请参阅
参考资料中的链接地址)。在 Microsoft Windows 2000 环境里(在 Linux 或 Unix 上唯一的不同之处就是用来编译和执行这些代码的命令语法),一旦 WSTK 安装和配置完毕,就可以跟随下面的指导来编译和执行“服务提供者”:
编译
打开一 shell 窗口定位到演示所在目录,然后从提示符开始输入以下内容:
%WSTK_HOME%\bin\wstkenv.bat
javac -classpath .;%WSTK_CP%;%WSTK_HOME%\uddi4j\lib\uddi4j.jar
*.java
|
执行
在相同 shell 窗口,现在输入:
java -cp .;%WSTK_CP%;%WSTK_HOME%\uddi4j\lib\uddi4j.jar
ServiceProviderXXXDemo
|
(用 Publish、Find 或 Unpublish 其中之一来代替 XXX)
这些演示成功执行后产生的输出如
表 3。
表 3:演示的输出
|
演示
|
输出
| | ServiceProviderPublishDemo | Service provider "demo provider" was published | | ServiceProviderFindDemo | Service Provider Name: demo provider Description: SRP provider demo | | ServiceProviderUnpublishDemo | Service provider "demo provider" was unpublished |
总结
现在您已熟悉了 SRP。希望本工具会对您有用。欢迎把这里的代码用到您自己的工作中,别忘了告知我们的 Web 服务团队一些对您有用的其他类别的文章或工具。在
参考资料部分列出了链接到 WSTK 主页以及该项目组反馈表单的链接地址。
参考资料
关于作者  | 
|  | Alfredo da Silva 是一名 IBM 公司的软件开发者。他是负责开发 IBM Web Services Toolkit (WSTK) 的团队成员。您可以通过
afdasilv@us.ibm.com联系 Alfredo。
|
对本文的评价
|  |