HomeDigital EditionSys-Con RadioSearch Web Services Cd
B2B Beginning WS Business Process Management Case Studies Content Management Distributing Computing e-Business Electronic Data Interchange Enterprise Industry Insight Integration Interviews Java & Web Services .NET Portal Product Reviews Scalability & Performance Security SOAP Source Code UDDI Wireless WS Standards WS Tips & Techniques WSDL WS Editorials XML

Source Code for this article

Web services are XML-based building blocks for assembling distributed systems. Now that it's everyone's favorite buzzword, many developers are interested in experimenting with the technology to see what the excitement is all about.

The first generation of Web services platforms, such as Apache SOAP, was great for getting services up and running, but their ease of use and performance left a lot to be desired. The second generation of platforms is intuitive, fast, and can dramatically reduce the learning curve associated with Web services.

This article describes one of these platforms, called GLUE, which is free for most commercial uses. I hope that it gives you a taste of how much fun it can be to work with Web services!

Before delving into a simple example, let's quickly review the technologies that make up a complete Web services platform.

The Web Services Technology Stack
There are three standards that most Web services platforms implement:

  • SOAP (Service Oriented Archit-ecture Protocol) is the standard for network communication between software services. SOAP messages are represented using XML and can be sent over any transport layer. HTTP is the most common transport layer, with implem-entations also available for SMTP, JMS, and the IBM MQseries.
  • WSDL (Web Services Des-cription Language) is the XML equivalent of a resume and describes what a Web service can do, where it resides, and how to invoke it.
  • UDDI (Universal Description, Discovery, and Integration) is the standard that allows information about businesses and services to be electronically published and queried. UDDI is the Web services matchmaker and enables the creation of fluid, dynamically-assembled systems. Implementations of these standards are normally hosted within an application server that provides a Web server, servlet engine, XML processor, and other supportive infrastructure. A complete Web services technology stack thus looks like Figure 1.
Figure 1
Figure 1

GLUE includes an implementation of this entire techn-ology stack in a 360K .jar file, which reduces setup problems and allows it to be used in almost any kind of application.

GLUE can be used standalone or within a third-party servlet engine such as Tomcat or BEA WebLogic. The examples discussed here were run in a standalone configuration.

Building Your First Web Service
The quickest way to get a feel for Web services is to build a few programs. This section will guide you through the creation of a simple Web service that you can run on your local computer or across the Internet. It's particularly fun if you can team up with a friend and invoke Web services between your home computers. A link to the source code for these examples is provided at the end of this article. The example in Listing 1 is a simple currency exchange service that returns the conversion rate between two countries. The Java interface for this service is straightforward, and defines methods for setting and getting the current value in US dollars of a particular country's currency as well as a method for obtaining the exchange rate between two country's currencies.

Most Web services platforms provide built-in support for all of the standard Java data types and some common utility classes, mapping them onto the XSD data types as shown in Table 1.

Table 1
Table 1

Byte arrays are converted into base64Binary, which is an efficient XSD encoding for binary data. All other single-dimensional arrays are mapped into their XSD equivalents. In addition, custom serializers allow objects to be sent between SOAP systems in a neutral and portable way.

Listing 2 is the implementation of Exchange, which stores currency values in a Hashtable.

GLUE has two key classes for building and deploying Web services. The first is Registry, which includes static methods for publishing Web services and binding to them. These methods are:

publish( String path, Object object ): Publish the object to the specified path. By default, all of the object's public static and instance methods are exposed and can be invoked by SOAP clients.

bind( String path, Class type ): Return a proxy to the service described by the specified path and that implements the specified interface type. The path can be the local name of the service or the URL of its WSDL file.

unpublish( String path ): Unpublish the object from the specified path.

The second is HTTP, which provides static methods for starting up an in-process Web server that can accept incoming SOAP requests:

startup( String path ): Start a Web server on the specified path.

shutdown(): Shut down any Web servers that were started using startup().

Listing 3 starts up a Web server on port 8004 of the local host to accept messages arriving on /soap. It then publishes an Exchange object as "exchange" for use by any SOAP client.

Note that the server does not exit when the last line is reached because the Web server has threads running, and Java does not halt until all threads have completed.

The client program binds to a Web service by invoking Registry.bind() with the path to its WSDL file. Because Java is a statically-typed language, the proxy that is returned by the binding operation must be cast to the interface of the appropriate type. Once the proxy is obtained, the client uses it to invoke the service as if it were a local Java object. A GLUE client can bind to any SOAP service using this approach (see Listing 4).

A GLUE server dynamically generates WSDL for the services that it hosts; if an incoming request for a file ends with .wsdl, it sees if the file name matches that of the path of a local service. If this is the case, the GLUE server examines the local Web service, generates and caches its WSDL description, and returns the WSDL file to the requestor.

To run the example, execute the ExchangeServer program in one window and the ExchangeClient program in another window. Here is the output for ExchangeServer:

java examples.ExchangeServer
GLUE (c) 2001 The Mind Electric
startup server on http://199.174.53.144:8004/soap
Here is the output for ExchangeClient:
java examples.ExchangeClient
usa/japan exchange rate = 2.5
If you want to run the same example across the Internet, simply replace the URL in the ExchangeClient with the URL of the remote server.

Managing Services From a Browser
Once you've built your first Web service, it's easy to interact with it from a Web browser. You can enter the URL of the SOAP endpoint into the browser and see the services, as well as invoke them directly from the console.

Figure 2 is a screenshot of a GLUE console that shows the exchange rate service, including its address and a list of its methods.

Figure 2
Figure 2

You can use the console for invoking the methods from the browser, and for viewing other Web services anywhere on the Internet.

Invoking Remote Services
Web services are all about building applications from network building blocks, and one of the best sites for experimenting with third-party services is XMethods, located at www.xmethods.net.

When you visit XMethods, you'll see a listing of Web services on their home page. Each service has a brief overview, which includes the hosting company, the name of the service, a description, and the Web services platform that it's running on.

When you click on a particular service in their listing, you're shown a page that contains details of the service, including its description, owner, location and WSDL (see Figure 3). The WSDL is the most important item, since it contains everything you need to invoke the service.

Figure 3
Figure 3

For example, the delayed stock quotes service has a WSDL file located at http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl. Most Web services platforms include a utility for automatically creating client-side access code from a WSDL file. For example, to generate a Java interface and helper class for the XMethods Stock Quotes service, you can enter the following GLUE command, using the -p option to place the code into the examples package.

wsdl2java
http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl -p examples
write file IStockQuote.java
write file StockQuote.java
The generated IStockQuote.java interface is a regular Java interface with no coupling to anything that is Web service specific. The name and argument types of each method are extracted automatically from the WSDL file.
package examples;

public interface IStockQuote
{
float getQuote( String symbol );
}

The StockQuote.java helper class simplifies access to the remote Web service. It defines a couple of static methods: one that returns a proxy to the specific Web service, and another that returns a proxy to a similar service but at a different specified location.
package examples;

import electric.registry.Registry;
importelectric.registry.RegistryException;

public class StockQuote
{
public static IStockQuote bind() throws RegistryException
{
return bind( "http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl" );
}

public static IStockQuote bind( String url ) throws RegistryException
{
return (IStockQuote) Registry.bind( url, IStockQuote.class );
}
}

To access the XMethods Stock Quotes service from an application, call StockQuote.bind(). The following client gets an IBM stock quote using this approach.
package examples;

public class QuoteClient
{
public static void main( String[] args )
throws Exception
{
IStockQuote quotes = StockQuote.bind();
float ibm = quotes.getQuote( "IBM" );
System.out.println( "IBM quote is " + ibm );
}
}

To run the example, execute the QuoteClient program from a window. Here's the output you should see:
java examples.QuoteClient
IBM quote is 116.1
Once you get used to building simple services, the next step is to build services that orchestrate groups of other Web services. Unfortunately, service aggregation is beyond the scope of this article.

Epilogue
Although this article only scratched the surface of Web services, I hope it encourages you to take the next step and start building Web services of your own.

I think that Web services are the most exciting thing to happen in the world of computing for a long time, and the dream of a smart network teeming with collaborating software services is getting very close.

Resources
GLUE home page: http://www.themindelectric.com/products/glue/glue.html
XMethods: http://www.xmethods.net
Source code of examples: http://www.themindelectric.com/products/glue/glue.html

Author Bio:
Graham Glass is the chief architect and founder of The Mind Electric. He believes that the evolution of the Internet will mirror that of a biological mind, and that architectures for helping people and businesses to network effectively will provide insight into those that wire together the human brain. His passion is creating the kind of world that currently only exists in science fiction books. Graham earned his BSc in Mathematics and Computer Science from the University of Southampton and his MS in Computer Science from the University of Texas at Dallas. graham@themindelectric.com

Web Services Made Easy, by Graham Glass
WSJ Vol 01 Issue 01 - pg.61

	


Listing 1
package examples;

/**
 * An interface for getting exchange rates.
 */
public interface IExchange
  {
  /**
   * Set the value, in US dollars, of the specified currency.
   * @param country The country.
   * @param value The value in US dollars.
   */
  void setValue( String country, double value );

  /**
   * Return the value of the specified currency.
   * @param country The country.
   * @return The value in US dollars.
   * @throws ExchangeException If the country is not recognized.
   */
  double getValue( String country ) throws ExchangeException;

  /**
   * Return the exchange rate between two countries.
   * @param country1 The country to convert from.
   * @param country2 The country to convert to.
   * @return The exchange rate.
   * @throws ExchangeException If either country is not recognized.
   */
  double getRate( String country1, String country2 )
    throws ExchangeException;
  }

Listing2
package examples;

import java.util.Hashtable;

/**
 * Simple implementation of IExchange.
 */
public class Exchange implements IExchange
  {
  Hashtable values = new Hashtable(); // in US dollars

  public void setValue( String country, double value )
    {
    values.put( country, new Double( value ) );
    }

  public double getValue( String country )
    throws ExchangeException
    {
    Double value = (Double) values.get( country );

    if( value == null )
      throw new ExchangeException( "country " + country + " not recognized" );

    return value.doubleValue();
    }

  public double getRate( String country1, String country2 )
    throws ExchangeException
    {
    return getValue( country1 ) / getValue( country2 );
    }
  }

Listing3
package examples;

import electric.service.registry.Registry;
import electric.server.http.HTTP;

public class ExchangeServer
  {
  public static void main( String[] args )
    throws Exception
    {
    // start a web server on port 8004, accept messages via /soap
    HTTP.startup( "http://localhost:8004/soap" );

    // initialize an instance of Exchange
    Exchange exchange = new Exchange();
    exchange.setValue( "usa", 1 );
    exchange.setValue( "japan", 0.4 );

    // publish an instance of Exchange
    Registry.publish( "exchange", exchange );
    }
  }

Listing4
package examples;

import electric.registry.Registry;

public class ExchangeClient
  {
  public static void main( String[] args )
    throws Exception
    {
    // bind to web service whose WSDL is at the specified URL
    String url = "http://localhost:8004/soap/exchange.wsdl";
    IExchange exchange = (IExchange) Registry.bind( url, IExchange.class );

    // invoke the web service as if it was a local java object
    double rate = exchange.getRate( "usa", "japan" );
    System.out.println( "usa/japan exchange rate = " + rate );
    }
  }

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.

  E-mail: info@sys-con.com

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.