Chapter Five. Messaging Infrastructure

Introduction

This chapter deals specifically with Java CAPS messaging infrastructure in order to provide the background necessary to understand how [EIP] patterns that employ the messaging infrastructure are implemented in this chapter and elsewhere in the book.

This chapter discusses Java CAPS JMS infrastructure implementation specifics that have significant bearing on implementation of other patterns:

  • Java Messaging Service

  • JMS Implementation Interoperability

  • Using JMS to Integrate Non-JMS Environment

  • JMS Queues and Topics

  • Temporary JMS Destinations

  • Security

  • Transactionality

  • Concurrency

  • Persistence

  • Selectors

  • FIFO Modes

  • Throttling

  • Redelivery Handling

  • Message Journaling

  • JMS Grid High-Availability JMS Implementation

This chapter then discusses specific [EIP] patterns that use the JMS or other Java CAPS infrastructure in their implementation:

  • Competing Consumers

  • Point-to-Point Channel

  • Publish-Subscribe Channel

  • Datatype Channel

  • Invalid Message Channel

  • Dead Letter Channel

  • Guaranteed Delivery

  • Channel Adapter

  • Messaging Bridge

  • Message Bus

Some of the patterns under discussion are presented in [EIP] in Messaging Channels, some in Message Construction, some in Messaging Endpoints.

Java Message Service (JMS)

The Sun JMS Specification defines a set of interfaces intended to unify client access to common services implemented in messaging infrastructures from disparate Message-Oriented Middleware (MOM) vendors [JMSSpec]. As a consequence, implementations from different vendors vary in their features and capabilities in the areas that the JMS Specification does not cover or explicitly leaves open to interpretation by implementers. In particular, JMS Specification does not address load-balancing and fault-tolerance functionality, asynchronous notification, administration, security, wire protocols, message type definitions, or message repository. Such nonstandard functionality is either provided by the implementation (e.g., administration), is built as part of an integration solution (e.g., load balancing, fault tolerance, security), or must be built into the integration solution explicitly.

JMS is an integral part of the Java CAPS. Sun SeeBeyond JMS implementation is the default mechanism through which messages are passed from component to component in a Java CAPS solution through release 5.1.3.

The various facilities of the JMS implementation are used to implement a number of patterns ranging from Content Router to Envelope Wrapper. Specific facilities used in these patterns are described in detail in the appropriate places.

Java CAPS 5.1.3 supports three JMS implementations from Sun as well as JMS implementations from other vendors, such as WebSphere MQ from IBM. The book discusses in detail the Sun SeeBeyond IQ Manager, the default Java CAPS JMS Message Server implementation, and briefly the Sun JMS Grid, the highly available JMS Message Server implementation that can be used to implement JMS clusters and other fault-tolerant solutions.

JMS Implementation Interoperability

The JMS Specification explicitly does not address physical implementation issues such as wire protocols or security. The most significant implication of this is that JMS implementations from different vendors are not interoperable. A solution that must use multiple JMS messaging implementations must provide one or more Messaging Bridges [EIP] to facilitate connecting the disparate messaging infrastructures.

Sun SeeBeyond JMS Message Server monitoring, message submission, message modification, message replay, and similar functionality are supported through the Enterprise Manager Web-based User Interface. Other JMS implementations may or may not have similar facilities. The administration and monitoring support for these other implementations may or may not be integrated with the Java CAPS environment, so the solution architecture should strive to minimize interactions with facilities outside the unified management domain to reduce complexity of operations support and runtime monitoring.

Using JMS to Integrate Non-Java Environments

Java CAPS is a J2EE-compliant environment. In general, to allow non-Java solutions, such as those based on .NET technologies or that use C or C++ language environments, to communicate with the Java CAPS–based integration solution, you would look at a higher-level Messaging Bridge that would transcend these low-level issues. You could, for example, use TCP-based Messaging Endpoints or use file system–based message exchange. The upside of this is the loose coupling. The downside is the increased overhead.

To allow non-Java CAPS–based solutions to readily exchange messages with the Java CAPS–based solutions, the Sun SeeBeyond JMS Message Server implementation provides a set of JMS application programming interfaces (APIs) and corresponding libraries for Java [JMSAPIJ], C/C++ [JMSAPIC], and COM+ [JMSAPICOM]. One or more of these API mechanisms can be used to allow an application to exchange messages with another application, whether Java CAPS–based or not, using the Sun SeeBeyond JMS Message Server. The APIs can also be used as the basis for higher-order wrapper APIs. For example, a C#-based simplified API, using the C/C++ API as the basis, has been developed and used in the field.

Queues versus Topics

JMS provides two kinds of managed objects: Connection Factories and Destinations. In a Java CAPS environment, Connection Factories, used to establish connections to JMS providers, are handled implicitly via deployment profiles and JMS Message Server containers. JMS objects that the developer deals with explicitly are JMS Destinations: queues and topics. A developer would use JMS queues to implement the point-to-point messaging style and JMS topics to implement the publish-subscribe messaging style. The distinction is not visible to a Java CAPS developer until a connectivity map needs to be constructed. At this point, the developer decides what kind of destination will be used and therefore what kind of messaging style will be implemented for the specific subset of integration solution to which the connectivity map applies. The developer is free to use both queues and topics in the same connectivity map to implement messaging that best addresses the business requirements of the solution.

A JMS queue is a Messaging Endpoint where only one receiver retrieves a particular message. If there is no current receiver, messages are retained in the queue until there is a receiver and messages are delivered, or until messages expire if finite message expiration is configured. Multiple receivers will compete for messages. A message delivered to one receiver will not be available to any other receiver.

A JMS topic is a Messaging Endpoint where all concurrent subscribers receive a copy of each message published to it. Effectively, each message is replicated as many times as there are active subscribers. In addition, if there are no active subscribers, and there are no durable subscriptions, messages will be discarded by the JMS Message Server. This behavior will change if there is a durable subscription. In this case, the JMS Message Server will keep messages until the there is a current subscription for that durable subscriber, in which case messages that were retained in the topic will be delivered to that subscriber.

The “if there are no current subscribers, and there are no durable subscriptions, messages will be discarded by the JMS Message Server” behavior can be put to good use. For example, a permanent Wire Tap [EIP] can be introduced such that as a message is processed by a component, a copy of it is published to the Wire Tap Topic. With no subscribers and no durable subscribers to the topic, the message will be discarded—a Dripping Wire Tap, if you like. At a later time, a component that processes messages from the Wire Tap could be implemented. This component only needs to subscribe to the Wire Tap Topic to start receiving messages that are published after that time. No changes to the publishing component are required.

If there is only one subscriber to a topic, messaging behavior is similar to that when there is only a single receiver from a queue. Rather than using a topic for the purpose of implementing a Dripping Wire Tap, you could send messages to a queue with a very short message lifetime and no receivers. The JMS Message Server would discard messages after they expired anyway. The net effect would be the same, but the resource consumption would not. After all, the Message Server would have to keep track of message expiration, however short, consuming resources to do so. With significant traffic, considerable resources could be wasted this way.

Sun SeeBeyond IQ Manager

JMS Destination Creation and Destruction

Unlike some other JMS implementations with which you might be familiar, where JMS Destinations have to be explicitly created and destroyed using some implementation-specific administration tools, the Sun SeeBeyond JMS Message Server, also known as the Sun SeeBeyond IQ Manager, does not require explicit creation or destruction of JMS Destinations. A JMS Destination is created automatically as soon as the first message intended for that destination is handed over to the JMS Message Server, or as soon as there is a subscriber to a topic or a receiver from a queue. JMS Destinations persist as long as the JMS Message Server is running or until explicitly deleted.

Note

Note

If a JMS queue has no receivers, or a JMS topic has no subscribers, in any solution deployed to a logical host, the JMS Destination will not exist until there is a message to be delivered to it. This behavior is a consequence of automatic creation of JMS Destinations, but it may cause you some trepidation if you are checking to make sure all JMS Destinations exist when you start the solution.

Note

Note

As a consequence of automatic creation and destruction of JMS topics, you may forget that a topic, with at least one durable subscriber registered, will be created each time the JMS Message Server starts, regardless of whether the subscriber ever actually subscribes. The durable subscription may have been registered during development iteration and, as a result of design change, may no longer be required. You must explicitly delete the JMS topic to remove the durable subscription.

Note

Note

There is no visual indication in the connectivity map to advise whether the topic subscription is or is not durable.

Temporary JMS Destinations

Temporary JMS Destinations are created by a component and exist only so long as the component that created them exists. In ordinary circumstances, and I cannot think of other circumstances where this would not be the case, there is no good reason and no good way to explicitly create and use a temporary JMS Destination in a Java Collaboration within a Java CAPS solution. There is no way to create one in an eInsight Business Process at all, except by wrapping that kind of functionality in a Java Collaboration. For the purpose of JMS Request/Reply, the requestReply() method of the JMS Object Type Definition (OTD) will transparently create and use a temporary JMS Destination. Because a JMS requestReply() method implicitly creates a temporary destination, each time it is executed a new temporary destination will be created. Furthermore, both the publisher/sender and the subscriber/receiver must be deployed to the same Integration Server for the requestReply() method to work.

If it is absolutely necessary to create a temporary JMS Destination, it is possible to do so by obtaining a QueueConnectionFactory or a TopicConnectionFactory using the technique addressed in section 5.6.7.2, which discusses the means of implementing a dynamic selector in a Java Collaboration and using the JMS API calls to create and use all necessary objects.

Chapter 3, section 3.2.1 “Temporary JMS Destinations,” in Part II (located on the accompanying CD-ROM), implements and discusses in detail a solution that uses an explicitly created JMS temporary queue.

Note

Note

The solution discussed in the example is built to make a point that temporary JMS Destinations can be created and used in Java CAPS. It is not a solution that makes sense or that addresses requirements that cannot be addressed more simply and elegantly without going to the trouble of using low-level JMS APIs.

Security

The Sun SeeBeyond JMS Message Server can, optionally, ensure confidentiality of messages in transit and require client authentication. Since the JMS Specification explicitly does not address these issues, the functionality is implementation-specific and therefore nonportable. See [JMSREF] for specific details.

Note

Note

The Sun SeeBeyond Integration Server uses global properties to reference keystores and truststores. See Chapter 14, “Security Features,” section 14.4.3.1, for more detail on where and how to change default truststore and keystore. As a consequence, both JMS and HTTP over SSL must use the same keystore and truststore. Bear this in mind when configuring channel security for either component.

Transactionality

By Sebastian Krueger

A transaction is a unit of work, a sequence of operations that succeed or fail as a single unit. Transactions are essential to the successful and robust working of any enterprise application.

The behavior of any JMS server is such that when a message gets delivered to a JMS Destination and the acknowledgment is received by the message sender, the message can immediately be forwarded to the message consumer.

JMS transactions provide the capability to guarantee that all messages in a group of messages will get to the Message Server, or none of them will. Thus, messages delivered to the Message Server within a single transaction are not forwarded to the consumer until the producer has confirmed that the last message has been successfully sent (called a commit).

The scope of a JMS transaction can include any arbitrary number of messages.

Each transaction covers either the producer’s session or the consumer’s session, but not both. Thus, it is possible for transacted consumers/producers to interact with nontransacted producers/consumers.

Any messages that are not committed in a transaction will not be acknowledged and will be redelivered at a later point in time.

In distributed systems, a two-phased commit protocol allows multiple distributed resources to participate in a single transaction.

For example, we may want to produce messages to the Sun SeeBeyond IQ Manager, as well as update an Oracle database in a single global transaction. If the database update fails, we want to ensure that the JMS message is not sent as well. Thus, all tasks in the global transaction must either succeed together or fail together.

A resource (such as an Oracle database) can only take part in a global transaction if it supports the two-phased commit protocol. This protocol is usually implemented using the XA interface, which was developed by the Open Group and is the most popular standard for distributed transactions.

In Java CAPS each Java Collaboration is implemented as an Enterprise Java Bean (EJB) that employs container-managed transactions. This means that the EJB container that is part of the Sun SeeBeyond LogicalHost will handle transactions, which frees the developer (i.e., you) from having to deal with them.

Each time a message is sent, it is a separate transaction. By default, XA is selected in the connectivity map, as shown in Figure 5-1. Thus, each send operation participates in the overall container transaction to form one global transaction.

Default Transactionality setting

Figure 5-1. Default Transactionality setting

Note

Note

The illustrations that follow make use of the Thread.sleep() construct. This construct, when used in a Java code running inside a J2EE container, violates the J2EE rules and should not be used. It is used here to “slow down” the collaboration to allow a human to inspect the related queue through the Enterprise Manager.

Rules are rules. It is okay to break the rules if the rule breaker is aware of and prepared to accept the consequences.

Thus, a transaction starts when the Java Collaboration Definition (JCD) is called and finishes when the JCD returns.

To demonstrate, consider the far-too-trivial example of having messages being sent out to a JMS destination by generating messages in a for-loop in the following manner in a single JCD. Figure 5-2 illustrates the points at which the XA transaction begins and ends.

Transaction boundary in a collaboration

Figure 5-2. Transaction boundary in a collaboration

The expected behavior is that as messages are added to the queue, they are not committed until the JCD successfully completes.

We can watch this behavior by listing the contents of the queue from the Enterprise Manager. Figure 5-3 points out the Available Count metric, which indicates the number of JMS messages available to all receivers. Hit refresh every 10 seconds or so. You will not see any messages in the queue even though the server.log clearly shows that messages are being successfully sent out.

Confirming transactional behavior of a JCD using the Enterprise Manager

Figure 5-3. Confirming transactional behavior of a JCD using the Enterprise Manager

And yet, messages are definitely sent to the queue. Figure 5-4 shows debugging messages logged by the executing collaboration each time through the send loop!

Collaboration execution trace

Figure 5-4. Collaboration execution trace

Once all messages have been sent to the queue, you can refresh the view into the queue, and you will see that 60 messages have been sent to the queue. Figure 5-5 points out the Available Count metric, now indicating that 60 messages have been received by the JMS Message Server and are available to potential receivers.

Committed JMS messages viewed through the Enterprise Manager

Figure 5-5. Committed JMS messages viewed through the Enterprise Manager

If at any time during the sending of all those messages the server fails, the entire batch of 60 messages would be rolled back.

Now let’s consider the Transacted setting shown in Figure 5-6.

Transacted setting

Figure 5-6. Transacted setting

Rebuild and redeploy the same project with the new setting selected in the connectivity map.

We can now watch every message arrive on the queue individually. That is, each message is committed as soon as the JCD receives an acknowledgment that it has arrived. Figure 5-7 indicates the commit point at which individual JMS messages are committed and are available to the potential receivers.

Transacted mode behavior

Figure 5-7. Transacted mode behavior

Note

Note

In releases prior to 5.1, the default configuration for JMS Publisher’s Transactionality property was Transacted. Each message was acknowledged as soon as it was received by the JMS Message Server. As of version 5.1.0, this default changed to XA. The behavior difference should be considered by developers used to the previous behavior or developers importing projects from release 5.0.

In an eInsight Business Process, this transaction behavior is the default. Unless we enforce XA over the entire Business Process, messages are immediately committed as they are acknowledged. For a detailed discussion of this topic, see Chapter 4, “Message Exchange Patterns,” section 4.8.3, and in this chapter, section 5.14.5.1.

Concurrency

By Saurabh Sahai

Often the demands for performance and throughput require the ability to perform concurrent processing of incoming messages making optimum use of available resources. By default, when using the Sun SeeBeyond JMS server, messages in Java CAPS are delivered serially to the message consumers such as Java Collaborations or eInsight Business Processes. To enable concurrent processing of available messages, the default message delivery mode can be changed from Serial to Connection Consumer Mode. When using the Connection Consumer Mode, the Server Session Pool property should be set to a value equal to the maximum concurrent threads desired for concurrent processing of messages from the specified JMS Destination.

Note

Note

The value specified for the Server Session Pool property must be less than or equal to the Message-Driven Bean (MDB) pool size configured for the integration server. The MDB pool size for each integration server is configured via the Enterprise Manager. Please refer to the eGate Integrator System Administration Guide for details regarding the setting of the MDB pool size.

Refer to Chapter 4, sections 4.8.1 and 4.8.2, for details on how to set up the concurrent consumer processing using the Sun SeeBeyond JMS Message Server. Section 5.8 also discusses an example of using eInsight processes to achieve concurrent message processing. The Sun SeeBeyond JMS server provides the ability to configure the order in which messages are processed by customizing the FIFO processing behavior for selected destinations. Using Connection Consumer Mode has implications for the order in which messages are processed.

Persistence

By Saurabh Sahai

The JMS Message Server is responsible for delivery of messages to registered consumers. Once the JMS Message Server receives the message from a producer, it keeps the message until it is successfully delivered to all consumers. The messages can be stored either in memory or in a persistent store. In the event of the Message Server crashing, all messages stored in memory by the Message Server will be lost forever and will not be delivered to the subscribers. Any messages that were stored in a persistent store, and not delivered to all registered consumers, will be available for delivery once the Message Server is up and running again.

For messages that need once and once only guaranteed delivery, as per the JMS Specifications, the Sun SeeBeyond JMS Server provides the facility to specify either the Persistent (which is the default) or Nonpersistent delivery mode to be used when sending messages. Using nonpersistent delivery mode has better performance characteristics and is suitable for cases where potential loss of messages is acceptable.

Note

Note

It is important to keep in perspective the difference between the JMS delivery mode and subscription durability in the case of JMS topics. In case of a failure, a topic consumer that has been marked as being durable may still lose messages that were sent with a delivery mode of Nonpersistent. A durable consumer is only guaranteed to receive messages that are available in the Message Server for that particular consumer. If the Message Server crashes, all nonpersistent messages will be lost irrespective of whether the consumer is using durable subscription.

Configuring the desired delivery mode is done via the connectivity map in the Enterprise Designer. To bring up the dialog box containing the configurable JMS parameters, click on the property icon available on the center of the link connecting to the JMS Destination and select the desired delivery mode. Figure 5-8 illustrates the two possible delivery mode settings.

Setting Persistent and Nonpersistent modes

Figure 5-8. Setting Persistent and Nonpersistent modes

As with updating other connector properties, the project will need to be rebuilt and the resulting EAR file redeployed subsequent to any change in the properties.

The Sun SeeBeyond JMS Message Server stores persistent messages in disk files. Additional measures, such as the use of redundant disk configurations, should be taken in a production environment to ensure integrity and availability of disks used for the message store.

Section 5.14 further discusses topics related to guaranteed delivery for solutions using the Sun SeeBeyond JMS Message Server.

Selectors

JMS message selectors are a special case of a general Message Filter pattern [EIP] required to be provided by JMS implementations. The Java CAPS JMS Message Server supports static JMS selectors configured through the JMS Receiver/Subscriber properties. A programmatic method of implementing dynamic selectors using a JCD also exists for cases where static selectors are not appropriate or where only dynamically configurable selectors will do. The following sections discuss examples of implementations of both types of selectors.

To recapitulate, the JMS Specification [JMSSpec], section 3.8.1, states that a message selector is a string that uses a subset of SQL92 conditional expression syntax to specify an expression that will be evaluated at runtime using JMS message header fields. A message selector cannot reference JMS message body values. Message header field references are restricted to the following fields: JMSDeliveryMode, JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and JMSType. In addition to these predefined fields, selectors can also use arbitrary user properties. See [JMSSpec] for additional information concerning the structure and use of JMS selectors.

Static Selector

Java CAPS does not provide a nonprogrammatic way of setting JMS properties, whether JMS defined or user defined. Sun SeeBeyond JMS IQ Manager implementation can only use JMS header properties as part of a selector expression, as defined in the JMS Specification. In addition to JMS header properties, Sun JMS Grid implementation can also use XPATH expressions to select messages based on the content of message body, as long as the message body is XML. This facility is specific to JMS Grid and is not portable. According to the JMS Specification, JMS selectors can be arbitrarily complex SQL92 expressions. Multiple JMS header and user-defined properties can be used. In ordinary circumstances, JMS selector expressions are specified in Java CAPS at design time and cannot be changed without rebuilding and redeploying the project that uses them. Static selectors are configured through the JMS Receiver and Subscriber connector properties in the connectivity map. Figure 5-9 shows a Message selector property whose value is a static selector expression.

__Book/MessagingInfrastructure/Selectors/StaticSelector/cm_StaticSelector

Figure 5-9. __Book/MessagingInfrastructure/Selectors/StaticSelector/cm_StaticSelector

Here the selector expression is:

JMSCorrelationID = '12345' OR JMSCorrelationID = '12346'

Only messages whose Correlation ID contains one of the two values will get delivered to the service svc_jcdLogMessage. All other messages will remain in the queue until they expire or until some other, less discriminating component picks them up. You must be careful to use single quotation marks around literal values because double quotation marks have a special function in SQL92.

This topic is illustrated with an example in Chapter 3, section 3.2.1.1, “Static Selector,” in Part II.

The presence of a static selector expression causes the JMS Message Server to deliver only selected messages to the collaboration downstream from the JMS Destination with the selector expression on the receiver/subscriber side.

Using static selectors, you can implement a Static Router pattern. For example, you can construct a connectivity map similar to that in Figure 5-10 to statically route messages to different services.

__Book/MessagingInfrastructure/Selectors/StaticSelector/cm_StaticRouter

Figure 5-10. __Book/MessagingInfrastructure/Selectors/StaticSelector/cm_StaticRouter

Here messages with different values are routed to different collaborations.

There are a couple of obvious drawbacks to implementing a static router this way, one of which is common to implementing a static router in general.

First, modifying a hardcoded static router, whether hardcoding is done within a component such as a Java Collaboration or a Business Process or is done within a connectivity map, requires that the component is modified and the deployment profile–bound application is redeployed. If the static routes are not-so-static, then this can become a major maintenance issue.

Second, and specifically applicable to the JMS selector–based static router, there is no way to specify a “catch-all” selector except by inversing the conjunction of all other defined selectors. As soon as one selector needs to be added or modified, the catch-all selector would need to be modified as well. Since multiple recipients from a single JMS queue are Competing Consumers, there is no way to predetermine which will receive a particular message. Selector expressions must be carefully constructed to ensure that no overlaps occur, otherwise unpredictable routing behavior will result.

Dynamic Selector

Building a dynamic selector requires a bit more work, but once the method is established, it can be applied as needed. Neither the JMS object, which is obtained by selecting the JMS OTD as one of the manipulation/output OTDs, nor the JMS input object, which is in fact a JMS Message object, provide access to the JMS Session object necessary to configure a selector, nor do they provide a way to find out what the selector expression is or to set one for the session. Since a JMS Session object is necessary, we will use the Java Naming and Directory Interface (JNDI) to first look up the JMS ConnectionFactory object and then the JMS Destination from which to receive messages using the dynamically constructed selector.

There is a fair bit of code involved in getting the infrastructure set up for a selective receiver with a dynamically constructed selector. The Java Collaboration shown in Listings 5-1 through 5-6 is broken into six parts to facilitate discussion.

The Collaboration uses classes from JMS and JNDI packages, so it needs to import them immediately following the package line, as in any other Java class, as shown in Listing 5-1. This code will be the same regardless of the specific selector expression used later.

Example 5-1. Book/MessagingInfrastructure/Selectors/DynamicSelector/jcdDynamicSelector

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueConnection;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.Queue;
import javax.jms.QueueReceiver;

A number of static, final class fields, constants if you like, are used, as shown in Listing 5-2.

Example 5-2. Book/MessagingInfrastructure/Selectors/DynamicSelector/jcdDynamicSelector

static final long lTimeout = 5 * 1000;
static final String cJMS_HOST = "localhost";
static final String cJMS_PORT = "20007";
static final String cRECEIVE_FROM = "qReceiveFrom";
static final String cPROVIDER_URL
                       = "stcms://" + cJMS_HOST + ":" + cJMS_PORT;
static final String cCONNECTION_FACTORY
                       = "connectionfactories/queueconnectionfactory";
static final String cINITIAL_CONTEXT_FACTORY
                       = "com.stc.jms.jndispi.InitialContextFactory";
static final boolean cTRANSACTED = true;

Note that it is more appropriate to obtain values for lTimeout, cJMS_HOST, cJMS_PORT, and cRECEIVE_FROM fields at runtime than to hardcode them. The values are hardcoded here in order not to obfuscate the essential JNDI and JMS code with matters that are tangential.

Next we need to add code to obtain the value for the JMSCorrelationID to be used in constructing the selector expression; this is shown in Listing 5-3. In this case, the value is the entire content of the JMS message. In a more realistic implementation, it could be some part of the input message, whether acquired through JMS or using some other connector. It is likely that this code will change to accommodate specific application requirements. The application may require using other Message header fields and user-defined properties in constructing the selector expression.

Example 5-3. Book/MessagingInfrastructure/Selectors/DynamicSelector/jcdDynamicSelector

public void receive
    (com.stc.connectors.jms.Message input
    ,ud1.udtCorrelationIDInput1752469071.Udtcorrelationidinput vCorrIDIn
    ,com.stc.connectors.jms.JMS W_toJMS )
        throws Throwable
{
    // construct dynamic selector expression
    ;
    vCorrIDIn.unmarshalFromString( input.getTextMessage() );
    String sCorrelationID = vCorrIDIn.getCorrelationid();
    ;
    String sSelector = "JMSCorrelationID = '" + sCorrelationID + "'";
    ;

Next we create a timed JMS Receiver with the dynamically constructed selector expression. It is unlikely that this code will change. This is pretty much how you would address the JNDI and JMS to obtain the selective receiver required for dynamic selector use. Listing 5-4 illustrates it.

Example 5-4. Book/MessagingInfrastructure/Selectors/DynamicSelector/jcdDynamicSelector

// get a receiver for the specific Queue object
;
QueueConnection myConnection = null;
QueueSession mySession = null;
QueueReceiver myReceiver = null;
;
try {
    java.util.Hashtable env = new java.util.Hashtable();
    env.put
      ( Context.INITIAL_CONTEXT_FACTORY, cINITIAL_CONTEXT_FACTORY );
    env.put( Context.PROVIDER_URL, cPROVIDER_URL );
    InitialContext jndiContext = new InitialContext( env );
    QueueConnectionFactory QCFactory =
        (QueueConnectionFactory) jndiContext.lookup
                                     ( cCONNECTION_FACTORY );
    myConnection = QCFactory.createQueueConnection();
    Queue myQueue = (Queue) jndiContext.lookup
                                     ( "queues/" + cRECEIVE_FROM );
    mySession = myConnection.createQueueSession
            ( cTRANSACTED, Session.AUTO_ACKNOWLEDGE );
    myReceiver = mySession.createReceiver( myQueue, sSelector );
    myConnection.start();
} catch ( Exception e ) {
    e.printStackTrace();
    throw new Exception( "
===>>> Exception from jndi processing", e );
}
;

Once the selective receiver is available, we can attempt to read one or more messages from the JMS queue. This part of the collaboration will likely change as required by the implementation. In this sample, we read as many messages that satisfy the selector expression as there are and append their bodies to a string. This is not particularly realistic but is simple enough for illustration of the concepts. In the example in Listing 5-5, we send the string, assembled by reading selected messages, to a “regular” JMS Destination configured through the connectivity map.

Example 5-5. Book/MessagingInfrastructure/Selectors/DynamicSelector/jcdDynamicSelector

// prepare canned text to preprend to messages
// sent out
;
String sOutText = "";
sOutText += "Using Selector Expression [" + sSelector + "]";
sOutText += "
Received input message with Correlation ID ";
sOutText += vCorrIDIn.getCorrelationid();
;
// is there at least one message in the correlation queue?
;
javax.jms.TextMessage m = null;
m = (javax.jms.TextMessage) myReceiver.receive( lTimeout );
if (m == null) {
    sOutText = "";
    sOutText += "
No candidate messages for the selector [";
    sOutText += myReceiver.getMessageSelector();
    sOutText += "] from queue [";
    sOutText += myReceiver.getQueue().getQueueName() + "]";
    mySession.rollback();
}
;
// process all related messages in the correlation queue
;
while (m != null) {
    sOutText += "
 Message Body: [";
    sOutText += m.getText();
    sOutText += "] for Message: ";
    sOutText += m.getJMSMessageID();
    m = (javax.jms.TextMessage) myReceiver.receive( lTimeout );
}
;
com.stc.connectors.jms.Message msgOut = W_toJMS.createTextMessage();
msgOut.getMessageProperties().setCorrelationID( sCorrelationID );
msgOut.setTextMessage( sOutText );
W_toJMS.send( msgOut );

Note that in addition to setting the body of the outgoing message, we are also setting the CorrelationID JMS header property just in case the downstream component has a need or use for it.

Finally, we dismantle the selective receiver infrastructure and finish, as shown in Listing 5-6.

Example 5-6. Book/MessagingInfrastructure/Selectors/DynamicSelector/jcdDynamicSelector

mySession.commit();
mySession.close();
myConnection.stop();
myConnection.close();
;
logger.debug( "
===>>> sent message: " + sOutText );

The collaboration discussed here is triggered by a JMS message that conveys the Correlation ID to be used by the selective receiver. The JMS queue used could be the same Queue as the one in which all other messages exist or it could be a different queue. In the former case, you would expect a static selector expression to pick just the message that starts the ball rolling and to ignore messages that the collaboration is to explicitly receive. In the latter case, you would have to ensure that the JMS queue that triggers the selective receiver collaboration receives only trigger messages and no others. The sample connectivity map in Figure 5-11 uses two distinct JMS queues, one to receive trigger messages and one to receive all other messages.

Book/MessagingInfrastructure/Selectors/DynamicSelector/cm_DynamicSelector

Figure 5-11. Book/MessagingInfrastructure/Selectors/DynamicSelector/cm_DynamicSelector

While what was discussed is a practical way of implementing a selective receiver with the selector expression created dynamically at runtime, it is a fairly inefficient one as the entire process of looking up and creating appropriate JMS objects and destroying them after use is performed each time through the collaboration. A knowledgeable reader can likely improve efficiency by using statics to hold various objects and not destroying objects on exit from the collaboration.

The connectivity map may or may not imply that a selective receiver is used. This depends on the site naming conventions and the designer’s willingness to provide hints to others that there exist implicit relationships that the connectivity map does not show.

This discussion is illustrated with an example in Chapter 3, section 3.2.1.2, “Dynamic Selectors,” in Part II.

Since the JMS Message Server URL is constructed using hardcoded values, the collaboration is not portable between Message Servers. A better way would be to configure the URL using values acquired at runtime so that changes can be externalized and made without affecting the collaboration or requiring projects that use it to be rebuilt and redeployed.

This method can be used to implement eGate-only-based correlations. Indeed, this method is used in Chapter 11, “Message Correlation,” section 11.11, to re-implement one of the Message Relationship patterns implemented using eInsight.

FIFO Modes

Behavior of JMS Competing Consumers, using the Sun SeeBeyond JMS Message Server, with respect to message sequencing can be configured so that message order is strictly preserved, loosely preserved, or not preserved. These configuration settings are referred to as FIFO modes and are discussed at length in Chapter 4, section 4.8.2.

Throttling

By Saurabh Sahai

The Integration Server delivers messages to registered consumers as fast as the consumers are able to accept them. In certain situations, the number of available messages on a particular destination, or within the JMS Message Server, starts to grow faster than messages can be processed. This can occur for any number of reasons, including use of serial message processing, having a small number of concurrent consumers, consumers involving substantial processing time, or consumers having problems that are transient in nature (such as connectivity to an external system). In such cases, producers send messages to the Message Server at a faster rate than these messages can be processed.

The Sun SeeBeyond JMS Message Server provides the means to throttle message producers so that the Integration Server does not become saturated and the message consumers can catch up with the message producers. Figure 5-12 shows the Messaging Behavior Tab in the Integration Server Administration console through which these settings of the Sun SeeBeyond IQ Manager can be changed.

Throttling settings for Sun SeeBeyond IQ Manager

Figure 5-12. Throttling settings for Sun SeeBeyond IQ Manager

Within the Sun SeeBeyond JMS Message Server, throttling of a message producer is governed by the following rules:

  • The JMS Message Server throttling threshold is set in the Server Throttling Threshold property. If the sum total of available messages on all the destinations within the Message Server is below this limit, throttling is not enforced.

  • The default value for this property is 100,000 messages. A value of 0 for this threshold will result in no throttling being enforced.

  • The Per-Destination Throttling Threshold determines the threshold at which producers for a particular destination will be throttled once the Server Throttling Threshold has been reached. When the number of messages on a given producer exceeds the Per-Destination Throttling Threshold and the Server Throttling Threshold is also reached, all producers for the destination will be throttled until one or both of the following become true:

    • The number of available messages within the JMS Message Server falls below the Server Throttling Threshold.

    • The number of available messages on the destination falls to a value less than the Per-Destination Throttling Threshold’s Throttling Lag.

  • The Throttling Lag denotes the number of messages that needs to be consumed from the destination before producers for that destination will be unthrottled.

The various properties governing the throttling behavior of the Message Server are set via the Integration Server Administration Console, as illustrated in Figure 5-12. Updating any of these values will require the restart of the server before the new values take effect.

Redelivery Handling

In Java CAPS, Java Collaborations execute in a context of a container-managed transaction. If collaboration execution fails, the transaction is rolled back. If the Java Collaboration was triggered by a JMS message, failure and transaction rollback will result in the message delivery failure. When that happens, the JMS Message Server will attempt to redeliver the message. Until the message is successfully delivered, it is not considered consumed, and messages following it, if any, back up. This is a necessary behavior aimed at ensuring that messages are not lost and are delivered in order. It is possible that the failure is transient and the message can be redelivered successfully. Once this happens, subsequent messages will be able to be delivered. This is not, however, likely. Collaboration failures usually occur because of programming errors, bad messages, resource exhaustion, or some other condition that is unlikely to be automatically resolved.

In ICAN 5.0, JMS automatic redelivery behavior would result in a redelivery loop that essentially brought the Integration Server down as redeliveries and rollbacks consumed all available resources. Since there was no means of delaying redelivery or limiting the number of delivery attempts, programmatic means of varying reliability had to be used.

Java CAPS 5.1 provides the means of delaying redelivery on failure, limiting the number of redelivery attempts, and specifying redelivery failure “I am giving up” action. Section 5.13 discusses at length the means of specifying redelivery handling in Java CAPS 5.1.x. It is worth noting at this point that the redelivery behavior, which was configured globally for each JMS Message Server in Java CAPS through release 5.1.1, changed in release 5.1.2 such that it is possible to specify different redelivery behavior for each sender/publisher.

Message Journaling

The Sun SeeBeyond JMS IQ Manager supports journaling of delivered messages. Journaling is enabled globally through the Integration Server Administration console or through the Enterprise Manager “Configure Integration Server” interface, shown in Figure 5-13. Figure 5-14 shows the Enable Journal checkbox checked.

Accessing Integration Server Configuration from the Enterprise Manager

Figure 5-13. Accessing Integration Server Configuration from the Enterprise Manager

Enabling Sun SeeBeyond IQ Manager Journaling

Figure 5-14. Enabling Sun SeeBeyond IQ Manager Journaling

Since journaling is enabled globally and journaled messages, even after expiration, are not removed from the journal storage, manual procedures must be put in place to remove messages from the journal storage to prevent it from growing indefinitely.

Once enabled, the Enterprise Manager Explorer node SeeBeyond_JMS_IQ_ Manager will enable access to journaled messages. Figure 5-15 shows the toolbar button that facilitates switching between Journaled and Live views.

Accessing journaled messages

Figure 5-15. Accessing journaled messages

Perhaps unintuitively, the Journal/Live display toolbar button says “L” when the display shows journaled messages and says “J” when the display shows live messages. To avoid confusion, look at the Status column (Figure 5-16). Journaled messages will have the status of journaled.

Switching between Journaled and Live message view

Figure 5-16. Switching between Journaled and Live message view

Alt+J will switch to Journaled and Alt+L will switch to Live.

Note

Note

The only way to remove messages from the journal store is by using the stcmsctlutil command-line tool, described in [JMSREF, pp. 105].

Journaling can be used as an implementation of a Message Store [EIP], a mechanism to selectively resubmit a message that has been already processed or a mechanism to resubmit a message that expired without having been consumed by a receiver or a subscriber. Some of these topics are discussed in Chapter 4, section 4.9.

Resilient JMS with JMS Grid

By Sebastian Krueger

High availability and scalability are important capabilities in an Enterprise-class messaging solution. The JMS Message Server has been one of the areas in messaging solutions where hardware-based high-availability implementations were needed to address resilience.

The Sun Java Message Service Grid (Sun JMS Grid) implementation provides a software-based high-availability implementation based on a multidaemon clustered architecture with fault tolerance and automated cluster recovery within heterogeneous networks. JMS Grid is JMS 1.1 compliant and supports dynamic destination creation, load balancing of clients across clusters, load balancing of queue messages across daemons, JMX-based management, automatic recovery of daemons, and SSL and HTTP/HTTPS Tunneling across firewalls, to name a few features.

Unlike the Sun SeeBeyond JMS Message Server, Sun JMS Grid supports wildcard destinations, allowing messages to be sent to or consumed from multiple destinations, using hierarchical notation. Sun JMS Grid also supports content-based selectors that operate on the JMS message body as well as the JMS message header, using XPath for XML messages and Beans selectors for Object messages.

JMS Grid consists of two or more cooperating JMS Message Servers, termed daemons, typically deployed to independent hardware platforms, treated as a cluster. Figure 5-17 illustrates a JMS Grid cluster with two daemons and two JMS clients, each connected to a different daemon in the cluster. Daemons in a JMS Grid cluster implement resilience by transparently replicating messages and maintaining synchronization among themselves. From the standpoint of a JMS client, the entire JMS Grid cluster, however it is configured and however many daemons it contains, is treated as a single JMS Message Server. JMS Grid clusters can be combined into JMS Grid networks.

JMS Grid cluster

Figure 5-17. JMS Grid cluster

Deploying a two-daemon JMS Grid cluster over two physical machines in a single site provides resilience in the face of single machine failure. The cluster will continue processing messages. All JMS clients connected to the machine that failed will be automatically reconnected to the surviving machine. Deploying a JMS Grid cluster in which participating machines are distributed over different sites, as shown in Figure 5-18, provides resilience in the face of a failure of the entire site. The cluster will continue processing messages in the surviving site. Any JMS clients connected to the JMS Grid daemon at the site that failed will be automatically reconnected to the daemon at the surviving site unless they themselves were brought down by the failure.

JMS Grid network

Figure 5-18. JMS Grid network

We would consider deploying a JMS Grid network, in which two or more JMS Grid clusters are interconnected, to create a Messaging Bridge [EIP] or to overcome latency and throughput issues that sometimes exist between components distributed over multiple sites with slow or low-bandwidth network links.

A typical JMS Grid network configuration would consist of a network of two clusters, each with two daemons. This kind of architecture provides intrasite as well as intersite redundancy.

Best Practice

Best Practice

Aim for a cluster size of two daemons if you use message persistence. Due to the JMS Grid’s support for fully replicated clustering of message daemons, every persistent message is stored on every node in the cluster before an acknowledgment is sent back to the message producer. Thus, the more daemons in a cluster, the longer the replication process will take.

When a message is published by a JMS client to the JMS Grid cluster, specifically to the daemon to which the client is connected, it is transparently and synchronously replicated to all other daemons in the cluster, as well as asynchronously across the network to the other cluster in the network. The message is acknowledged to the JMS client only once it has been replicated across all daemons in the cluster. This behavior enables the message subscriber/receiver to receive the message from any daemon in the cluster, to which it happens to be connected, completely transparently. If the daemon to which the message was submitted fails, the subscriber/receiver will still receive the message from the daemon to which it is connected. Should an entire cluster fail, a failover to any other cluster provides complete recovery of all messages in real time.

JMS Grid is highly configurable, and it would be possible to write an entire book about JMS Grid alone. A simple example is given below.

JMS Grid is a separately installed product. The Java CAPS environment in eDesigner must be configured to support all JMS Grid daemons to which the JMS client, publisher/sender, or subscriber/receiver can connect when deployed to that environment. JMS Grid daemons are very much like Sun SeeBeyond IQ Managers or Sun SeeBeyond Message Servers, from the perspective of eDesigner environment configuration. Figure 5-19 shows a Java CAPS environment in which one Sun SeeBeyond Integration Server and two instances of the Sun JMS Message Grid Servers are configured.

JMS Grid Message Servers in a Java CAPS environment

Figure 5-19. JMS Grid Message Servers in a Java CAPS environment

The JMSGrid1 represents the first daemon (daemon01), and the JMSGrid2 represents the second daemon (daemon02).

Although this implementation is quite unrealistic, for simplicity let’s assume daemon01 is listening on port 60607 on localhost, shown in Figure 5-20, and daemon02 is listening on port 60608, also on localhost, shown in Figure 5-21.

Daemon to listen on port 60607

Figure 5-20. Daemon to listen on port 60607

Daemon to listen on port 60608

Figure 5-21. Daemon to listen on port 60608

Best Practice

Best Practice

When JMS Grid is installed, a standalone daemon is configured on port 50607. Standalone daemons are instances of JMS Grid message daemons that do not contain any clustering capabilities. It is a good idea to configure any cluster-capable daemons on a port other than the default 50607 to ensure that the default standalone daemon is not accidentally addressed.

Now let’s create a deployment profile and deploy components, as shown in Figure 5-22. Here the sender (svc_jcdFileToJMS → 1JMSGridQueue) will connect to JMSGrid1 daemon, and the receiver (qJMSGridQueue → svc_jcdJMSToFile) will connect to JMSGrid2 daemon. The JMS Grid cluster will take care of propagating messages between daemons.

JMS Destinations deployed to JMS Grid daemons

Figure 5-22. JMS Destinations deployed to JMS Grid daemons

If the JMS Message Servers to which the publisher/sender and the subscriber/receiver are deployed were not part of the same JMS Grid cluster, there would be a disconnect between the sender and the receiver. Unless a separate component somehow transported the message from one JMS Message Server to the other, the message would not go past the queue to which it was queued. The JMS Grid cluster implementation provides the component with that functionality.

The following behavior will be observed at runtime:

  • A message is picked up from a file and sent to JMSGrid1/qJMSGridQueue (daemon01).

  • JMS Grid cluster infrastructure replicates the message from daemon01 to daemon02.

  • Message is picked up from JMSGrid02/qJMSGridQueue and written to a file.

This discussion is illustrated with an example in Chapter 3, section 3.3, “Resilient JMS with JMS Grid,” in Part II.

Unlike the Sun SeeBeyond IQ Manager, which is “self-administering,” the JMS Grid Admin Console must be used to create required networks, clusters, and daemons.

Let’s create a runtime environment now.

The default installation is straightforward and well documented in [JMSGridUserGuide]. Once you have started the JMS Grid Admin Console, create the JMS Grid Network with one JMS Grid cluster and two JMS Grid daemons, as shown in Figure 5-23. Vary hosts and port numbers as appropriate.

JMS Grid daemons in JMS Grid Admin Console

Figure 5-23. JMS Grid daemons in JMS Grid Admin Console

On Windows, start both daemons by executing the following commands:

startserver.bat /n daemon01
startserver.bat /n daemon02

Let’s now submit the file to be picked up and observe that the message is correctly sent, and transparently replicated and received.

As mentioned, you would normally ensure that all JMS clients are aware of all daemons in the cluster in order to be able to be transparently failed over from daemon to daemon. This awareness is configured by specifying the URLs of all daemons participating in the cluster separated by a comma. Figure 5-24 shows the Sun Java Message Service Grid Server URL property whose value contains references to two daemons.

http://localhost:60607,http://localhost:60608
Configuring JMS Grid client connection configured for failover

Figure 5-24. Configuring JMS Grid client connection configured for failover

Note the comma between the daemon message server URLs.

The [JMSGridUserGuide] goes into the specific details of what configuration settings are recommended for maximum throughput, as well as client load balancing, client failover, and fault tolerance.

As you have seen, the actual JMS Grid specifics have absolutely no effect on the development process. Apart from specifying the JMS Grid Message URL, there was no JMS Grid–specific code anywhere. This is a great advantage, as you can develop your code without having to worry about high availability, scalability, or resilience during development. Once you migrate to your production environment, you get all these for free. No refactoring of any previous development effort is required.

Best Practice

Best Practice

Develop your Java CAPS solutions using the Sun SeeBeyond IQ Manager that is part of the Logicalhost domain. This is the easiest option for quickly testing your projects, as you don’t have to worry about starting and stopping the JMS Grid message daemons or any added JMS Grid configuration overhead. Then when you migrate to your test and production environments, you can switch to a JMS Grid setup without any extra development effort.

The JMS Grid message daemons can provide you with the required high availability and resilience that your enterprise may need. It is highly configurable and leaves a lot of room for custom tuning to your particular requirements.

Competing Consumers

Messages might be arriving at a particular Java Collaboration faster than the collaboration can process them. If the collaboration’s activities do not rely on messages arriving in order, it might be useful to have multiple copies of the collaboration work concurrently, starting a new copy of the collaboration as soon as a message arrives, achieving parallel processing. Even if serial processing is required, a degree of parallelism can be achieved by configuring the appropriate FIFO Mode [JMSREF, p. 69].

eGate and Java Collaborations

One way to implement the Competing Consumers pattern in Java CAPS is to explicitly replicate processing services in the connectivity map. Figure 5-25 shows three instances of the service configured to receive from the same JMS queue in order to parallelize message processing.

Explicitly replicated services

Figure 5-25. Explicitly replicated services

By default, each receiver is configured with Serial mode concurrency, meaning only one copy of the receiver will be created. It will receive a message when it is ready and a message is available. Messages that cannot be delivered because the receiver is busy will be queued until it is no longer busy.

In the example in Figure 5-25, there are three explicit receivers. Each would be implemented using the same Java Collaboration. You would merely drag the collaboration onto the Connectivity Map Editor Canvas three times.

Another way to implement the Competing Consumers pattern is to drag a single Java Collaboration to the Connectivity Map Editor Canvas and configure the JMS Connector Basic Concurrency property to Connection Consumer mode. Figure 5-26 shows the Concurrency property of the JMS consumer configured to support Connection Consumer mode.

Replicating services through Connection Consumer mode

Figure 5-26. Replicating services through Connection Consumer mode

Figure 5-27 shows the advanced property Server Session Pool Size set to the desired maximum number of services, to execute in parallel, when the Concurrency is set to Connection Consumer mode.

Specifying Server Session Pool Size property value

Figure 5-27. Specifying Server Session Pool Size property value

Warning

Warning

There is no visual indication that the receiver operates in a Connection Consumer mode. When inspecting connectivity maps, keep an eye out for these things, as solution runtime behavior may be very different in either case.

Warning

Warning

FIFO modes affect parallelism in Connection Consumer mode.

This works only if the service is implemented as a Java Collaboration. Java Collaborations are expected to be relatively short-lived. An implicit transaction is started when the message is delivered to the consumer and only completed when the consumer completes. The longer the consumer takes to process a message, the more likely it is that a new message will become available and a new copy of the consumer will be started to process it.

eInsight Business Processes

If the receiver is an eInsight Business Process, the behavior is very different. An eInsight Business Process is, effectively, a Web Services orchestration. Since Business Processes can be long-running, as in hours, days, or even months, it would normally be impossible in practice to impose on them transactional behavior like that imposed on short-lived Java Collaborations. Business Process Execution Language for Web Services (BPEL4WS), which is at the core of eInsight, relies on compensating transactions to reverse side effects produced by individual steps in the Business Process rather than on commit/rollback transactional behavior for the entire Business Process. As of Java CAPS 5.1, XA transactionality can be imposed in specific circumstances over an eInsight Business Process.

The implication for the discussion on Competing Consumers is that as soon as the JMS Receive Web Service delivers a message to the next activity in the Business Process, it sends an acknowledgment the JMS Message Server. The JMS Message Server completes the transaction and, if another message is available, delivers the next message to a new instance of the Business Process. In all likelihood, both instances will continue executing in parallel for a while.

If there is considerable message traffic, in all but the most trivial case of “do nothing” Business Process, there may be many process instances running concurrently. This is similar to the behavior observed with Java Collaboration configured for Connection Consumer mode, but there is a critical difference. The number of concurrent Business Process instances receiving messages from a JMS Destination cannot be throttled through the Server Session Pool Size. In fact, eInsight behaves, to all intents and purposes, the same way regardless of the setting of the JMS Connector Concurrency property, unless Sun SeeBeyond JMS Time Order Group is defined or the entire Business Process is subjected to XA transactional semantics.

Warning

Warning

Unchecked, this behavior could result in explosive growth in the number of Business Process instances, competing for finite machine resources and effectively bringing the whole solution to a halt.

The number of concurrently executing eInsight Business Processes can be configured on a per-eInsight-Business-Process-execution-engine basis in version 5.1.0 (Figure 5-28) and on a per-eInsight-Business-Process basis in version 5.1.1 or later (Figure 5-29), both through the Integration Server eInsight engine configuration property MaxConcurrentInstances.

MaxConcurrentInstances in 5.1.0

Figure 5-28. MaxConcurrentInstances in 5.1.0

MaxConcurrentInstances in 5.1.1 and later

Figure 5-29. MaxConcurrentInstances in 5.1.1 and later

Note

Note

As of Java CAPS 5.1, XA transactional behavior can be imposed on the entire eInsight Business Process. This effectively serializes processing, and instead of behaving like Competing Consumers, a new eInsight Business Process instance is not created to receive a message until the previous instance finishes processing a message.

This facility must be turned on with a great deal of forethought. Imposing XA transactional semantics on long-running processes that access external resources with exclusive locks may result in greatly increased contention for scarce resources and/or deadlocks.

As mentioned before, the eInsight Business Processes that are receivers behave much like Java Collaboration receivers with the JMS Connector property Concurrency configured to Connection Consumer mode. This effectively means that multiple parallel Business Process instances will be executing. Since Business Processes are likely to be long-lived, and the execution duration is largely dependent on the time it takes the various Web Services Business Processes invoked to respond, it is likely that different messages may take different amounts of time to be processed. The messages may arrive at their destination in an order different from that in which they arrived at the JMS Destination from which the Business Process picked them up, unless Sun SeeBeyond JMS Time Order Group is implemented to serialize message processing on a per-Message-Server basis.

Note

Note

If preservation of message ordering in the presence of Business Processes as receivers is important, the solution will need to enforce serialization or implement resequencing of messages at the destinations where sequence matters.

Point-to-Point Channel

A Point-to-Point Channel ensures that only one receiver consumes a given message [EIP]. The Point-to-Point Channel is none other than a JMS queue, discussed earlier in section 5.5.

Publish-Subscribe Channel

A Publish-Subscribe Channel has a single input channel and multiple output channels, one for each subscriber [EIP]. The Publish-Subscribe Channel is none other than the JMS topic, discussed earlier in section 5.5.

Datatype Channel

A Datatype Channel [EIP] is a channel over which only one type of message is transmitted. [EIP] suggests using this approach to address the issue of a receiver not knowing what message type it is receiving without additional information, for example, a Format Indicator [EIP].

JMS Message Body Formats

Most receivers simply receive data and provide it to processing components as a single payload buffer, whether a byte array or a string. Some receivers are, however, “sensitive” to data representation in that they provide multiple buffers of different types, only one of which is populated, as dictated by the sender. The most obvious example of these is a JMS client. JMS clients operate in pairs: one JMS client sends/publishes a message to the JMS Message Server and another receives/subscribes to it.

JMS recognizes different message body representations, most notably TextMessage, BytesMessage, MapMessage, StreamMessage, and ObjectMessage. Java CAPS JMS client OTD provides different message buffers for different types. To interoperate, either the sender and the receiver must both agree on the form of the JMS body, or the receiver must have a way of figuring out the form of the JMS message body.

Note

Note

Java CAPS through version 5.1.3 does not provide an ObjectMessage buffer for either sending or receiving, so, effectively, it does not support ObjectMessage type. Even if it did, the usefulness of the ObjectMessage, which by definition is supposed to carry a Java serializable object, would be questionable as non-Java receivers would have no way to deal with these kinds of messages.

Note

Note

Since one can specify name/value pairs in JMS header user properties, the relevance of the MapMessage format is somewhat questionable.

Note

Note

The usefulness of the StreamMessage format is somewhat questionable. StreamMessages carry Java primitive types that non-Java components may be unable to interpret.

This discussion is illustrated with detailed examples in Chapter 3, section 3.4.1, “JMS Message Body Formats,” in Part II.

Endpoint-Dependent Datatypes

Concern with the datatype of the message implies that the receiver cares about what the datatype of the message payload is, implying in turn that the payload is structured, and it is this structure that is of specific interest.

Whether or not a Java CAPS channel is a Datatype Channel depends principally on the endpoint from which a Java CAPS component receives messages. If the endpoint is an HL7 eWay, for example, HL7 being a very common healthcare standard, the eWay will reject any messages that are not HL7 messages before they make it to a Java Collaboration or a Business Process. If configured to do so, the HL7 eWay can also reject HL7 messages that are not the correct version or do not originate from the correct source, to name a few of the available options. With an endpoint of this type, a processing component can assume that it will only deal with messages of the type it is expecting because all other kinds will not make it that far. Endpoints other than the HL7 eWay may similarly prefilter messages by datatype before delivering them to processing components—see relevant eWay documentation for specifics.

Generic endpoints, like the HTTP eWay, the TCP/IP eWay, a JMS client, or the Batch eWay, are oblivious to the type of payload data with which they are dealing (but see discussion of JMS message body formats in section 5.11.1). Such endpoints will deliver messages to processing components, which are expected to deal with messages as best they can.

Multiple Datatypes in Java Collaborations

Java Collaborations can have only one input message, so the [EIP] suggestion that a component receives different messages from different channels is not, strictly speaking, implementable in a Java Collaboration. Once triggered by that one message source, be it a scheduler, a JMS Message Server, an HTTP server, or some other endpoint, the Collaboration can explicitly invoke receive methods of other endpoints, polling multiple channels for messages. This is one way in which the Datatype Channel pattern can be implemented, though implementing the Format Indicator pattern using a single JMS endpoint is less complex and therefore easier and more efficient.

Assume a JMS text message arrives at a Java Collaboration. The collaboration may assume it is only dealing with one type of message, unmarshal the message, and process it. If the message is of the wrong type, the unmarshal operation will fail and throw an UnmarshalException. What happens to the message at that point very much depends on how the collaboration is designed.

If the collaboration does not handle the exception, the exception will be propagated up and will eventually cause the message to be rolled back to the JMS Destination from which it came. Unless overridden by JMS redelivery handling configuration for the JMS Destination (version 5.1.2) or globally (version 5.1.1), the message will be immediately submitted back to the collaboration, which, having not changed in the meantime, will treat it the same as before—badly.

If the collaboration handles the exception, by virtue of having a try-catch surrounding the unmarshal operation, it can ignore the message and return (message loss), it can deliver the message to an Invalid Message Channel [EIP], write it to a file, or do any number of other things depending on what the designer needs to do.

One of the ways to handle a non-unmarshalable message is to unmarshal it into another OTD to see if the message has a different structure. This brute-force approach may be valid if there is no other way to distinguish message types except by trying to unmarshal them into successive OTDs until one fits. If the volume of messages that have the structure that successfully unmarshals into the first OTD is significantly greater than the volume of messages with different structures, this approach is even fairly efficient.

Rather than using a trial-and-error approach, it might be better to use a Format Indicator [EIP], discussed in Chapter 4, section 4.10. In the case of a JMS message, the Format Indicator could be carried as a JMS message header user-defined property so it would be available for controlling execution flow even before the payload was unmarshaled.

Multiple Datatypes in Business Processes

Unlike a Java Collaboration, an eInsight Business Process can have multiple receive activities configured using a Business Process Execution Language (BPEL) Event-Based Decision construct. This in effect achieves for eInsight Business Processes what [EIP] suggests as an approach to implementing a Datatype Channel pattern. Event-Based Decision can be used to implement a variety of solutions, including timeouts, gathers, message-driven alternatives, and others, where message sources, message types, or timer events may vary at runtime. Examples of the use of this construct for timeouts and message type alternatives are provided in Chapter 11, “Message Correlation,” section 11.10. A detailed implementation example of a multi-input Service Activator is provided in Chapter 7, section 7.5, “Multi-Input Service Activator,” in Part II.

An eInsight Business Process is not inherently any more clever at detecting different datatypes than a Java Collaboration is. Using the Event-Based Decision construct to receive different messages only works if each alternate receive activity receives from a different source. Even if there is more than one JMS receive activity, each has to be related to a different JMS Destination; otherwise a randomly chosen branch of the Event-Based Decision will be used, defeating the purpose of having an Event-Based Decision.

Much as was the case with a Java Collaboration, from the standpoint of a JMS receive activity in an eInsight Business Process, all messages are the same if they are of the same JMS message body format: text, bytes, or map. Also, much as was the case with the Java Collaboration, it is not until a JMS message is unmarshaled into an OTD that the Business Process can access elements of the message if it succeeded in unmarshaling, or until it discovers that the message has the wrong datatype if not. Solutions to these issues are exactly the same as solutions to these issues in Java Collaborations: discard the message, requeue the message, or try different OTDs until successful unmarshaling occurs.

Note that unlike in the case of a Java Collaboration, an eInsight Business Process has no way of rolling back the JMS receive unless the entire Business Process is configured as subject to an XA transaction. A JMS message is deemed to have been consumed as soon as it is delivered to the Business Process and is acknowledged as such. As of version 5.1.1, the entire Business Process can be made subject to an XA transaction; therefore, an unhandled failure somewhere in the process will result in a fault being propagated and the XA transaction being rolled back. This, in turn, will result in the JMS message being rolled back and redelivered, moved, or deleted depending on the configuration of redelivery handling; see section 5.13.

Invalid Message Channel

Unlike a Dead Letter Channel [EIP], discussed in section 5.13, to which messages that cannot be delivered are sent, the Invalid Message Channel [EIP] is a channel for messages that are received but that the components cannot process for one reason or another. The discussion on handling messages of different datatypes in section 5.11 touched upon the subject of what to do with a message that is not acceptable to the component that received it.

From the Java CAPS perspective, an Invalid Message Channel is just a channel. Components that receive messages they cannot process can send these messages to any channel they are configured to use. It is the solution architecture–specific decision, rather than a Java CAPS feature or facility, that dictates whether Invalid Message Channels will be used, by which components, and in what circumstances.

Dead Letter Channel

By Andrew Walker

In most circumstances, an EAI infrastructure must guarantee message delivery. Messages must not be lost. This expected behavior would result in continuous attempts to deliver a message regardless of whether the recipient is present or able to receive the message. However well a particular integration solution may be designed, there may be circumstances when a message cannot be delivered to its intended destination. The reasons may be many and varied, including misconfiguration of a sender or removal of a receiver from the system. To prevent continuous redelivery attempts on the one hand, and undetected message loss on the other hand, the solution must make provision for finite retries and diversion of undeliverable messages to alternate destinations, typically known as a Dead Letter Queues, referred to by [EIP] as Dead Letter Channels.

It was only with the release of Java CAPS 5.1.0 that this mechanism became available in the Sun SeeBeyond JMS IQ Manager. In previous versions of the JMS Server this facility did not exist, so message redelivery continued indefinitely. In discussing this topic, we need to be mindful of the difference between a Dead Letter Channel and an Invalid Message Channel. A Dead Letter Channel is a function of the messaging system itself and not of any of the other components that interact with it, an obvious example of this being a Java Collaboration.

Java CAPS Releases Prior to 5.1.2

Unless specified otherwise, the following discussion applies to Java CAPS releases prior to release 5.1.2.

In the Sun SeeBeyond JMS IQ Manager, the Dead Letter Channel is implemented using the JMS Redelivery feature. It is configured globally for an individual JMS IQ Manager; thus the configuration will be applied to all messages that are processed through that JMS IQ Manager regardless of whether the messages are held in topics or queues and regardless of the message producers and/or consumers. As such, it can be seen as an “all-or-nothing” feature.

Let’s take a look at how the JMS Redelivery feature can be configured to implement a Dead Letter Channel. As illustrated in Figure 5-30, configuration of redelivery handling is done through the STC Message Server URL property of the JMS IQ Manager. No changes to the connectivity map are required.

Configuring redelivery handling

Figure 5-30. Configuring redelivery handling

The URL has the form:

stcms://<jmshost>:<jmsport>?JMSJCA.redeliveryhandling=<redeliverySpecification>

To enable Dead Letter Channel behavior, you must use the move() option in the JMS Redelivery configuration URL. This option instructs the JMS IQ Manager to move an undeliverable message to another queue or topic. The parameters to the move option determine the destination. Examples are:

  • 1:25;10:250;100:5000;200:move(queue:qDeadLetter)

    After the message has failed 200 redelivery attempts, move the message to a JMS queue named qDeadLetter.

  • 1:25;10:250;100:5000;200:move(topic:tpcDeadLetter)

    After the message has failed 200 redelivery attempts, move the message to a JMS topic named tpcDeadLetter.

  • 1:25;10:250;100:5000;1000:move(same:DLQ$)

    After the message has failed 1,000 redelivery attempts, move the message to the same type of destination as the source message (JMS topic or JMS queue), the name of which is DLQ<original_Topic_or_Queue_name>.

Redelivery configuration is designed to be applied to each message individually regardless of its source or destination. Thus, when formulating the required syntax for the configuration, you must think at the message level and remember that the configuration will take effect for all messages that are processed through that particular JMS IQ Manager.

Actually, if you do not explicitly enter any configuration for JMS Redelivery, a default configuration will take effect. The default configuration is as follows:

  • After 3 redeliveries, 25ms delay

  • After 5 redeliveries, 50ms delay

  • After 10 redeliveries, 100ms delay

  • After 20 redeliveries, 1 sec delay

  • After 50 redeliveries, 5 sec delay

The default behavior would be encoded as 3:25;5:50;10:100;20:1000;50:5000. However, as can be seen, the default configuration does not include the move() option, thus Dead Letter Channel is not enabled by default in the Sun SeeBeyond JMS IQ Manager; message redelivery attempts will continue indefinitely, though at increasing time intervals, until the message is delivered, expires, or is explicitly removed from the JMS Destination. Note that the delay value must not exceed 5 seconds (5,000 milliseconds).

The JMS Redelivery feature, and thus the implementation of the Dead Letter Channel, is limited to message delivery retries only. It is not intended to handle other nondelivery conditions such as message expiration. Message expiration can be handled, if required, using the Journaling feature discussed in section 5.6.11.

As can be seen from this discussion, the Dead Letter Channel facility provided in the SeeBeyond JMS IQ Manager is simply an extension of the normal JMS topic and queue infrastructure. There is nothing special about the topics or queues that are used as targets in the JMS Redelivery move() option. They function in exactly the same way as other topics and queues and are indistinguishable from them. This is in contrast to some other messaging systems, such as IBM WebSphere MQ, where Dead Letter Queues exist and are configurable as an identifiably separate feature.

Java CAPS Release 5.1.2

By Michael Czapski

Java CAPS release 5.1.2 extends redelivery handling implementation such that individual redelivery configurations can be specified for each sender/publisher. Configuration options are specified through JMS Sender/Publisher connector configuration properties in the connectivity map, illustrated in Figure 5-31.

__Book/MessagingInfrastructure/DeadLetterChannel/DLQMove/cmDLQMove

Figure 5-31. __Book/MessagingInfrastructure/DeadLetterChannel/DLQMove/cmDLQMove

Note

Note

If Action is specified as “no final action,” message redelivery attempts will continue until the message is delivered or until it is manually removed from the JMS Destination.

Note

Note

If there is a redelivery handling specification provided at the Sun SeeBeyond JMS IQ Manager URL in the Java CAPS environment in releases 5.1.2 and 5.1.3, as shown in Figure 5-32, it will override any redelivery handling specification for individual JMS Destinations!

Sun SeeBeyond STCMS redelivery handling specification

Figure 5-32. Sun SeeBeyond STCMS redelivery handling specification

Note, too, that redelivery specification, wherever it is configured, is J2EE application-specific. If there is a specification at the IQ Manager level when an application is built, it will affect that application (EAR file). If it is subsequently changed, the newly built EAR files will carry the changed specification.

Redelivery handling is illustrated with an example in Chapter 3, section 3.4.2, “Dead Letter Channel in 5.1.2,” in Part II.

Documentation Note

The JMSJCA implementation, used to provide support for redelivery handling, is documented in <LogicalHostRoot>/extras/JMSJCA-readme.html. This document, and related material in the same directory, provides deep-dive technical information on the implementation of JMSJCA and its options.

Guaranteed Delivery

Guaranteed Delivery is the property of the messaging system whereby, even in the presence of system failures, a message, once sent, is always delivered to the recipient. As [EIP] points out, Guaranteed Delivery comes at a price both in terms of the necessary physical infrastructure and in terms of performance impact. The enterprise architect must weigh the costs against the benefits to settle on the means of achieving Guaranteed Delivery at a cost that is commensurate with the benefit gained or cost avoided.

Is Guaranteed Delivery Always Required?

Guaranteed Delivery, desirable as it may sound in the abstract, may not always be required and, in many circumstances, may be inappropriate. Let’s consider, for example, a Web Service providing stock quotes, a frequently quoted Web Services scenario. The Web Service invoker typically polls the stock quote service at an interval. From the invoker’s perspective, if the quote response does not make it back, there is no great harm done. The response is expected to come on the next poll. The quotes are transient, they change frequently and unpredictably, so a missed quote is unlikely to have a great impact on the business application that is using the service. A delayed quote, on the other hand, depending on how long it is delayed, as not reflecting temporal reality, may have serious adverse consequences. Let’s imagine our service is implemented in such a way that when it receives a quote request, it guarantees that the response is delivered to the requester regardless of failures that the infrastructure may experience. The component that provides quotes is built in such a way that it never loses quotes. Let us further imagine a failure has occurred and the component that provides quotes is not available for 30 minutes. Our service will not get, and therefore will not deliver, the response for 30 minutes. The quote that is eventually delivered is 30 minutes old and, in the absence of a catch-up mechanism, all subsequent quotes are 30 minutes old until the system is reset. Clearly, guaranteed delivery in this kind of solution is not only unnecessary but harmful.

Let’s consider a twist on the scenario. Let’s assume the quote requester is prepared to wait for a quote for no more than 6 seconds before assuming the response will never come and retrying the request. There are two undesirable things that will happen to the service implementation that guarantees delivery. First, it will have 10 × 30 = 300 outstanding requests before it can deliver a response. Second, 299 of these responses will not be deliverable, as the requester, having abandoned these requests, will no longer be there to receive the responses. The service will unnecessarily waste resources maintaining information about requests and will perform the work necessary to produce the responses that will never be delivered.

Web Services, so much in vogue these days, are typically implemented using the Request/Reply pattern. This is perhaps because one-way operation Web Services are less well understood or less well supported by development tools. The enterprise architect must seriously consider the appropriateness of using request/reply Web Services in applications in which Guaranteed Delivery is required or the appropriateness of requiring Guaranteed Delivery in request/reply scenarios with short-lived/ “impatient,” stateless requesters.

Java CAPS Facilities for Guaranteed Delivery

Once it has been determined that Guaranteed Delivery of a particular level is required, and that the physical infrastructure to support it is available, it is time to consider which facilities of Java CAPS can be used to achieve it for the particular solution or its subset.

Guaranteed Delivery is typically achieved by storing in-flight messages in persistent, possibly redundantly configured storage until delivered; implementing a message service–level acknowledgment scheme with commit/rollback and retry functionality; implementing an application-level acknowledgment scheme with retry functionality; or implementing a multiphase commit protocol, possibly using XA to coordinate transaction processing over multiple cooperating resources. A number of these mechanisms can be used jointly to achieve increasing levels of reliability.

Java CAPS provides in-flight message persistence using JMS for in-between services Guaranteed Delivery and eInsight Persistence for Guaranteed Delivery within a Business Process.

Java CAPS solutions can take advantage of JMS Transacted Sessions, Persistent Delivery mode, and Message Acknowledgments. JMS is used to persist messages between Java Collaborations and/or Business Processes. As of Java CAPS 5.1, Java Collaborations by default operate in XA mode, so when JMS is the source of the message, if an exception occurs the message that the collaboration is operating upon will be rolled back.

For both Java Collaborations and eInsight Business Processes, what happens to a message received through a non-JMS endpoint in case of a failure depends on whether Java CAPS acknowledged message receipt and whether this makes sense for the endpoint, and whether the endpoint considers the message consumed at the time of the failure. In the case of an HTTP eWay or any other HTTP-based server endpoint like a Web Services implementation, the message will be dropped with the expectation that the HTTP client will take steps to recover, whatever that may mean in its context.

eInsight Business Processes, once a message is received by them, can optionally persist the message to the eInsight Persistence Store between individual Business Process activities. Persistence permits message recovery to the last point of persistence.

Persistence Notes

All forms of Guaranteed Delivery require persistent storage of messages while they are vulnerable to failure-induced loss. JMS persistence is implemented as a set of disk files with an internal structure required to support JMS messages, message expiry, message journaling, selectors, and other features a JMS implementation must support. eInsight Persistence is implemented as a set of database tables, in one of the supported relational database management systems (RDBMSs), which allow point-in-time recovery of Business Process instances in flight as well as monitoring eInsight process instances. Solutions architects may implement their own forms of persistence.

A large subset of Java CAPS solutions makes heavy use of JMS. To increase availability of JMS and to reduce or eliminate potential for message loss, Sun JMS Grid can be considered as the JMS implementation for high-availability and Guaranteed Delivery. JMS Grid, discussed in section 5.7, provides transparent JMS message replication across multiple JMS Grid cluster members and transparent JMS client failover, both of which assist in Guaranteed Delivery of JMS messages.

Failure scenarios are not restricted to the failure of Java CAPS components. The potential for hardware failures is typically the principle motivator for concern over Guaranteed Delivery. A catastrophic loss of a system to which a Java CAPS solution is deployed, through system crash for example, may result in message loss if steps are not taken to persist in-flight messages. The loss of a storage device to which messages are persisted will definitely result in data loss, potentially on a very large scale. Thus it is not enough to use persistence and other software-based means to assure Guaranteed Delivery; storage device redundancy and resilience measures, such as RAID (Redundant Arrays of Independent Disks) devices, disk replication/mirroring, and/or cluster-based redundant storage configuration will also have to be used.

The configuration of file systems at the operating system level may affect Guaranteed Delivery in the presence of persistence. Some configurations of file systems, in order to optimize disk I/O, allow the caching of disk writes. If the disk I/O cache contains unwritten data at the time of hardware failure, message loss may occur. Raw disks or write-through caches can be used. Configuration of such facilities, while potentially affecting Java CAPS–based solutions, is well beyond the scope of this book.

JMS-Based Guaranteed Delivery

To put the theoretical assertions about Guaranteed Delivery into perspective, let’s consider some Guaranteed Delivery–related facilities a Java Message Service must provide.

JMS has the notions of Transacted and non-Transacted Sessions, Persistent and non-Persistent Delivery modes, and message timeToLive. The Sun SeeBeyond JMS Message Server can also be configured to control caching disk writes. Configuration of all these things has an impact on whether Guaranteed Delivery can be achieved, at what cost, and what expectation the sender and the receiver can have from the messaging system in different circumstances.

Message Expiry

The Sun SeeBeyond JMS Message Server can be globally configured to expire undelivered messages after a period of time. By default, this period is set at 30 days. This topic is discussed in Chapter 4, section 4.9. Individual JMS clients, embedded in custom components such as JMS OTDs, allow setting of timeToLive properties for individual messages. Both of these configuration choices affect a solution’s ability to guarantee message delivery. If a message expires before it gets delivered to a component, it effectively becomes lost, as far as the solution is concerned, thus compromising Guaranteed Delivery.

Transacted Sessions

The Sun SeeBeyond JMS Message Server supports Transacted and XA Sessions. Consumers always operate in XA Session mode. Producers can operate in Transacted or XA Session mode. Figure 5-33 illustrates the Transaction mode property value of the JMS receiver configured to support transacted sessions.

__Book/MessagingInfrastructure/GuaranteedDelivery/JMSGuaranteedDeliveryFile/cmJMSGuaranteedDelivery

Figure 5-33. __Book/MessagingInfrastructure/GuaranteedDelivery/JMSGuaranteedDeliveryFile/cmJMSGuaranteedDelivery

In Transacted mode, messages are committed automatically and cannot be rolled back even if an exception is thrown by the Java Collaboration.

In XA mode, a two-phase commit protocol is used, which prevents message loss and message duplication in the event of system failure.

Persistent Delivery Mode

The JMS Provider can be instructed to deliver messages using the Persistent Delivery mode. In this mode, the JMS Provider will take care that the message is not lost in transit due to JMS Provider failure. A provider in Persistent Delivery mode will deliver the message once and only once. This is in contrast with Non-Persistent Delivery mode where the provider will ensure that the message is delivered at most once. To ensure that the JMS Provider does not discard partly processed messages in case of failure, the JMS client should use Client Acknowledgment mode or Transacted Session. Only Persistent Delivery mode in conjunction with Client Acknowledgment or Transacted Session mode guarantee once-and-only-once delivery, assuming a failure that destroys the message in persistent storage does not occur.

The Java CAPS Persistent Delivery mode that applies to the JMS Destination is configured through the JMS Connector properties in the connectivity map. If it is desired to nominate Delivery mode on a per-message basis, then the Delivery Mode JMS Message property can be set programmatically within a Java Collaboration or a Business Process.

The Sun SeeBeyond Message Server global property Sync to Disk, which is disabled by default, can be enabled to force synchronization of the JMS cache with the physical device in a Unix environment. Figure 5-34 shows this setting in the Stable Storage tab of the Sun SeeBeyond IQ Manager section of the Integration Server Administrator console. Enabling this option minimizes the possibility of message loss arising out of system failure at the expense of performance and affects the “persistence” of the Persistent Delivery mode.

SyncToDisk property of Sun SeeBeyond JMS IQ Manager

Figure 5-34. SyncToDisk property of Sun SeeBeyond JMS IQ Manager

eInsight Guaranteed Delivery

An eInsight Business Process typically represents a series of distinct activities, operating on one or more messages, possibly accessing multiple external resources, potentially involving human interaction, and frequently built to take minutes, hours, or days to complete.

The long-running nature of Business Processes poses special challenges to Guaranteed Delivery.

eInsight XA Transactionality

XA transactionality is not, strictly speaking, related to Guaranteed Delivery. XA is, more properly, “Guaranteed Nondelivery on Failure.” XA transactionality can play an important role in ensuring data consistency at persistence points in persistence-based Guaranteed Delivery solutions. If, for example, an eInsight Business Process is triggered by a JMS receive and it fails before completion, the JMS message will normally have been consumed and other activities within the Business Process may have made permanent changes to external resources such as database tables. Imposing XA transactionality on the process in these circumstances will allow the side effects to be rolled back, the JMS message to be rolled back to the JMS Destination, and the whole process retried as part of recovery processing.

XA transactional semantics can be imposed upon an eInsight Business Process such that either all activities that participate in a transaction complete or none do. This naturally applies only to activities that support XA. Some activities, such as writing to files, do not support commit/rollback, so they cannot be rolled back even if the Business Process is an XA process.

This discussion is illustrated with a detailed example in Chapter 3, section 3.5.1.1, “eInsight XA Transactionality,” in Part II.

XA does not guarantee delivery. However, since it does guarantee transactional consistency, it plays a critical role in Guaranteed Delivery solutions.

eInsight Persistence

Rather than rolling back all activities that were performed prior to failure, we could configure eInsight to resume the process at the point at which it was interrupted. To achieve this functionality, we must enable process persistence, the facility where Business Process state is persisted in a database and can be used for failure recovery and process-instance state monitoring.

Before persistence can be used, appropriate database tables must be created and the eInsight engine must be configured to support persistence. See eInsight Business Process Manager User’s Guide, Release 5.1.3, sections dealing with persistence for details. For the purpose of this section, we will assume that the eInsight persistence tables are created and the eInsight engine is configured. Figure 5-35 lists the persistence tables used in Java CAPS 5.1.2, and Figure 5-36 illustrates the values of the eInsight engine properties used for persistence configuration.

eInsight persistence tables

Figure 5-35. eInsight persistence tables

eInsight persistence configuration

Figure 5-36. eInsight persistence configuration

The eInsight persistence-based Guaranteed Delivery ensures messages are not lost, and long-running Business Processes can completed successfully in spite of failures and restarts.

This discussion is illustrated with a detailed example in Chapter 3, section 3.5.1.2, “eInsight Persistence,” in Part II.

Solution-Specific Guaranteed Delivery

However much the software and hardware infrastructure may provide by way of support for Guaranteed Delivery, the solution design will also have a part to play in enhancing or negating the benefits of appropriate infrastructure deployment and configuration.

One of the most common issues in solution design is how to deal with the unavailability of external systems on the outbound side. The message, having successfully traversed a complex integration solution, arrives at an endpoint that is supposed to deliver it to an external system. The external system is down. The endpoint infrastructure may not know that the external system is down until the message arrival requires the container to trigger it and the container attempts to validate the connection state prior to triggering the endpoint, or until a delivery to the external system is attempted by the endpoint and fails.

If the container tries to trigger an endpoint component as a result of a message arriving through JMS, it will roll the message back. The redelivery handling, if configured, may retry delivery several times before giving up and redirecting the message to a Dead Letter Queue, Invalid Message Queue, or a queue that triggers some component that simply discards it. Here Guaranteed Delivery configuration must take place outside Java Collaborations or eInsight Business Processes, since these are not invoked. The solution designer may enhance Guaranteed Delivery facilities by taking care to implement appropriate undeliverable message handling, possibly involving human intervention, or may negate the effort and resources put into implementing Guaranteed Delivery infrastructure by explicitly discarding the message or by allowing the message to be expired and discarded by JMS.

If the failure arises within a solution-specific component, such as a Java Collaboration or an eInsight Business Process, the component designer has a great deal of latitude in implementing logic that will assist or interfere with Guaranteed Delivery. Examples of how certain solutions can handle exceptions to aid or hinder Guaranteed Delivery are scattered throughout the book. Specific sections, most notably in Chapter 9, “Messaging Endpoints,” section 9.4.2, and in Chapter 13, “Scalability and Resilience,” sections 13.3 and 13.4, discuss specific delivery exception handling solutions, and exception and compensation handling in general.

Summary

A number of facilities and services must come together when designing solutions that require Guaranteed Delivery. Java CAPS can assist in implementing Guaranteed Delivery through JMS and eInsight persistence. Hardware-based resilience and recovery measures can assist in ensuring that messages are not lost as a result of hardware failures. Operating system–based resiliency and recovery measures can also assist by transparent replication and restartability.

To truly guarantee message delivery, a combination of all of these must be used where appropriate. The enterprise architect plays a critical role in determining what measures must be taken and whether the cost–benefit ratio is appropriate.

Channel Adapter

From the messaging system’s perspective, the Channel Adapter [EIP] is a piece of infrastructure that intermediates between it and some application that cannot directly interact with the messaging solution. Arguably, the difference between a Channel Adapter and an endpoint is fairly subtle. For the purpose of this discussion, a Channel Adapter is an endpoint purposely built to allow communication between Java CAPS and some third-party application. Such an endpoint, in addition to providing communication services, also incorporates a greater or lesser amount of application-specific “knowledge” and frequently uses application-specific APIs to communicate with the application in a way that is facilitated and supported by the application vendor.

Java CAPS provides a number of prebuilt Channel Adapters for various common applications like SAP, PeopleSoft, Oracle applications, and others; see the list of application eWays and eWay documentation for the appropriate application to determine availability and capabilities of prebuilt Channel Adapters.

Java CAPS may not have prebuilt Channel Adapters for less common or home-grown applications. How to incorporate such applications into a messaging solution is dependent on what facilities exist to extract data from, or supply data to, these applications.

Some applications may be able to “export” data in the form of files or may be able to “import” content of files produced by others. In these cases, one of the variants of the Batch eWay, together with suitable transformation components, may be used to implement a Channel Adapter.

Some applications may be using a relational database with a well-documented schema to store application data and may even provide triggers when data in specific tables changes. Java CAPS Database or JDBC eWays, in conjunction with the appropriate transformation components, can be used to integrate such applications into messaging solutions. Whether such database-based Channel Adapters can be invoked using database triggers, or whether they must poll database tables, will depend on the application. Whether such Channel Adapters can directly modify data in the tables will also depend on the application, site requirements around data integrity, and the application vendor’s attitude toward third parties directly modifying data and bypassing the vendor’s application logic. All such considerations will have to be accounted for when determining whether to develop a database-based Channel Adapter and what functionality that Adapter can reasonably provide.

For applications using C, C++, or Java programming languages, as well as those capable of using Microsoft COM/DCOM, a JMS-based Channel Adapter can be developed. The Java CAPS API Kit provides APIs and related libraries for these languages. The APIs are documented, with examples, in a series of Java CAPS eGate API Kit documents.

Messaging Bridge

Organizations that have multiple messaging systems that must exchange messages may need to implement a Messaging Bridge [EIP].

Java CAPS offers a variety of means to assist in developing Messaging Bridge solutions. The Java CAPS eGate API Kit allows third-party Java-, C-, C++-, and COM/DCOM-based solutions to exchange messages directly with the Sun SeeBeyond JMS Message Server. IBM WebSphere MQ–based JMS implementation, Sun JMS Grid, and Sun Java Messaging Service JMS implementations can be transparently integrated with the Java CAPS environment, thus providing JMS-based Messaging Bridge between different JMS implementations. Endpoints, eWay Adapters, can be used to facilitate exchange of messages between Java CAPS and other messaging systems where other means are not available.

The Messaging Bridge can also be used to bridge two or more independent Java CAPS solutions, a Java CAPS solution and an ICAN 5.0.x solution, an SRE 5.0 solution, or even a TRE 5.0 solution. For those not familiar with the last three, ICAN 5.0 is a Java CAPS immediate predecessor, SRE (Schema Runtime Environment) is an ICAN-compatible and Java CAPS-compatible implementation of the original eGate 4.5.3, and TRE (Tables Runtime Environment) is an ICAN-compatible and Java CAPS-compatible implementation of the original DataGate 3.x. The SRE and TRE are not discussed here. ICAN 5.0 and Java CAPS are sufficiently similar to make the following discussion, which concentrates on Java CAPS only, directly applicable.

Bridging Independent Java CAPS Solutions

You will recall that, in most cases, in order for Java CAPS to subscribe to or receive from a JMS Destination, or to publish or send to a JMS Destination, you must create a connectivity map. This is where JMS Destinations are placed and connected to Java Collaborations or eInsight Business Processes that interact with these destinations.

In the Sun SeeBeyond JMS implementation, the JMS Message Server and the JMS clients, where both senders/publishers and receivers/subscribers are clients, all communicate with one another using the TCP protocol. The JMS Message Server is a part of the Java CAPS Application Server domain. Its properties, in particular the port on which it will listen for connections from JMS clients, are configured when the domain is created. These properties live in the domain-specific configuration directory in a file called stcms.default.Properties. When the JMS Message Server starts, it reads that file, among others, and starts listening for client connections on the specified port. In contrast, client connectivity properties, particularly which host and port to use to connect to the JMS Message Server, are configured through the eDesigner in the Java CAPS Environment → Logical Host → Sun SeeBeyond IQ Manager (JMS Message Server). Figure 5-37 shows the value of the STC Message Server URL pointing out the host and port values used to point the clients at the appropriate JSM Message Server instance.

Sun SeeBeyond IQ Manager JMS Message Server URL property

Figure 5-37. Sun SeeBeyond IQ Manager JMS Message Server URL property

Note that there is no reconciliation between the host and port values specified in eDesigner and the port number on which a JMS Messages Server listens for connections. If the JMS Message Server corresponding to the values specified in eDesigner does not exist, the deployed client will fail to start and will log exceptions in the server.log. Conversely, if there is a TCP listener, on a host specified in the eDesigner, listening on the specified port, supporting the Sun SeeBeyond JMS implementation’s Wire Protocol, the client will connect to it and exchange messages regardless of whether or not that listener is running within the same Integration Server domain as the client. It is this “disconnected” nature of the implementation that is exploited in bridging independent Sun SeeBeyond JMS Message Server instances, whether Java CAPS, ICAN, SRE, TRE, or a combination of these.

Every JMS Destination deployed to a specific Message Server will use the JMS Message Server communication parameters specific to that Message Server to connect and exchange messages.

A Java CAPS eDesigner environment can have multiple logical hosts, each of which can have zero or one Integration Server and/or zero or more JMS Message Servers. Even if multiple message servers are defined in the environment, the domain startup will only cause one to be started. It is possible to configure, through eDesigner, a JMS Message Server with a hostname and port number different from the JMS Message Server that is associated with the runtime domain. An expectation is that some other compatible JMS Message Server is running on the host whose name is configured in the properties and listening on the nominated port for JMS client connections.

To establish a Messaging Bridge between two independent Java CAPS installations, you would point specific JMS clients in one installation at the JMS Message Server in another installation by adding a subordinate JMS Message Server whose host name and port number were in fact those of the JMS Message Server in the other installation. This JMS Message Server would not actually correspond to its runtime counterpart in the domain corresponding to the Java CAPS installation in which it is defined. A JMS Message Server defined in this way is sometimes called a Shadow Message Server.

A two-domain environment configuration with mutual shadow JMS Message Servers might look like that shown in Figure 5-38, where JCAPS02_MS in envJCAPS01 is a shadow for a real JMS Message Server JCAPS02_MS in envJCAPS02, and the JCAPS01_MS in envJCAPS02 is a shadow for a real JMS Message Server JCAPS01_ MS in envJCAPS01.

JMS Message Server Shadow configuration

Figure 5-38. JMS Message Server Shadow configuration

The JMS Message Server JCAPS01_MS in environment envJCAPS01 does not specify a host or a port, as shown in Figure 5-39, thus allowing the domain-specified values to be used.

Default STC Message Server URL

Figure 5-39. Default STC Message Server URL

The JMS Message Server JCAPS02_MS in environment envJCAPS01 specifies the host name and port number of the JMS Message Server in the other domain, where a JMS Message Server with that host name and port number actually runs. Figure 5-40 illustrates the STC Message Server URL property where the host and port are explicitly specified.

Actual host and port numbers for the Shadow Message Server

Figure 5-40. Actual host and port numbers for the Shadow Message Server

In order to allow projects deployed to the integration server JCPAS01_IS to publish to JMS Destinations in the JMS Message Server hosted in the envJCAPS02, the envJCAPS01 must have a shadow JMS Message Server defined. If it is necessary for projects deployed to envJCAPS02 to also publish to JMS Destinations hosted in envJCAPA01, envJCAPS02 must also have a shadow JMS Message Server defined to point to the JMS Message Server hosted in the envJCAPS01; otherwise only one shadow server is required.

Given the environments just described, and two connectivity maps as shown in Figure 5-41, you would create two deployment profiles, one each for each of the domains.

__Book/MessagingInfrastructure/MessageBridge/JavaCAPSBridge/cmJavaCAPSBridgeXXX

Figure 5-41. __Book/MessagingInfrastructure/MessageBridge/JavaCAPSBridge/cmJavaCAPSBridgeXXX

The connectivity map cmJavaCAPSBridgeSender is used in deployment profile dpJavaCAPSBridgeSender, and the components are mapped as shown in Figure 5-42. Note that publication svc_jcdJMStoJMS → qPassOn is deployed to the shadow JMS Server JCAPS02_MS running in environment envJCAPS02. This collaboration is what implements the Messaging Bridge that transfers messages between the two Java CAPS domains.

Components mapped in dpJavaCAPSBridgeSender

Figure 5-42. Components mapped in dpJavaCAPSBridgeSender

The components defined in the connectivity map cmJavaCAPSBridgeReceiver are all deployed to the Integration Server and Message Server in the environment envJCAPS02 in the usual way, as shown in Figure 5-43. This deployment is a standard deployment.

Components mapped in dpJavaCAPSBridgeReceiver

Figure 5-43. Components mapped in dpJavaCAPSBridgeReceiver

Bridging Other JMS Messaging Implementations

To create a Message Bridge between the Sun SeeBeyond JMS Message Server and the Sun JMS Grid Server, you would define both JMS Message Server objects in the environment and configure them appropriately.

Given the environment shown in Figure 5-44, with a Sun SeeBeyond Message Server, Grid01_SBYN_MS, and a Sun JMS Grid Message Server, Grid01_JMSGrid_ MS, both defined in the same logical host, you would be able to create a Message Bridge sending messages from the Sun SeeBeyond Message Server to the Sun JMS Grid Message Server, and vice versa.

Environment for bridging between Sun SeeBeyond IQ Manager and JMS Grid

Figure 5-44. Environment for bridging between Sun SeeBeyond IQ Manager and JMS Grid

Java CAPS supports the use of JMS messaging implementations from vendors other than Sun. In addition to the Sun SeeBeyond Message Server, the Sun JMS Grid, the Sun Java System JMS Server, IBM Web Sphere MQ, and JMS Message Server is supported. Figure 5-45 shows the list of JMS Message Server implementations supported by Java CAPS 5.1.3, “out of the box” and selectable directly for use in configuring Java CAPS environments.

JMS implementations supported by Java CAPS 5.1.3

Figure 5-45. JMS implementations supported by Java CAPS 5.1.3

Other Bridging Solutions

In addition to bridging between different JMS implementations and JMS implementations in independent Java CAPS installations, any one or more of the variety of eWays, Connectors, and Adapters can be used to create a Messaging Bridge between independent messaging systems. If, for example, the ability to send messages over a TCP/IP channel is the lowest common denominator for interoperability, then the TCP/IP eWay can be used to receive messages from the other messaging system or send messages to it. Similarly, the HTTP eWay or even a Batch eWay could be used to bridge the technological divide between two messaging solutions.

Message Bus

Message Bus [EIP] is an enterprise integration infrastructure used by enterprise applications as a means of interacting with other enterprise applications in a loosely coupled manner. The Message Bus implements the Canonical Data Model [EIP] and a common command structure. Enterprise applications connect to the Message Bus using appropriate adapters. These adapters convert, if necessary, between the canonical message and application-specific messages and facilitate exchange of messages between the application and the Message Bus. Since receiving applications may not know what sending application sent the messages, the Bus must implement a set of commands that all participating applications understand. These could be get, add, update, and similar commands to request the application to perform the corresponding operation in an application-specific manner. Implied in this model is the means of routing messages from intending to intended applications. By defining a set of commands that participating applications implement in an application-independent manner, you effectively create a set of services with predefined interfaces and operations. These services shelter other participants from each other’s implementation and technology specifics. Ultimately, the Message Bus becomes the Enterprise Service Bus and enables an enterprise to implement a service-oriented architecture.

Java CAPS provides the messaging infrastructure, in the form of one or more JMS Message Server implementations from Sun, IBM, or others. This messaging infrastructure would be the basis of the Message Bus’s common communications infrastructure. Enterprise applications would be connected to the Bus using one of over 80 Java CAPS eWay Adapters and would be accessed by the Bus’s infrastructure as Web Services endpoints, JMS request/reply endpoints, or in any other way that the enterprise architects chose as the corporate standard. The OTD framework would be used to define and implement the Canonical Data Model. While Java CAPS supplies all the technology required to implement a Message Bus, as defined by [EIP], the design of the Canonical Data Model and service interfaces and the choice of Adapters are enterprise-specific. The Message Bus for the enterprise would ultimately be designed by the enterprise’s architecture and implementation teams.

When discussing the Message Bus, the [EIP] uses an example of an interactive application that uses the Bus to access data from multiple disparate systems. In effect, the example discusses a service orchestration implementation or, as Java CAPS and others call it, a Composite Application. Java CAPS, through the eVision product, goes further than just facilitating construction of a Message Bus. It also provides the means to develop an Enterprise Web Application that uses other parts of the Java CAPS suite to facilitate creation of Composite Applications using the Message Bus.

Chapter Summary

This chapter discussed details of the default Java CAPS messaging infrastructure, the Sun SeeBeyond IQ Manager, in order to provide the background necessary to understand how [EIP] patterns that employ the messaging infrastructure are implemented in this chapter and elsewhere in the book. A JMS Grid product, the high-availability JMS implementation, was mentioned, and a number of [EIP] messaging patterns were discussed.

This chapter discussed Sun SeeBeyond Java CAPS JMS specifics that have a significant bearing on implementation of EAI patterns:

  • Java Messaging Service

  • JMS Implementation Interoperability

  • Using JMS to Integrate Non-JMS Environments

  • JMS Queues and Topics

  • Sun SeeBeyond IQ Manager (JMS Message Server)

  • JMS Grid High-Availability JMS Implementation

This chapter also discussed specific [EIP] concepts and patterns that use the JMS or the Java CAPS infrastructure in their implementation:

  • Competing Consumers

  • Point-to-Point Channel

  • Publish-Subscribe Channel

  • Datatype Channel

  • Invalid Message Channel

  • Dead Letter Channel

  • Guaranteed Delivery

  • Channel Adapter

  • Messaging Bridge

  • Message Bus

Some of the patterns discussed are presented in [EIP] in Messaging Channels, some in Message Construction, and some in Messaging Endpoints.

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

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