From XML-RPC to SOAP: A Migration Guide
2008-03-12 18:06
225 查看
http://webservices.xml.com/pub/a/ws/2002/12/18/endpoints.html
December 18, 2002
Poking at the reasons behind technology standards can lead to interesting results. The really good ones, like the first ANSI C specification, include a detailed rationale for key decisions. Most internet standards don't spend the effort but prefer, instead, to allow an archived mailing list to act as a primary source. And, even then, it can be fun to play standards archaeologist.
The primary motivator behind XML-RPC is Dave Winer, owner of a small ISV company, and one of the first webloggers. Winer was part of the initial, self-selected group that created SOAP. According to Don Box's Brief History of SOAP, Winer grew impatient with corporate delays. In July, 1998, Winer posted the specification for XML-RPC. At that point, the Namespaces in XML group had published two drafts; final recommendation publication wouldn't happen until January, 1999. Given the state of flux, and all the churn caused by following XML Schema drafts which Don describes in his article, it isn't surprising that XML-RPC avoids namespaces altogether.
It is surprising, however, that XML-RPC doesn't use XML attributes. One might surmise that doing without attributes makes parsing much simpler. XML-RPC is well-suited to simple lexical handling: divide the input stream into "tags", which are simple words surrounded by angle brackets, and values. In hindsight, however, it makes for strange XML. For example, compare
But let's move forward a few years. Now SOAP 1.1 is available for just about any platform you could care about. SOAP 1.2 is almost done -- if they ever get it out of last call -- and we've already passed over the hype curve for web services. The time has come for the XML-RPC community to move forward; the time has come to migrate to SOAP, achieving interoperability across both systems. Let's see how easy it can be.
Ignore the first two open tags.
Ignore the last two close tags.
If you don't handle namespaces, assume the client got it right.
This doesn't achieve full SOAP interoperability, but that's not our goal. Our goal is for SOAP clients to be able to send messages to "XML-RPC servers" and for those messages to be understood. Wrapping XML-RPC in a SOAP
The next step is to consider the way SOAP and XML-RPC both use -- or, perhaps, abuse -- HTTP. According to the XML-RPC specification,
use
the URL is a routing hint;
the
calls must have a
calls must have a
Once again, we're in luck. SOAP can use
Don't reject messages that are missing
XML-RPC servers sending responses or XML-RPC clients talking to SOAP servers need only wrap their messages in the SOAP elements as shown above.
As a practical exercise in achieving interoperability, we'll use WSDL (and, therefore, XML Schema) to specify the XML-RPC encapsulation.
We start with a WSDL file. It begins with the typical large block of namespace declarations (though it's only about half of what DevStudio.NET seems to use). Since all XML-RPC messages have the same "shape", it's all one set of message and port types for WSDL. We'll get into schema details in a moment.
In this case the most reasonable thing to do is split the WSDL into separate pieces -- XMLRPCTypes.xsd, XMLRPCabstract.wsdl (the
For those who really enjoy holiday fables, you can figure out how to put such information into UDDI.
An XML-RPC request is a complex element named
The primitive XML-RPC parameters are pretty much a subset of the XML Schema datatypes:
XML-RPC also provides
XML-RPC experts will realize that I've left out a couple of twists that make things a little more complicated. First, any value that doesn't have a type is a string. Second,
I've only sketched out the framework; the devil inhabits the details. But it certainly seems possible to achieve what John Lennon sung about:
From XML-RPC to SOAP: A Migration Guide
by Rich SalzDecember 18, 2002
What is XML-RPC?
As you might expect from the name, XML-RPC is a way of using XML to send classic Remote Procedure Calls (RPC) over the net. XML-RPC's use of XML is very simple. It doesn't use namespaces. It doesn't even use attributes.Poking at the reasons behind technology standards can lead to interesting results. The really good ones, like the first ANSI C specification, include a detailed rationale for key decisions. Most internet standards don't spend the effort but prefer, instead, to allow an archived mailing list to act as a primary source. And, even then, it can be fun to play standards archaeologist.
The primary motivator behind XML-RPC is Dave Winer, owner of a small ISV company, and one of the first webloggers. Winer was part of the initial, self-selected group that created SOAP. According to Don Box's Brief History of SOAP, Winer grew impatient with corporate delays. In July, 1998, Winer posted the specification for XML-RPC. At that point, the Namespaces in XML group had published two drafts; final recommendation publication wouldn't happen until January, 1999. Given the state of flux, and all the churn caused by following XML Schema drafts which Don describes in his article, it isn't surprising that XML-RPC avoids namespaces altogether.
It is surprising, however, that XML-RPC doesn't use XML attributes. One might surmise that doing without attributes makes parsing much simpler. XML-RPC is well-suited to simple lexical handling: divide the input stream into "tags", which are simple words surrounded by angle brackets, and values. In hindsight, however, it makes for strange XML. For example, compare
<value> <i4>42</i4> </value>to
<value type="i4">42</value>For the first few years while SOAP cooked, XML-RPC met an important need. XML parsers -- particularly those in the common scripting languages -- were simple, and it was usually easy to create an XML-RPC client library (e.g., the Python implementation is less than 900 lines) and to get remote access to services over the Web.
But let's move forward a few years. Now SOAP 1.1 is available for just about any platform you could care about. SOAP 1.2 is almost done -- if they ever get it out of last call -- and we've already passed over the hype curve for web services. The time has come for the XML-RPC community to move forward; the time has come to migrate to SOAP, achieving interoperability across both systems. Let's see how easy it can be.
Wrapping XML-RPC in SOAP
The first step is to wrap XML-RPC messages in a SOAP envelope, which is trivial. We'll treat the wrapped message as a pure XML document and put it in a SOAP body:<S:Envelope xmlns:S="http://schemas.xmlsoap.org/envelope/"> <S:Body xmlns=""> [XML-RPC content here] </S:Body> </S:Envelope>The XML-RPC implementation are drop-dead simple.
Ignore the first two open tags.
Ignore the last two close tags.
If you don't handle namespaces, assume the client got it right.
This doesn't achieve full SOAP interoperability, but that's not our goal. Our goal is for SOAP clients to be able to send messages to "XML-RPC servers" and for those messages to be understood. Wrapping XML-RPC in a SOAP
Bodyachieves the goal. (Making sure that the SOAP clients don't send anything surprising will be explained below.)
The next step is to consider the way SOAP and XML-RPC both use -- or, perhaps, abuse -- HTTP. According to the XML-RPC specification,
use
POST;
the URL is a routing hint;
the
Content-Typeis
text/xml;
calls must have a
Hostheader; and
calls must have a
User-Agentheader.
Once again, we're in luck. SOAP can use
POST, and it does not specify a particular value for the URL. For implementations that don't allow the application code to set the
Hostand
User-Agentheader, sending the message through a nearby HTTP proxy should suffice. To be truly liberal in what we accept, however, we should add the following to our list of XML-RPC implementation changes:
Don't reject messages that are missing
Hostor
User-Agentheaders.
XML-RPC servers sending responses or XML-RPC clients talking to SOAP servers need only wrap their messages in the SOAP elements as shown above.
Constraining SOAP
So far all the work to achieve interoperability has put the effort -- however minor -- on the XML-RPC community. It's only fair to ask what the SOAP community has to do. It turns out that most of the work will be in defining constraints so that the SOAP libraries generate messages that their new brethren can understand.As a practical exercise in achieving interoperability, we'll use WSDL (and, therefore, XML Schema) to specify the XML-RPC encapsulation.
We start with a WSDL file. It begins with the typical large block of namespace declarations (though it's only about half of what DevStudio.NET seems to use). Since all XML-RPC messages have the same "shape", it's all one set of message and port types for WSDL. We'll get into schema details in a moment.
<definitions name="http://www.xml.com/endpoints/xmlrpcwrap/" targetNamespace="http://www.xml.com/endpoints/xmlrpcwrap/" xmlns:tns="http://www.xml.com/endpoints/xmlrpcwrap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <types> <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.xml.com/endpoints/xmlrpcwrap/"> ... </xsd:schema> </types> <message name="XMLRPCRequest"> <part name="body" type="tns:Request"/> </message> <message name="XMLRPCResponse"> <part name="body" type="tns:Response"/> </message> <portType name="XMLRPCPort"> <operation name="XMLRPCExchange"> <input message="tns:XMLRPCRequest"/> <output message="tns:XMLRPCResponse"/> </operation> </portType>As I've discussed before, WSDL is a frustrating mix of magic redundant verbosity and often needless abstraction. We now need to write a WSDL
bindingelement to specify how to instantiate the abstract message exchanges. It's fairly simple: SOAP over HTTP as uninterpreted XML documents. In WSDL jargon, that's "doc/literal" -- an XML-document transported literally, without encoding.
<binding name="XMLRPCBinding" type="tns:XMLRPCPort"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="XMLRPC"> <soap:operation soapAction="RSalz rocks"/> <input> <soap:body use="literal" namespace="http://www.xml.com/endpoints/xmlrpcwrap/"/> </input> <output> <soap:body use="literal" namespace="http://www.xml.com/endpoints/xmlrpcwrap/"/> </output> </operation> </binding>The
servicepart is where it might get interesting. An actual service element is fairly simple.
<service name="XMLRPC"> <port name="XMLRPC" binding="tns:XMLRPCBinding"&gr; <soap:address location="http://www.example.com/xmlrpc"/> </port> </service>At issue here is the fact that different XML-RPC servers may require particular URLs for their operation dispatch. While the example above shows a generic interface, some require the "method name" to be the last component of the URL.
In this case the most reasonable thing to do is split the WSDL into separate pieces -- XMLRPCTypes.xsd, XMLRPCabstract.wsdl (the
message,
portType, and
bindingelements) -- that can be imported into an application-specific file which has
serviceand
portelements with the appropriate URLs.
For those who really enjoy holiday fables, you can figure out how to put such information into UDDI.
XML Schema for XML-RPC
Let's now flesh out the XML Schema that defines XML-RPC messages.An XML-RPC request is a complex element named
methodCall, which has a name identifying the method and a
paramselement with a list of input parameters.
<xsd:complexType name="methodCallType"> <xsd:sequence> <xsd:element name="methodName" type="xsd:string"/> <xsd:element name="params" minOccurs="0"> <xsd:element name="param" type="tns:paramType" minOccurs="0" maxOccurs="unbounded"/> </xsd:element> </xsd:sequence> </xsd:complexType> <element name="methodCall" type="tns:methodCallType"/>According to the specification, the methodName is limited to the characters "[A-Za-z0-9_.:/]". Rewriting the
complexTypeto include that facet restriction is left as an exercise for the reader.
The primitive XML-RPC parameters are pretty much a subset of the XML Schema datatypes:
<xsd:complexType name="typedscalarType"> <xsd:choice> <xsd:element name="i4" type="xsd:int"/> <xsd:element name="base64" type="xsd:base64Binary"/> <xsd:element name="double" type="xsd:float"/> ... </xsd:choice> </xsd:complexType>The others --
boolean,
dateTime.iso8601, and
string-- should map pretty easily into XML Schema types, perhaps with additional facet restrictions.
XML-RPC also provides
structand
arrayto build up more complex datatypes. A structure is an array of members, each of which has a name and typed value:
<xsd:complexType name="structType"> <xsd:sequence> <element name="member" type="structmemberType" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence </xsd:complexType> <xsd:complexType name="structmemberType"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="value" type="typedscalarType"/> </xsd:sequence> </xsd:complexType>Arrays are like structs, except there is a single
dataelement that has a list of
valueitems. Playing standards archaeologist again, it would be interesting to know what problem the extra level of indirection was meant to solve.
XML-RPC experts will realize that I've left out a couple of twists that make things a little more complicated. First, any value that doesn't have a type is a string. Second,
value,
struct, and
arrayare mutually recursive; like any reasonable programming language, it's possible to have an array of structures with simple values and nested arrays. Solving this requires delving into some of the more arcane areas of XML Schema, which is also left as an exercise for the reader.
Ho ho ho
So where are we? With a few simple changes, XML-RPC applications should be able to send and receive SOAP messages to and from well-behaved SOAP applications. Perhaps surprisingly, most of the work is in constraining the SOAP applications to be well-behaved. In the standards world, when a specification has many options and possibilities, and you define yourself to a conformant subset, that's called a profile. So what we've started work on is a SOAP profile, defined in WSDL, that should make it easy for "legacy" XML-RPC applications to interoperate.I've only sketched out the framework; the devil inhabits the details. But it certainly seems possible to achieve what John Lennon sung about:
I hope some day you'll join us
and the world will be as one.
Happy Holidays!
and the world will be as one.
相关文章推荐
- Guide to Database Migration from Microsoft SQL Server using MySQL Workbench
- Migration guide from STS Gradle to Buildship
- [Error: Unsupported configuration, downgrade Nodemailer to v0.7.1 or see the migration guide https:/
- An Illustrated Guide to IPsec
- A guide to analyzing Python performance
- REST 和 SOAP、RPC 有何区别?
- SOA、SOAP、RPC、REST、DUBBO的区别与联系
- An amazing guide to Neural Networks
- The Absolute Beginner’s Guide to Node.js( Node.js 新手指南 (Manuel Weiss))
- A Comprehensive guide to Fine-tuning Deep Learning Models in Keras
- The penultimate guide to stopping a DDoS attack – A new approach
- The Beginner’s Guide to iptables, the Linux Firewall
- A Developer's Guide to Data Modeling for SQL Server: Covering SQL Server 2005 and 2008
- The Complete Guide to C++ Strings, Part II - String Wrapper Classes
- The Definitive Guide to Grails, Second Edition
- How To Test SOAP over JMS Web Services With SOAPUI
- An incomplete guide to LaTex
- Beej's Guide to Network Programming 学习笔记
- Guide to Cisco Frame Relay Traffic Shaping
- Guide to Computer Network Security