主题
企业架构
作者:Mike Wooten
10/30/2007
本文将提供一系列关于JAX-WS自定义绑定的教程——这些教程是JAX-WS规范的一部分,主要涵盖WSDL到Java映射。其中多处提到了JAXB自定义绑定。
介绍 JAX-WS 自定义绑定之后,本文将通过以下教程介绍如何执行各种自定义任务:
然后,我将在示例代码中演示如何使用JAX-WS和JAXB自定义绑定的结果。自定义绑定适用于服务使用者和服务提供者,因此示例代码中将反映以下内容:
JAX-WS自定义绑定是JAX-WS规范的一部分,主要涵盖WSDL到Java映射。JAXB规范中有一个类似的部分涵盖了XSD到Java映射。
这已经足够好了,可是为什么还要控制WSDL到Java(或XSD到Java)映射呢?我将使用您最近可能遇到的一些场景来解答这个问题。
假设有一个WSDL使用 parameters 值作为每个 <message><part> 元素的 name 属性。您的JAX-WS工具将抱怨它们无法通过此WSDL生成JAX-WS工件,原因是 name 属性的值不是惟一的。可以通过将 ?WSDL 链接到服务端点来获取WSDL,托管服务端点的一方已经声明自己不能控制WSDL,因为WSDL将“自动”生成。
通过自定义绑定可以保证 name 属性的惟一性,从而解决此问题。
某个项目需要使用JAX-WS Web服务的Java方法名和参数匹配由公司体系结构团队生成UML工件。要实现这一点,需要修改发给合作伙伴的WSDL,而您无法完成这一操作。
通过自定义绑定,您可以将JAX-WS Web服务中的方法签名(比如说,方法名和输入参数)与UML工件中的内容相匹配。
您的团队的这样一个策略:通过XML模式生成的所有类 必须在完全限定名中包含以下内容,以便于指定:
通过自定义绑定,您可以指示JAXB工具满足这一需求(当它们生成JAXB类时)。
以上只是可以(需要)使用自定义绑定的场景中的一部分。我将在本文中讨论如何完成这些操作,因此我将从最基本的定义开始。
通常,人们更愿意将自定义绑定称作 绑定声明,因此本文其余部分将使用后面这个术语。从本质上说,绑定声明就是使用XML表示的一组“指令”,这些指令既可以嵌入WSDL或XML模式文件,也可存放在外部XML文件中。对于后者,将使用XPath表达式选择WSDL或XML模式文件中的目标内容。基于XML文件的方法是SOA架构师和开发人员的首选,因为它可以提供灵活性同时又不会牺牲可维护性或治理能力。
绑定声明是一组XML元素,由Sun的 wsimport Ant任务进行处理。在第一篇文章中,我已经指出BEA的Ant任务(即 jwsc、 wsdlc 和 clientgen)将从内部调用 wsimport 任务。在与本文相关的代码中,我将在使用BEA的 wsdlc Ant任务。因此我将wsdlc包含在 run-wsdlc Ant目标中:
<target name="run-wsdlc" depends="clean">
<taskdef name="wsdlc" classname="weblogic.wsee.tools.anttasks.WsdlcTask" classpathref="compile.classpath" />
<mkdir dir="${src.dir}"/>
<property name="binding.declaration.files" value="server-jaxws.xbd,shared-jaxb.xbd"/>
<wsdlc
type="JAXWS"
srcWsdl="etc/${wsdl.file.name}.wsdl"
destJwsDir="WebContent/WEB-INF/lib"
destImplDir="${src.dir}"
explode="false"
verbose="${verbose}"
debug="${debug}"
failonerror="true"
>
<binding dir="etc" includes="${binding.declaration.files}"/>
<classpath>
<path refid="compile.classpath"/>
</classpath>
</wsdlc>
</target>
此处,我们需求讨论一下 type="JAXWS" 属性和 <binding>子元素。绑定声明位于 <binding> 元素的 includes 属性所指定的文件中。我使用.xbd(表示XML绑定声明)作为文件扩展名。 type="JAXWS"属性通知 wsdlc Ant任务将文件传递给 wsimport Ant任务。
<property> 元素用于保存所使用的两个绑定自定义文件的名称。第一个文件(名称为 etc/server-jaxws.xbd)用于服务提供者端的JAX-WS绑定声明。第二个文件(名称为 etc/shared-jaxb.xbd)与JAXB相关,并且同时用于服务提供者端和服务使用者端。
使用JAX-WS可以指定WSDL中的信息如何映射到为JAX-WS Web服务和JAX-WS Web服务使用者生成的Java代码。这种Java代码包括:
SEI提供者接口类
实现SEI提供者接口类的框架类(框架类)
框架类中所使用的方法和参数的名称
用于报错的异常类
在Web服务的方法签名中使用 java.util.Vector,而不是 java.util.List*
为Java对象生成的子类、超类和超接口,作为某个Web服务的返回值和输入参数*
生成的 enum 类和指派给其成员的值*
*使用JAXB绑定自定义文件完成
本文下一部分将介绍如何通过JAX-WS 绑定声明完成上述非星号项目。
现在,我将介绍JAX-WS绑定声明的一些使用方法。
这种绑定声明与JAXB结合可能比与JAX-WS结合具有很大的价值,但是我们不能因此而否认它的重要性。
我在第一篇文章中介绍过通过JAXB实现这种绑定声明。本文将继续介绍通过JAX-WS实现这种绑定声明。使用目的仍然相同: 即控制生成类的Java包名。下面是 shared-jaxb.xbd 绑定声明文件的内容(用于指定通过XML模式文件生成的类的Java包名):
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" > <jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
schemaLocation="datastaging_exceptions.xsd" node="/xs:schema" > <jxb:schemaBindings>
<jxb:package name="services.datastaging.exceptions"/> </jxb:schemaBindings> </jxb:bindings> </jxb:bindings>
使用这个 shared-jaxb.xbd 文件将导致通过 datastaging_exceptions.xsd 文件生成的所有JAXB类的Java包名都使用 services.datastaging.exceptions。如果没有指定绑定声明文件,则类的Java包名将以 datastaging_exceptions.xsd 文件中的( <schemas> 元素的) targetNamespace 属性为基础。
注意:不要在 wsdlc、 jwsc 或 clientgen Ant任务上使用 package 属性。此操作将覆盖绑定声明文件中的 <package>绑定声明。
如果您的XML模式文件使用了 <xs:include> 或 <xs:import> 元素,那么事情将更具挑战。如果含有 <xs:schema> 的 WSDL 使用了 <xs:import> 元素也同样如此。不管哪种情况,您都希望使用JAXB绑定声明文件指定Java包名。以下是的JAXB绑定声明文件的摘录,它演示了如何使用OASIS WS-Notification规范中的 XML 模式实现这一目的。
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" > <jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
schemaLocation="schemas/oasis-wsn13.xsd"
node="/xs:schema" > <jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
node="//xs:schema/xs:import[@namespace='http://docs.oasis-open.org/wsn/b-2']" > <jxb:schemaBindings> <jxb:package name="org.oasis_open.docs.wsn.b_2"/> </jxb:schemaBindings> </jxb:bindings> <jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
node="//xs:schema/xs:import[@namespace='http://docs.oasis-open.org/wsn/br-2']" > <jxb:schemaBindings> <jxb:package name="org.oasis_open.docs.wsn.br_2"/> </jxb:schemaBindings> </jxb:bindings> <jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
node="//xs:schema/xs:import[@namespace='http://docs.oasis-open.org/wsn/t-1']" > <jxb:schemaBindings> <jxb:package name="org.oasis_open.docs.wsn.t_1"/> </jxb:schemaBindings> </jxb:bindings> ... </jxb:bindings> </jxb:bindings>
请注意黑体部分, node 属性中的XPath表达式使内容具有可单击特性。第一个嵌套的 <jxb:bindings> 元素包含 schemaLocation 属性,该属性设置使用XML模式文件。其他嵌套 <jxb:bindings> 元素的 node 属性用于处理XML模式文件中的各种 <xs:import> 元素。
一个绑定声明文件中可以嵌入多个含有 schemaLocation 属性的 <jxb:bindings> 元素。如果对于模块性和易重用性的要求比较高,则不适合使用此方法。为每个XML模式都使用一个单独的绑定声明可提高易用性等方面。此外,还可以更容易地将它们组织到可重用的软件资产中,以实现治理目的。