19. 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.

19.1 Message History Configuration

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

<int:message-history/>

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" 
    service-interface="org.springframework.integration.history.sample.SampleGateway"
    default-request-channel="bridgeInChannel"/>

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

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();
assertTrue(historyIterator.hasNext());
Properties gatewayHistory = historyIterator.next();
assertEquals("sampleGateway", gatewayHistory.get("name"));
assertTrue(historyIterator.hasNext());
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.

[Note]Note
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.