利用 WAS 6.1 WebService 功能部件包开发 JAX-WS 2.0 Web services

引言

JAX-WS 2.0 的全称为 Java API for XML-Based Web services (JAX-WS) 2.0。JAX-WS 2.0 是对 JAX-RPC 1.0 规范的扩展,是 JAX-RPC 1.1 的后续版本, JAX-RPC 2.0 标准发布不久后便被重新命名为 JAX-WS 2.0。 JAX-WS 2.0 是面向 Java 5 的开发 Web services 的最新编程标准,它提供了新的编程模型和对以往的 JAX-RPC 方式的 Web services 进行了增强。在 WebSphere 应用服务器 6.1 Web services 功能部件包中提供了对 JAX-WS 2.0 的支持。本文结合 WebSphere 里的开发工具 AST(Application Server Toolkit) 讲述了 JAX-WS 2.0 标准下 Web services 的开发过程,同时介绍了 JAX-WS 2.0 一些重要的 API 和命令行工具 wsimport,wsgen 的使用。本文对于想了解 Web services 最新变化和准备采用 JAX-WS 2.0 编程的相关人员有一定的帮助。




 


回页首 




JAX-WS 2.0 介绍

和以往的 JAX-RPC 相比,JAX-WS 2.0 的主要特点有:

新的 API 和新的编程模型。新的 API 主要包含在 javax.xml.ws 包中,包括 service 端和 client 端的一些核心类。新的编程模型包括增强的 Handler Framework,异步调用和 Provider/Dispatch 动态编程模型。
采用 annotations 来描述 Web services,不再依赖部署以往的 Web service 描述文件。
通过 JAXB 2.0 完成 xml data 和 Java 对象的绑定,改变了 JAX-RPC 1.0 里同时存在两套 binding 机制的不便。
MTOM/XOP(SOAP Message Transmission Optimization Mechanism/XML Binary Optimized) 和 swaRef(SOAP Attachment Refenreces),解决了在 SOAP 消息里传输二进制附件的问题,同时对消息传输进行了优化。
对 SOAP 1.2 的支持。
针对上述特点,Web services 功能部件包主要在以下几个方面提供了相应的支持:
在 WAS(WebSphere Application Server) runtime 中增加了对 JAX-WS 2.0 的支持 , 使得基于 JAX-WS 2.0 的 Web services 能在 WAS 中部署运行。
新增了用于创建 JAX-WS 2.0 应用的一些命令行工具,如 wsimport 和 wsgen。
在 AST 中增加了开发 JAX-WS 2.0 应用的插件。
此外,功能部件包同时提供了对其它如 JAXB_2.0, MTOM/XOP API 以及基于 PolicySet 安全化 Web services 等高级特性的支持。




 


回页首 




JAX-WS 2.0 开发过程

同基于 JAX-RPC 的 Web services 一样,JAX-WS 2.0 的开发分为 service 端和 client 端。在 service 端,可以选择自顶向下或自底向上的方式来创建 Web services,这两种方式可以通过 AST 或命令行工具来完成。在 client 端,一般通过 AST 或命令行工具根据 WSDL 文件创建用于调用 Web services 的辅助类,然后再在自己的代码中使用这些辅助类。 JAX-WS 2.0 提供了多种 client 端的编程模型。下面将分别介绍 service 端和 client 端的开发过程。

Service 端的开发

JAX-WS 2.0 有两种开发过程 : 自顶向下和自底向上。自顶向下方式指通过一个 WSDL 文件来创建 Web services,自底向上是从 Java 类出发创建 Web services。两种开发过程最终形成的文件包括:

SEI(service endpoint interface)。一个 SEI 对应 WSDL 中 Web service 的一个 port,在 Java 中是一个 Java 接口。
SEI 实现类。
WSDL 和 xsd 文件。
Web services 既可以包含在一个 web module 中发布,也可以包含在 EJB module 中发布。下面我们结合实例来看一个自顶向下的 Web services 的开发过程。该例子包含的 Web services 很简单:一个 service,该 service 只有一个 port,该 port 只有一个操作 addNumber。

首先,我们开发一个普通的 Java Bean。在 AST 中创建两个项目:一个动态 web 项目,包含我们示例的 Web services;另一个 J2EE 项目,用于生成 ear。

清单 1. 用于创建 Web service 的一个普通 Java Bean

package com.ibm.ws.demo.server; public class SimpleBean {public int addNumber(int i , int j) {return i + j;}}




在 AST 工具中,选中该类,在右键弹出菜单中,启动 Web service 创建向导。在向导中,您需要选择 Web services 运行时的 runtime 为 IBM WebSphere JAX-WS。同时,选择生成 WSDL 文件。其余步骤按缺省设置。

最后生成的项目结构如下:




上图中,SimpleBeanDelegate.java, AddNumber.java 和 AddNumberResponse.java 为向导生成的 java 类,WebContent 下还生成了两个 Web service 的描述文件 SimpleBeanService.wsdl 和 SimpleBeanService_schema1.xsd。

在 AST 中导出 ear 文件,在 WebSphere 管理控制台上部署,再启动应用。在浏览器中通过下面形式的 URL 可以验证 Web services 是否成功启动。

http://hostname:port/webmodule/QName

注意 AST 中自动生成的一个代理类 SimpleBeanDelegate.java:

清单 2. 用于部署 Web service 的代理类 SimpleBeanDelegate.java

import javax.jws.WebService;import javax.xml.ws.BindingType;import javax.jws.soap.SOAPBinding; @WebService (targetNamespace="http://server.demo.ws.ibm.com/", serviceName="SimpleBeanService", portName="SimpleBeanPort", WSDLLocation="WEB-INF/WSDL/SimpleBeanService.WSDL")public class SimpleBeanDelegate{ SimpleBean _simpleBean = new SimpleBean(); public int addNumber(int i, int j) {return _simpleBean.addNumber(i,j);} }




上面这个类是真正用于部署 Web services 的类,该类采用了 Annotation 来描述 Web services。 Annotation 是 Java 5 的一大语言特性,采用 Annotation 描述 Web services 的元数据,减轻了开发者的部署负担。在 javax.jws 包中定义了如下主要的 Annotation:

javax.jws.WebService
javax.jws.WebMethod
javax.jws.WebParam
Client 端的开发

客户端开发的通常过程是从已有的 WSDL 出发,创建辅助类 JAXB 对象和 service 代理类,然后基于这些类开发自己的客户端应用。在 AST 中,选中工程 SimpleJaxWS 下的 WSDL 文件 SimpleBeanService.WSDL,在右键菜单中启动 Web services 客户端创建向导。在创建过程中,同样需要选择 runtime 为 IBM WebSphere JAX-WS, 其它按默认设置。最终生成的客户端项目结构如下:




其中自动生成的 Java source 包括 JAXB 对象 , 如上图中的 AddNumber.java,AddNumberResponse.java, ObjectFactory.java 以及 package-info.java 类,和 service 代理类,如上图中的 SimpleBeanDelegate.java, SimpleBeanPortProxy.java 以及 SimpleBeanService.java 类。然后,再写一个测试类 WSClient.java,该类是一个独立运行的 Java application。测试时,您需要在 classpath 中添加一个 thin client:com.ibm.jaxws.thinclient_6.1.0.jar。该 jar 在 $WAS_HOME/runtimes 目录下可以找到。

清单 3. 调用 Web service 的客户端 WSClient.java

public class WSClient { QName serviceName = new QName("http://server.demo.ws.ibm.com/","SimpleBeanService");QName portName = new QName("http://server.demo.ws.ibm.com/","SimpleBeanPort"); String host = "9.186.117.142" ;String port = "9080" ; String endpt ;String WSDLURL ;SimpleBeanService service = null;  public WSClient() { endpt = "http://"+ host +":" + port +"/SimpleJaxWS/SimpleBeanService" ;WSDLURL = "http://"+ host +":" + port + "/SimpleJaxWS/SimpleBeanService/WEB-INF/WSDL/SimpleBeanService.WSDL" ; |-------10--------20--------30--------40--------50--------60--------70--------80--------9|  |-------- XML error: The previous line is longer than the max of 90 characters ---------|  } /*** Get the SEI from endpoint address* @param endpt* @return*/public SimpleBeanDelegate getSEIFromEndpoint() { SimpleBeanDelegate port = null ;BindingProvider p = null; try { service = new SimpleBeanService(null, serviceName);System.out.println("Looking up service "+ service.getServiceName()); port = service.getSimpleBeanPort();p = (BindingProvider) port;p.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpt);//p.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE); |-------10--------20--------30--------40--------50--------60--------70--------80--------9|  |-------- XML error: The previous line is longer than the max of 90 characters ---------| //p.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY, "invoke");  |-------10--------20--------30--------40--------50--------60--------70--------80--------9|  |-------- XML error: The previous line is longer than the max of 90 characters ---------|   } catch (Exception e) {e.printStackTrace() ;} return port ; }   public void simpleCall() { try {  SimpleBeanDelegate port = getSEIFromEndpoint() ; System.out.println(port.addNumber(8, 9));  } catch (Exception e) {e.printStackTrace();}}  public static void main(String[] args) {  WSClient client = new WSClient() ; client.simpleCall() ;  }




客户端调用 Web service 的常见过程为:先创建一个 service 对象,再从 service 对象获得 SEI,最后调用 SEI 的方法去访问 Web service。

Web services 客户端的异步调用方式

除了上述的同步调用方式外,JAX-WS 2.0 还提供了异步调用,采用异步调用,客户端不需要等待 SOAP response 消息的返回,就可以继续别的处理。异步调用方式有 polling 和 callback 两种,这里只讲 callback 方式。 callback 就是提供一个 callback 函数,供消息返回时调用。在 Java 中,该 callback 函数是一个实现了特定接口的类。如果要异步方式访问 Web services,首先得在 SEI 中生成一个异步调用的方法。在用 AST 中的 Web services 向导工具创建 Web services 客户端时,注意选中“生成异步调用方法”:

生成的异步调用方法如下:

清单 4. 用于异步调用 Web service 的方法定义

@WebMethod(operationName = "addNumber")@RequestWrapper(localName = "addNumber", targetNamespace = "http://server.demo.ws.ibm.com/", className = "com.ibm.ws.demo.client.AddNumber")@ResponseWrapper(localName = "addNumberResponse", targetNamespace = "http://server.demo.ws.ibm.com/", className = "com.ibm.ws.demo.client.AddNumberResponse")public Future < ? > addNumberAsync(@WebParam(name = "arg0", targetNamespace = "")int arg0,@WebParam(name = "arg1", targetNamespace = "")int arg1,@WebParam(name = "asyncHandler", targetNamespace = "")AsyncHandler < AddNumberResponse > asyncHandler);




当 SOAP response 返回时,客户端 runtime 会调用我们提供的 AsyncHandler。下面是一个实现了 AsyncHandler 的类。

清单 5. 用于异步调用 Web service 的 Handler 类,处理返回的 SOAP 消息

import javax.xml.ws.AsyncHandler;import javax.xml.ws.Response; public class CallbackHandler implements AsyncHandler <AddNumberResponse>{ public void handleResponse(Response response) { AddNumberResponse res = (AddNumberResponse)response ;//do something with the response...System.out.println("Response result is : " + res.getReturn());}}




最终,客户端异步调用 Web services 的形式为:

清单 6. 异步调用 Web service 的代码

public void asyncCall() { try {  SimpleBeanDelegate port = getFromJavaBeanImpl(endpt) ;CallbackHandler asyncHandler = new CallbackHandler() ;port.addNumberAsync(8, 9, asyncHandler) ;  //do other things... } catch (Exception e) {e.printStackTrace();}}




Provider/Dispatch 编程模型

JAX-WS 2.0 还提供了 service 端和 client 端的动态编程模型:Provider/Dispatch 模型。Provider<T> 和 Dispatch<T> 分别是 service 端和 client 端提供的两个接口,该编程模型可以让您在 xml message 级别上工作。换言之,您可以通过编程操纵整个 SOAP 信封或 SOAP 信封的 body。 T 的类型和另一个参数 Service.Mode 组合在一起,决定了操作的 xml message 到底是整个 SOAP 信封还是部分。T 的两种类型为 Source 和 SOAPMessage,两种 Service 模式为 Service.Mode.MESSAGE 和 Service.Mode.PAYLOAD。下面给出了其中一种组合的示例。

Service 端的代码示例

清单 7. 以 Provider 模式实现 Web service 的 service 端 Java 类

@WebServiceProvider @ServiceMode(value=Service.Mode.MESSAGE) public class ProviderImpl implementsProvider<SOAPMessage> { public SOAPMessage invoke(SOAPMessage msg) { //here the msg is the entire SOAP request // do request processingSOAPMessage response = ...; return response; } }




Client 端的代码示例

清单 8. 以 Dispatch 模式调用 Web service 的 client 端 Java 类

//create the serviceService service = Service.createService(QName serviceQName);//or Service service = Service.createService(URL WSDLLocation, QName serviceQName);//set the bindingservice.addPort(QName portName, String SOAPBinding.SOAP11HTTP_BINDING, String endpointAddress);//create the dispatchDispatch dispatch = service.createDispatch(QName portName, Class clazz, Service.Mode mode);//Dispatch dispatch = service.createDispatch(QName portName, JAXBContext jaxbcontext, Service.Mode mode); //invoke the Web servicesObject response = dispatch.invoke(T);dispatch.invokeOneway(T);//or Response<T> response = dispatch.invokeAsync(T);//or Future<?> response = dispatch.invokeAsync(T, AsyncHandler);




这里的问题是如何生成类型 T 的实例,答案是通过 JAXB 标准提供的 API 将 Java object 转化为 xml message 对象。




 


回页首 




通过 wsgen,wsimport 工具创建 Web services

除了 AST 中提供的图形界面开发方式外,Web services 功能部件包还提供了创建 Web services 的命令行工具。其中,wsgen 支持从 Java class 创建 Web services,wsimport 支持从 WSDL 创建 Web services。分别对应于 JAX-RPC 方式下的 Java2WSDL 和 WSDL2Java。

清单 9. wsgen 命令格式

wsgen [options] < SEI >

主要选项:

-d 指定生成的 class 文件的位置。
-s 指定生成的 Java source 文件的位置。
-r 指定生成的 resources 文件的位置。如 WSDL,xsd 的位置。
-WSDL,-servicename,-portname 三个参数指定生成的 WSDL 文件中的 service 和 port 的名称。
注意:这里的 SEI 是一个 endpoint implementation class,而不是一个接口。你必须先写好一个 endpoint 的实现类,如上面的 SimpleBeanDelegate,该类中用 @WebService 声明好 Web service,再将它编译成 class 文件,才能提供给 wsgen 使用。

清单 10. wsgen 使用实例

wsgen.sh -cp classes -s src -d bin -r web -WSDL com.ibm.ws.demo.server.SimpleBeanDelegate




清单 11. wsimport 命令格式

wsimport [options] <WSDL_URI>

主要选项:

-d 指定生成的 class 文件的位置。
-s 指定生成的 Java source 文件的位置。
-WSDLlocation 指定生成的 Java source 中 @WebService.WSDLLocation 和 @WebServiceClient.WSDLLocation 的值。
清单 12. wsimport 使用实例

wsimport.sh -d classes -s src -WSDLlocation /WEB-INF/WSDL/SimpleBeanService.WSDL SimpleBeanService.WSDL 






 


回页首 




通过 Ant task 自动构建 Web services 应用

WebSphere 同时提供了用于创建 Web services 的 ant task,这些 task 的参数和 wsgen,wsimport 是一致的。利用这些 ant task,您可以在大型项目中完成自动构建工作。

清单 13. 在 Ant 中使用 wsgen 和 wsimport

<wsgen sei="..."destdir="directory for generated class files"classpath="classpath"resourcedestdir="directory for generated resource files such as WSDLs"sourcedestdir="directory for generated source files" keep="true|false" verbose="true|false"genWSDL="true|false" protocol="soap1.1|soap1.2"servicename="..."portname="..."extension="true|false"><classpath refid="..."/></wsgen> <wsimport WSDL="..." destdir="directory for generated class files" sourcedestdir="directory for generated source files" keep="true|false" extension="true|false" verbose="true|false" version="true|false" WSDLLocation="..." catalog="catalog file" package="package name"><binding dir="..." includes="..." /> </wsimport>




结束语

本文向您讲述了 JAX-WS 2.0 的主要特性,并通过示例展示了 Web services 新的编程模型和 API 及其开发过程。通过本文,您可以对 JAX-WS 2.0 有一个初步的了解,并懂得如何通过 WebSphere 提供的工具开发简单的符合 JAX-WS 2.0 的 Web services。值得说明的是,本文并没有向您介绍 JAX-WS 2.0 的全部特性,您可以通过本文提供的参考资源获得更多信息。





参考资料

学习

JAX-WS 相关内容
Web 服务提示与技巧: JAX-RPC 与 JAX-WS 的比较
Web 服务提示与技巧: JAX-RPC 与 JAX-WS,第 2 部分
Web 服务提示与技巧: JAX-RPC 与 JAX-WS 的比较,第 3 部分
Web 服务提示与技巧: JAX-RPC 与 JAX-WS 的比较,第 4 部分
在 WebSphere Application Server Community Edition V2.0 中开发和部署 JAX-WS Web 服务
设计与开发 JAX-WS 2.0 Web 服务
WebSphere 应用服务器 6.1 Web Services 功能部件包入门 :本文将介绍 WebSphere 应用服务器 6.1 Web Services 功能部件包提供的新增内容,解答一些常见问题,同时指引读者去利用它提供的样本程序加深对它的理解。

WebSphere Application Server - Web Service 功能部件包信息中心 :了解更多产品的信息

JAX-WS 2.0 的规范、API 类和 Javadoc

MTOM 规范 :阅读 MTOM 规范

IBM developerWorks SOA and Web services 专区 提供了大量的文章,以及关于如何开发 Web 服务应用程序的初级、中级和高级教程。

使用 IBM SOA Sandbox 进行试验!通过 IBM SOA 进行实际的亲手实践来提高您的 SOA 技能。

IBM SOA 网站 提供 SOA 的概述,并介绍 IBM 是如何帮助您实现 SOA 的。

了解关于 developerWorks 技术事件和网络广播 的最新消息。请特别关注以下 SOA 和 Web 服务技术讲座:
Building SOA solutions and managing the service lifecycle
SCA/SDO: To drive the next generation of SOA
访问 Safari 书店 ,浏览有关这些技术主题以及其他方面的书籍。

猜你喜欢

转载自imthinking.iteye.com/blog/1133056