rubysoapwsdlsoap4r

Having issue while using soap4r, unable to add namespace, encoding style to soap envelope


I am having problems with one of the soap service I'm using. I am using soap4r for consuming the soap service. But somehow they are expecting something else than what I am sending. This is what I'm sending:

<?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:Header>
        <authenticate env:mustUnderstand="0">
          <username>USERNAME</username>
          <apiKey>API_KEY</apiKey>
        </authenticate>
        <SoftLayer_Network_Media_Transcode_AccountInitParameters env:mustUnderstand="0">
          <id>ID</id>
        </SoftLayer_Network_Media_Transcode_AccountInitParameters>
        <SoftLayer_Network_Media_Transcode_AccountObjectFilter env:mustUnderstand="0">
          <transcodeJobs>
            <transcodeStatus>
              <name>
                <operation>Complete</operation>
              </name>
            </transcodeStatus>
          </transcodeJobs>
        </SoftLayer_Network_Media_Transcode_AccountObjectFilter>
  </env:Header>
  <env:Body>
    <n1:getTranscodeJobs xmlns:n1="http://api.service.softlayer.com/soap/v3/"
        env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    </n1:getTranscodeJobs>
  </env:Body>
</env:Envelope>
Which does not return the desired output. What they are expecting is:
<?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" xmlns:n1="http://api.service.softlayer.com/soap/v3/"
        env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <env:Header>
        <authenticate env:mustUnderstand="0">
          <username>USER_NAME</username>
          <apiKey>API_KEY</apiKey>
        </authenticate>
        <SoftLayer_Network_Media_Transcode_AccountInitParameters env:mustUnderstand="0">
          <id>id</id>
        </SoftLayer_Network_Media_Transcode_AccountInitParameters>
        <n1:SoftLayer_Network_Media_Transcode_AccountObjectFilter env:mustUnderstand="0">
          <transcodeJobs>
            <transcodeStatus>
              <name>
                <operation>Complete</operation>
              </name>
            </transcodeStatus>
          </transcodeJobs>
        </n1:SoftLayer_Network_Media_Transcode_AccountObjectFilter>
  </env:Header>
  <env:Body>
    <n1:getTranscodeJobs >
    </n1:getTranscodeJobs>
  </env:Body>
</env:Envelope>
namespace and encoding style in the root (as they are using it in the header ObjectFilter). soap4r is generating the previous request, and i am not able to change it to the later one which actually works.

Here is how I am using soap4r:

class SLHeader < SOAP::Header::SimpleHandler
  def initialize(tag, out)
    @out = out
    super(XSD::QName.new(nil, tag))
  end
  def on_simple_outbound
    @out
  end
end
SOAP_WSDL_ENDPOINT = "endpoint"
service = "service name"
initParams = {'id' => ID}
objectFilter = {'transcodeJobs' => {'transcodeStatus' => {'name' => {'operation' => STATUS}}}}
driver = SOAP::WSDLDriverFactory.new(SOAP_WSDL_ENDPOINT + service + "?wsdl").create_rpc_driver
driver.headerhandler << SLHeader.new('authenticate', {'username' => @auth_user, 'apiKey' => @auth_key})
driver.headerhandler << SLHeader.new(service + 'InitParameters', initParam)
driver.headerhandler << SLHeader.new(service + 'ObjectFilter', objectFilter)


Solution

  • I strongly recommend that you don't waste too much time with soap4r.

    If it works, then it's great. But if your SOAP service has particular expectations or is broken in some way, then it is absolutely useless (and impossible to fix without a large amount of monkey patches). The internal state of the library is also pretty bad, and it doesn't work in Ruby 1.9.

    For SOAP interfaces I have started using handsoap, which allows you to manually construct SOAP messages that are exactly how your service expects them to be. It's a little more work, but it has saved me a lot of headaches similar to yours. It also works in Ruby 1.9. I have not looked back.