Murphy Bytes

August 16, 2011

Consume SOAP Webservices the Easy Way with JAX-WS and JRuby

Filed under: Uncategorized — John Murphy @ 7:42 pm

SOAP has a bad reputation in the Ruby community. Most Rubyists prefer Restful services because they are a lot easier to consume and are well supported in tools like Rails. However, there are times where you have to consume a SOAP based web service. In this article, I’ll show you how you can easily consume a SOAP client using JRuby and JAX-WS. The source code for this exercise can be found here.

First, I’m going to grab the wsdl that defines the service we want to consume. Then I’m going to use the JAX-WS wsimport utility to turn the wsdl into java code. Then I’ll compile the Java code and create a jar that I will then use in my ruby code to interact with the web service.

Requirements

You’ll need to install a couple of things to get started. These include the following:

I’d also suggest RVM but that is optional. If you want to build something based on my example you’ll want to clone my git repository.


> git clone ssh://git@github.com/murphybytes/SampleSoapClient.git
> cd SampleSoapClient
> bundle install

So now you have your environment set up. What next? Let’s think a bit about how we want to structure our project. We are consuming the web service so lets make that a sub project of our main project. We’ll put the web service artifacts in SampleSoapClient/Webservice So we end up with something like this.


SampleSoapClient/lib
SampleSoapClient/spec
SampleSoapClient/script
SampleSoapClient/Webservice/generated
SampleSoapClient/Webservice/test
SampleSoapClient/Webservice/wsdl

I like to include the wsdl files defining the service in my project. With the wsdl files in place I’ll need to write an ant build script that will turn my wsdl into a jar that I can use in my Ruby code. Creating the build.xml is probably the hardest part of the project. Once you create your build script, you can use it as the template for the script to consume any SOAP based web service. Here’s mine.


<project name="OrderHistoryServiceAdapter" basedir="." default="jar">
  <taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
    <classpath path="lib/jaxws-tools.jar" />
  </taskdef>
  <target name="clean">
    <delete includeemptydirs="true" failonerror="false" >
      <fileset dir="bin" includes="**/*" />
      <fileset dir="generated" includes="**/*" />
      <fileset dir="dist" />
    </delete>
  </target>

  <target name="compile" depends="clean">
    <wsimport
wsdl="wsdl/OrdersHistoryService.wsdl"
destdir="bin"
sourcedestdir="generated"
xadditionalHeaders="true"
/>
    <javac destdir="bin" >
      <src path="test" />
      <src path="src" />
      <classpath path="lib/junit-4.9b3.jar" />
    </javac>
  </target>

  <target name="jar" depends="compile">
    <mkdir dir="dist" />
    <jar destfile="dist/OrdersHistoryService.jar" basedir="bin" />
  </target>

  <target name="test" depends="jar" >
    <junit printsummary="true" showoutput="true" >
      <classpath>
<pathelement path="dist/OrdersHistoryService.jar" />
<pathelement path="lib/junit-4.9b3.jar" />
      </classpath>
      <formatter type="plain" />
      <test name="com.eris.orderhistory.test.SessionTokenManagerTest" />
    </junit>
  </target>
</project>

Now, using JRuby, we can interact with our web service using pure Ruby code. All we have to do is add the requisite requires and import the classes that we want to use. Here’s an example.


# required to import native java
require 'java'
# the jar that implements our web service
require 'WebServiceClient/dist/OrdersHistoryService.jar'

# import native java classes
java_import com.currenex.webservice.definitions.AuthenticationPortType
java_import com.currenex.webservice.definitions.OrdersHistoryPortType

That’s all there is to it!

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress