Registry and Repository 和ESB 建立策略驱动的 SOA

WS-Policy 规范提供了用于表示 Web 服务支持的策略的简单语言。IBM® WebSphere® Service Registry and Repository 支持对策略文档进行加载、更改和检索,同时还支持使用策略附件将给定的策略与某个服务链接起来。然后诸如企业服务总线之类的运行时组件可以使用该链接,以检索为特定服务或操作定义的策略并相应地采取行动。本文介绍如何利用存储在注册中心的标准 WS-Policy 文档影响 ESB 中的运行时行为——然后动态更改该行为而无需进行代码更改或重新部署。

来自 IBM WebSphere Developer Technical Journal

引言

利用企业服务总线(Enterprise Service Bus,ESB)的目标之一是关注事项分离。实现服务逻辑时可以将重点放在业务相关的关注事项上,而更加面向技术的逻辑可以在 ESB 中以及在其他地方实现。

此外,可以采用适当方式创建此“集成”逻辑,通过使您能够在外部定义其行为,从而使得适应不断变化的需求更加容易。服务注册中心支持存储和检索基于标准的策略,可将其定位为策略决策点,然后由 ESB 执行策略强制。

本文描述如何在 IBM WebSphere ESB 实现一个中介,该中介检索策略信息以做出运行时决策,并遵循 IBM WebSphere Service Registry and Repository(以下称为 Service Registry)中的 WS-Policy 标准。本文描述的示例非常简单,但是很容易进行扩展以包括更加复杂的场景和策略。








什么是策略?

即使仅考虑在 IT 系统领域中的使用方式,策略这个术语也具有多重含义,并在许多不同的上下文中使用。本文描述的是适用于 Web 服务的策略。更明确地说,我们是在讨论采用标准语言表示的策略,即 WS-Policy(有关此标准和其他标准的更多信息,请参见参考资料)。

简而言之,WS-Policy 标准为您提供了一种以 XML 描述策略的语言。每个策略包括一个或多个断言。这些断言并不真正遵循任何预定义的格式,只不过它们使用 XML 并嵌入在名为 的元素中。例如,下面的代码片段显示了一个“audit”策略:


清单 1
				



可以认为上面的示例差不多就是可能的最基本策略,因为它仅包括一个名为 Audit 的策略断言。

除了定义 元素以外,WS-Policy 标准还描述如何创建由多个策略断言组成的策略,以及如何定义必须满足哪些策略或者是否必须满足所有的策略(举例而言)。为此,该标准提供了两个附加元素,分别名为 和 。此外,它还允许您通过 元素引用另一个策略。就是这么简单!该规范仅定义了四个元素,外加上一个名为 Optional 的属性。

有关如何组合策略断言的详细信息超出了本文的范围,但是要点在于,WS-Policy 是一种相对开放的语言,它仅定义了非常基本的元素集。

存在一组将 WS-Policy 语言应用于特定领域的附加规范。例如,WS-SecurityPolicy 规范定义了一组用于定义安全相关策略的策略断言;WS-AtomicTransaction 规范定义了描述服务的事务行为的策略,等等。

WS-Policy 和 WSDL

策略的一个主要用例是描述 Web 服务提供者的功能或需求。我们可以重用上面的示例:使用 WS-Policy,您可以指示必须对 Web 服务请求消息加密,或者可以定义服务请求必须遵循的事务上下文,或者可以简单地指示服务的某个行为。例如,可以使用 Audit 策略指示对发送到某个服务的所有消息进行日志记录以用于审核目的。

那么如何将策略与 Web 服务关联起来呢?您可以将策略添加到 WSDL 定义:

  • 可以将 WS-Policy 元素直接添加到 WSDL,然后将它们与其中的 WSDL 元素关联起来。这允许将策略范围界定到单个操作,甚至界定到服务中的单个消息,或者界定到整个服务。
  • 通过使用 元素,可以从 WSDL 中引用在外部文件中定义的 WS-Policy 元素。

将策略添加到 WSDL 定义意味着该策略将成为定义它的 WSDL 的一部分。对策略做出更改将需要更改 WSDL 文件。如果不将策略断言复制到使用它们的每个 WSDL 中,则很难跨多个服务重用策略断言。为了解决此问题,您可以利用另外一个标准 WS-PolicyAttachment,此标准定义了将 WSDL 定义的元素与策略链接在一起而无需对其中任一方作出更改的方法。本质上,您将创建一个文档,其中包含指向现有 WSDL 定义的链接,以及策略定义。或者——这也是下面的示例中采用的方法——附件也可以包含指向现有策略文档的链接,而不是包含策略定义本身。

图 1 显示了将 WSDL 中的服务定义与策略链接在一起的 PolicyAttachment 的示例。在此示例中,所有三个部分分别存在于单独的文件中,因此可以单独地进行开发和维护。


图 1. 将策略与 WSDL 定义链接在一起的策略附件
图 1. 将策略与 WSDL 定义链接在一起的策略附件
过程互操作性
不同供应商推出的工具和运行时产品可能不支持这里描述的将策略信息与服务定义联系在一起的所有样式。此示例适用于 WebSphere 产品集,但是在移植到不同的环境时可能需要更改。

Service Registry 中的 WS-Policy 和 WS-PolicyAttachment 定义

WebSphere Service Registry and Repository 支持对策略和策略附件进行加载、检索和编辑。加载新的 WSDL 文件时,将会自动检测并解析 WSDL 中包含的策略定义。在加载任何 WSDL 时,注册中心创建一组表示服务定义的不同部分的逻辑对象,并且所包括的策略只是该服务定义的另一个部分。

除此之外,您可以加载包含与 WS-Policy 或 WS-PolicyAttachment 兼容的定义的 XML 文件。这些文档也将进行解析,并创建相应的一组逻辑对象。

这里还未说明的一件事情在于,当在注册中心将服务定义和策略作为单独的文件加载时,策略附件如何在一方面链接到服务定义,在另一方面链接到某个策略。

策略附件使用 元素“指向”正确的服务元素。对于加载到 Service Registry 中的附件,您可以指定特定于 Service Registry 的查询,用于选择适当的元素。该查询的示例类似如下:


清单 2
				


wsrr:xpath="/WSRR/WSDLService[matches(@name, 'IBM.*')]">




上面的清单中的 元素指向存储在 Service Registry 中的所有名称以“IBM”开头的服务定义。 元素中的 xpath 属性允许您选择对其应用该策略的服务元素。

元素包含一个名为 URI 的属性,此属性引用策略定义。在 Service Registry 的情况下,此属性与 元素中的 Name 属性相关(WS-Policy 规范没有定义如何引用驻留在单独文件中的策略定义)。因此,类似如下的策略定义:


清单 3
				
Name="http://www.ibm.com/samples/mypolicy">
...

可以在附件中按如下方式进行引用:


清单 4
				
URI="http://www.ibm.com/samples/mypolicy"/>

同样,引用语法随所使用的环境而异;此示例在使用 Service Registry 时有效。有关如何加载和编辑策略文档的详细信息,请参见 Service Registry 信息中心








从中介流组件中查询 Service Registry

现在您已经了解如何在 Service Registry 中链接策略和服务定义,下面需要了解如何在运行时检索此信息。毕竟,您希望利用这些定义来影响 ESB 的行为。

创建 SOAP API 代理

Service Registry 提供了各种各样的 API,支持以编程方式访问其内容。分别存在 Java™ API、Web 服务 API、EJB API 和 REST API。那么您在从 WebSphere ESB 中访问注册中心的时候使用哪一个 API 呢?

一个显而易见的选择是 Java API(由一组包含客户端 Java 代理的 JAR 文件表示),其中包括 SDO 标准的实现,该实现与 WebSphere ESB 中包括的 SDO 实现不兼容。因此,使用此 API 将产生类版本冲突。

EJB API 要求将 WebSphere ESB 中介模块配置为注册中心的 EJB 客户端。这可能不是简单明了的活动,具体取决于运行两个产品的操作环境。

REST API 是另一个有效的选项,但是不存在从 Java 代码中使用此 API 进行编程的简单方法。例如,您无法容易地生成封装此 API 的 Java 代理,并使得 Java 客户端能够访问该代理。

留给我们就只有 SOAP API 了。注册中心完全可以通过其 Web 服务接口进行访问,并且它公开了一组 WSDL 和 XML 模式定义,您可以将其用于生成基于 JAX-RPC 的代理。

您可以在 http://[hostname]:[portnumber]/WSRR6_2/services/WSRRCoreSDOPort?wsdl 检索将用于本文其余部分的核心 API 的 WSDL 定义。然后您可以使用 WebSphere Application Server、WebSphere ESB 或 WebSphere Integration Developer 附带的 WSDL2Java 实用工具,以生成客户端代理以及相关的类和接口。但是,使用此实用工具时,您需要启用 allowRelativeNamespace 选项。假设您将 Service Registry 安装在本地计算机上的端口 9080 上,则调用应该类似如下:


清单 5
				
WSDL2Java -r client -properties allowRelativeNamespace=true
http://localhost:9084/WSRR6_2/services/WSRRCoreSDOPort?wsdl

此调用将创建您需要的所有 Java 类和接口。然后您可以在 WebSphere Integration Developer 中将它们导入某个 Java 项目,从而使它们对您在项目中开发的任何中介可用。

类似地,您还可以在 WebSphere Integration Developer 中通过导入 WSDL 文件(包括其依赖模式)完成同样的任务,并使用该工具中的 Web 服务向导生成客户端包。在 WebSphere Integration Developer 中,要知道您还需要通过 Preferences 窗口设置 allowRelativeNamespace 选项,如图 2 所示。


图 2. 在 WebSphere Integration Developer 中设置 allowRelativeNamespace 选项
图 2. 在 WebSphere Integration Developer 中设置 allowRelativeNamespace 选项

在客户端代码中,您现在需要获得该客户端代理的实例。下面的代码片段显示了获得该客户端代理实例的过程的大致示例(本文显示的所有代码以及完全可操作的示例可以在本文附带的下载文件中获得)。


清单 6
				
import
com.ibm.www.xmlns.prod.serviceregistry._6._2.ws.sdo.WSRRCoreSDOServiceLocator;
import
com.ibm.www.xmlns.prod.serviceregistry._6._2.ws.sdo.portType.WSRRCoreSDOPortType;

...

java.net.URL url = new java.net.URL(
"http://localhost:9080/WSRR6_2/services/WSRRCoreSDOPort");

WSRRCoreSDOPortType port =
new WSRRCoreSDOServiceLocator().getWSRRCoreSDOPort(url);
...

您需要根据您安装 Service Registry 实例的主机名称和端口号调整代码中使用的 URL。

Service Registry 安全性

如果您的 Service Registry 在安全模式下运行,您需要添加附加的代码来建立客户端和注册中心之间的连接。您需要定义密钥存储区文件名和密码,以及信任存储区文件名和密码,如下所示:


清单 7
				
System.setProperty("javax.net.ssl.trustStore","C:\\WebSphere\\AppServer\\profiles\\
AppSrv03\\etc\\trust.p12");

System.setProperty("javax.net.ssl.trustStorePassword","WebAS");

System.setProperty("javax.net.ssl.keyStore","C:\\WebSphere\\AppServer\\profiles\\
AppSrv03\\etc\\key.p12");
System.setProperty("javax.net.ssl.keyStorePassword","WebAS");

java.net.URL url = new java.net.URL(
"http://localhost:9080/WSRR6_2/services/WSRRCoreSDOPort");

WSRRCoreSDOPortType port =
new WSRRCoreSDOServiceLocator().getWSRRCoreSDOPort(url);

上面使用的文件位置和密码只是示例,您必须对其进行更改以适应您自己的运行时环境。此外,一旦获得了该代理的实例,您必须在存根上设置有效的用户 ID 和密码,如下所示:


清单 8
				
((javax.xml.rpc.Stub)port)._setProperty(javax.xml.rpc.Stub.USERNAME_PROPERTY,"admin");
((javax.xml.rpc.Stub)port)._setProperty(javax.xml.rpc.Stub.PASSWORD_PROPERTY,"admin");
...

同样,上面使用的值 (admin/admin) 仅只是示例。

查询策略文档

要使用您在上面的代码中检索到的代理实例,您必须准备一个查询对象,并将其插入发送到注册中心的 datagraph。下面的代码显示了如何完成此设置:


清单 9
				
import **monj.DataGraphType;
import com.ibm.www.xmlns.prod.serviceregistry._6._0.sdo.BaseObject;
import com.ibm.www.xmlns.prod.serviceregistry._6._0.sdo.GraphQuery;
import com.ibm.www.xmlns.prod.serviceregistry._6._0.sdo.WSRR;
...
GraphQuery query = new GraphQuery();
query.setDepth(-1);
query.setBsrURI("_1");
DataGraphType dg = new DataGraphType();
WSRR wsrr = new WSRR();
BaseObject[] artefacts = new BaseObject[] {query};
wsrr.setArtefacts(artefacts);
wsrr.setRoot("_1");
dg.setWSRR(wsrr);

最后,您需要设置将对注册中心执行的查询字符串。当然,在此例中,您希望查询应用于服务的某个部分的策略文档。此查询与将策略附加到服务的方式密切相关。下面的查询语句将返回所有的 PolicyDocument 对象,而不管它们是否附加到任何服务:


清单 10
				
query.setQueryExpression("/WSRR/PolicyDocument");

作为另一个示例,下一个查询返回所有已应用于以名称“IBM”开头的服务的 PolicyAttachment 对象(这就是我们在前面的示例中用于 元素的查询):


清单 11
				
query.setQueryExpression(
"/WSRR/PolicyAttachment[appliesTo(.)/WSDLService[matches(@name, 'IBM.*')]]");

如果您希望在将查询表达式插入代码之前对其进行测试,可以使用 Service Registry REST 接口。例如,您可以将以下 URL 输入浏览器的地址栏:


清单 12
				
http://localhost:9080/WSRR/6.2/Metadata/XML/GraphQuery?query=/WSRR/PolicyAttachment
[appliesTo(.)/WSDLService [matches(@name, ‘BM.*’]]

这将立即在浏览器窗口中返回满足该查询条件的所有策略附件。通过替换上面的字符串中“query=”之后的表达式部分,您可以进一步试验不同类型的查询,这很可能比在代码中测试查询更加简单。








示例

到目前为止,您已了解了如何定义策略,将其附加到服务,并将其加载到注册中心。您还了解了如何生成注册中心的 SOAP 客户端,并将其用于查询和检索策略及策略附件信息。下面您将在一个示例中将这些内容组合起来,以说明如何创建基于服务的已定义策略做出运行时决策的 WebSphere ESB 中介。

名称和命名空间

您创建的中介将基于已定义的策略做出决策。可以将策略范围界定到某个服务定义的各个元素;例如,界定到某个操作、消息、特定端口或整个服务。所有这些元素都具有名称和使它们可识别的命名空间。假设您希望查询已附加到某个操作的策略。您需要将该操作的名称和命名空间添加到查询字符串,其如下所示:


清单 13
				
/WSRR/PolicyAttachment[appliesTo(.)[(@name='TheOperation') and
(@namespace='http://mynamespace')]]

在此例中,操作和命名空间名称是硬编码的,但是如果您希望创建可跨多个服务和操作重用的中介,则应该对这些值使用参数。WebSphere ESB 还没有提供允许您检索当前执行的流的服务名称和操作名称的 API。因此,为了实现动态查询,用于获得值的唯一选项是向中介原语引入用户定义的属性。

假设
本文假设您熟悉如何为 WebSphere ESB 构建中介模块和中介流组件。与详细的步骤不同,本文描述该解决方案是如何构建的,以便您拥有足够的信息构建您自己的类似解决方案。或者,您可以将本文提供的项目交换文件导入 WebSphere Integration Developer,并在其中进行部署和测试。本文使用了 WebSphere Integration Developer 和 WebSphere ESB V6.1.2 以及 Service Registry V6.2(本文编写之际的最新版本)来创建此示例。

实际运用

  1. 为简单起见,您可以将公开可用的温度转换服务用于此示例。请检索其 WSDL 服务定义并将该 WSDL 导入新的中介模块,以便您能够将其与您的中介关联起来。另外还要将该 WSDL 加载到注册中心。

  2. Temperature Converter 服务有一个名为 CelciusToFahrenheit 的操作。要定义要求审核的策略并将其附加到此操作,您将首先创建一个名为 audit.xml 的文件,其中具有以下内容:



    清单 14
    						
    xmlns:tns="http://www.ibm.com/samples"
    Name="http://www.ibm.com/samples/auditpolicy">


    将此策略文档加载到注册中心。

  3. 下一步,创建一个名为 auditattachment.xml 的文件,其中包含以下附件代码:



    清单 15
    						
    xmlns:wsrr="http://www.ibm.com/xmlns/prod/serviceregistry/6/2/wspolicy"
    xmlns="http://www.ibm.com/samples">

    wsrr:xpath="/WSRR/WSDLPortType[@name='TemperatureConversionsSoapType' and
    @namespace='http://webservices.daehosting.com/temperature']/
    operations[@name='CelciusToFahrenheit']"/>



    请注意 元素中的 xpath 属性的值,该值指出所引用的策略应用于名为 TemperatureConversionSoapType 的端口类型中名为 CelciusToFahrenheit 的操作,该操作在 http://webservices.daehosting.com/temperature 命名空间中。您稍后将看到您在中介中执行的策略查询如何与此直接相关。

  4. 在将附件文件加载到注册中心以后,您应该能够在 Service Registry 管理控制台中导航到该附件(图 3)。



    图 3. WSRR 管理控制台中的策略附件
    图 3. WSRR 管理控制台中的策略附件

  5. 当您单击该附件的 Graphical View 时,可以清楚地看到它将 CelciusToFahrenheit 操作与 Audit 策略链接在一起(图 4)。



    图 4. 策略附件的图形视图
    图 4. 策略附件的图形视图

  6. 在中介模块中,创建一个用于测试的带 SOAP/HTTP 导出的简单组装、执行策略查找的中介流组件,以及到 Temperature Converter 服务的导入(图 5)。



    图 5. 策略中介模块的组装
    图 5. 策略中介模块的组装

  7. 在 PolicyMediation 组件实现中,您仅向 CelciusToFahrenheit 操作的请求流添加了特定的功能,如图 6 所示。



    图 6. 中介流组件
    图 6. 中介流组件

请注意,这里添加了一个名为 PolicyRetrieval 的自定义中介原语。该原语具有两个输出终端,其中一个直接连接到 Callout 节点,另一个连接到名为 MessageLogger 的 Message Logger 原语。本质上,如果消息在自定义中介原语的第一个输出端子上激发,则不对其进行记录,而如果在第二个端子上激发,则会将其记录到数据库。

该自定义中介原语使用一个名为 PolicyQueryTest 的 Java 实用工具类,其中封装了上面介绍的注册中心代理代码:


清单 16
				
try {
PolicyQueryTest pq = new PolicyQueryTest();
pq.init(WSRRPortURL);
if (pq.hasPolicyDefined(PolicyQueryTest.AUDIT_POLICY_NAME,
operationNamespace, operationName))
auditOut.fire(smo);
else
out.fire(smo);
} catch (Exception x) {
System.out.println("Exception during policy query : "+x.getMessage());
throw new ServiceRuntimeException(x);
}

上面的清单表明了在注册中心找到用于审核的策略时如何在 auditOut 终端上激发消息。此终端连接到上面所示的 MessageAudit 原语。PolicyQueryTest 类使用以下查询字符串确定是否为该操作定义了审核策略:


清单 17
				
query.setQueryExpression(
"/WSRR/PolicyAttachment[appliesTo(.)[(@name='"+operationName+"') and
(@namespace='"+namespace+"')]]");

然后该代码解析返回的响应消息,以确定该策略附件是否的确引用了 Audit 策略。(这里未显示此代码。)

您可以通过 Service Registry 管理控制台更改策略内容,从而对此代码做进一步的试验。例如,如果将已定义的策略元素更改为包含名为 的元素,则中介将不会找到预期的策略,并将在直接连接到 Callout 节点的终端上激发消息,从而将不会记录消息。

您可以看到使用此机制如何使您能够影响 ESB 的行为,以及它如何基于您存储在注册中心的策略定义对传入请求进行处理。








总结

本文介绍了 WS-Policy 如何为您提供了用于表示 Web 服务所支持的策略的简单语言。许多其他标准扩展了此语言以处理不同的领域,例如安全性,同时,您还可以定义自己的自定义策略。

WebSphere Service Registry and Repository 支持对策略文档进行加载、更改和检索。它还支持使用策略附件将给定的策略和服务链接在一起。然后诸如企业服务总线之类的运行时组件可以使用该链接,以检索为特定服务或操作定义的策略并相应地采取行动。向运行时添加所需的自定义逻辑的方法之一是生成基于 JAX-RPC 的 SOAP 代理。

最后,本文介绍了一个说明如何在运行于 WebSphere ESB 中的中介流中利用此代理的示例。该示例检查是否为某个操作定义了 Audit 策略,如果是,则确保对请求消息进行记录。

本文将其用作基本示例,用于说明如何利用注册中心存储的标准 WS-Policy 文档影响 ESB 中的运行时行为。现在可以通过更改注册中心的策略来动态更改该行为,并且不需要进行任何代码更改或代码重新部署。








致谢

作者感谢 IBM Software Group Worldwide Technical Sales 团队的 Laura Olson 对本文提供的帮助。









下载

描述名字大小下载方法
Code samplePolicyMediationExample.zip285 KBHTTP
关于下载方法的信息


参考资料



关于作者


Andre Tost 是 IBM Software Services for WebSphere 组织的一名高级技术人员,他在这个部门帮助 IBM 的客户建立面向服务的体系结构。他专长于 Web 服务和企业服务总线技术。在从事目前的工作之前,他有十年的时间在 IBM 软件开发工作中担任各种合作伙伴支持、开发和构架设计方面的角色,目前他在 WebSphere Business Development 小组工作。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14789789/viewspace-539715/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/14789789/viewspace-539715/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值