WS-Notification的使用---来自阿红

JAX-WS:

SOAP XML marshaling

ServiceMix使用JAX-WSJAXB 2.0来创建WS-*规范的POJO、接口,例如WS-Addressing, WS-Notification, WS-ReliableMessaging, WS-Resourceframework等等。这种方法的唯一缺点是Java5特定的,因此不能在JDK1.5以下的JVM运行。要使用JDK1.4 JVM,或者使用XMLBeans,或者使用Retroweaver之类的工具来把JDK1.5实现转换为JDK1.4二进制。

WS-Notification

WS-Notification支持当前的实现是POJO,可以直接在应用中调用,也可以打包为远程的Web服务(使用遵从JAX-WS约束的SOAP协议栈来访问)。当前使用JAX WS RI(参考实现)

WS-Notification的接口在org. servicemix.wspojo.notification 包中,由JAX-WSWSDL文件生成而来,依赖于JAVA5 JAX-WS以及JAXB2.0注解。

WS-Notification的实现在WS-Notification interfaces are here .

接口的apidoc org. servicemix.wspojo.notification

 

使用 WS-Notification

为了可以pub/sub,需要一个NotificationConsumer 或者 NotificationBroker当前的实现都是ActiveMQNotificationBroker 这个Broker会创建一个到ActiveMQ代理的连接(缺省时是在同一个JVM内嵌入broker)。

Publish一个 WS-Notification消息,如下:

EndpointReferenceType consumer = createEPR(ReceiverComponent.SERVICE, ReceiverComponent.ENDPOINT);

wsnBroker.subscribe(consumer, "myTopic", null, true);

 

Element body = parse("<hello>world</hello>");

      wsnBroker.notify("myTopic", body);

sub

PullPoint pullPoint = wsnCreatePullPoint.createPullPoint();

Subscription subscription = wsnBroker.subscribe(pullPoint.getEndpoint(), "myTopic", null);

运行时依赖

除了ActiveMQServiceMix的依赖之外,WS-Notification还依赖于:

  • JAX-WS JAXB 2.0 APIs (annotations) 将内嵌在JAVA 6,但在JDK 5中只需添加jaxb-api.jar 以及 jaxws-api.jar
  • JAX-WS 实现。如果想要支持SOAP协议上的远程服务。当前使用JAX-WS RI

ServiceMix WSIF Example

Web Services Invocation Framework (WSIF)提供了调用Web服务的Java API,隐藏服务是如何提供的细节,例如是通过SOAPJMS还是其他什么,等等。

下面说明ServiceMix构件使用不同的实现协议,例如Axis、本地JavaEJBJMSJCA或者CCI,与Apache WSIF交互,来调用Web服务。

WSIF example 演示了如何通过WSIF展示Web服务(over JMS队列):

NOTE: 本实例不是一个完整的可run的例子。它只是通过一个典型实用的web应用演示了WSIFServiceMix构件中是怎么使用的。图中的下列构件没有完全实现:

1. Web Form没有创建

2. 没有配置servicemix.xml HTTP BC的目标服务为"checkAvailabity"构件.

下面给出的关键代码片断摘自一个更大的例子,可以在Apache Web Services Project中找到。本实例中,客户端应用通过JMS队列向Web服务应用提交ZIP CodeWeb服务检查此ZIP Code地区的DSL服务是否可用,发送JMS队列消息回映客户。客户端使用WSIF来隐藏JMS实现细节。

在本实例中,客户端使用WSIF APIWeb服务发送ZIP Code请求。WSIF为客户端处理JMS细节。ServiceMix WSIF API向客户提供统一的API,处理Web服务调用的细节,简化客户端编程。

此实例中显示了ServiceMix客户API的重要特性:如何为一个Web服务绑定包含附加的用来配置服务实现的WSIF元数据的WSDL文件。

也就是说,servicev.wsdl文件包含了WSIFWSDL的扩展,扩展中绑定了Web服务的传输协议。

例子的详细分析

逻辑流程:

1.     用户打开Web浏览器,访问一个Web表单,输入信息后按submit按钮提交Zip Code。提交按钮发送表单和Zip Code

2.     ServiceMix HTTP BC通过客户API创建一个InOut exchange message. 消息发送到NMR,随后到checkAvailability 构件

3.     checkAvailability 构件发送请求到JMS队列

4.     Web 服务使用MDB实现,它的"onMessage" 方法监听队列中的消息

5.     MDB处理请求,并通过一个临时队列发送回应消息给checkAvailability构件。回应或者是‘true’,或者是‘false

6.     checkAvailability 构件从队列中收到回应消息

7.     checkAvailability 构件回应 HTTP 客户

8.    客户发送结果给Web Form,显示处理结果。

程序细节

对应的servicemix.xml文件:

<component id="checkAvailability" service="foo:checkAvailability" class="org.servicemix.components.wsif.WSIFBinding">

<property name="definitionResource" value="classpath:org/servicemix/components/wsif/service.wsdl"/>

</component>

Service.wsdl:位于servicemix_src_install_dir/servicemix-components/src/test/resources/org/apache/servicemix/components/wsif

 

<service name='CheckServiceAvailability'>

<port name='CheckAvailabilityPort' binding='tns:CheckAvailabilityJMSBinding'>

<!-- ActiveMQ configuration -->

<jms:address destinationStyle="queue"

jndiDestinationName="dynamicQueues/test.org.servicemix.example.wsif"

jndiConnectionFactoryName="ConnectionFactory"

initialContextFactory="org.activemq.jndi.ActiveMQInitialContextFactory"

jndiProviderURL="tcp://localhost:61626"/>

</port>

</service>

 

<jms:address jmsVendorURI="xxx"

    jndiDestinationName="xxx"

    destinationStyle="xxx"

    jndiConnectionFactoryName="xxx"

    initialContextFactory="xxx"

    jndiProviderURL="xxx"

    jmsProviderDestinationName="xxx"

    jmsImplementationSpecificURI="xxx" />

  • port 元素中只能有一个jms:address
  • jmsVendorURI 是可选元素,WSIF不使用。不过允许客户端来获取JMS实现。
  • destinationStyle jmsImplementationSpecificURI中必须有一个元素(且仅有一个)要指明
  • jmsImplementationSpecificURI 以实现特定的格式表示的队列管理器和队列.WSIF目前未实现
  • destinationStyle 的值为queue topic, 但目前WSIF没有实现Topic
  • 若指明了destinationStyle,jndiDestinationNamejmsProviderDestinationName二选一地要指明其中一个.
  • jndiDestinationName WSIF将发送请求消息的目的JMS QueueJNDI名字
  • jmsProviderDestinationName WSIF将发送请求消息的目的JMS QueueJMS名字
  • 若指明了jndiDestinationNamethenjmsProviderDestinationName,则必须指定jndiConnectionFactoryName
  • 当指定的是jmsProviderDestinationName名时,jndiConnectionFactoryName 有可能要使用,因为replyTo QueueJNDI名字有可能要传到WSIF
  • jndiConnectionFactoryNameWSIF将使用的连接工厂的JNDI名字
  • 若指明了destinationStyle jndiProviderURL /initialContextFactory (同时或者任意一个都可以)需要指明。
  • jndiProviderURL initialContextFactory 指明了要使用的JNDI数据库。未指定则WSIF使用缺省的JNDI

WSIF 使用下列顺序查找JNDI中的队列和队列管理器 :

1.     在缺省的(本地)JNDI查找 java:comp/env/<name>

2.     WSDL中指定的JNDI中查找 java:comp/env/<name>

3.     在缺省的(本地)JNDI查找 <name>  

4.     WSDL中指定的JNDI中查找 <name>

 

编码WSDL1.1partsXML vs. properties

JBI规范要求使用XML编码机制编码WSDL1.1partsServiceMix支持此要求。另外,ServiceMix也支持NMR消息的消息属性,直接使用wsdl文件中的命名parts,因此避免了不必要的XML marshalling

作为可选方案,也可以写一个Java客户而不是Web Form来调用Web服务。下列Java客户端代码使用支持WSIF方式调用的ServiceMix客户API,传入和传出命名参数。此Java客户功能类似上图中的Http Client。也需要配置来与”checkAvailablity”服务通讯,即要配置”checkAvailablity”为它的NMR消息目的地。

 

InOut exchange = client.createInOutExchange();

exchange.getInMessage().setProperty("zipCode", "10505");

client.sendSync(exchange);

NormalizedMessage out = exchange.getOutMessage();

String result = (String) out.getProperty("result");

System.out.println("Found value: " + result);

 

上述Java 代码使用WSDL 1.1 service.wsdl ,直接使用它的命名的parts:

<message name='checkAvailabilityRequest'>

<part name='zipCode' type='xsd:string'/>

</message>

<message name='checkAvailabilityResponse'>

<part name='result' type='xsd:string'/>

</message>

<portType name='CheckAvailabilityPortType'>

<operation name='checkAvailability'>

<input message='tns:checkAvailabilityRequest'/>

<output message='tns:checkAvailabilityResponse'/>

</operation>

</portType>

<binding name='CheckAvailabilityJMSBinding' type='tns:CheckAvailabilityPortType'>

<jms:binding type="TextMessage"/>

<format:typeMapping encoding="XML" style="Java">

<format:typeMap typeName="xsd:string" formatType="java.lang.String"/>

</format:typeMapping>

<operation name='checkAvailability'>

<input>

<jms:input parts="zipCode"/>

<jms:property message="Request" part="myInt"/>

<jms:propertyValue name="myLiteralString" type="xsd:string" value="Hello World"/>

</input>

<output>

<jms:output parts="result"/>

</output>

</operation>

</binding>

 

WebServices消息在不同的技术中的表示方法

如果通过BPEL服务引擎、JAXRPC应用等等发送JBI实现的WSDL (1.1)消息,就必须对其加以转换/调整。

如下的WSDL消息:

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"

    targetNamespace="urn:sample"

    xmlns:tns="urn:sample"

    xmlns:xsd="http://www.w3.org/2001/XMLSchema" >

    <types>

        <xsd:schema targetNamespace="urn:sample">

            <xsd:element name="value" type="xsd:string" />

        </xsd:schema>

    </types>

    <message name="sampleMessage">

        <part name="part1" type="xsd:string" />

        <part name="part2" element="tns:value" />

    </message>

</definitions>

对应的两个消息实例:

A bpel2.0中:概念化地在一个独立的xml文档中实现每个WSDL消息部分(part)。在这种情况下,或者文档元素相当于一个合成元素,其类型等同于部分(part)type属性;或者文档元素就是部分(part)的element属性本身所引用的元素。

<ns2:message xmlns:ns2="http://com.bea.sample.bpelmessage">
first value!
</ns2:message>

 

<ns1:value xmlns:ns1="urn:sample">second value!</ns1:value>

B JBI

 对于JBIWSDL (1.1)消息是在一个xml文档中实现的,该文档的元素将每个消息部分包装为子元素。   

<jbi:message version="1.0" type="ns1:sampleMessage"

    xmlns:ns1="urn:sample" xmlns:jbi="...">

    <jbi:part>first value!</jbi:part>

    <jbi:part>

        <ns1:value>second value!</ns1:value>

    </jbi:part>

</jbi:message>

 

C JAXRPC 2.0

  JAXRPC方法稍微有点不同,因为JAXRPCWSDL消息绑定到Java,而不是在xml文档中表示它。但是这种方法还是类似于BPEL,因为它将每个WSDL消息部分绑定到单独的Java方法参数。

在这种情况下,可以考虑稍微改动一下前面的WSDL定义,使其更适合于RPC

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"

    targetNamespace="urn:sample"

    xmlns:tns="urn:sample"

    xmlns:xsd="http://www.w3.org/2001/XMLSchema" >

    <types>

        <xsd:schema targetNamespace="urn:sample">

            <xsd:element name="value1" type="xsd:string" />

            <xsd:element name="value2" type="xsd:string" />

        </xsd:schema>

    </types>

 

    <message name="sampleMessage">

        <part name="part1" element="tns:value1" />

        <part name="part2" element="tns:value2" />

    </message>

 

    <portType name="samplePT">

        <operation name="sampleOper">

            <input message="tns:sampleMessage" />

        </operation>

    </portType>

</definitions>

对应的Java绑定如下:

void sampleOper(java.lang.String part1, java.lang.String part2)throws RemoteException

 

D WSDL 2.0

WSDL 2.0是这样解决这个问题的:避开WSDL消息部分概念,使用W 3C Schema元素指定WSDL消息,W 3C Schema元素在实现为文档实例时就已经具有显式映射了。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值