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 obtains a 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 "sender" and "receiver" instead of "client" and "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 API provided by JAXM resides in the javax.xml.messaging package. In order to compile a JAXM client, you need to have the JAR files jaxm-api.jar and jaxm-runtime.jar on your CLASSPATH , together with 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.