Ruby Web Service Application - SOAP4R
What is SOAP?
Simple Object Access Protocol (SOAP) is a protocol for exchanging data.
SOAP is a simple XML-based protocol that allows applications to exchange information over HTTP.
SOAP is a lightweight, simple, and XML-based protocol designed for exchanging structured and typed information over the web.
For more SOAP tutorials, please visit: http://www.w3cschool.cc/soap/soap-tutorial.html.
SOAP4R Installation
SOAP4R is developed and implemented by Hiroshi Nakamura for Ruby's SOAP applications.
SOAP4R download link: http://raa.ruby-lang.org/project/soap4r/.
Note: Your Ruby environment may already have this component installed.
In a Linux environment, you can also use gem to install this component with the following command:
gem install soap4r --include-dependencies
If you are developing in a Windows environment, you need to download the zip file and install it by executing install.rb.
SOAP4R Services
SOAP4R supports two different types of services:
- CGI/FastCGI-based service (SOAP::RPC::CGIStub)
- Standalone service (SOAP::RPC::StandaloneServer)
This tutorial will introduce how to build a standalone SOAP service. The steps are as follows:
Step 1 - Inherit SOAP::RPC::StandaloneServer
To implement your own standalone server, you need to write a new class that is a subclass of SOAP::RPC::StandaloneServer:
class MyServer < SOAP::RPC::StandaloneServer
...............
end
Note: If you want to write a FastCGI-based server, you need to inherit the SOAP::RPC::CGIStub class, and the rest of the program will remain the same.
Step 2 - Define Handler Methods
Next, we define the methods for the web service. Here, we define two methods: one for adding two numbers and one for dividing two numbers:
class MyServer < SOAP::RPC::StandaloneServer
...............
# Handler methods
def add(a, b)
return a + b
end
def div(a, b)
return a / b
end
end
Step 3 - Publish Handler Methods
Next, we add the methods defined on the server. The initialize method is public and used for external connections:
class MyServer < SOAP::RPC::StandaloneServer
def initialize(*args)
add_method(receiver, methodName, *paramArg)
end
end
Here are the descriptions of the parameters:
Parameter | Description |
---|---|
receiver | The object that contains the method. If the service method is defined in the same class, this parameter is self. |
methodName | The name of the method to call for the RPC request. |
paramArg | Parameter names and modes |
To understand inout and out parameters, consider the following service method, which requires two input parameters: inParam and inoutParam. After the function executes, it returns three values: retVal, inoutParam, and outParam:
def aMeth(inParam, inoutParam)
retVal = inParam + inoutParam
outParam = inParam . inoutParam
inoutParam = inParam * inoutParam
return retVal, inoutParam, outParam
end
The public call method is as follows:
add_method(self, 'aMeth', [
%w(in inParam),
%w(inout inoutParam),
%w(out outParam),
%w(retval return)
])
Step 4 - Start the Service
Finally, we start the service by instantiating the derived class and calling the start method:
myServer = MyServer.new('ServerName',
'urn:ruby:ServiceName', hostname, port)
myServer.start
Here are the descriptions of the request parameters:
Parameter | Description |
---|---|
ServerName | The name of the service, which you can choose as you like. |
urn:ruby:ServiceName | Here, urn:ruby is fixed, but you can choose a unique ServiceName for your service. |
hostname | Specifies the host name. |
port | The port for the web service. |
Example
Following the above steps, we create a standalone service:
Example
require "soap/rpc/standaloneserver"
begin
class MyServer < SOAP::RPC::StandaloneServer
# Expose our service
def initialize(*args)
add_method(self, 'add', 'a', 'b')
add_method(self, 'div', 'a', 'b')
end
# Handler methods
def add(a, b)
return a + b
end
def div(a, b)
return a / b
end
end
server = MyServer.new("MyServer",
'urn:ruby:calculation', 'localhost', 8080)
trap('INT){
server.shutdown
}
server.start
rescue => err
puts err.message
end
After executing the above program, a local service listening on port 8080 is started and exposes two methods: add and div.
You can run the above service in the background:
$ ruby MyServer.rb &
SOAP4R Client
In Ruby, the SOAP::RPC::Driver class is used to develop SOAP clients. Let's take a detailed look at the usage of the SOAP::RPC::Driver class.
To call a SOAP service, you need the following information:
- SOAP service URL (SOAP Endpoint URL)
- Method namespace URI for the service
- Service method name and parameter information
Next, we'll create a SOAP client step by step to call the SOAP methods: add and div.
Step 1 - Create a SOAP Driver Instance
We can call the new method by instantiating the SOAP::RPC::Driver class, as shown below:
SOAP::RPC::Driver.new(endPoint, nameSpace, soapAction)
Here are the descriptions of the parameters:
Parameter | Description |
---|---|
endPoint | The URL address to connect to the SOAP service. |
nameSpace | The namespace used for all RPCs by the SOAP::RPC::Driver object. |
soapAction | The value for the SOAPAction field in the HTTP header. If it's an empty string, it defaults to nil. |
Step 2 - Add Service Methods
To add SOAP service methods to the SOAP::RPC::Driver, we can call the following method on the SOAP::RPC::Driver instance:
driver.add_method(name, *paramArg)
Here are the descriptions of the parameters:
Parameter | Description |
---|---|
name | The name of the remote web service method. |
paramArg | Specifies the parameters for the remote program. |
Step 3 - Call the SOAP Service
Finally, we can call the SOAP service using the SOAP::RPC::Driver instance:
result = driver.serviceMethod(paramArg...)
serviceMethod is the actual name of the SOAP service method, and paramArg is the list of method parameters.
Example
Based on the above steps, we can write the following SOAP client:
Example
#!/usr/bin/ruby -w
require 'soap/rpc/driver'
NAMESPACE = 'urn:ruby:calculation'
URL = 'http://localhost:8080/'
begin
driver = SOAP::RPC::Driver.new(URL, NAMESPACE)
# Add remote service methods
driver.add_method('add', 'a', 'b')
# Call remote service methods
puts driver.add(20, 30)
rescue => err
puts err.message
end
The above example only briefly introduces Ruby's web services. For more information, please refer to the official documentation: Ruby's Web Service