Feb 26, 2009 1
XML-RPC, SOAP and Polymorphism
According to the XML-RPC specification a XML_RPC request may only contain scalar <value>s or non-scalar <struct>s. The specification unfortunately does not provide any standard for encoding the type of data encoded in the <struct>s. This has the side effect of not being able to support polymorphism in service method parameters as it leaves the sever no choice but to rely on the method signature in the API declaration when trying to determine what to instantiate for a given <struct> in the XML-RPC request.
Let’s say you have the following declarations:
class SubscriptionsApi < ActionWebService::API::Base
api_method(
:create_subscription,
:expects => [
{ :customer => Logical::Customer },
{ :payment_method => Logical::PaymentMethod }
]
)
end
module Logical
class PaymentMethod < ActionWebService::Struct
end
class CreditCard < PaymentMethod
member :card_number, :string
# ...
end
class PayPal < PaymentMethod
member :login, :string
# ...
end
end
Now you want to make a call to the service method and pass either a CreditCard or a PayPal. XML-RPC will encode the request like so:
<methodCall> <methodName>create_subscription</methodName> <param> <struct> <member> <name>card_number</name> <value>4111-1111-1111-1111</value> </member> </struct> </param> </methodCall>
This provides no type information to the server so the server will attempt to instantiate a Logical::PaymentMethod which will of course not have a card_number member as it’s specific to the CreditCard subclass. SOAP, on the other hand, does encode the parameter types allowing you to utilize this type of polymorphism in your service parameters. Here’s the same request encoded in SOAP.
<?xml version="1.0" encoding="utf-8" ?> <env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <env:Body> <n1:CreateSubscription xmlns:n1="urn:ActionWebService" env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <payment_method xmlns:n2="http://www.ruby-lang.org/xmlns/ruby/type/custom" xsi:type="n2:Logical..CreditCard"> <card_number xsi:type="xsd:string">1</card_number> </payment_method> </n1:CreateSubscription> </env:Body> </env:Envelope>
The current implementation of ActionWebService resurrected by datanoise did not support this type of polymorphism in SOAP requests. However, I submitted a patch recently which provides for this functionality. Hopefully it’s accepted.

