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

5 Comments . Comments Feed . Trackback URI
Thu, 6 Nov 08 01:34 am . Navjeet wrote:

This solution really helped me to fix a similar problem I was having. In my cases soap4r was not adding n1 namespace to the arguments to the method, just to the method only. By applying this fix, it took out apply namespace to method name also and CXF generated web service seems to be happy with that. Thanks a lot.

Tue, 2 Mar 10 08:03 pm . Yasir wrote:

Thanks a lot dude.
I was going to bang my head with a wall.
thanks a lot. you saved wall :)

Sat, 13 Nov 10 06:52 pm . Zapped wrote:

10x a lot!

and almost the same thing for a SOAP4R server:

in [ServiceName]Proxy.rb
add
self.use_default_namespace = true

after
self.mapping_registry = DefaultMappingRegistry::EncodedRegistry
self.literal_mapping_registry = DefaultMappingRegistry::LiteralRegistry

Sun, 6 Feb 11 10:39 pm . Taryn East wrote:

This was written a few years back. The option has been deprecated, but there’s a new one now: use_default_namespace for this exact purpose.

Thu, 3 Nov 11 04:04 pm . Donapieppo wrote:

Had the same problem in ruby 1.9.2 spox-soap4r and use_default_namespace
worked.
Thanks a lot!

Add Your Comment



(optional)