Accessing a Java AXIS web service with Ruby and SOAP
I’ve been working with soap4r in Ruby to access some Java web services which use AXIS 1.1. The particular api I’m accessing requires an initial authentication call which returns a token that must be passed in all subsequent SOAP headers. This is a pretty common scenario, but it took me awhile to get it working correctly.
There were basically two “tricks”. The first which I found on a few other blogs entails creating a HeaderHandler (some suggested SimpleHeaderHandler, but that didn’t work for me because of trick #2). Here’s what I ended up with:
[ruby]
class ClientAuthHeaderHandler < SOAP::Header::Handler
HEADER =
XSD::QName.new(’http://www.foo.com/SecurityPass’,
‘SecurityPass’)
def initialize(token)
super(HEADER)
@token = token
end
def on_outbound
el = SOAP::SOAPElement.new(HEADER, @token)
el.extraattr['xsi:type'] = “xsd:string”
SOAP::SOAPHeaderItem.new(el, false)
end
end
[/ruby]
The second “trick” was in the on_outbound method. What I found was that AXIS was requiring the xsi:type to be included in the header that I added or it wouldn’t be recognized. Using extraattr was the only way I could figure out how to coerce it to be included. I suspect at some point this will be unnecessary, but for now it did the trick.
Here’s a simple example:
[ruby]
class FooService
# pass STDOUT to wiredump to see messages
def initialize(uri, wiredump=nil)
@uri = uri
@wiredump = wiredump
end
def svc(ref)
ws = SOAP::WSDLDriverFactory.new(”#{@uri}#{ref}?wsdl”).create_rpc_driver
ws.wiredump_dev = @wiredump
ws.generate_explicit_type = true
ws.headerhandler << ClientAuthHeaderHandler.new(@sec_token) if !@sec_token.nil?
ws
end
def authenticate(username, password)
ws = svc(”/services/AuthenticationService”)
@sec_token = ws.authenticate(username, password)
end
def lookup(stuff)
ws = svc(”/services/LookupService”)
ws.lookup(stuff)
end
end
[/ruby]




