The asynchronous messaging and reliable delivery features of JAXM are implemented by a messaging provider. The specification itself says very little about the provider, other than to describe the API needed to access it, leaving the details to be determined by implementations. In practice, application code is almost unaffected by the presence of a provider, but it is very important to understand how to configure the provider and how to deploy the application with the appropriate settings required to access it. In this section, we look at the API that application code uses to work with the provider, and at how to configure the provider included with the JAXM reference implementation.
When a message provider is in use, the logical flow of a message is still directly from the sender to the receiver, but the actual flow is somewhat different, as shown in Figure 4-4.
In order to send messages, the
sender first connects to the local provider and determines whether it
supports the messaging profile that it wants to use; if so, it
MessageFactory for that profile. Each
message is then handled as follows:
The sender creates a SOAP message using the SAAJ API with the
MessageFactory for the selected messaging profile.
The message is sent to the local provider. This operation returns control to the caller as soon as the provider receives the message, and the sender is free to continue with other processing.
The provider stores the message in its outgoing queue.
A separate thread handles queued messages, dispatching each of them in turn to the receiving provider. If the receiving provider is not accessible, the message is left in the queue and retried later.
The remote provider (eventually) receives the message and stores it in its dispatching queue.
If the message receiver is active, the message is delivered to it. Otherwise, it is held in the dispatching queue until it can be delivered, or until the retry count has expired.
The receiver processes the message.
It is important to note that the message flow is entirely asynchronous to the sender: once the message is delivered to the local provider, its eventual transmission is scheduled separately (and, in the reference implementation, in a separate thread). Similarly, when the message is received by the remote provider, it is simply written to a queue and dispatched at a later time to the intended recipient. The asynchronous nature of the message flow and the fact that it involves intermediaries is in sharp contrast to the direct connection used by SAAJ applications. The message flow is strictly unidirectional: there is no provision (and no possibility) for a reply message, and therefore this flow models the fire-and-forget message mode described earlier in this chapter. If the application-level protocol requires a reply or an acknowledgement, then a separate (asynchronous) message is sent by the receiver to the original sender, using the reverse message path to that shown in Figure 4-4.
You will notice that the diagrams in this chapter use the terms
“receiver” instead of
“service,” since we are focusing on
the messaging aspects rather than on the roles of the sender and
receiver in the web service. It is important to keep these separate.
Although the client is the sender and the service is the receiver
when the service is first invoked, the roles are reversed when the
service eventually sends a reply to the client. Unlike the
synchronous programming model used by SAAJ, in which the service
receives a message in its
onMessage( ) method and
simply returns a
SOAPMessage to be sent back to
the client (almost as a side effect), the service has to explicitly
send the reply via its local messaging provider. In this chapter, we
will use the term “JAXM client” to
refer to either the sender or the receiver, since we consider both to
be clients of the messaging provider.
The arrangement shown in Figure 4-4 is fine when both the sender and the receiver are implemented using JAXM, but this is not the most general case. In the real world, one party may not be associated with a messaging provider, an obvious example of which is a JAXM client accessing a web service running on the Microsoft .NET platform or vice versa. As far as the client or service implementation is concerned, this makes no difference — only the configuration details need to change, as we’ll see later in this chapter. The only configuration that does not work is an asynchronous JAXM client connecting to a web service that expects to reply synchronously using the same underlying transport connection as the one on which it received the request. For an explanation of why this does not work, see Section 4.3.3, later in this chapter.
In Chapter 3, you saw an example SAAJ application in which the service was implemented as a servlet in the Tomcat web container and the client was a freestanding Java application. Both JAX-RPC and SAAJ allow the client either to be an application or to reside in a container. However, all JAXM applications (including the part you would naturally think of as the “client”) must be hosted in a web container or an EJB container. At the time of this writing, the JAXM reference implementation supports only deployment of JAXM applications as servlets within a web container, so the examples used in this chapter are all hosted by servlets. In the future, it is expected that JAXM will also be supported by EJB containers in the form of Message Driven Beans.
The JAXM 1.1 specification uses the term “JAXM client” to refer either to a client that uses a messaging provider or to one that makes a direct connection to a web service; therefore, it sometimes talks about “freestanding JAXM clients.” In this book, we make a sharp distinction between the following two cases:
A client that connects directly
to a service without using a messaging provider is considered to be a
SAAJ client. Such a client needs only to use the API provided by the
javax.xml.soap package, and can only use a
synchronous request/response model. SAAJ clients can be freestanding
J2SE applications, or they may reside in a container.
that uses a messaging provider is a JAXM client. These clients use
javax.xml.soap package to construct their
messages, and use the
to interact with the provider. Only JAXM clients can use the
asynchronous messaging features of the provider, and they must be
hosted by a web container (or an EJB container in the future).
The API provided by JAXM
resides in the
package. In order to compile a JAXM
client, you need to have the JAR files
saaj-api.jar for access to the
javax.xml.soap package. At runtime, you
additionally need access to all of the JAR files listed in Table 3-1. Inclusion of these JAR files is usually
automatic, however, since the client is actually deployed in a web
container in which JAXM and SAAJ should already have been installed.
The messaging provider that is provided with the JAXM reference implementation is implemented as a servlet that resides at the URL http://localhost:8081/jaxm-provider in the default deployment. There is also a web application at the URL http://localhost:8081/jaxm-provideradmin that can be used to configure the provider. Further information on the provider and its configuration are found later in this chapter.