CXF调用.net webservice之any 元素

 

CXF调用.net webserviceany 元素 

这两天工作之余帮前公司的小弟调一个比较恶心的Web Service问题。是CXF Java客户端调用.net Web Service的接口。接口返回类型是复杂类型,而且是 type,这个类型比较变态,cxfwsdl2java不能很好的转换该类型。请看详请。

 

接口Wsdl主要内容展示:

xml version="1.0" encoding="utf-8" ?>

-

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

    xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"

    xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://esf.soufun.com/"

    xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"

    xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://esf.soufun.com/"

    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

    -

    <wsdl:types>

       -

       <s:schema elementFormDefault="qualified" targetNamespace="http://esf.soufun.com/">

//.net接口

           <s:element name="AgentInfo">

              -

              <s:complexType>

                  -

                  <s:sequence>

                     <s:element minOccurs="0" maxOccurs="1" name="userName"

                         type="s:string" />

                     <s:element minOccurs="0" maxOccurs="1" name="pwd" type="s:string" />

                  s:sequence>

              s:complexType>

           s:element>

           -

//.net 接口返回类型。

           <s:element name="AgentInfoResponse">

              -

              <s:complexType>

                  -

                  <s:sequence>

                     -

                     <s:element minOccurs="0" maxOccurs="1" name="AgentInfoResult">

                         -

                         <s:complexType mixed="true">

                            -

                            <s:sequence>

                               

                            s:sequence>

                         s:complexType>

                     s:element>

                  s:sequence>

              s:complexType>

           s:element>

           -

           //省略N多字

    <wsdl:service name="Service">

       -

       <wsdl:port name="ServiceSoap" binding="tns:ServiceSoap">

           <soap:address

               location="http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx" />

       wsdl:port>

       -

       <wsdl:port name="ServiceSoap12" binding="tns:ServiceSoap12">

           <soap12:address

               location="http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx" />

       wsdl:port>

    wsdl:service>

wsdl:definitions>

 

关于类型

元素

元素使我们有能力通过未被 schema 规定的元素来拓展 XML 文档!

下面这个例子是从名为 "family.xsd" XML schema 中引用的片段。它展示了一个针对 "person" 元素的声明。通过使用 元素,我们可以通过任何元素(在 之后)扩展 "person" 的内容:



 

   

     

     

     

   

 

现在,我们希望使用 "children" 元素来扩展 "person" 元素。这此种情况下我们就可以这么做,即使以上这个 schema 的作者没有声明任何 "children" 元素。

请看这个 schema 文件,名为 "children.xsd"




targetNamespace="http://www.devwb.com"

xmlns="http://www.devwb.com"

elementFormDefault="qualified">





 

   

     

      maxOccurs="unbounded"/>

   

 





下面这个 XML 文件(名为 "Myfamily.xml"),使用了来自两个不同的 schema 中的成分,"family.xsd" "children.xsd"






xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:SchemaLocation="http://www.microsoft.com family.xsd

http://www.devwb.com children.xsd">





David

Smith



  mike









Tony

Smith





上面这个 XML 文件是有效的,这是由于 schema "family.xsd" 允许我们通过在 "lastname" 元素后的可选元素来扩展 "person" 元素。

均可用于制作可扩展的文档!它们使文档有能力包含未在主 XML schema 中声明过的附加元素。

以上是网上介绍any的一个例子,一句话总结就是any可以是任意的复杂类型。并且是扩展的方法,不固定。

生成Java client stub

wsdl2java -p com.soufun.esf -d src -all

http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx?wsdl

 

简要说明:

-p:生成类的包路径

-d:生成的类放在哪

-all:生成所有东西

 

生成的接收文件片断,可以看到any类型转换成List.

    @XmlAccessorType(XmlAccessType.FIELD)

    @XmlType(name = "", propOrder = { "content" })

    public static class AgentInfoResult {

 

       @XmlMixed

       @XmlAnyElement(lax = true)

       protected List content;

 

错误的调用代码:

    public static void test() throws MalformedURLException {

       URL wsdlURL = new URL(

              "http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx?wsdl");

       Service ss = new Service(wsdlURL, SERVICE_NAME);

       ServiceSoap port = ss.getServiceSoap12();

       AgentInfoResult resp = port.agentInfo("kkxxx", "password");

       System.out.println("agentInfo.result=" + resp.getContent());

    }

下面是.net应该返回的any格式

 

 

 

List里面应该有对象Agent对象才对,但是没有,agentnull.

也就是说wsdl2java无法正常转换any type类型到java相关对象。

 

正确的调用方法:

xerces-2.6.2.jar包解析any返回内容

    /**

     * 获取.net webservice any类型的数据。

     */

    public static void test2() {

       JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

 

       factory.getInInterceptors().add(new LoggingInInterceptor());

       factory.getOutInterceptors().add(new LoggingOutInterceptor());

       factory.setServiceClass(ServiceSoap.class);

       factory.setAddress("http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx?wsdl");

       ServiceSoap service = (ServiceSoap) factory.create();

       com.soufun.esf.AgentInfoResponse.AgentInfoResult result = service

              .agentInfo("kkxx", "password");

        // javax.xml.soap.SOAPElement e=(SOAPElement)

       // result.getContent().get(0);

       for (int i = 0; i < result.getContent().size(); i++) {

           org.apache.xerces.dom.ElementNSImpl element = (ElementNSImpl) result

                  .getContent().get(i);

           System.out.println(element.getAttributes().getNamedItem("account"));

           System.out.println(element.getAttributes().getNamedItem("name")

                  .getNodeValue());

           System.out.println(element.getAttributes().getNamedItem("level"));

           System.out.println(element.getAttributes().getNamedItem("score"));

           System.out.println(element.getAttributes().getNamedItem("mobile"));

           System.out.println(element.getAttributes().getNamedItem("email"));

           System.out.println(element.getAttributes().getNamedItem("mobile"));

           System.out.println(element.getAttributes().getNamedItem(

                  "expiredDate"));

       }

    }

 

 

这个里面result.getContent()里面的agent依旧为null,只好直接用org.apache.xerces.dom.ElementNSImpl接收相应any转换的元素,然后解析。

 

成功,结果如下:

信息: Outbound Message

---------------------------

ID: 1

Address: http://agentinterfacen.test.soufun.com/HouseImportService/Service.asmx?wsdl

Encoding: UTF-8

Content-Type: text/xml

Headers: {SOAPAction=["http://esf.soufun.com/AgentInfo"], Accept=[*/*]}

Payload: xmlns="http://esf.soufun.com/">ljcs2lj123456

--------------------------------------

2011-4-13 0:33:18 org.apache.cxf.interceptor.LoggingInInterceptor logging

信息: Inbound Message

----------------------------

ID: 1

Encoding: UTF-8

Content-Type: text/xml; charset=utf-8

Headers: {content-type=[text/xml; charset=utf-8], X-AspNet-Version=[2.0.50727], connection=[keep-alive], Vary=[Accept-Encoding], Date=[Tue, 12 Apr 2011 16:34:04 GMT], Content-Length=[716], X-UA-Compatible=[IE=EmulateIE7], X-Powered-By=[ASP.NET], Server=[nginx], Cache-Control=[private, max-age=0]}

Payload: xml version="1.0" encoding="utf-8"?>xmlns="http://esf.soufun.com/">杜佳霖" level="三级" score="2500" mobile="01059107070" email="[email protected]" right="" expiredDate="2011-3-24 0:00:00" xmlns="">链家导入测试" phone="" />uesd="0" />十万火急" remain="0" uesd="0" />新推房源" remain="0" uesd="0" />

--------------------------------------

account="ljcs2"

杜佳霖

level="三级"

score="2500"

mobile="01059107070"

email="[email protected]"

mobile="01059107070"

expiredDate="2011-3-24 0:00:00"

 

总结

Cxf不能很好的处理.net web service中的any 元素,只好借助变态的解析方法。.net应该返回标准元素,如string等,这样的web service各语言调用起来才方便。Java也可以接收xml string后再解析。

 

相信此文能给那些想从cxf java客户端调用.net web service any元素的人带来方便。我在遇到此问题时,google了国内外的网站,没有提到cxf调用any类型的办法,所以总结写下此文,给后来者提供方便。

 

如果大家以前用cxf处理过.net any类型,有更好的办法,也希望能说说。

你可能感兴趣的:(分布式应用,Java,SOA)