2012-01-13 139 views
2

我已經編寫了一個ColdFusion Web服務供外部客戶端使用。它基本上讓他們發送一些用戶信息,並返回用戶的購物車的內容,讓他們添加項目到用戶的購物車。爲了簡單起見,我們只會介紹「getCart」方法。調用ColdFusion Web服務時,會導致「org.xml.sax.SAXException:Bad types」異常的原因是什麼?

他們需要Web Service在SOAP信封中返回Xml,但是他們還需要Xml來包含特定的複雜數據類型。例如,每個請求都需要返回狀態碼和消息,作爲ReturnInfo類型的一部分。所以,我寫了一個硬編碼的WSDL他們與所列出的複雜數據類型消耗(我基本上採取了ColdFusion的生成WSDL和編輯它):

/ws/Cart.wsdl

<?xml version="1.0" encoding="UTF-8"?> 
<wsdl:definitions targetNamespace="http://cart.ws" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://cart.ws" xmlns:intf="http://cart.ws" xmlns:tns1="http://model.cart.ws" xmlns:tns2="http://rpc.xml.coldfusion" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <wsdl:types> 
    <schema elementFormDefault="qualified" targetNamespace="http://cart.ws" xmlns="http://www.w3.org/2001/XMLSchema"> 
     <import namespace="http://model.cart.ws"/> 
     <import namespace="http://rpc.xml.coldfusion"/> 
     <element name="addItemToCart"> 
     <complexType> 
      <sequence> 
      <element name="loginID" type="xsd:string"/> 
      <element name="spikeId" type="xsd:int"/> 
      <element name="cartItem" type="tns1:CartItem"/> 
      </sequence> 
     </complexType> 
     </element> 
     <element name="addItemToCartResponse"> 
     <complexType> 
      <sequence> 
      <element name="addItemToCartReturn" type="tns1:ReturnInfo"/> 
      </sequence> 
     </complexType> 
     </element> 
     <element name="fault" type="tns2:CFCInvocationException"/> 
     <element name="getCart"> 
     <complexType> 
      <sequence> 
      <element name="loginID" type="xsd:string"/> 
      <element name="spikeId" type="xsd:int"/> 
      </sequence> 
     </complexType> 
     </element> 
     <element name="getCartResponse"> 
     <complexType> 
      <sequence> 
      <element name="getCartReturn" type="tns1:CartResponse"/> 
      </sequence> 
     </complexType> 
     </element> 
    </schema> 
    <schema elementFormDefault="qualified" targetNamespace="http://model.cart.ws" xmlns="http://www.w3.org/2001/XMLSchema"> 
     <import namespace="http://rpc.xml.coldfusion"/> 
     <complexType name="CartItem"> 
     <sequence> 
      <element name="quantity" nillable="true" type="xsd:int"/> 
      <element name="sku" nillable="true" type="xsd:string"/> 
     </sequence> 
     </complexType> 
     <complexType name="ReturnInfo"> 
     <sequence> 
      <element name="code" nillable="true" type="xsd:int"/> 
      <element name="message" nillable="true" type="xsd:string"/> 
     </sequence> 
     </complexType> 
     <complexType name="CartResponse"> 
     <sequence> 
      <element name="cartItems" nillable="true" type="tns1:ArrayOfCartItems"/> 
      <element name="returnInfo" nillable="true" type="tns1:ReturnInfo"/> 
     </sequence> 
     </complexType> 
     <complexType name="ArrayOfCartItems"> 
     <sequence> 
      <element maxOccurs="unbounded" minOccurs="0" name="cartItems" type="tns1:CartItem"/> 
     </sequence> 
     </complexType> 
    </schema> 
    <schema elementFormDefault="qualified" targetNamespace="http://rpc.xml.coldfusion" xmlns="http://www.w3.org/2001/XMLSchema"> 
     <import namespace="http://model.cart.ws"/> 
     <complexType name="CFCInvocationException"> 
     <sequence/> 
     </complexType> 
    </schema> 
    </wsdl:types> 
    <wsdl:message name="CFCInvocationException"> 
    <wsdl:part element="impl:fault" name="fault"/> 
    </wsdl:message> 
    <wsdl:message name="addItemToCartRequest"> 
    <wsdl:part element="impl:addItemToCart" name="parameters"/> 
    </wsdl:message> 
    <wsdl:message name="getCartRequest"> 
    <wsdl:part element="impl:getCart" name="parameters"/> 
    </wsdl:message> 
    <wsdl:message name="addItemToCartResponse"> 
    <wsdl:part element="impl:addItemToCartResponse" name="parameters"/> 
    </wsdl:message> 
    <wsdl:message name="getCartResponse"> 
    <wsdl:part element="impl:getCartResponse" name="parameters"/> 
    </wsdl:message> 
    <wsdl:portType name="Cart"> 
    <wsdl:operation name="addItemToCart"> 
     <wsdl:input message="impl:addItemToCartRequest" name="addItemToCartRequest"/> 
     <wsdl:output message="impl:addItemToCartResponse" name="addItemToCartResponse"/> 
     <wsdl:fault message="impl:CFCInvocationException" name="CFCInvocationException"/> 
    </wsdl:operation> 
    <wsdl:operation name="getCart"> 
     <wsdl:input message="impl:getCartRequest" name="getCartRequest"/> 
     <wsdl:output message="impl:getCartResponse" name="getCartResponse"/> 
     <wsdl:fault message="impl:CFCInvocationException" name="CFCInvocationException"/> 
    </wsdl:operation> 
    </wsdl:portType> 
    <wsdl:binding name="cart.cfcSoapBinding" type="impl:Cart"> 
    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> 
    <wsdl:operation name="addItemToCart"> 
     <wsdlsoap:operation soapAction=""/> 
     <wsdl:input name="addItemToCartRequest"> 
     <wsdlsoap:body use="literal"/> 
     </wsdl:input> 
     <wsdl:output name="addItemToCartResponse"> 
     <wsdlsoap:body use="literal"/> 
     </wsdl:output> 
     <wsdl:fault name="CFCInvocationException"> 
     <wsdlsoap:fault name="CFCInvocationException" use="literal"/> 
     </wsdl:fault> 
    </wsdl:operation> 
    <wsdl:operation name="getCart"> 
     <wsdlsoap:operation soapAction=""/> 
     <wsdl:input name="getCartRequest"> 
     <wsdlsoap:body use="literal"/> 
     </wsdl:input> 
     <wsdl:output name="getCartResponse"> 
     <wsdlsoap:body use="literal"/> 
     </wsdl:output> 
     <wsdl:fault name="CFCInvocationException"> 
     <wsdlsoap:fault name="CFCInvocationException" use="literal"/> 
     </wsdl:fault> 
    </wsdl:operation> 
    </wsdl:binding> 
    <wsdl:service name="CartWebService"> 
    <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> 
     Contains WebService methods for retrieving and updating Cart data 
    </wsdl:documentation> 
    <wsdl:port binding="impl:cart.cfcSoapBinding" name="cart.cfc"> 
     <wsdlsoap:address location="http://mysite/ws/cart/cart.cfc"/> 
    </wsdl:port> 
    </wsdl:service> 
</wsdl:definitions> 

每次調用它們對任何Web服務給他們同樣的錯誤:

[1/13/12 12:26:19:557 EST] 00000018 SystemErr  R org.xml.sax.SAXException: Bad types (interface javax.xml.soap.SOAPElement -> class ws.cart.model.CartResponse) Message being parsed: <?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<soapenv:Body> 
    <getCartResponse xmlns="http://cart.ws"> 
    <getCartReturn xsi:type="ns1:Document" xmlns:ns1="http://xml.apache.org/xml-soap"> 
    <ns2:CartResponse xmlns="http://model.cart.ws" xmlns:ns2="http://model.cart.ws"> 
    <ns2:ReturnInfo xmlns="http://model.cart.ws"> 
     <code xmlns="">1</code> 
     <message xmlns="">Items are pending in cart</message> 
    </ns2:ReturnInfo> 
    <cartItems xmlns=""> 
     <cartItem> 
     <sku>ABC123</sku> 
     <quantity>2</quantity> 
     </cartItem> 
    </cartItems> 
    </ns2:CartResponse> 
    </getCartReturn> 
    </getCartResponse> 
</soapenv:Body> 
</soapenv:Envelope> 

我不是很熟悉SOAP,或CF複雜數據類型,所以我有點困在這裏。這裏是我的CF代碼:

/ws/cart.cfc:

<cfcomponent 
    displayname="CartWebService" 
    hint="Contains WebService methods for retrieving and updating Cart data" 
    style="document" 
    wsdlfile="Cart.wsdl" 
    namespace="http://cart.ws" 
    > 
    <cffunction 
     name="getCart" 
     access="remote" 
     displayname="Get Cart" 
     hint="Returns cart data (Skus, Quantities) for a given UserId" 
     description="Returns cart data (Skus, Quantities) for a given UserId" 
     output="false" 
     returntype="xml"> 
     <cfargument name="loginID" type="String" default="" /> 

     <cfscript> 
      var response = 
       CreateObject("component", "ws.cart.model.GetCartResponse"); 
      var cart = CreateObject("component", "lib.Cart"); 
      var _loginId = UCase(Trim(ARGUMENTS.LoginID)); 
      var i = 1; 
      var cartItem = CreateObject("component", "ws.cart.model.CartItem"); 

      /* 
      Validation/processing.... 
      */ 

      // get the cart data 
      cart = cart.init(_loginId); 

      qCartItems = cart.getItems(); 

      if (qCartItems.RecordCount) { 
       for (i=1; i<=qCartItems.RecordCount; i++) { 
        cartItem = 
         CreateObject("component", "ws.cart.model.CartItem"); 
        cartItem.quantity = qCartItems["quantity"][i]; 
        cartItem.sku = qCartItems["sku"][i]; 

        ArrayAppend(response.cartItems, cartItem); 
       } 

       // responde with the Xml of status code, status message, and cart items 
       return response.setCode(1).toXML(); 
      } 

      // default response - no items in cart 
      return response.setCode(0).toXML(); 
     </cfscript> 
    </cffunction> 
</cfcomponent> 

/ws/model/CartItem.cfc

<cfcomponent 
    displayname="Cart Item" 
    hint="Represents an item in the cart (existing or to be added/updated)" 
    namespace="http://model.cart.ws" 
    output="false"> 
    <cfproperty name="quantity" type="Numeric" /> 
    <cfproperty name="sku" type="String" /> 
</cfcomponent> 

/WS /模型/ GetCartResponse .cfc

<cfcomponent 
    displayname="Cart Response" 
    hint="Contains Cart Items and Return Info" 
    namespace="http://model.cart.ws" 
    extends="ReturnInfo" 
    implements="IReturnInfo" 
    output="false"> 
    <cfproperty 
     name="cartItems" 
     displayname="Array of Cart Items" 
     hint="Array of Cart Items" 
     type="CartItem[]" /> 

    <cfscript> 
     THIS.cartItems = []; 
    </cfscript> 

    <cffunction name="getMessage" returntype="String" output="false"> 
     <cfscript> 
      switch(THIS.code) { 
       // Success: no items in cart 
       case 0: 
        return "No items in cart."; 

        break; 
       // Success: items are pending in cart 
       case 1: 
        return "Items are pending in cart"; 

        break; 
      } 

      return ""; 
     </cfscript> 
    </cffunction> 

    <cffunction name="toXML" returntype="XML" output="false"> 
     <cfscript> 
      var cartResponseXML = XmlNew(true); 
      var i = 1; 
      var numCartItems = ArrayLen(THIS.cartItems); 

      cartResponseXML["xmlRoot"] = 
       XmlElemNew(
        cartResponseXML, 
        "http://model.cart.ws", 
        "CartResponse" 
        ); 

      cartResponseXML["xmlRoot"]["ReturnInfo"] = 
       XmlElemNew(
        cartResponseXML, 
        "http://model.cart.ws", 
        "ReturnInfo" 
       ); 
      cartResponseXML["xmlRoot"]["ReturnInfo"]["code"] = 
       XmlElemNew(cartResponseXML, "code"); 
      cartResponseXML["xmlRoot"]["ReturnInfo"]["code"].XmlText = 
       THIS.code; 
      cartResponseXML["xmlRoot"]["ReturnInfo"]["message"] = 
       XmlElemNew(cartResponseXML, "message"); 
      cartResponseXML["xmlRoot"]["ReturnInfo"]["message"].XmlText = 
       THIS.message; 

      cartResponseXML["xmlRoot"]["cartItems"] = 
       XmlElemNew(cartResponseXML, "cartItems"); 

      for (i=1; i<=numCartItems; i++) { 
       cartItem = THIS.cartItems[i]; 
       cartItemXML = XmlElemNew(cartResponseXML, "cartItem"); 
       cartItemXML["sku"] = XmlElemNew(cartResponseXML, "sku"); 
       cartItemXML["sku"].XmlText = cartItem.sku; 
       cartItemXML["quantity"] = 
        XmlElemNew(cartResponseXML, "quantity"); 
       cartItemXML["quantity"].XmlText = cartItem.quantity; 

       ArrayAppend(
        cartResponseXML["xmlRoot"]["cartItems"].XmlChildren, 
        cartItemXML 
       ); 
      } 

      return cartResponseXML; 
     </cfscript> 
    </cffunction> 
</cfcomponent> 

回答

0

可能是一些事情,但是最常被忽略的原因是:

您已經更改了方法的簽名(函數參數,類型,參數個數,返回類型等)但ColdFusion已經緩存了該存根。

解決方案

轉到ColdFusion管理員,並在數據&服務 - > Web服務,發現其中包括WSDL的URL,並且或者刷新一下,或者完全刪除。

可能不是您的具體解決方案,但是一個合理的起點。

0

如果您無權訪問CF管理員並需要刷新Web服務;您可以創建一個頁面來刷新Web服務。包括以下兩行:

<cfobject action="CREATE" type="JAVA" class="coldfusion.server.ServiceFactory" name="ServiceFactory"> 
<cfset ServiceFactory.getXMLRPCService().refreshWebService("http://cart.ws?WSDL")> 

最後一行包含指向需要刷新的Web服務的WSDL的URL。

相關問題