Ruby for Java Programmers, Part VI

6 05 2006

In the previous episode from this series, I showed you how to use XML-RPC to call Java code from Ruby over the network. In this article, we will do the same, but using SOAP instead of XML-RPC. One advantage of SOAP over XML-RPC is the fact that SOAP endpoints can be described using WSDL and, by using Ruby’s extensibility, new methods can be created on the fly to mirror the methods declared in the WSDL, therefore giving us a lot of nice loose coupling.

Moreover, toolkits exist to automatically create WSDL descriptions from Java classes, so you won’t have to do it by hand. One of these toolkits, and the one we’ll be using in the examples here, is XFire. The most recent version of XFire available at the time I’m writing this is 1.1-RC1. I suspect this example will work just as well when 1.1 final is released. You’ll also need Java5 and Maven 2.

Maven is handy for automatically downloading all the necessary dependencies and running the demo inside a servlet container, using the Jetty6 plugin, without writing much code or configuration. Of course, you can always download all the necessary JARs by hand and drop them, together with the demo code, into the servlet container of your liking.

You can follow XFire’s Quick Start tutorial to set up a simple SOAP service, or you can simply grab a copy of this archive, which adds some more data to the tutorial sample, unzip it and run mvn jetty6:run from its root directory, once you have Maven installed. Go grab a cup of coffee while Maven downloads all the dependencies. Finally test that everything is OK by requesting a copy of the WSDL file from http://localhost:8080/services/BookService?wsdl.

On Ruby’s side, all that is needed is already provided by Ruby’s own core soap library, in particular SOAP::WSDLDriverFactory.

Here’s how you’d call your service from Ruby:

require 'soap/wsdlDriver'
WSDL_URL = 'http://localhost:8080/services/BookService?wsdl'
driver = SOAP::WSDLDriverFactory.new(WSDL_URL).create_rpc_driver
books = driver.getBooks(nil)
p books.out.book[0].title
book = driver.findBook(:isbn => '222')
p book.out.title

A couple of minor nits:

  1. The BookService#getBooks method in Java takes no arguments, but if you try to call driver.getBooks without arguments, Ruby complains about a missing argument. Apparently, passing a ‘nil’ value fixes it, but I’d like to know why this is so.
  2. XFire add this extra ‘out’ element to its generated schema. This is mildly annoying as you always have to use it in order to access the real values you are interested in.

On the pro side, you can set up all of this with very little configuration. The only configuration that is going to change from one application to another is XFire’s services.xml file which maps service names to service classes, and even this is pretty straightforward:

<beans xmlns="http://xfire.codehaus.org/config/1.0">
  <service>
    <name>BookService</name>
    <namespace>http://sourcesense.com/BookService</namespace>
    <serviceClass>com.sourcesense.xfire.demo.BookService</serviceClass>
  </service>
</beans>

Technorati Tags: , , , , .

Advertisements

Actions

Information

5 responses

22 07 2006
Dalibor Topic

I’m not sure if you are familiar with the way it’s being done in POI ruby bindings, but you may want to check out

http://www.sengupta.net/talks/Avik_Java_Ruby.sxi

22 07 2006
ugo

Interesting. Too bad the file is for OpenOffice, a PDF version would have been welcome :). Anyway, I found some information on the POI website as well. Thanks.

14 08 2006
Robert

The reason for both issues is that soap4r doesn’t completely support wrapped document/literal services, and so you end up with getBooks taking a GetBooksRequest object, and returning a GetBooksResponse object, rather than automatically unwrapping the content.

13 09 2006
Agylen » Re: Outsourcing the performance-intensive functions

[…] Well, the era of islands did never actually begin for pragmatic developers, to be honest, but anyway I think this sentence, and all of David’s piece, could very well be taken as an endorsement of the work I’ve been doing: investigating the integration between the Ruby and Java worlds. […]

26 01 2007
kelly

Thanks for your example code on how to call a SOAP service from a ruby client. I’ve been looking for this everywhere!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: