Savon vs. Handsoap: Calling a service

This documentation is deprecated, please have a look at “”:!

p. The two libraries have different approaches on how to get things done. While Handsoap is using an oldschool inheritance style definition:

class HandsoapBankCode < Handsoap::Service
  endpoint :uri => "some_wsdl", :version => 2

  def on_create_document(doc)
    doc.alias "tns", "some_namespace"

  def on_response_document(doc)
    doc.add_namespace "ns1", "some_namespace"

p. Savon clients are just a kind of wrapper or proxy around a WSDL:

client = "some_wsdl"

p. While inheritance is a base concept of object oriented programming, it’s usually better to use delegation instead. For not being stuck on the API of the Handsoap::Service class, one would wrap things up into some other class or module, creating more code than necessary.

p. The proxy style client of Savon is less code and provides a flexible API, especially looking at SOAP calls.

p. Using “rspec”: to demonstrate the expected behavior of the clients results in two identical spec for getting a zip code of a concrete client implementation:

describe "Savon" do
  it "should return the corrent zip code for a given bank" do
    zip_code = Shootout::SavonBankCode.zip_code @bank_code
    zip_code.should eql @zip_code

describe "Handsoap" do
  it "should return the corrent zip code for a given bank" do
    zip_code = Shootout::HandsoapBankCode.zip_code @bank_code
    zip_code.should eql @zip_code

p. Compared to the spec, the code of the two implementations differs a great deal. The task at hand is to call the getBank method of the “SOAP endpoint”: providing a blz (bank code) parameter and extracting the plz (zip code) value of the response.

p. Using the Handsoap client class defined above, sending the “invoke()” message to the Handsoap::Service will do the job:

def zip_code(bank_code)
  response = invoke("tns:getBank") do |message|
    message.add "tns:blz", bank_code

p. The bank code parameter is assigned in the block, which yields a “SOAP message object”: The resulting XML document is wrapped and can be accessed using some predefined XML library. Handsoap enables you to choose between different types of XML parsers like “REXML”:, “ruby-libxml”: or “nokogiri”:

p. Savon’s proxy client on the other hand is dynamic and can be accessed directly with the name of the SOAP method and a block:

class SavonBankCode
  def self.zip_code(bank_code)
    client = Shootout.endpoints[:bank_code][:uri]
    response = client.get_bank { |soap| soap.body = { "wsdl:blz" => bank_code } }

p. The block yields a “SOAP request object”: for setting the payload or tweaking defaults like the SOAP header. Converting the response to a hash is a convenient way to access the desired result. The conversion is done using “crack”:

1 thought on “Savon vs. Handsoap: Calling a service

  1. Pingback: Savon Handsoap Shootout | #nofail

Comments are closed.