I ve written a ColdFusion Web Service for an external client to consume. It basically let s them send over some user information, and returns the contents of the user s shopping cart, and let s them add items to the user s shopping cart. For simplicity sake, we ll just cover the "getCart" method.
他们需要网络服务局将Xml送回SOAP信封,但还需要Xml控制具体的复杂数据类型。 例如,每一项请求都需要作为<代码>ReturnInfo类型的一部分,归还身份代码和电文。 因此,我写了一份硬编码的WSDL,供他们用内部概述的复杂数据类型消费(我基本上采用由冷战产生的WSDL,并编辑):
<>strong>/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>
他们对网络服务的每一电话给他们同样的错误:
[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中的复杂数据类型,因此,这里的迷魂药。 我的《家庭法》:
<>strong>/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/model/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>