I was playing with SOAP4R again lately, as I needed to connect to a web service, and the experience had been smooth, from the code generation using wsdl2ruby up to the part when I tried to connect to the service.

My SOAP request could not be translated by the server, because SOAP4R will automatically append n1, n2, n#…namespace to your elements or attributes, and the service that was expecting elements without n# namepace.

 <n1:ServiceContext xmlns:n1="http://domain.com/name">
      <n1:UserName>x</n1:UserName>
      <n1:UserAccessKey>x</n1:UserAccessKey>
      <n1:Password>x</n1:Password>
 </n1:ServiceContext>

I thought, to fix this should be easy, by changing some settings when generating the request document, but the problem was, where should I set.

Not being able to find any clue in the rdoc and SOAP4R how-tos, forced me to code-trace like a British spy, but thanks to ruby-debug for making it easier.

And here is the trick, to use default namespace or to remove the default n1, n2, n# namepace, when calling SOAP::RPC::Driver#add_[rpc|document]_operation method, set the elementformdefault or attributeformdefault option to true, for element and attribute namespace handling respectively.

If you are using wsdl2ruby to generate your SOAP::RPC::Driver, edit [ServiceName|default]Driver.rb and append the options to each of the methods generated:

Methods = [
  [ "http://domain/ws/ServiceName:Operation", "operationMethod",
    [ ["in", "operationMethodRequest", ["::SOAP::SOAPElement", "http://domain.com/ws/ServiceName", "OperationMethodRequest"]],
      ["out", "OperationMethodResult", ["::SOAP::SOAPElement", "http://domain.com/ws/ServiceName", "OperationMethodResponse"]] ],
         { :request_style =>  :document, :request_use =>  :literal,
           :response_style => :document, :response_use => :literal, :faults => {},  
           :elementformdefault => true, :attributeformdefault => true  }
    ],
    
    # Other methods
    ....
  ]

If you are like me, most likely you will have quite a number of methods to apply, what you can do is to put a short plug in init_methods to enable that options for all methods, and that, will be nice and DRY.

[ServiceName|'default']Driver.rb
-------------------------------

def init_methods
  Methods.each do |definitions| 
    # set options to use default namespace instead of using n[#]
    opt = definitions.last
    opt.merge!({
      :elementformdefault => true,
      :attributeformdefault => true
    })
    
    # rest of the codes generated by wsdl2ruby
    if opt[:request_style] == :document
      add_document_operation(*definitions)
    else
      add_rpc_operation(*definitions)

      ....              
    end
  end
end

No Comments . Comments Feed . Trackback URI

Add Your Comment



(optional)