Exposing Web Services on Your Web Site






Exposing Web Services on Your Web Site

Problem

You want to offer SOAP and XML-RPC web services from your web application.

Solution

Rails comes with a built-in web service generator that makes it easy to expose a controller's actions as web services. You don't have to spend time writing WSDL files or even really know how SOAP and XML-RPC work.

Here's a simple example. First, follow the directions in Recipe 15.16 to create a database table named items, and to generate a model for that table. Don't generate a controller.

Now, run this from the command line:

	./script/generate web_service Item add edit fetch
	      create app/apis/
	      exists app/controllers/
	      exists test/functional/
	      create app/apis/item_api.rb
	      create app/controllers/item_controller.rb
	      create test/functional/item_api_test.rb

This creates an item controller that supports three actions: add, edit, and fetch. But instead of web application actions with .rhtml views, these are web service actions that you access with SOAP or XML-RPC.

A Ruby method doesn't care about the data types of the objects it accepts as arguments, or the data type of its return value. But a SOAP or XML-RPC web service method does care. To expose a Ruby method through a SOAP or XML-RPC interface, we need to define type information for its signature. Open up the file app/apis/item_api.rb and edit it to look like this:

	class ItemApi < ActionWebService::API::Base
	  api_method :add, :expects => [:string, :string], :returns => [:int]
	  api_method :edit, :expects => [:int, :string, :string], :returns => [:bool]
	  api_method :fetch, :expects => [:int], :returns => [Item]
	end

Now we need to implement the actual web service interface. Open app/controllers/item_controller.rb and edit it to look like this:

	class ItemController < ApplicationController
	  wsdl_service_name 'Item'

	  def add(name, value)
	    Item.create(:name => name, :value => value).id
	  end

	  def edit(id, name, value)
	    Item.find(id).update_attributes(:name => name, :value => value)
	  end

	  def fetch(id)
	    Item.find(id)
	  end
	end

Discussion

The item controller now implements SOAP and XML-RPC web services for the items table. This controller can live alongside an items controller that implements a traditional web interface.[8]

[8] 'You can even add your web interface actions to the ItemController class. Then a single controller will implement both the traditional web interface and the web service interface. But you can't define a web application action with the same name as a web service action, because a controller class can contain only one method with a given name.

The URL to the XML-RPC API is http://www.yourserver.com/item/api, and the URL to the SOAP API is http://www.yourserver.com/item/service.wsdl. To test these services, here's a short Ruby script that calls the web service methods through a SOAP client:

	require 'soap/wsdlDriver'
	
	wsdl = "http://localhost:3000/item/service.wsdl"
	item_server = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver

	item_id = item_server.add('foo', 'bar')

	if item_server.edit(item_id, 'John', 'Doe')
	  puts 'Hey, it worked!'
	else
	  puts 'Back to the drawing board…'
	end
	# Hey, it worked!

	item = item_server.fetch(item_id)
	item.class                                    # => SOAP::Mapping::Object
	item.name                                     # => "John"
	item.value                                    # => "Doe"

Here's the XML-RPC equivalent:

	require 'xmlrpc/client'
	item_server = XMLRPC::Client.new2('http://localhost:3000/item/api')
	
	item_id = item_server.call('Add', 'foo', "bar")
	if item_server.call('Edit', item_id, 'John', 'Doe')
	  puts 'Hey, it worked!'
	else
	  puts 'Back to the drawing board…'
	end
	# Hey, it worked!

	item = item_server.call('Fetch', item_id)
	# => {"name"=>"John", "id"=>2, "value"=>"Doe"}
	item.class # => Hash

See Also

  • Matt Biddulph's article "REST on Rails" describes how to create REST-style web services on top of Rails (http://www.xml.com/pub/a/2005/11/02/rest-on-rails.html)

  • Recipe 16.3, "Writing an XML-RPC Client," and Recipe 16.4, "Writing a SOAP Client"

  • Recipe 16.5, "Writing a SOAP Server," shows a nonRails implementation of SOAP web services



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows