noSQL – Rails models with SOAP

Using a DB is a natural thing for a Rails developer. Since Rails is a database driven application framework, that does not come as a big surprise. But there are times where environmental constraints do not allow the freedom to use the weapon of choice…

Imagine a legacy Java SOA landscape that provides tons of webservices but does not permit access to a transaction DB. Sounds phoney? Ask your local J2EE consultant!

Working around this constraint, it would be great if one could just wire a SOAP service into Rails as a backing of model data. Using Rails without a database is a little bit tricky, especially if you don’t want to forego the power of ActiveRecord!

so why use Rails then?

There are a lot of people that would say “Why don’t you use Sinatra instead?”.

First of all, most Ruby developers know how to use Rails. The Rails community is large, lively and a great resource for knowledge. Features like REST come for free and nobody want’s to miss model validations. In general, Rails plugins are lazy programmers best friend!

working with ActiveForm

A simple way to get your SOAP backed noSQL model working with ActiveRecord::Validations is probably by using ActiveForm. It provides validations for non ActiveRecord models and is available on github.

You can install the Rails plugin via:

# (re)install from git as a plugin
script/plugin install --force git://

Using the plugin in your code is simple. Inherit from ActiveForm instead of ActiveRecord::Base:

# app/models/blog.rb
class Blog < ActiveForm
  column :title
  column :message, :type => :text
  validates_presence_of :title, :message

It’s possible to remove all evidence of database connectivity. Just kick ActiveRecord from the list of Rails frameworks and re-add it as a gem (this step is not necessary, so you might skip it and work with Rails sqlite3 default):

# config/environment.rb do |config|
  config.gem "activerecord", :version => '2.3.5'
  config.frameworks -= [ :active_record, :active_resource, :action_mailer ]

Doing so will allow you to delete the database.yml file in your application.

Savon for multi-tier persistence

Accessing an enterprise SOAP service with Savon is easy and integrating Savon into a Rails model requires just two steps:

  • implementing a to_hash method
  • implementing a save hook

Since Savon communication is based on data hashes, you have to provide a thin mapping layer to convert your model into a request hash that matches your SOAP interface:

# app/models/blog.rb
  def to_hash
    { :data => {:title=>title, :message=>message} }

Pushing the data to the webservice requires some custom ‘persistence’ code to be implemented. A good place for that code should be in one of the model’s save hooks:

# app/models/blog.rb
  def after_save
    client = "http://localhost:8080/"! do |soap|
      soap.namespace = "urn:savon:blog"
      soap.body = to_hash

Overwriting the after_save method is a neat way to let the model code be readable for other Rails developers. Sticking to conventions is a best practice and reduces complexity greatly!

more information?

There is a working example using a local soap4r server available on github.

no SQL - no problem!

Savon Handsoap Shootout

This documentation is deprecated, please have a look at!

Looking into The Ruby Toolbox there are currently two popular SOAP client libraries available. In this short article I am going to crunch the candidates Savon, which is currently the most “popular” library, and Handsoap which follows short after. Both are open source projects hosted on github.


This article won’t cover all facets of both libraries. I concentrate on the features that are relevant for integrating a Ruby SOAP client into our particular SOA platform. That platform is commonly based on Java SOAP services based on frameworks such as CXF and Axis providing interfaces to internal business logic.

Since this is not a complete feature list, it should show you at least how to work with the APIs and which client might be the best choice for yourself.


Having lots of Java Guys around here, there is no great focus on things like beautiful API design or Ruby magic, the client should just work! Living in a Java environment, the SOAP client has to integrate smoothly with JRuby. Since a lot of Ruby libraries lack support for JRuby, we always have to monkey patch a lot of code to make it run on the JRE.


We refer to free, public SOAP services, so everyone can run the examples by themselves.

All the examples seen here can be cloned/downloaded from github.


Have fun!

Savon vs. Handsoap: Calling a service

This documentation is deprecated, please have a look at!

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"

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

client = "some_wsdl"

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.

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

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

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.

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

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.

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 } }

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.

Savon vs. Handsoap: Accessing a WSDL

This documentation is deprecated, please have a look at!

Both clients provide an interface to work with a WSDL. While the Handsoap WSDL support is hidden in some helper class, WSDLs are a first class citizen in Savon. The code for printing out the available SOAP actions looks like this:

require "handsoap/parser"
wsdl =
wsdl.bindings.each {|binding| binding.actions.each{|action| p }}

The Handsoap parser class is part of a Rails generator. The generator can be used for creating a Handsoap service class skeleton and tests:

$ script/generate handsoap

      exists  app
      exists  app/models
      create  app/models/blz_service.rb
      exists  test
      exists  test/integration
      create  test/integration/blz_service_test.rb
Endpoints in WSDL
  You should copy these to the appropriate environment files.
  (Eg. `config/environments/*.rb`)
# wsdl:
  :uri => '',
  :version => 2

The skeleton provides method stubs for adding request parameters and result parsing:

def get_bank
  soap_action = ''
  response = invoke('tns:getBank', soap_action) do |message|
    raise "TODO"

Savon vs. Handsoap: Authentication

This documentation is deprecated, please have a look at!

The libraries provide support for multiple authentication protocols. While Handsoap’s authentication support is more low level, Savon provides an API for that task.

WSSE authentication

As you might expect, the Handsoap way for this aspect is to implement a callback method for the document creation. Using Savon you can attach your credentials on a WSSE object inside your request block. Compare the two implementations:

def on_create_document(doc)
  doc.alias 's', "http://docs...xsd"
  header = doc.find("Header")
  header.add "s:Security" do |s|
    s.set_attr "env:mustUnderstand", "0"
    s.add "s:Username", @@username
response = client.get_bank do |soap, wsse|
  wsse.username = @@username

HTTP authentication

The same approach is used by Handsoap to offer HTTP authentication:

def on_after_create_http_request(http_request)
  http_request.set_auth @@username, @@password

Savon provides support for this feature just yet (since 0.7.0):

client.request.basic_auth "username", "password"

SSL support

At the time of writing only Savon supports SSL authentication directly. This is achieved by passing a configuration hash to the Savon::Client:

client = "some_wsdl"
  :cert =>"client_cert.pem")),
  :key =>"client_key.pem"), "password if one exists"),
  :ca_file => "cacert.pem",
  :verify_mode => OpenSSL::SSL::VERIFY_PEER

While the Handsoap documentation states that support for SSL is not yet implemented, there might be a chance to enable it through the use of the preconfigured http driver.