7. System Management

7.1 JMX Support

Spring Integration provides Channel Adapters for receiving and publishing JMX Notifications. There is also an inbound Channel Adapter for polling JMX MBean attribute values, and an outbound Channel Adapter for invoking JMX MBean operations.

7.1.1 Notification Listening Channel Adapter

The Notification-listening Channel Adapter requires a JMX ObjectName for the MBean that publishes Notifications to which this listener should be registered. A very simple configuration might look like this:

 <jmx:notification-listening-channel-adapter id="adapter"

The notification-listening-channel-adapter registers with an MBeanServer at startup, and the default bean name is "mbeanServer" which happens to be the same bean name generated when using Spring's <context:mbean-server/> element. If you need to use a different name be sure to include the "mbean-server" attribute.

The adapter can also accept a reference to a NotificationFilter and a "handback" Object to provide some context that is passed back with each Notification. Both of those attributes are optional. Extending the above example to include those attributes as well as an explicit MBeanServer bean name would produce the following:

 <jmx:notification-listening-channel-adapter id="adapter"

Since the notification-listening adapter is registered with the MBeanServer directly, it is event-driven and does not require any poller configuration.

7.1.2 Notification Publishing Channel Adapter

The Notification-publishing Channel Adapter is relatively simple. It only requires a JMX ObjectName in its configuration as shown below.


 <jmx:notification-publishing-channel-adapter id="adapter"

It does also require that an MBeanExporter be present in the context. That is why the <context:mbean-export/> element is shown above as well.

When Messages are sent to the channel for this adapter, the Notification is created from the Message content. If the payload is a String it will be passed as the "message" text for the Notification. Any other payload type will be passed as the "userData" of the Notification.

JMX Notifications also have a "type", and it should be a dot-delimited String. There are two ways to provide the type. Precedence will always be given to a Message header value associated with the JmxHeaders.NOTIFICATION_TYPE key. On the other hand, you can rely on a fallback "default-notification-type" attribute provided in the configuration.


 <jmx:notification-publishing-channel-adapter id="adapter"

7.1.3 Attribute Polling Channel Adapter

The attribute polling adapter is useful when you have a requirement to periodically check on some value that is available through an MBean as a managed attribute. The poller can be configured in the same way as any other polling adapter in Spring Integration (or it's possible to rely on the default poller). The "object-name" and "attribute-name" are required. An MBeanServer reference is also required, but it will automatically check for a bean named "mbeanServer" by default just like the notification-listening-channel-adapter described above.

 <jmx:attribute-polling-channel-adapter id="adapter"
     <si:poller max-messages-per-poll="1" fixed-rate="5000"/>

7.1.4 Operation Invoking Channel Adapter

The operation-invoking-channel-adapter enables Message-driven invocation of any managed operation exposed by an MBean. Each invocation requires the operation name to be invoked and the ObjectName of the target MBean. Both of these must be explicitly provided via adapter configuration:

 <jmx:operation-invoking-channel-adapter id="adapter"

Then the adapter only needs to be able to discover the "mbeanServer" bean. If a different bean name is required, then provide the "mbean-server" attribute with a reference.

The payload of the Message will be mapped to the parameters of the operation, if any. A Map-typed payload with String keys is treated as name/value pairs whereas a List or array would be passed as a simple argument list (with no explicit parameter names). If the operation requires a single parameter value, then the payload can represent that single value, and if the operation requires no parameters, then the payload would be ignored.

If you want to expose a channel for a single common operation to be invoked by Messages that need not contain headers, then that option works well.

7.1.5 Operation Invoking outbound Gateway

Similar to operation-invoking-channel-adapter Spring Integration also provides operation-invoking-outbound-gateway which could be used when dealing with non-void operations and return value is required. Such return value will be sent as message payload to the 'reply-channel' specified by this Gateway.

 <jmx:operation-invoking-outbound-gateway request-channel="requestChannel"

Another way of provideing the 'reply-channel' is by setting MessageHeaders.REPLY_CHANNEL Message Header

7.1.6 MBean Exporter

Spring Integration components themselves may be exposed as MBeans when the IntegrationMBeanExporter is configured. To create an instance of the IntegrationMBeanExporter, define a bean and provide a reference to an MBeanServer and a domain name (if desired). The domain can be left out in which case the default domain is "org.springframework.integration".

 <jmx:mbean-exporter default-domain="my.company.domain" server="mbeanServer"/>

 <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
     <property name="locateExistingServerIfPossible" value="true"/>

The MBean exporter is orthogonal to the one provided in Spring core - it registers message channels and message handlers, but not itself. You can expose the exporter itself, and certain other components in Spring Integration, using the standard <context:mbean-export/> tag.

MBean Features

All the MessageChannel, MessageHandler and MessageSource instances in the application are wrapped by the MBean exporter to provide management and monitoring features.

7.2 Message History

The key benefit of messaging architecture is loose coupling where participating components do not maintain any awareness about one another. This fact alone makes you architecture extremely flexible  allowing you to change components without affecting the rest of the flow, change messaging routs,   message consuming styles (polling vs event driven) etc... However, this unassuming style of architecture could prove to be problematic when things go wrong. For example, if something happened you would probably like to get as much information about the message as you can (its origin, where it was etc.)

Message History is one of those patterns that could help by giving you an option to maintain some level of awareness of a message path either for debugging purposes or to maintain an audit trail. Spring integration provides a simple way to configure your message flows to maintain Message History by adding Message History header to a Message every time a message goes through a tracked component.

7.2.1 Message History Configuration

To enable Message History all you need is define message-history element in your configuration.


Now every named component (component that has an 'id' defined) will be tracked. The framework will set the '$history' header in your Message who's value is  very simple - List<Properties>. The need for this simple structure is mandated by the loosely coupled architecture of messaging systems where the framework must not require you to share any dependencies outside of Java itself. 

<int:gateway id="sampleGateway" 

<int:chain id="sampleChain" input-channel="chainChannel" output-channel="filterChannel">
    <int:header name="baz" value="baz"/>

The above configuration will produce a very simple Message History structure:

[{name=sampleGateway, type=gateway, timestamp=1283281668091},
 {name=sampleChain, type=chain, timestamp=1283281668094}]

To get access to Message History all you need is access the MessageHistory header. For example:

Iterator<Properties> historyIterator =
    message.getHeaders().get(MessageHistory.HEADER_NAME, MessageHistory.class).iterator();
Properties gatewayHistory = historyIterator.next();
assertEquals("sampleGateway", gatewayHistory.get("name"));
Properties chainHistory = historyIterator.next();
assertEquals("sampleChain", chainHistory.get("name"));

Some times you might not want to track all of the components. To accomplish this all you need is provide tracked-components attribute where you can specify comma delimited list of component names and/or patterns you want to track.

<int:message-history tracked-components="*Gateway, sample*, foo"/>

In the above example, Message History will only be maintained for all of the components that end with 'Gateway', all components that start with 'sample' and 'foo' component.

Remember, that by definition History is immutable (you can't re-write history,although some try), therefore Message History can not be changed once written. Every attempt will end in exception.