8.4. Web Service Communication Patterns

Up to now we have concentrated on Web service interactions between two entities. Let's take a look at the bigger picture and see how Web service interactions operate within a larger business collaboration. Often Web service interactions are part of larger business collaborations that may involve multiple synchronous and asynchronous Web service interactions. Although Web service interactions within a single business collaboration may be related, current Web service technologies treat these interactions as stateless. As a result, a developer needs a way to associate messages that are part of a single business collaboration. This issue is made more difficult because collaboration sometimes requires that messages be split into multiple sub-messages, where each sub-message is processed by a different entity or partner. Not only does the developer need to relate these sub-messages to the original message, but the developer may also need to join together replies to the sub-messages.

As part of good Web service endpoint design, you need to consider the interactions in which the service is involved. Client-to-service endpoint communication is one such interaction. You may have other, more complex interaction patterns even involving multiple participants. For example, a particular request may take several Web service interactions to complete. This often happens when there are multiple steps in a workflow. Since different services process parts of a request, you need to correlate these interactions and identify individual requests that together make up a larger job.

The following sections present some strategies for handling these Web service communication problems. You can use these strategies separately or in combination, depending on an individual scenario.

8.4.1. Correlating Messages

Sometimes a business collaboration requires multiple Web service calls. In these cases, the developer needs a way to indicate that the messages passed in these Web service calls are related. A developer should use a correlation identifier to keep together messages for related Web service calls.

A correlation identifier is useful for Web services with interactions that are more complex than can be handled by a simple reply. When a Web service must invoke multiple processing steps to handle the request, the service often needs some means to identify the request at a later time. Correlation identifiers provide just such an identity for a request.

For example, a correlation identifier might be useful in these scenarios:

  • A client submits an order and later wants to track the order status.

  • A request is broken up into multiple subtasks that are asynchronously processed. The request manager aggregates subtasks as they complete, finally marking the entire job complete. Often, many jobs run at the same time, requiring the manager to correlate each job's multiple subtasks. Adventure builder's order processing module illustrates this scenario.

  • A Web service interaction may require a higher level of service in terms of handling errors and recovery. If an error occurs, the service may have to track the state of the request.

  • A client needs to make several request and reply interactions as part of a conversation, and it needs to identify those calls belonging to the conversation.

  • A client may make duplicate submissions of a message, and the service needs to eliminate these duplications.

The correlation identifier must be unique in the participating systems. In addition, you must decide whether the client or the service generates the identifier, and where to generate it. For example, the calling client may generate an identifier, including it with calls to a service. Or, the service may generate the identifier and assign it to the incoming call, and perhaps return the identifier with the response.

The server can also embed useful information into an identifier that it generates, making processing easier. For example, a client often needs confirmation indicating that the server has received the client's message. An identifier generated at the server side can serve as a confirmation identifier. Server-side identifier generation also allows better control by providers, since they can employ their own policies.

The customer Web site collects information from a Web user and puts that information together into an order. The Web site then places the order into adventure builder's system via a Web service call to the order receiver module, passing the order information as a message. The order information includes the client-generated correlation identifier. The order receiver module receives the order message and uses the correlation identifier to eliminate duplicate order submissions.

A correlation identifier is a form of context information that needs to be communicated from the client to the server. For strategies on how to pass the correlation identifier from client to server, see “Passing Context Information on Web Service Calls” on page 366.

Use correlation identifiers for associating groups of related messages.

8.4.2. Splitting and Joining Messages

Often, a service receives a request, which it fulfills as a series of subtasks run in parallel. When all tasks complete, the service gathers the results and checks if the criteria for completion is met. A service can split a message into subtasks, often including a correlation identifier with the individual pieces so that they can be rejoined successfully when they have all completed. Such identifiers may be needed since often subtasks complete out of sequence. A service can also independently use split and join operations.

For example, the order processing center receives a single purchase order from a customer. Figure 8.3 on page 345 shows the workflow for handling a message. The order processing center splits that order into a set of sub-orders: an order for an airline reservation, an order for a hotel room, and orders for all activities. It then sends each sub-order to the suppliers, and they process their tasks, invoicing the order processing center when completed. The order processing center aggregates these supplier invoices to fulfill the order.

How do you implement this split and join pattern? For guidelines on splitting an incoming document, see “Fragmenting Incoming XML Documents” on page 153. The order processing center splits a purchase order document into multiple XML documents by extracting the relevant information for each supplier, then sending that relevant information as a sub-order to the suppliers. It includes a correlation identifier with the sub-order to correlate all submessages generated from a single message.

For the join operation, the order processing center waits for all suppliers to fulfill the sub-orders, then it does some further processing to complete the order. Notification from suppliers may arrive in an arbitrary, nonsequential, order. The order processing center implements the join operation using message-driven beans. When it processes a sub-order, a supplier sends an invoice message to the order processing center through a Web service call. On receiving the invoice message, the order processing center workflow manager checks whether the join condition is met and updates its state accordingly. When all invoices are received, the workflow manager changes the order status to “COMPLETED” and directs the CRM system to notify the user.

Figure 8.6 shows split and join operations on an adventure builder customer purchase order. The customer orders an adventure package, plus hotel and airline reservations. All this information is contained with the purchase order. The order processing center logic splits the purchase order into sub-orders, and sends each sub-order to the appropriate supplier for processing. For example, the order processing center sends the activity sub-order to an activity supplier and the airline sub-order to the airline reservation processing. Each supplier, when it completes a sub-order, submits an invoice for its work. The order processing center receives the separate invoices at varying times. It checks to see if the join condition is met and updates the order status accordingly.

When splitting messages, it is good to use correlation identifiers to later associate the responses during the join.

Figure 8.6. Split and Join Operations


8.4.3. Refactoring Synchronous to Asynchronous Interactions

Sometimes your application requires an asynchronous Web service interaction. Web services that use asynchronous interactions tend to be more responsive and scale better. However, Web services provide only a synchronous mode of operation, especially when using the HTTP protocol. In your application you can convert this synchronous interaction to an asynchronous request and reply. You may be able to refactor some of the synchronous interactions of a Web service application to asynchronous interactions.

Figure 8.7 illustrates a synchronous interaction. Notice how the client must suspend its processing until the service completes processing of the request and returns a response.

Figure 8.7. Synchronous Communication


On the other hand, with the asynchronous interaction shown in Figure 8.8, the client continues its processing without waiting for the service. In both the synchronous and asynchronous communication figures, the vertical lines represent the passage of time, from top to bottom. The vertical rectangular boxes indicate when the entity (client or service) is busy processing the request or waiting for the other entity to complete processing. In Figure 8.8, the half-arrow indicates asynchronous communication and the dashed vertical line indicates that the entity is free to work on other things while a request is being processed.

Figure 8.8. Asynchronous Communication


When a component makes a synchronous call to another component, the calling component must wait for the receiving component to finish its processing. If the calling component instead makes the call asynchronously, the caller can proceed with its own work without waiting for the receiving component to do its job.

Let's look at what needs to be done to convert a synchronous endpoint to an asynchronous endpoint.

  • Change a synchronous request/reply interaction into a request that returns void as the immediate reply.

  • Change the client code to send the message request and immediately return.

  • Have the client establish a reply address for receiving the response and include this reply address in the request. By including a reply address, the service knows where to send the response message.

  • A correlation identifier needs to be established between the request message and the service response message. Both the client and the service use this identifier to associate the request and the reply.

  • Refactor the server endpoint to accept the request, send it to a JMS queue for processing later, and immediately return an acknowledgement to the client. The service retains the correlation identifier.

  • Have the service processing layer use a message-driven bean to process the received request. When a response is ready, the service sends the response to the reply address. In addition to the results, the response message contains the same correlation identifier so that the service requestor can identify the request to which this response relates.

  • Have the client accept the response at a Web service that it establishes at the reply address.

The JMS queue stores the messages until the message-driven beans are ready to process them, thereby controlling the rate of delivery. Thus, the component can process the messages without being overwhelmed, which helps the service to scale better. Figure 8.9 illustrates the process of converting an endpoint from synchronous to asynchronous communication.

Figure 8.9. Converting from Synchronous to Asynchronous Communication


Optionally, the client can further increase its responsiveness by employing some asynchronicity when making the Web service call itself. For example, a stand-alone client that uses a Swing GUI might spawn a thread to make the Web service call, allowing the client to continue its user interactions while the Web service handles the call. Or, a J2EE client component might use a JMS queue to make Web service calls—that is, rather than making the JAX-RPC call directly, the client places the request into a JMS queue and a message-driven bean makes the Web service call to deliver the request.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset