Building legacy SOAP APIs in Ruby on Rails

I’ve already consumed some SOAP web-services in ruby using savon and as expected it wasn’t the dreamworld for a rails-dev. Perhaps some Java or .NET developers love to generate connector-code for webservices from the WSDL with all that IDE integration and autocomplete-features but as ruby developer you just want use a simple, lightweight, restfull API instead.

Rails and SOAP actually doesn’t fit very well together but sometimes it’s also necessary to provide an oldschool SOAP webservice. E.g. when the customer has multiple systems talking to an existing service and just want to switch to your system without changing their whole implementations.

In this article I want to talk about a gem I’ve found that takes away some pain from you and allow to define SOAP methods directly in your rails controller. It’s called wash_out – man, how I love these ironic names ;-)

Let’s say we want to create a simple webservice that allows to calculate the FizzBuzz value of a number. In this case we’d need one method that gets an integer as an input parameter and also returns one – very simple but a nice example:

int getFizzBuzz(int number)

Accordning to this requirement the rails controller could look like the following:

# just a normal rails controller
class FizzBuzzController < ApplicationController
  # define a custom soap namespace (optional)
  soap_service namespace: 'urn:FizzBuzz'

  # define the method we want to provide with
  # its signature and map it to a controller action
  soap_action 'getFizzBuzz',
    args: :integer,
    return: :string,
    to: :get_fizz_buzz

  # the actual implementation as standard rails action
  # raising a special exception type if parameters are missing
  # and rendering a soap response directly from the ruby datatypes
  def get_fizz_buzz
    raise SOAPError, "parameter value is missing!" if params[:value].nil?
    render soap: fizz_buzz(params[:value])
  end

  private

  # just a simple helper method to do the actual "calculation"
  def fizz_buzz(number)
    return 'Fizz' if number % 3 == 0
    return 'Buzz' if number % 5 == 0
    number
  end

end

The SOAP enabled controller needs a special declaration in the routes.rb file:

Rails.application.routes.draw do
  wash_out :fizz_buzz
end

We can now test this e.g. using SoapUI with the WSDL at http://0.0.0.0:3000/fizz_buzz/wsdl or just implement some quick request specs using rspec:

require 'spec_helper'

describe 'SOAP actions' do

  describe 'getFizzBuzz' do

    it 'returns the number back' do
      post '/fizz_buzz/action', <<-SOAP
        <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:FizzBuzz">
           <soapenv:Header/>
           <soapenv:Body>
              <urn:getFizzBuzz soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
                 <value xsi:type="xsd:int">23</value>
              </urn:getFizzBuzz>
           </soapenv:Body>
        </soapenv:Envelope>
      SOAP
      expect(response).to_not be_error
      expect(response.body).to include '<value xsi:type="xsd:string">23</value>'
    end

    # [...]

  end

end

As you can see the gem allows to easily integrate the SOAP technology into a standard rails development workflow. Have fun but as also the readme of the gem tells us:

If you have a chance, try to avoid using SOAP.

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s