LG #96
<< Prev | TOC | Front Page | FAQ | Next >>
...making Linux just a little more fun! |
By Rob Tougher |
I spend a lot of my free time learning new (and old) technologies. Partly because I want to keep getting better as a software developer, but mostly because I'm a geek and I think it's fun. I think that most software developers spend at least some of their time improving their trade.
I decided for my latest project to look at Apache Axis. Apache Axis is an open source implementation of the Simple Object Access Protocol, or SOAP. Basically, SOAP provides a standardized protocol for passing data between machines (Exchanging data in a distributed environment is not a new concept - I've used COM, CORBA, and raw BSD sockets to send data from one machine to another. Actually, my very first Linux Gazette article was about socket programming in C++).
The goal of this project was to create a simple web service, and create consumers of that web service in Java and Python. This article details my steps in reaching that goal.
My first step was to set up my development environment. I decided to use two machines as part of this project - my Debian server and my Powerbook. I figured I would use my Powerbook to compile Java class files using Eclipse, and deploy those class files to an instance of Tomcat and Axis running on the Debian server. I already had Eclipse and the latest Java SDK installed on the Powerbook, so that was all set. I had no idea what the state of my Debian machine was, so I had to do some detective work before proceeding.
First was Java. I ssh'd into my Debian box and checked my environment. For a Java installation the JAVA_HOME environment variable needs to be set, so I figured that would be the first place to check. I called "set", looked through the output, and failed to find the property. I then viewed my .bashrc file, and noticed that JAVA_HOME was being set. Odd. So .bashrc wasn't being called. Maybe sshd doesn't call your bash files? I typed "bash" at the prompt, pressed return, typed "set", and the JAVA_HOME property showed up. So I guess ssh doesn't run the bash stuff. I ran "java --version", and it returned "1.4.1_01". Good. I then went to Java's site, and realized that version 1.4.2 of the Java SDK was released! So I did have to install Java. I downloaded the bin file to my Powerbook, scp'd it to my Debian box, chmod'd it, ran it, and then updated the environment variable declarations in my .bashrc file. One last check, "java -version", returned 1.4.2. Java installation was complete.
Next was Tomcat. Tomcat is a J2EE servlet container that is hosted at the Apache Jakarta site. Tomcat installation was simple as well. I downloaded Tomcat 4.1.27 from the main web site, scp'd it to the Debian box, and unpacked it in my ~/apps directory. Then, per the online docs, I simply ran bin/startup.sh, and browsed to port 8080 of my Debian box using Mozilla. Success! I had previous servlet container experience, so I was not worried about this.
Next was Eclipse. Eclipse is an open source IDE that IBM has developed. I decided that I would run Eclipse on my Powerbook to compile any Java files I needed, and transfer them over to the Debian box. I could easily have run Eclipse on the Debian box(and I have used Eclipse on my Linux machine at work), but my Debian box runs headless so I would have to use Eclipse through my Powerbook's X Server. Not the speediest setup. So I just clicked my Eclipse icon on my desktop, and voila, Eclipse was running on my Powerbook (I'm actually writing this article right now using JEdit on my Powerbook).
Next was Axis. I downloaded Axis from the main site, copied it over to my Debian box, extracted it, and copied the "axis" directory from the distribution into my Tomcat webapps directory. After restarting Tomcat, I browsed to http://debianbox:8080/axis, and received the Axis home page. Success!
Last, but not least, I needed a way to call SOAP services using Python. I had never used SOAP with Python, so I wasn't aware of any projects that implemented it. My first step was to do a quick check on my Debian machine by calling "apt-cache search soap". It returned the "python-soappy" package. So I installed it, and found the new file in /usr/lib/python2.1/site-packages.
So that was it. Installation proceeded very smoothly.
My next step in this project was to create a simple web service. A first program would be incomplete without "Hello World" somewhere in there, so I decided to use the following Java source code:
public class HelloWorldService { public String HelloWorld(String data) { return "Hello World! You sent the string '" + data + "'."; } }
Next I had to deploy this source code to Axis. I spent some time reading through the Axis docs, and realized that there are basically two ways of deploying web services - an easy instant way that has some restrictions, and a longer custom way that is more flexible:
The custom way seemed simple, but I decided for the purposes of this article that I would go the instant route. I leave it up to the reader to experiment with WSDD's.
Back to my example. I had the above Java source code that I wanted to deploy to Axis. So I changed my file's extension to *.jws, and moved it into the Axis directory. Then I checked to see that the service was installed by browsing to the service's address:
I received an HTML page saying that there was a service installed at that location. Success! I went a step further by trying to call my HelloWorld method:
I received the XML from the method call. The call completed successfully!
Creating the web service turned out to be very simple. My next task was to create a Java client that could call the service.
The following is the source code for my Java client:
import java.net.MalformedURLException; import java.net.URL; import java.rmi.RemoteException; import javax.xml.namespace.QName; import javax.xml.rpc.ServiceException; import org.apache.axis.client.Call; import org.apache.axis.client.Service; public class HelloWorldClient { public static void main(String[] args) throws ServiceException, MalformedURLException, RemoteException { Service service = new Service(); Call call = (Call)service.createCall(); call.setTargetEndpointAddress(new URL("http://debianbox:8080/axis/HelloWorldService.jws")); call.setOperationName(new QName("http://soapinterop.org/", "HelloWorld")); String returnValue = (String)call.invoke(new Object[]{"My name is Rob."}); System.out.println(returnValue); } }
I found this code as part of the Axis documentation. Who says that the copy-paste antipattern is bad? :)
In order to compile the Java client I had to set up an Eclipse project. I created a project named "AxisTest", and imported the axis.jar, jaxrpc.jar, commons-logging.jar, commons-discovery.jar, and saaj.jar archives from the Axis distribution. After compiling the source file, I ran it and received data from the service. The Java client was a success.
Because SOAP is language independent, I thought that I should be able to create a Python client to call my web service. I did a quick Google search and found the main web site for Python Web Services. I viewed the README for SOAPPY, and found an example similar to the following:
#!/usr/bin/env python import sys import SOAP remote = SOAP.SOAPProxy( "http://debianbox:8080/axis/HelloWorldService.jws", "", "") result = remote.HelloWorld("My name is Rob.") print result
I ran this on my Debian box and received the correct message from the Axis service.
I'm happy with the result of my experiments with Apache Axis. I reached all of the goals that I set for myself in the beginning, and I came to the conclusion that Axis is an excellent way to exchange data between machines in a distributed environment.
Rob is a software developer in the New York City area.