Query Soap Service Using Ruby

Posted by mike on September 29, 2008

OK, to get this out of the way.  I know, SOAP is lame and REST is cool.  However, there may still be times when you need to query data from a SOAP web service.  This article is an attempt to document the process of retrieving and working with that data.

In this example I will describe how to query the WSDL to get a list of methods and parameters, and use that to submit the method call.  I will be calling a web service method called ‘webMethod’ that accepts one parameter called ‘publishDate’.  If you don’t already know this information about the web service you are communicating with, there is a free tool called SoapUI that works pretty well.  It’s written in Java, so you should be able to get it to work on about any platform.

Depending on the version of Ruby you are running, the first thing that may be required is to install soap4r:

gem install soap4r

Next is to set the location of the WSDL file on the web server, set the encoding, and instantiate the driver:

require ’soap/wsdlDriver’
wsdl = ‘http://server/WebService.asmx?WSDL’
driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
XSD::Charset.encoding = ‘UTF8′

This next line will create two logs in the directory of the process called devLog_webMethod_response.xml and devLog_webMethod_request.xml that will show the raw request and response each time the process is called.  In place of webMethod will be the actual method name of the web service being called.  This can be commented out when the application is moved to production.

driver.wiredump_file_base = “devLog”

Now it’s time to retrieve the data:

@response = driver.webMethod(:publishDate => ‘2008-09-01‘)

At this point @response contains the XML response from the web service.  In order to retrieve the data we will need to know a little bit about the structure of the XML.  We can find out this information by opening the log file created by the previous step.  Let’s open devLog_webMethod_response.xml:

<?xml version=”1.0″ encoding=”utf-8″ ?>
<soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance xmlns:xsd=”http://www.w3.org/2001/XMLSchema>
<soap:Body>
<WebMethodResponse xmlns=”WebMethod>
<WebMethodResult>
<Article>
<Name>Example 1</Name>
<Headline>Poor Excuse For An Article</Headline>
<Body>Nothing to see here, move along please.</Body>
</Article>
<Article>
<Name>Example 2</Name>
<Headline>Woot!  I Made Headlines</Headline>
<Body>Yeah, OK.  Another poorly written example article.</Body>
</Article>
</WebMethodResult>
</WebMethodResponse>
</soap:Body>
</soap:Envelope>


OK, so here we have two articles that contain the data we are after and they are both inside the WebMethodResult tags.  So to access those bits we might do something like:

@response.webMethodResult.article.each do |article|
puts article["Name"]
puts article["Headline"]
puts article["Body"]
end


That works great as long as there is always more than one article.  If, on the other hand, there is only one article in the result, it is no longer an array and the .each method will fail.  So to get around this we can move our logic to a method and then test the article first to see which way we should handle it.  So the previous code might be rewritten as:

def print_article(article)
puts article["Name"]
puts article["Headline"]
puts article["Body"]

end

if(@response.webMethodResult.article.is_a?(Array))
@response.webMethodResult.article.each do |article|
print_article(article)
end
else
print_article(@response.webMethodResult.article)
end



If you are asked to do some work with SOAP based web services, hopefully this makes it a little easier to get up and running.

IE 7 and Word Wrap

Posted by mike on September 25, 2008

I guess this is what I get for doing most of my testing in Firefox. I created an aspx page to be opened in a javascript window.open to allow a customer to preview some rendered HTML. I used labels in the aspx page and then populated those with data returned from a database. Everything looked great in Firefox, but when I checked it in Internet Explorer, there was no word wrapping. Each line ran off the page. After some research I found a CSS property called word-wrap. The property is part of the CSS3 draft and is used to force word wrapping. Since this is a simple page that is opened in a pop-up window, I was able to fix the problem by simply adding the following to the CSS style.

body {
  word-wrap: break-word;
}

If I understand the CSS3 draft correctly, this should actually force a word wrap even if it occurs in the middle of a word. However, in testing with both Firefox and IE 7, this is not the case. It breaks at the end of the word.

ruby.exe Unable To Locate Component readline.dll 1

Posted by mike on August 30, 2008

I just installed ruby 1.8.7 on a Windows machine and when I started IRB:

readlineError

The fix:

  1. Go to http://gnuwin32.sourceforge.net/packages/readline.htm and download the binaries zip file.
  2. Unzip the file.
  3. Change directory to the new directory created by unzipping the file.
  4. Change directory to the bin directory.
  5. Copy the readline5.dll file.
  6. Change directory to your ruby/bin directory (for me this is C:\ruby\bin).
  7. Paste readline5.dll file there.
  8. Rename file readline.dll.

As long as your ruby\bin directory is set in your PATH environment variable, that should take care of the problem.

Ruby on Rails Development Environment on Ubuntu Linux 8.04.1 1

Posted by mike on August 13, 2008

I just went through the process of setting up a new Linux desktop for Rails development.  In an effort to keep it short and to the point, I’ve trimmed up some of the info that I found useful from wiki.rubyonrails.org.  This is just a basic development stack.  I plan to write another post on the editors that I’ve tried and what I’ve found to work best for me so far.  Anyway, let’s get started.  I tend to work primarily at a command prompt, so that’s the method I’ve described here.  Open a terminal window and follow along:

sudo apt-get install ruby rdoc libyaml-ruby libzlib-ruby ri libopenssl-ruby ruby1.8-dev build-essential

You don’t want to install the rubygems package from the Ubuntu repository.  It is consistently out of date, so you will need to pull the tarball down from RubyForge:

wget http://rubyforge.org/frs/download.php/38646/rubygems-1.2.0.tgz
tar xvzf rubygems-1.2.0.tgz
cd rubygems-1.2.0
sudo ruby setup.rb

At least with the versions I’ve installed, I had to create a symbolic link to gem1.8:

sudo ln -s /usr/bin/gem1.8 /usr/bin/gem

You should now be able to do a gem update:

sudo gem update --system

And install Rails:

sudo gem install rails

Now it’s time to take care of the database installation:

sudo apt-get install mysql-server libsqlite3-0 libsqlite3-dev
sudo gem install mysql sqlite3-ruby

If you want to install RMagick:

sudo apt-get install imagemagick libmagick9-dev
sudo gem install rmagick

That should do it.  Now go have some fun!

How to change the default editor in Debian and Ubuntu

Posted by mike on August 10, 2008

I’ve been a fan of Ubuntu Linux since I first started using it a few years ago.  One of the first things I do when building a new Ubuntu machine is set the default editor to Vim.  I have been using Vi for a long time and the keyboard shortcuts are very natural for me, so the first time I typed a command like visudo or crontab -e and got the Nano editor, I was shocked.  With Ubuntu 8.04 it’s really very easy:

Open a terminal window (Applications/Accessories/Terminal)
Type: sudo apt-get install vim-full

That should do it.  By default only the vim.tiny package is installed and installing the vim package (apt-get install vim) only gets you vim.basic.  Both of those will leave the default editor as Nano.  Installing the vim-full package will take care of modifying the default editor for you to be vim.gnome.  If you would like to change the setting to something else, or that didn’t work with the version of Debian or Ubuntu that you have, try:

sudo /usr/sbin/update-alternatives --config editor

Then pick the number that corresponds with your choice.