欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

axis 1.4调用cxf 2.x服务接口,自定义对象数组参数丢失问题 博客分类: WebJava webservicecxfaxisnull空 

程序员文章站 2024-03-06 17:56:56
...
最近在做一个项目,遇到了一个奇怪的问题:webservice接口能够正常调用,但却出现了部分参数传递正确,个别参数的值丢失(null)的情况。由于以前未曾遇过,为了这个问题还折腾了几天,那个苦呀。
 
简单描述一下需求:
项目中有一个现网的webservice接口,原来是A厂家提供服务端,B厂家提供客户端进行调用。现在A厂家不做了,需要由我们来实现服务端。
 
好,开始干吧...,嗯...自己测试通过,部署到测试环境,找B厂家测试一下,好的,原来的业务流程都能正常跑通,接口上线吧...
过了几天,客户反馈有个参数为空,检查呀检查呀,哦,是接口中传递过来的某个参数为空。于是,找了B厂家进行测试确认,对方还提供了抓包,我自己也抓了包,发现该参数的确是有传递的。这就奇怪了,从未遇到过接口的参数出现丢失的问题。刚开始以为接口写得有问题,从命名空间、参数名等注解、对象数组参数的声明等进行排查,最终都无济于事。还尝试过升降cxf的版本,结果还会抛不同的异常,这回可真纳闷了...
 
由于B厂家一直是在现网使用当中的,未曾对接口进行改动,所以刚开始一直怀疑是自己的问题。后来实在没办法,只能找B厂家一起解决。联调工作本来不复杂,但B厂家做开发的远在异乡,还上不了网。需要测试还得发布版本让其他支撑人员部署到测试环境,再和我们进行联调。由于我们的本地网络和他们的测试环境的网络是不通的,我们又必须得部署到测试环境与他们进行测试。这个过程可真够麻烦的,效率非常非常的低,非常难排查问题。
 
在这个过程中,通过google了解过axis1.4似乎存在这样的问题,但资料不多。在测试的过程中也向对方了解过,他们用的的确是axis1.4。曾经想过如果使用axis1.4进行实现应该就没问题了,但问题在于从未使用过axis,一方面研究要花时间,另一方面我一直坚信这么强大的框架(cxf),即使有不兼容的地方应该也有办法解决吧。还曾想过修改cxf源代码来实现,但后来感觉还没必要走这一步,不太合理。
 
再后来,实在是没信心了。还是找找axis1.4的例子来参考,成功率应该比较高。结果呢,不必猜大家也都知道,也就花了不到半天的时间就把问题解决了。折腾了这么久的问题,本来一直以为解决之后会很兴奋,没想到最后解决了都没啥感觉,也许这是因为我心里早就知道用axis1.4就会成功的原因吧,如果能用cxf解决这个问题也许还会兴奋一点。
 
 
一、根据wsdl文件生成java代码命令
1、cxf
wsdl2java -d D:\wsdl D:\wsdl\Services.wsdl
wsdl2java -d D:\wsdl -server D:\wsdl\HelloWorld.wsdl (生成服务端启动类)
wsdl2java -d D:\wsdl -client D:\wsdl\HelloWorld.wsdl (生成客户端调用类)
 
2、axis
java -cp axis.jar;commons-logging.jar;commons-discovery-0.2.jar;jaxrpc.jar;saaj.jar;wsdl4j-1.6.2.jar;activation.jar;mail.jar org.apache.axis.wsdl.WSDL2Java D:\wsdl\Services.wsdl
 
 
二、总结一下遇到的问题或异常(以下内容部分名称进行了修改,大家懂的)
1、axis1.4调用cxf2.1.3,接口是通的,丢失对象数组参数
2、axis1.4调用cxf2.4.2,报命名空间异常,这一点在cxf2.4.2应该是控制得比较严格吧:
WARNING: Interceptor for {http://a.b.c/}CmImplService#{http://a.b.c/}sciRsp has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: Unexpected wrapper element {urn:cnRsp}sciRsp found. Expected {http://a.b.c}sciRsp.
如果解决了命名空间问题,还会报:
org.apache.cxf.interceptor.Fault: Unmarshalling Error: unexpected element (uri:"", local:"myparams"). Expected elements are <{}a>,<{}b>,<{}c>,<{}d>
3、使用cxf根据axis1.4的wsdl生成java代码
wsdl2java -d D:\wsdl -server -client D:\wsdl\DeployManage.wsdl
提示:
WSDLToJava Error: Rpc/encoded wsdls are not supported in JAXWS 2.0
WSDLToJava Error: Thrown by JAXB : undefined simple or complex type 'soapenc:Array'
 
以下为引自网络的一些内容(  尝试过,1)、2)的处理方式对于某些情况是可以的,但对于我遇到的情况却是不可行的 ):
1)WSDLToJava Error: Thrown by JAXB : undefined simple or complex type 'soapenc:Array'
 
对与同一个wsdl文件,我尝试过使用axis2是可以正常转过来java代码。 
但是,当使用cxf时,出现了报错: 
 
Java代码:
WSDLToJava Error: Thrown by JAXB:  
Thrown by JAXB:  
undefined simple or complex type 'soapenc:Array'  
wsdl的出错部分: 
 
Xml代码:
<s:schema targetNamespace="http://iamsweb.gmcc.net/WS/AbstractTypes">  
      <s:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>  
      <s:complexType name="StringArray">  
        <s:complexContent mixed="false">  
          <s:restriction base="soapenc:Array">  
            <s:sequence>  
              <s:element minOccurs="0" maxOccurs="unbounded" name="String" type="s:string" />  
            </s:sequence>  
          </s:restriction>  
        </s:complexContent>  
      </s:complexType>  
    </s:schema>  
这时,只需增加schemaLocation。如 
 
Xml代码:
<s:schema targetNamespace="http://iamsweb.gmcc.net/WS/AbstractTypes">  
      <s:import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"/>  
      <s:complexType name="StringArray">  
        <s:complexContent mixed="false">  
          <s:restriction base="soapenc:Array">  
            <s:sequence>  
              <s:element minOccurs="0" maxOccurs="unbounded" name="String" type="s:string" />  
            </s:sequence>  
          </s:restriction>  
        </s:complexContent>  
      </s:complexType>  
    </s:schema>  
 
2)WSDLToJava Error: Rpc/Encoded WSDLs Are Not Supported with CXF
WSDLToJava Error: Rpc/encoded wsdls are not supported in JAXWS 2.0
 

RPC/encoded is a vestige from before SOAP objects were defined with XML Schema. It’s not widely supported anymore. You will need to generate the stubs using Apache Axis 1.0, which is from the same era.

java org.apache.axis.wsdl.WSDL2Java http://someurl?WSDL

You will need the following jars or equivalents in the -cp classpath param:

axis-1.4.jar
commons-logging-1.1.ja
commons-discovery-0.2.jar
jaxrpc-1.1.jar
saaj-1.1.jar
wsdl4j-1.4.jar
activation-1.1.jar
mail-1.4.jar

This will generate similar stubs to wsimport.

Alternatively, if you are not using the parts of the schema that require rpc/encoded, you can download a copy of the WSDL and comment out those bits. Then run wsimport against the local file.

If you look at the WSDL, the following bits are using rpc/encoded:

<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

 
3)
Rpc/encoded wsdls are not supported in JAXWS 2.0
 
"Rpc/encoded wsdls are not supported in JAXWS 2.0"这个错误,出现在用NB6创建WebService客户端时,该服务WSDL文件有如下语句:
       <wsdl:binding name="AgentBankServiceSoapBinding" type="impl:AgentBankService">
      <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
      <wsdl:operation name="refundPayDetailInput">
         <wsdlsoap:operation soapAction=""/>
         <wsdl:input name="refundPayDetailInputRequest">
            <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://pay.foundercy.com" use="encoded"/>
         </wsdl:input>
到网上查阅了相关信息,一般说法是JAX-WS 2.0无法直接支持rpc/ecn类型的服务,在一篇为rpc/enc类型的google服务讲解使用JAX-WS2.0变通的方法访问服务时有所提到.而Axis2的 wsdl2java工具对于rpc/enc类型的wsdl文件牏处理时恐怕也有相似的问题.更不幸的是,服务端的WSDL对于客户有开发人员来说几乎是不可能改变的.有如下一些解决方案可能会有用:
1  用回老版本工具,比如Axis1或使用JAX-RPC类型等等.
2  手工做些辅助的工作,如Accessing Google Web Service using JAX-WS 所述的一样.
3  对服务端的WSDL作些相应在改变,比如将encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 句去掉,并将use="encoded"改为use= "literal".
4 在向导中把J2EE改为1.4版本之前.
没有仔细的研究,但是此服务导入VS2005时却没 现什么问题,暂时决定在.net平台下用C#来做.
 
(转载请注明来源:http://zhanjia.iteye.com/blog/1987912)