axis2 访问 axis 1.4

来源:互联网 发布:股票精灵软件 编辑:程序博客网 时间:2024/05/18 17:44
axis2 与 axis1.4 的一个兼容性问题 这个问题是我在实际项目中使用 axis2 stub 访问一个 webservice 并发送一段二进制数据时遇到的。 
webservice 是由德国人实现的,并部署在德国。
刚开始并不知道他们的 webservice 是使用什么技术实现的,他们也不提供除 wsdl 之外的任何信息。
在进度延期的情况下,德国人给了一段之前测试过的有效的 stub 。由于一些实际环境的困难,并不能在我方运行这个 stub 。
注意到这个客户端中包含了一个 axis.jar 包,被证实是 axis1.4 。
于是使用 axis1.4 利用德方提供的 wsdl 生成了一个 skeleton + stub 。
利用 tcpmon 来观察使用 stub(axis1.4) 和 stub(axis2) 分别向这个 skeleton(axis1.4) 发送的 soap 消息,从而找到问题的突破口。


WSDL 中有如下一段定义:


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:java/lang" 
xmlns:tns="urn:java/lang" elementFormDefault="qualified">
<xs:complexType name="ArrayOfjava.lang.Byte">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="java.lang.Byte"
type="xs:byte" nillable="true"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
...
<xs:schema xmlns:xs="http://www.w3.org/2001XMLSchema" xmlns:s1="urn:java/lang" 
targetNamespace="urn:ZighouseTest" xmlns:tns="urn:ZighouseTest" 
elementFormDefault="qualified">
<xs:element name="test">
<xs:complexType>
<xs:sequence>
<xs:element name="data" type="s1:ArrayOfjava.lang.Byte" nillable="true"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
...


使用 axis1.4 的 wsdl2java 工具生成 java 代码,并利用这些代码产生一个 soap 消息的内容如下:


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<test xmlns="urn:ZighouseTest">
<data>
<ns1:java.lang.Byte xmlns:ns1="urn:java/lang">60</ns1:java.lang.Byte>
<ns1:java.lang.Byte xmlns:ns2="urn:java/lang">63</ns1:java.lang.Byte>
<ns1:java.lang.Byte xmlns:ns3="urn:java/lang">120</ns1:java.lang.Byte>
<!--
...
there are bulks of ns1:java.lang.Byte elements
-->
</data>
</test>
</soapenv:Body>
</soapenv:Envelope>


使用 axis2 的 wsdl2java 工具生成 java 代码,并利用这些代码产生一个 soap 消息的内容如下:


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns3:test xmlns:ns3="urn:ZighouseTest">
<ns3:data>
<ns2:Byte xmlns:ns2="urn:java/lang">60</ns2:Byte>
<ns2:Byte xmlns:ns2="urn:java/lang">63</ns2:Byte>
<ns2:Byte xmlns:ns2="urn:java/lang">120</ns2:Byte>
<!--
...
there are bulks of ns2:Byte elements 
-->
</ns3:data>
</ns3:test>
</soapenv:Body>
</soapenv:Envelope>


通过比较发现 axis1.4 生成的 soap 内容中对 java.lang.Byte[] 中的元素给的 qname 是类型的全名,即带了 package 名的类名(java.lang.Byte)。
而在 axis2 生成的 soap 内容中对应的 qname 只是类的简名(Byte),省略了 package 名。这会导致兼容性问题。


如果已经部署了一个老系统,它使用的 webservice 是由 axis1.4 生成的 skeleton,而当一个新的业务系统需要与这个老系统进行交互时,如果新业务系统使用 axis2 生成 stub,
就会导致不能正确地通讯。因为 skeleton(axis1.4) 只认全名的元素(java.lang.Byte),而 stub(axis2) 给的内容是简名的元素(Byte)。


解决办法是有的。如果坚持使用 stub(axis2),在不修改老系统的前提下则需要修改 stub(axis2) 中的代码,把 qname 改为类的全名。即找到所有如下的内容:


new javax.xml.namespace.QName("urn:java/lang", "Byte")


并把其中的 "Byte" 替换成为 "java.lang.Byte" 就可以了。这之后使用 stub(axis2) 生成的 soap 消息中使用的就是用类的全名表示的元素了。


建议:不要在定义 wsdl 时使用 byte, int, long 等 primitive 数据类型的数组,而应该使用 base64Binary 类型。
因为从上面的例子不难看出对一上字节进行表达的 soap 消息使用了过多的冗余信息,极有可能导致效率问题。
不过当使用 axis2 的 java2wsdl 工具生成 wsdl 时,已经考虑了这个问题,会自动生成使用 base64Binary 类型的元素描述。
即使如此,最好对自动生成的 wsdl 文件也应该仔细地读一下,确保文件中所描述的内容是有效的。
 
0 0