1.2. A short introduction to Web Services

Before we take a closer look at what the Web Services Resource Framework (WSRF) is, we need to have a basic understanding of how Web Services work (so we can better appreciate how WSRF extends Web Services). If you’re already familiar with Web Services, you can safely skip this section.
For quite a while now, there has been a lot of buzz about “Web Services,” and many companies have begun to rely on them for their enterprise applications. So, what exactly are Web Services? To put it quite simply, they are yet another distributed computing technology (like CORBA, RMI, EJB, etc.). They allow us to create client/server applications.
For example, let’s suppose I keep a database with up-to-date information about weather in the United States, and I want to distribute that information to anyone in the world. To do so, I could publish the weather information through a Web Service that, given a ZIP code, will provide the weather information for that ZIP code.

The clients (programs that want to access the weather information) would then contact the Web Service (in the server), and send a service request asking for the weather information. The server would return the forecast through a service response. Of course, this is a very sketchy example of how a Web Service works. We’ll see all the details in a moment.

Figure 1.4. Web Services
Web Services

Some of you might be thinking: “Hey! Wait a moment! I can do that with RMI, CORBA, EJBs, and countless other technologies!” So, what makes Web Services special? Well, Web Services have certain advantages over other technologies:

  • Web Services are platform-independent and language-independent, since they use standard XML languages. This means that my client program can be programmed in C++ and running under Windows, while the Web Service is programmed in Java and running under Linux.
  • Most Web Services use HTTP for transmitting messages (such as the service request and response). This is a major advantage if you want to build an Internet-scale application, since most of the Internet’s proxies and firewalls won’t mess with HTTP traffic (unlike CORBA, which usually has trouble with firewalls).

Of course, Web Services also have some disadvantages:

  • Overhead. Transmitting all your data in XML is obviously not as efficient as using a proprietary binary code. What you win in portability, you lose in efficiency. Even so, this overhead is usually acceptable for most applications, but you will probably never find a critical real-time application that uses Web Services.
  • Lack of versatility. Currently, Web Services are not very versatile, since they only allow for some very basic forms of service invocation. CORBA, for example, offers programmers a lot of supporting services (such as persistency, notifications, lifecycle management, transactions, etc.). Fortunately, there are a lot of emerging Web services specifications (including WSRF) that are helping to make Web services more and more versatile.

However, there is one important characteristic that distinguishes Web Services. While technologies such as CORBA and EJB are geared towards highly coupled distributed systems, where the client and the server are very dependent on each other, Web Services are more adequate for loosely coupled systems, where the client might have no prior knowledge of the Web Service until it actually invokes it. Highly coupled systems are ideal for intranet applications, but perform poorly on an Internet scale. Web Services, however, are better suited to meet the demands of an Internet-wide application, such as grid-oriented applications.

1.2.1. A Typical Web Service Invocation

So how does this all actually work? Let’s take a look at all the steps involved in a complete Web Service invocation. For now, don’t worry about all the acronyms (SOAP, WSDL, …). We’ll explain them in detail in just a moment.

Figure 1.5. A typical Web Service invocation
A typical Web Service invocation
  1. As we said before, a client may have no knowledge of what Web Service it is going to invoke. So, our first step will be to discover a Web Service that meets our requirements. For example, we might be interested in locating a public Web Service which can give me the weather forecast in US cities. We’ll do this by contacting a discovery service (which is itself a Web service).
  2. The discovery service will reply, telling us what servers can provide us the service we require.
  3. We now know the location of a Web Service, but we have no idea of how to actually invoke it. Sure, we know it can give me the forecast for a US city, but how do we perform the actual service invocation? The method I have to invoke might be called “string getCityForecast(int CityPostalCode)“, but it could also be called “string getUSCityWeather(string cityName, bool isFarenheit)“. We have to ask the Web Service to describe itself (i.e. tell us how exactly we should invoke it)
  4. The Web Service replies in a language called WSDL.
  5. We finally know where the Web Service is located and how to invoke it. The invocation itself is done in a language called SOAP. Therefore, we will first send a SOAP request asking for the weather forecast of a certain city.
  6. The Web Service will kindly reply with a SOAP response which includes the forecast we asked for, or maybe an error message if our SOAP request was incorrect.

1.2.2. Web Services Architecture

So, what exactly are SOAP and WSDL? They’re essential parts of the Web Services Architecture:

Figure 1.6. The Web Services architecture
The Web Services architecture
  • Service Processes: This part of the architecture generally involves more than one Web service. For example, discovery belongs in this part of the architecture, since it allows us to locate one particular service from among a collection of Web services.
  • Service Description: One of the most interesting features of Web Services is that they are self-describing. This means that, once you’ve located a Web Service, you can ask it to ‘describe itself’ and tell you what operations it supports and how to invoke it. This is handled by the Web Services Description Language (WSDL).
  • Service Invocation: Invoking a Web Service (and, in general, any kind of distributed service such as a CORBA object or an Enterprise Java Bean) involves passing messages between the client and the server. SOAP (Simple Object Access Protocol) specifies how we should format requests to the server, and how the server should format its responses. In theory, we could use other service invocation languages (such as XML-RPC, or even some ad hoc XML language). However, SOAP is by far the most popular choice for Web Services.
  • Transport: Finally, all these messages must be transmitted somehow between the server and the client. The protocol of choice for this part of the architecture is HTTP (HyperText Transfer Protocol), the same protocol used to access conventional web pages on the Internet. Again, in theory we could be able to use other protocols, but HTTP is currently the most used one.

In case you’re wondering, most of the Web Services Architecture is specified and standardized by the World Wide Web Consortium, the same organization responsible for XML, HTML, CSS, etc.

1.2.3. Web Services Addressing

We have just seen a simple Web Service invocation. At one point, a discovery service ‘told’ the client where the Web Service is located. But… how exactly are Web services addressed? The answer is very simple: just like web pages. We use plain and simple URIs (Uniform Resource Identifiers). If you’re more familiar with the term URL (Uniform Resource Locator), don’t worry: URI and URL are practically the same thing.
For example, the discovery registry might have replied with the following URI:

http://webservices.mysite.com/weather/us/WeatherService

This could easily be the address of a web page. However, remember that Web Services are always used by software (never directly by humans). If you typed a Web Service URI into your web browser, you would probably get an error message or some unintelligible code (some web servers will show you a nice graphical interface to the Web Service, but that isn’t very common). When you have a Web Service URI, you will usually need to give that URI to a program. In fact, most of the client programs we will write will expect to receive a Web service URI as a command-line argument.

[Tip]
If you’re anxious to see a real Web service working, then today’s your lucky day! A “Weather Web Service” is probably one of the most typical examples of a simple web service. You can find a real Weather Web Service here:

Wait a second… You didn’t actually try to visit that URI, did you? Haven’t you been paying attention? That’s a Web service URI, so even though it may look and feel like the URIs you type in your browser when you want to visit your favorite website, this URI is meant only for software that “knows” how to invoke Web services.
Fortunately, the authors of that web service have been kind enough to provide a description of the Web service, along with a web interface so you can actually invoke the service’s methods. If you feel specially curious, you can even take a look at the Web service’s WSDL (also available in a slightly more readable version)
For example, if you visit the web interface you’ll see that the Weather Web service offers a getWeatherReport operation that expects a single string parameter (an IATA airport designation, e.g. ORD for Chicago O’Hare and LHR for London Heathrow). If you invoke getWeatherReport, the Web service will return a WeatherReport structure with all sorts of interesting weather data. Fun!

1.2.4. How does this work in practice?

OK, now that you have an idea of what Web Services are, you are probably anxious to start programming Web Services right away. Before you do that, you might want to know how Web Services-based applications are structured. If you’ve ever used CORBA or RMI, this structure will look pretty familiar.
First of all, you should know that despite having a lot of protocols and languages floating around, Web Services programmers usually only have to concentrate on writing code in their favorite programming language and, in some cases, in writing WSDL. SOAP code, on the other hand, is always generated and interpreted automatically for us. Once we’ve reached a point where our client application needs to invoke a Web Service, we delegate that task on a piece of software called a stub. The good news is that there are plenty of tools available that will generate stubs automatically for us, usually based on the WSDL description of the Web Service.

Figure 1.7. Client and server stubs are generated from the WSDL file
Client and server stubs are generated from the WSDL file

Using stubs simplifies our applications considerably. We don’t have to write a complex client program that dynamically generates SOAP requests and interprets SOAP responses (and similarly for the server side of our application). We can simply concentrate on writing the client and/or server code, and leave all the dirty work to the stubs (which, again, we don’t even have to write ourselves… they can be generated automatically from the WSDL description of a web service).
The stubs are generally generated only once. In other words, you shouldn’t interpret the “Typical Web Service Invocation” figure (above) as saying that we go through the discovery process every single time we want to invoke a Web service, and generate the client stubs every time we want to invoke the service. In general, we only go through the discovery step once, then generate the stubs once (based on the WSDL of the service we’ve discovered) and then reuse the stubs as many times as we want (unless the maintainers of the Web service decide to change the service’s interface and, thus, its WSDL description). Of course, there are more complex invocation scenarios, but for now the one we’ve described is more than enough to understand how Web services work.

A Typical Web Service Invocation (redux)

So, let’s suppose that we’ve already located the Web Service we want to use (either because we consulted a discovery service, or because the Web service URI was given to us), and we’ve generated the client stubs from the WSDL description. What exactly happens when we want to invoke a Web service operation from a program?

Figure 1.8. A typical Web Service invocation (more detailed)
A typical Web Service invocation (more detailed)
  1. Whenever the client application needs to invoke the Web Service, it will really call the client stub. The client stub will turn this ‘local invocation’ into a proper SOAP request. This is often called the marshaling or serializing process.
  2. The SOAP request is sent over a network using the HTTP protocol. The server receives the SOAP requests and hands it to the server stub. The server stub will convert the SOAP request into something the service implementation can understand (this is usually called unmarshaling or deserializing)
  3. Once the SOAP request has been deserialized, the server stub invokes the service implementation, which then carries out the work it has been asked to do.
  4. The result of the requested operation is handed to the server stub, which will turn it into a SOAP response.
  5. The SOAP response is sent over a network using the HTTP protocol. The client stub receives the SOAP response and turns it into something the client application can understand.
  6. Finally the application receives the result of the Web Service invocation and uses it.

1.2.5. The server side, up close

Finally, let’s take a close look at what the server looks like, specially what software we should expect to have to get Web services up and running on our server.

Figure 1.9. The server side in a Web Services application
The server side in a Web Services application
  • Web service: First and foremost, we have our Web service. As we have seen, this is basically a piece of software that exposes a set of operations. For example, if we are implementing our Web service in Java, our service will be a Java class (and the operations will be implemented as Java methods). Obviously, we want a set of clients to be able to invoke those operations. However, our Web service implementation knows nothing about how to interpret SOAP requests and how to create SOAP responses. That’s why we need a…
  • SOAP engine: This is a piece of software that knows how to handle SOAP requests and responses. In practice, it is more common to use a generic SOAP engine than to actually generate server stubs for each individual Web service (note, however, that we still need client stubs for the client). One good example of a SOAP engine is Apache Axis (this is, in fact, the SOAP engine used by the Globus Toolkit). However, the functionality of the SOAP engine is usually limited to manipulating SOAP. To actually function as a server that can receive requests from different clients, the SOAP engine usually runs within an…
  • Application server: This is a piece of software that provides a ‘living space’ for applications that must be accessed by different clients. The SOAP engine runs as an application inside the application server. A good example is the Jakarta Tomcat server, a Java Servlet and Java ServerPages container that is frequently used with Apache Axis and the Globus Toolkit.
    Many application servers already include some HTTP functionality, so we can have Web services up and running by installing a SOAP engine and an application server. However, when an application server lacks HTTP functionality, we also need an…
  • HTTP Server: This is more commonly called a ‘Web server’. It is a piece of software that knows how to handle HTTP messages. A good example is the Apache HTTP Server, one of the most popular web servers in the Internet.
[Note]
Terminology in this area is still a bit inconsistent, so you might encounter different terms for the concepts we’ve just seen. In particular, it’s very common to use the term Web services container as a catch-all term for the SOAP engine + application server + HTTP server.
Advertisements