Until recently, web service interactions were solely synchronous and request-response in nature. However, it soon became clear that the synchronous request-response type of interaction is a very small subset of messaging scenarios. Messaging is very important in constructing loosely coupled systems, and as a result, this limitation is critical. Web service specifications, such as WS-addressing and WSDL, have incorporated the concepts of messaging, and lay the foundation to cover a wider range of messaging scenarios. The Apache Axis2 architecture assumes neither one message exchange pattern, nor synchronous/asynchronous behavior. This article explains messaging concepts and how Axis2 can be used to implement several well-known messaging scenarios.
Throughout the history of computing, one of the greatest challenges has been in distributed computing: when the resources are distributed, interprocess communication becomes quite difficult. Researchers are still looking for better solutions. Interestingly, almost all of the solutions for the problem of distributing computer power emerge from two conceptual bases: remote procedure calls (RPC) and messaging.
Unquestionably, using RPCs is the more popular technique among developers, partly due to its resemblance to using local procedure calls. It has an air of familiarity for programmers, and creates a natural tendency towards using RPC style in a distributed system. Messaging, on the other hand, is not remarkably popular, and quite a few developers are likely to raise their eyebrows if it is mentioned. Nevertheless, messaging provides certain advantages over RPC systems in certain scenarios.
The fundamental differences between RPC and messaging frameworks are as follows.
Web services are defined based on XML messaging, and the following three parameters describe a given web service's messaging interaction.
|
Related Reading
Java Web Services in a Nutshell |
In the most abstract form, web service messaging is based on sending and receiving messages. A given message is sent by one party, and received by a another. The messages might be related to each other, and it is important to identify the most common use cases among those related groups of messages; such message groups are defined as message exchange patterns, or MEPs.
A service requester's behavior in the transient period between two related messages defines the synchronous/asynchronous behavior in the client API. In the synchronous case, invocation at the client API would block, and wait until the related message arrives at the destination. In the non-blocking case, the client invocation continues without blocking, and when a related message arrives, it is correlated with earlier messages.
Transports are categorized as one-way or two-way, based on simplex or duplex behavior. Transports like SMTP and JMS are one-way transports, and are non-blocking in nature. On the other hand, transports like HTTP and TCP are two-way, and the related message may travel back in the return channel. Actually, in web service messaging, two-way transports may be used as a one-way transports, but in such cases, they can be effectively treated as one-way.
According to the W3C recommendation, a message exchange pattern is a template that establishes a pattern for the exchange of messages between two communicating parties. A MEP identifies a common grouping of related messages. The MEPs are defined based on the service requester and service provider, and it is important to note that the MEPs are named based on message characteristics in the service provider, for the sake of clarity. All of the names can be understood by replacing the in with request and out with response.
For an example, let us consider two well-known MEPs.
The concept of MEPs is still evolving, and the number of patterns is unlimited, so web service middleware implementations are compelled to implement only a few chosen MEPs. "Fire and forget" and "request-response" are the ones that are used explicitly, and most other patterns can be constructed using these two.
|
Synchronous/asynchronous (or blocking/nonblocking) behavior is based on the thread that handles the web service invocation. A synchronous service will block, and wait for related messages to arrive. On the other hand, an asynchronous invocation will just return, and waiting for related messages will be done by a different thread that runs in the background.
Both approaches have strong use cases. Consider a bank transaction that needs a number of messages to fly back and forth: the bank transaction is sequential by nature, as results are required to arrive before execution goes to the next step, so synchronously waiting for the results make sense. On the other hand, consider a flight reservation program that needs to collect data from many sources, and match based on the results. In this case, the asynchronous approach would work, since the program can submit all of the requests and work on the data as they arrive. Considering network latency, the asynchronous approach would yield much better results.
The synchronous invocations are simple: the invocations wait for the related messages to arrive, and can be coded like any local procedure call. But the correlation of the asynchronous messages is complex, and the client has to work to handle the complexities. Still, there are cases where doing extra work to handle the complexity can be justified.
The behavior of the transport layer is a critical factor that decides how web service messaging takes place. Transports are categorized as one-way or two-way, according to their behavior.
One-way transports reduce the complexity of web service
messaging, as the related message must come from a separate
channel. On the other hand, if the transport is two-way,
messaging has a choice of using transport as one-way or two way.
For an example, when the transport is HTTP, the related message may
come from the return path of the HTTP connection, or the web
service provider might write HTTP 200 to indicate
that there is no response coming on the same connection, in which case
the response is sent over a separate HTTP connection.
Web service addressing (also called WS-addressing) lays the framework for the information exchange between different parties that takes place in a web service interaction. The following five parameters define an interaction.
The service provider declares the first two, and the client is free to define the other parameters. The client-level synchronous/asynchronous behavior is completely transparent to the service provider, and the client uses WS-addressing to explain the web service messaging.
Among many other constructs, WS-addressing defines four headers:
To, ReplyTo, RelatesTo,
FaultTo, and a special address that is called the
Anonymous address. When a service provider receives a SOAP
message, it finds the target service based on the To
address and invokes the service. The results, if there are any, are
sent to the ReplyTo address, and any error is sent to
the FaultTo address. If any of the above headers are
not specified or have the value Anonymous, the result is sent via
the return path of a two-way transport (since Anonymous always
resolves to the return path of a two-way transport).
Transports, together with WS-addressing, define a mechanism to
find interrelated messages. Messages are related either because
they share the same transport channel, or because they all share
common information that links them to each other. The
RelateTo header of the web service addressing provides
precisely this relationship.
The following table shows different values of the addressing headers for a few well-defined message interactions.
| MEP | Sync/Async | Transport Behavior | Message | To |
ReplyTo |
RelatesTo |
|---|---|---|---|---|---|---|
| In-Only | NA | One-way | IN | Optional | Optional | NA |
| In-Out | Sync | One | IN | Optional | Anonymous | NA |
| OUT | Anonymous | Optional | IN-Message | |||
| In-Out | Async | One | IN | Optional | Anonymous | NA |
| OUT | Anonymous | Optional | IN-Message | |||
| In-Out | Async | two | IN | Required | Required | NA |
| OUT | Required | Optional | IN-Message |
|
The Axis2 client API handles In-Only and In-Out MEPs with all
messaging combinations discussed in the last section. The space of
the MEPs are unlimited; as a result, Axis2 is compelled to provide
a core that can support any message exchange pattern, but provides
API support only for the two most widely used patterns: In-Only and
In-Out. There are two ways to implement more complex patterns:
combine In-Out and In-Only patterns to achieve the desired pattern,
or write a new implementation for the desired pattern. As Axis2
provides support for any MEP in the core level, implementing either
is fairly straightforward. The In-Only and In-Out MEPs are
supported with the two classes InOnlyMEPClient and
InOutMEPClient, described in the next two
sections.
InOnlyMEPClientThe InOnlyMEPClient class provides support for
fire-and-forget messaging, and treats all transport types as
one-way transports. The real difference between
InOnlyMEPClient and InOutMEPClient is
that the addressing parameters are not locked in the former, and
addressing parameters are controlled by Axis2 in the latter. As the
addressing parameters can be controlled, the
InOnlyMEPClient can be used as the messaging API, and
used as the building block to build more complex message
interactions on top of it.
InOutMEPClientInOutMEPClient and the Call class that
extends the InOutMEPClient provide the API for
request-response messaging. Axis2 takes care of the complete
operation, and all of the addressing properties except the
To address are under the control of the Axis2.
Users can configure InOutMEPClient to behave
differently using the following four parameters:
The client API currently provides support for HTTP and SMTP transports. The following matrix shows the possible combinations for these parameters and how they combine to provide different effects.
| Messaging interaction | Sender transport | Listener transport | Use separate Listener | Blocking |
|---|---|---|---|---|
| Sync/One Channel | HTTP | HTTP | FALSE | TRUE |
| Async/One Channel | HTTP | HTTP | FALSE | FALSE |
| Async/Two Channel | HTTP | HTTP | TRUE | FALSE |
| SMTP | SMTP | TRUE | FALSE | |
| Sync/Two Channel | HTTP | HTTP | TRUE | TRUE |
| SMTP | SMTP | TRUE | TRUE |
The following code samples show how to do several well-defined interactions with Apache Axis2. The user may configure Axis2 to switch between different interactions by simply switching the properties in the client API. The client API of Axis2 supports only XML-level messaging, and OMElement represents a chunk of XML.
The one-way MEP is simple in that there is exactly one way it can behave, as there is only one message that goes back and forth. The messages are treated asynchronously and the transport is one-way.
There are four ways a request-response message can behave:
The following code samples show how these cases can be addressed with Axis2. Pay attention to how the four properties of the client API are used.
OMElement payload = ....
Call call = new Call();
call.setTo(
new EndpointReference(AddressingConstants.WSA_TO,
"HTTP://...));
call.setTransportInfo(Constants.TRANSPORT_HTTP,
Constants.TRANSPORT_HTTP, false);
OMElement result =
(OMElement) call.invokeBlocking(
operationName.getLocalPart(), payload);
Here, the SOAP messages travel through the same HTTP connection.
The addressing properties are not specified, so they will be
defaulted to Anonymous at the server side. The client API will
block until the response message arrives.
|
//this is the payload goes on the body of SOAP message
OMElement payload = ....
Call call = new Call();
call.setTo(
new EndpointReference(AddressingConstants.WSA_TO,
"HTTP://...));
call.setTransportInfo(Constants.TRANSPORT_HTTP,
Constants.TRANSPORT_HTTP, false);
Callback callback = new Callback() {
public void onComplete(AsyncResult result) {
//what user can do to result
}
public void reportError(Exception e) {
//on error
}
};
call.invokeNonBlocking(operationName.getLocalPart(),
payload, callback);
As before, the SOAP messages travel through the same HTTP connection and the invocation does not require addressing. The client API will not block and the callback will be executed once the response message arrives.
OMElement payload = ....
Call call = new Call();
call.setTo(
new EndpointReference(AddressingConstants.WSA_TO,
"HTTP://...));
call.setTransportInfo(Constants.TRANSPORT_HTTP,
Constants.TRANSPORT_HTTP, true);
Callback callback = new Callback() {
public void onComplete(AsyncResult result) {
....
}
public void reportError(Exception e) {
...
}
};
call.engageModule(new Qname("addressing"));
call.invokeNonBlocking(operationName.getLocalPart(), method, callback);
In this case, the SOAP messages travel through two HTTP
connections, addressing is mandatory, and the presence of the
ReplyTo header instructs the server to send the
response in a separate channel. The client does not block, and when
the response message arrives, the callback is invoked.
OMElement payload = ....
Call call = new Call();
call.setTo(
new EndpointReference(AddressingConstants.WSA_TO,
"HTTP://...));
call.setTransportInfo(Constants.TRANSPORT_HTTP,
Constants.TRANSPORT_HTTP, true);
OMElement result =
(OMElement) call.invokeBlocking(
operationName.getLocalPart(), payload);
This uses a "In-Out, asynchronous HTTP as one-way transport" type of invocation under the curtain, but the invocation blocks until the result arrives in the second connection, and execution returns with the result.
In summary, the behavior of web service messaging is based on three parameters: the message exchange pattern, the synchronous/asynchronous behavior of the client, and the behavior of the transport. Axis2 is built on a core that is not bound to any type of MEP, yet provides client API support for the most widely used MEPs: one-way and request-response. The article explains the concepts behind the Axis2 messaging support and how the client API is used.
Srinath Perera is a principal architect for Apache Axis2.
Ajith Ranabahu is a committer for the Apache Axis2 project and has been working on web-service-based projects for the past three years.
Return to ONJava.com.
Copyright © 2009 O'Reilly Media, Inc.