Webservices using Axis

Posted by Matt Osentoski Fri, 23 Feb 2007 14:56:00 GMT

This article is a howto that describes setting up a web service using the 'Bottom Up' approach.

Intro

The first step to building web services is to figure out which method to start with. (Top down or Bottom up)

Bottom Up Development

Creating a web service from a Java Bean. This method creates a WSDL file automatically from Java code. To get this type of system to work, you will have to create a WSDD file which describes which java objects should be exposed as webservices. This approach is easier in the sense that you don't have to create a WSDL file, however the downside is that there is a greater risk that the WSDL file generated will not work with other systems. I would recommend trying Bottom Up development first. You can switch to Top Down development if you run into severe interoperability problems.

Top Down Development

This approach starts with the WSDL file. Java files are then generated from WSDL using a utility (WSDL2Java). This method has the highest chance of interoperability, but requires that you create a WSDL file from scratch, which can be very difficult and error prone process without the help of tools.

Bottom Up Development (Using JWS files)

Create a web service from a Java Bean that is renamed with the .jws extension This method creates a web service from a Java bean without the need to create a WSDD or WSDL file. It is the easiest approach to use, but also the most limiting in terms of functionality and interoperability. This method should NOT be used!!

Development (Bottom Up) - Server

Assuming you've chosen to develop using the Bottom Up approach, begin by creating your Java Objects. I generally create three layers:
1) Business Object Layer. This layer consist of the Beans that make up my model
2) DAO layer for database persistance. (Using Hibernate or JDBC)
3) Service Layer. This is the loosely grained layer used for making the web service calls (Ex: getCustomerByName(String name)). This is also the layer that will generate the WSDL file(s).

(NOTE: Save yourself a lot of pain and write some tests. There's nothing worse than trying to resolve an obscure Hibernate error while end-to-end testing your services)

Now that your Java code has been written (and hopefully tested ;) ) you can begin to write your WSDD file. The purpose of the WSDD file is to describe which java class will be exposed using web services. See this WSDD file as an example. The most important part is the comment section, I included, called 'Put your service definitions here'. Follow the example to add your own classes. If you're deploying your web services as a web application, the WSDD file should be called 'server-config.wsdd' and placed under your /WEB-INF directory. The Axis servlet will look for this file on startup. (This also saves you the annoyance of using the Axis admin tools for service startup.)

Now you will need to add the following Axis 1.2 library dependencies under /WEB-INF/lib:
axis.jar
commons-discovery.jar
commons-logging.jar
jaxrpc.jar
log4j-1.2.8.jar (your version may vary)
saaj.jar
wsdl-4j-1.5.1.jar (again.. your version may vary)

All of these libraries are included with Axis.

Next, you will have to modify your web.xml file to startup the Axis servlet and services. See this web.xml file as an example.

At this point you can compile all of your Java code into /WEB-INF/lib (as a jar) or /WEB-INF/classes and deploy the War file. Your web services should now be running.
To check, try accessing your services from a web browser:
http://localhost:8080/yourAppName/services/SomeService?wsdl

(Note: 'YourAppName' is the name of your application context. 'SomeService' will be the name of your service as defined in the WSDD file.)

This will display the WSDL file that is dynamically created. To call a method use:
http://localhost:8080/yourAppName/services/SomeService?method=aMethodThatDoesCoolStuff

(NOTE: 'aMethodThatDoesCoolStuff' would be the name of a method in your service layer. You can also set method params by adding paramName=paramValue pairs at the end of the URL)


Development - Client

The client code is automatically created using a utility called WSDL2Java. See this wsdl_run.bat script for an example that creates client code. A simple example for creating client stubs is also below:
java -cp %CLASS_PATH% org.apache.axis.wsdl.WSDL2Java -o .\src -d Session -p test.ws http://localhost:8080/myapp/services/MyService?wsdl

This command will create all the model objects and SOAP bindings. There will be a class called MyServiceSoapBindingStub that you will instantiate using another class called MyServiceImplServiceLocator to make web service calls. Compile all the generated code then call the web service using the example below.

Example:
MyServiceImplServiceLocator locator = new MyServiceImplServiceLocator();
MyServiceSoapBindingStub soapCall = (MyServiceSoapBindingStub) locator.getMyService();
String coolText = soapCall.aMethodThatDoesSomethingCool();
System.out.println("Output from WS: " + coolText + "\n\nYes! It works!!");

Posted in  | Tags , ,  | no comments

Problems with WSDL2ruby

Posted by Matt Osentoski Mon, 12 Feb 2007 21:04:00 GMT

The other day, I was trying to create a quick and dirty SOAP client for my Axis server, when I encounter the following error:

uninitialized constant SOAP::Mapping::EncodedRegistry (NameError)

Let me start from the beginning.. I installed soap4r using:
gem install soap4r
After soap4r was installed, I ran WSDL2ruby to create the SOAP client stubs.
wsdl2ruby.rb --wsdl http://localhost:8080/axis/services/someCoolService?wsdl --type client --force
Now that the client code had been generated, I launched the client and received the error message above. The problem was caused by Ruby grabbing the soap4r classes that are included in the distribution and not the gem. To fix this, explicitly point to the soap4r gem libary.

Solution


Open up the defaultMappingRegistry.rb file and make sure the require statements look like:
require 'default.rb'
require 'rubygems'
require_gem 'soap4r'
require 'soap/mapping'
NOTE:
require 'rubygems' --and--
require_gem 'soap4r'
were added.

Posted in  | Tags , , ,  | 4 comments

Creating dynamic WHERE clauses with ActiveRecord

Posted by Matt Osentoski Wed, 24 Jan 2007 19:58:00 GMT

Hibernate has a class called Criteria that's used to help eliminate the logic in dynamic queries. I was building a Ruby on Rails application recently and wanted similar functionality, but didn't see the equivalent of a Criteria object in ActiveRecord. I searched around for a 3rd party library and found a few, but wasn't interested in a heavy API. So, I rolled my own Class to create dynamic WHERE clauses.

The class is called SqlBuilder and works on the principle that the ActiveRecord find() method can accept a String and Hash of parameters in the :conditions clause. What my class does is create the SQL string, inserting symbols in place of values.

To use my class in your own code, grab the sql_builder.rb file here and follow the sample code below:

require 'sql_builder'
 
builder = SqlBuilder.new
builder.where_helper('division', params['division'], 'divisions.id')
builder.where_helper('vehicle', params['vehicles'], 'vehicles.id')
builder.where_helper('notes', params['notes'].strip, 'claims.notes', 'AND', 'LIKE')
sql_conditions, sql_conditions_hash = builder.get_sql_conditions()

@claims = Claim.find(:all, :include => [:divisions, :vehicles],
 :conditions => [sql_conditions, sql_conditions_hash])


Disclaimer: This is a very, very simple Class and probably won't work for every scenerio. If you have very complex needs you should check out some of the other libraries, that are out there.

Posted in  | Tags ,  | no comments

Ruby named language of the year by Tiobe

Posted by Matt Osentoski Mon, 08 Jan 2007 15:25:00 GMT

Ruby has been named language of the year by Tiobe and is now ranked in the top 10 languages. Follow the link below to read the article:

http://www.tiobe.com/tpci.htm

Posted in  | Tags  | no comments

Installing Typo in the root of your domain on Site5

Posted by Matt Osentoski Tue, 02 Jan 2007 19:42:00 GMT

Site5 has an automated process for adding Typo blogs to your website. This works fine except the blog is created in a directory off of the domain. For example: www.test.com/blog instead of www.test.com. Follow the steps below to install Typo into the root of your domain. This process should also work for your own custom Rails apps.

1. Setup SSH access on your Site5 account. Contact: shared@site5.com.

2. Download the latest version of Typo at: http://rubyforge.org/projects/typo/

3. Create a directory for your Rails applications. SSH into your account and create a rails_apps directory.
	> cd ~
	> mkdir rails_apps
4. SFTP your Typo file into the rails_apps directory you just created. The directory should be something like: /home/your_site_name/rails_apps

5. Expand the Typo file. SSH back into your account and issue the following commands:
	> cd rails_apps
	> gunzip -c typo-4.0.3.tar | tar xvf -
(NOTE: replace typo-4.0.3.tar with the name of the file you grabbed from rubyforge.org.)

6. Rename the original public_html directory.
	> cd ~
	> mv public_html public_html_orig
7. Create a symbolic link to typo's public directory.
	> cd ~
	> ln -s /home/your_site_name/rails_apps/typo-4.0.3/public public_html
8. Create the Typo database and database user. Login to the SiteAdmin for your account and create a new database user and database. Make sure you give the user the appropriate rights to the database you just created.

9. Prepopulate the typo database. (NOTE: This can also be accomplished using the import function in phpMyAdmin from SiteAdmin.)
	> mysql -u sitename_username -p
	use your_database_name
	source /home/your_site_name/rails_apps/typo-4.0.3/db/schema.mysql.sql
10. Modify the environment.rb file. This file should be located at:
/home/your_site_name/rails_apps/typo-4.0.3/config/environment.rb
Uncomment the following line:
ENV['RAILS_ENV'] = 'production'
Then add the RAILS_ROOT after:
RAILS_ROOT = '/home/your_site_name/rails_apps/typo-4.0.3'
11. Modify the database.yml file. This file should be located at:
/home/your_site_name/rails_apps/typo-4.0.3/config/database.yml

Modify the entries for the production application using the database information from Step 8.

12. Verify your .htaccess file. Located at: /home/your_site_name/rails_apps/typo-4.0.3/public/.htaccess
This file should contain the following lines:
RewriteEngine On

RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
13. Restart dispatch.fcgi. From a command prompt, run the following line:
	> pkill -9 -u your_username_here -f dispatch.fcgi
(NOTE: replace your_username_here with the username you used to SSH into the server.)

You should be all set! Try to access your domain, you should be greeted with the Typo setup screen.

Posted in  | Tags , ,  | no comments

Welcome

Posted by Matt Osentoski Sun, 31 Dec 2006 22:12:00 GMT

Hello, my name is Matt Osentoski. I've been in the IT industry for over nine years. My career has spanned a broad range of areas including:
  • Novell, NT, Unix Administration
  • Networking (Switches, routers, etc)
  • Digital Circuits (t1, t3, Oc3, etc)
  • Java Development
  • PHP / Ruby on Rails Development
Today I'm a software developer building and maintaining J2EE applications. I've been working with Java since 1998. Recently, I've been having a bit of a falling out with Java and have been moving toward more scripting based development methodologies using Ruby on Rails and PHP. Ruby on Rails especially has been a great experience compared to my years working with Java and I will probably write about my experiences here at great length.

Over the years I have compiled a large amount of HOWTOs and just general information for solving a wide variaty of problems. My goal with this website is to share these solutions and examine the future direction of the computer industry.

no comments