使用开放源代码框架的 Java 应用程序的 Web 服务集成模式,第 1 部分: 实现调用模式

发表于:2007-05-24来源:作者:点击数: 标签:框架java源代码开放应用程序
主要有四种用于集成 Web 服务的模式。本系列包括两个部分,本文是第 1 部分,将对 开发 服务和客户机的方式进行建议,以便通过使用流行的开放源代码框架调用采用所有四种服务端点模式的 Web 服务。我们将讨论其中两种模式,即请求-响应模式和单向端点模式,将
主要有四种用于集成 Web 服务的模式。本系列包括两个部分,本文是第 1 部分,将对开发服务和客户机的方式进行建议,以便通过使用流行的开放源代码框架调用采用所有四种服务端点模式的 Web 服务。我们将讨论其中两种模式,即请求-响应模式和单向端点模式,将同时涵盖文档样式和 RPC Web 服务调用演示的内容。本系列的下一篇文章将描述其他两种集成模式,要求-响应模式和通知模式。

引言

在今天的企业中,Web 服务作为一项应用程序集成机制,正在迅速地扩大其应用领域。Web 服务还为应用程序提供了通过 Internet 与外部应用程序进行通信的功能,以实现企业间的 (B2B) 集成。简单对象访问协议(Simple Object Aclearcase/" target="_blank" >ccess Protocol,SOAP)是用于在此类情况下调用 Web 服务的协议之一。SOAP 提供了针对客户机和服务间的通信进行了格式化的基于 XML 的标准化消息。SOAP 通常使用 HTTP 进行传输,但也支持使用 JMS 等其他传输协议。

服务的 Web 服务描述语言(Web Services Description Language,WSDL)定义提供该服务的细节,包括端点、端口、操作和消息等。服务和端点提供服务的连接细节,例如,如果服务可通过 HTTP 使用,则端点为一个 URL,如果服务可通过 JMS 使用,则端点提供 JMS 域名和查询名。网络服务端点的 WSDL 规范定义端点可支持的四个传输原语(也称为操作)。即单向、请求-响应、要求-响应和通知。Web 服务可以通过四种模式中的任何一种进行调用。这些模式处于 WSDL 抽象级别,而到 SOAP 的“绑定”可通过将操作指定为面向 RPC 或面向文档的操作而在集成机制方面提供更多的变化。Java™ 应用程序的一个总趋势是在开发应用程序时使用开放源代码软件。不过,尝试在 Java 应用程序中实现这些集成模式时,我们发现,并没有任何单个开放源代码软件能提供同时实现所有四种模式的功能。为了实现这四种模式,我们必须将 Axis 和 WSIF 等组件中的各种可用功能结合使用。

在请求-响应模式中,端点(此时为实际的 Web 服务)在接收到需要响应的客户机消息时,会发送回一个相关消息。在此模式中,客户机——即应用程序——将调用 Web 服务,而 Web 服务对其进行响应;例如,当在线购物车向信用卡公司发送要记入借方的金额时,信用卡公司将使用事务 ID 进行响应。

在单向模式中,端点(Web 服务)从客户机接收一个不需要进行响应的消息。在此模式中,客户机(应用程序)向 Web 服务发送信息,且并不会等待响应。客户机可以从服务请求一些信息,但它不会等待,而服务可以在稍后将响应发送回来。

后面的部分将讨论如何实现 Java 应用程序与支持这两种模式的服务端点的集成。





回页首


用于 Web 服务实现的开放源代码框架

Web 服务和客户机可以通过使用各种开放源代码框架来实现。来自 Apache 的 Axis 就是一个使用 Web 服务的框架,可以用于编写 Web 服务客户机。它提供了 Axis 服务器(实际是一个 SOAP 引擎)和一个 Axis 客户机(可允许客户机调用 SOAP Web 服务)。它使用 SOAP 作为进行通信的应用协议。Axis 缺省情况下支持 HTTP 作为传输协议,但也内置了一个 JMS 扩展。

Web 服务调用框架(Web Service Invocation Framework,WSIF)可用于为各种类型的服务编写客户机。它使用服务的 WSDL 定义来调用服务。可以使用基于 WSIF 的客户机调用 Web 服务和调用使用 Java Message Service (JMS)、Enterprise JavaBean (EJB)、Java 程序及本机代码实现的服务。使用 WSIF 的客户机并不需要知道服务的实现细节,而仅需要服务的 WSDL 即可。

WSIF 框架使得编写 Web 服务客户机变得非常简单,特别对于使用 JMS、Java 和 EJB 程序的动态客户机更是如此。服务的参数细节在 WSDL 中定义,这些细节在执行时就已经知道了。

应该注意,WSIF 调用文档样式的 Web 服务方面有一些限制。从应用程序(在本例中为客户机)的角度而言,我们将与请求-响应模式集成归类为“同步调用”类型的活动,而单向模式则属于“异步调用”类型。





回页首


应用程序客户机端点调用的请求

同步调用

在同步调用中,客户机将消息发送给服务,并等待响应。服务接收到该消息,对其进行处理,并发送回响应。

按照 WSDL 语法中的定义,请求-响应操作包含输入和输出元素——首先是输入,然后是输出。


清单 1. 请求-响应操作的 WSDL
            <wsdl:definitions .... >
            <wsdl:portType .... > *
            <wsdl:operation name="nmtoken" parameterOrder="nmtokens">
            <wsdl:input name="nmtoken"? message="qname"/>
            <wsdl:output name="nmtoken"? message="qname"/>
            <wsdl:fault name="nmtoken" message="qname"/>*
            </wsdl:operation>
            </wsdl:portType >
            </wsdl:definitions>
            

WSIF 可提供动态调用 Web 服务的灵活性。WSIF 将对 WSDL 进行解析,获取为服务定义的关于服务、端口、绑定和操作的信息。用户可以在运行时选择端口、传输和操作,并提供输入参数来调用 Web 服务。此处的优势在于,不需要为每个 Web 服务编写独立的客户机。使用 WSIF 的另一个优势是,即使 Web 服务的端点改变,客户机也不用改变。事实上,客户机甚至不需要知道 Web 服务的位置。而且,如果在将来给定服务作为 EJB 提供,客户机可以使用新 WSDL 调用 EJB,而不要对客户机代码进行任何修改。WSIF 对 WSDL 进行分析,从而为输入、输出和错误的 WSIFService、WSIFPort、WSIFoperation、WSIFMessage 创建对象实例,并执行相应操作。WSIF 分发中提供了一个动态调用 Web 服务的一个示例。此方法特别适用于调用简单 Web 服务。WSIF 可以用于调用 RPC 和文档样式的 Web 服务。在清单 2 中,示例代码演示了如何使用 WSIF 来调用 RPC 样式的 Web 服务。


清单 2. 使用 WSIF 的 RPC 样式请求-响应 Web 服务客户机示例代码
            // ...
            // get service factory object
            WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
            // get service object for given wsdl definition object and service object
            WSIFService dpf =
            factory.getService(definition, service);
            // get port from wsif service object for given port name
            port = dpf.getPort(portName);
            // get operation object from port object for given operation and input/output message names
            MILY: Andale Mono, Lucida Console, Monaco, fixed, monospace" twffan="done">|-------- XML error:  The previous line is longer than the max of 90 characters ---------|
            WSIFOperation operation = port.createOperation(
            operationName,
            inputMessage,
            outputMessage);
            // create input message
            WSIFMessage input = operation.createInputMessage();
            // invoke the service
            operation.executeRequestResponseOperation(input, output, fault);
            

如果 Web 服务是文档样式的 Web 服务,则应用程序可以使用 Axis 客户机:

  • 应用程序动态创建一个客户机(在应用程序执行期间完成),并使用 Web 服务定义中提供的端点信息(具体的端口地址)。
  • 客户机创建 Axis 客户机的“Call”对象的实例,并将 Call 对象中的目标端点地址设置为 Web 服务端点的地址。
  • 接下来,客户机读取调用的服务所需的输入参数。为此,客户机会在运行时使用 JAXB[12] 将 Java 格式的输入参数转换为 XML 元素对象 (org.w3c.dom.Element)。Java Architecture for XML Binding (JAXB) 提供了一种非常方便的方法,可将 XML 模式绑定到 Java 代码中的表示形式。
  • 客户机将创建一个由这些 Element 对象组成的数组,并调用 Axis Call 对象的 invoke 方法。
  • invoke 方法构造 SOAP 请求消息,并通过发送消息来调用服务,从服务获取输出参数,然后将其作为 org.apache.axis.message.SOAPBodyElement 对象数组返回给客户机。
  • 客户机然后构造与从服务接受到的输出参数对应的等效 Java 对象,这同样也是在运行时使用 JAXB(从 XML 到 Java 绑定)完成的。
  • 然后,客户机将这一组 Java 对象提供给应用程序。

 

这种调用方法尤其适合用于调用具有复杂数据类型的文档样式 Web 服务。会首先使用 JAXB 将复杂数据类型转换为 XML,然后传递给服务调用者。输入参数也以 XML 格式接收,并使用 JAXB 解析回 Java 对象。


清单 3. 使用 WSIF 的 RPC 样式请求-响应 Web 服务客户机示例代码
            SOAPBodyElement[] element = // create SOAPBodyElement array using input objects
            // create call object
            Service service = new Service();
            Call call = (Call) service.createCall();
            // set end point (http address)
            call.setTargetEndpointAddress(endPoint);
            // invoke the service by passing the SOAPBodyElement
            Vector output = (Vector) call.invoke(element);
            // create element array from vector
            Element elemArray[] = new Element[output.size()];
            for (int i = 0; i < output.size(); i++) {
            if (output.get(i) instanceof Element) {
            elemArray[i] = (Element) output.get(i);
            }
            if (output.get(i) instanceof SOAPBodyElement) {
            elemArray[i] = ((SOAPBodyElement) output.get(i)).getAsDOM();
            }
            }
            // convert Element array back into Java Objects using JAXB
            

异步调用

在异步调用中,客户机将消息发送到服务,服务然后使用该消息。此时,客户机并不会等待服务进行应答。

如 WSDL 语法所定义的,单向操作仅具有输入元素。


清单 4. 单向操作的 WSDL
            <wsdl:definitions> <wsdl:portType .... > *
            <wsdl:operation name="nmtoken">
            <wsdl:input name="nmtoken"? message="qname"/>
            </wsdl:operation>
            </wsdl:portType >
            </wsdl:definitions>>
            

可以通过使用 SOAP over JMS 实现异步调用。JMS 的缺省行为就是进行异步消息传递。


清单 5. 使用 SOAP over JMS 的单向 Web 服务客户机示例代码
            // ...
            // provide JMS handler
            Call.addTransportPackage(packageName);
            Call.setTransportForProtocol(
            "JMSTransport",
            JMSTransport.class);
            // get client configuration
            EngineConfiguration defaultConfig =
            (new
            DefaultEngineConfigurationFactory()).getClientEngineConfig();
            // create custom configuration for client
            SimpleProvider config = new SimpleProvider(defaultConfig);
            // get chain for given transport
            SimpleTargetedChain chain =
            new SimpleTargetedChain(
            new JMSSender(connectionFactory, destination));
            config.deployTransport("JMSTransport", chain);
            // create service using custom configuration
            Service service = new Service(config);
            Call call = (Call) service.createCall();
            call.setOperation(super.getOperation());
            // set JMS specific information (topic/queue name, context factory) in call
            // these values will be needed in chain for actually sending JMS message
            call.setProperty(JMSConstants.DESTINATION, destination);
            call.setProperty(
            "transport.jms.ConnectionFactoryJNDIName",
            connectionFactory);
            if (destinationDomain.equalsIgnoreCase("topic")) {
            call.setProperty(JMSConstants.DOMAIN,
            JMSConstants.DOMAIN_TOPIC);
            }
            if (destinationDomain.equalsIgnoreCase("queue")) {
            call.setProperty(JMSConstants.DOMAIN,
            JMSConstants.DOMAIN_QUEUE);
            }
            call.setTransport(new JMSTransport());
            // invoke the web service
            call.invoke(params);
            // ...
            

WSIF 支持异步调用。可以通过调用 API 中的不同方法来使用 WSIF 客户机进行异步调用。


清单 6. 使用 WSIF 的单向 Web 服务客户机示例代码
            // ...
            // create operation
            WSIFOperation operation = port.createOperation(
            operationName,
            inputMessage,
            outputMessage);
            // prepare input
            WSIFMessage input = operation.createInputMessage();
            // invoke web service one-way
            operation.executeInputOnlyOperation(input);
            // ...
            





回页首


结束语

在本文中,我们对 Web 服务端点的请求-响应模式和单向模式进行了详细的讨论。而且说明,在标识了功能后,可以如何使用采用开放源代码框架的相应 Web 服务来支持这两种模式。在本系列的第 2 部分,我们将讨论 Web 服务中涉及的客户机端点可支持的其他两个集成模式,即要求-响应模式和通知模式。

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)