This is an article in a series of articles introducing Spring Integration 5. I imagine most of the examples can be applied to earlier versions of Spring Integration as well, it just happens that I started out with Spring Integration 5 and I have little reason to investigate compatibility with previous versions.
The articles assume no previous experience of Spring Integration apart from any earlier articles in the series.
Examples Repository
All the examples in this series of articles are taken from my Spring Integration Scrutinized repository that is available on GitHub.
Spring Integration Messages
In this article I am going to take a closer look at what must be the foundation of Spring Integration in particular and system integration in general: The message.
A message in Spring Integration consists of a message payload and a number of message headers. This is similar to messages in other integration frameworks and products, such as Apache ActiveMQ, Apache Camel etc.
In Spring Integration, there are two types of messages; immutable and mutable messages. Immutable messages are the most common type and should be preferred.
Creating Messages
Spring Integration messages can be created in two different ways, either the traditional Java way using the Java new operator or using a message builder.
Creating Immutable Messages Using New
The first code example is taken from the GenericMessageTests class and shows how to create an immutable message using the new Java operator:
/** * Tests creating an immutable message using new. * * Expected result: * A message should be created with the expected payload and with one expected * message header having the expected key and value. In addition, there will be * an id and a timestamp message header that are set on all messages upon creation. */ @Test public void createMessageUsingNew() { final Message<String> theMessage; final Map<String, Object> theMessageHeadersMap; /* * Create and populate the map that holds the message headers * that are to be set on the message. */ theMessageHeadersMap = new HashMap<>(); theMessageHeadersMap.put(MESSAGE_HEADER_NAME, MESSAGE_HEADER_VALUE); /* Create the message. */ theMessage = new GenericMessage<>(GREETING_STRING, theMessageHeadersMap); /* Verify the created message. */ Assert.assertTrue("Message should be a GenericMessage", theMessage instanceof GenericMessage); Assert.assertEquals("Message payload should be the greeting string", GREETING_STRING, theMessage.getPayload()); Assert.assertEquals("Message should contain three message headers", 3, theMessage.getHeaders().size()); Assert.assertTrue("Message should contain expected header", theMessage.getHeaders().containsKey(MESSAGE_HEADER_NAME)); Assert.assertEquals("Message header value should be expected value", MESSAGE_HEADER_VALUE, theMessage.getHeaders().get(MESSAGE_HEADER_NAME)); assertContainsTimestampAndIdHeaders(theMessage); }
Note that:
- A hash-map is created and a key-value pair is inserted into the map.
This map will be used to hold the message headers of the new message.
Note that, at the time of writing, the map will be used in the message created and should not be re-used or manipulated after having created the message. - The new message, an instance of GenericMessage, is created.
The constructor takes an object, a string in this example, that will become the payload of the new message and the hash-map created earlier which will be used in the new message, along with its contents, to contain the message headers. - The rest of the test verifies the different qualities of the new message.
Especially noteworthy is that the new message is expected to contain three message headers. When a message is created a message id and a timestamp will be added to the message headers. The message id is an instance of the Java class UUID and the timestamp contains the current time in milliseconds at the time of message creation.
Creating Mutable Messages Using New
Creating a mutable message using new is accomplished in an identical way as creating immutable messages apart from, of course, the name of the class. The following test is taken from the MutableMessageTests class:
/** * Tests creating a mutable message using new. * * Expected result: * A message should be created with the expected payload and with one expected * message header having the expected key and value. In addition, there will be * an id and a timestamp message header that are set on all messages upon creation. */ @Test public void createMessageUsingNew() { final Message<String> theMessage; final Map<String, Object> theMessageHeadersMap; /* * Create and populate the map that holds the message headers * that are to be set on the message. */ theMessageHeadersMap = new HashMap<>(); theMessageHeadersMap.put(MESSAGE_HEADER_NAME, MESSAGE_HEADER_VALUE); /* Create the message. */ theMessage = new MutableMessage<>(GREETING_STRING, theMessageHeadersMap); /* Verify the created message. */ Assert.assertTrue("Message should be a MutableMessage", theMessage instanceof MutableMessage); Assert.assertEquals("Message payload should be the greeting string", GREETING_STRING, theMessage.getPayload()); Assert.assertEquals("Message should contain three message headers", 3, theMessage.getHeaders().size()); Assert.assertTrue("Message should contain expected header", theMessage.getHeaders().containsKey(MESSAGE_HEADER_NAME)); Assert.assertEquals("Message header value should be expected value", MESSAGE_HEADER_VALUE, theMessage.getHeaders().get(MESSAGE_HEADER_NAME)); assertContainsTimestampAndIdHeaders(theMessage); }
Note that:
- A hash-map that is to hold the message headers of the new message is created and a key-value pair is inserted into the map.
As with the immutable message, the map will be used in the message created and should not be re-used or manipulated after having created the message. - The new message, an instance of MutableMessage, is created.
The constructor parameters are a message payload and the hash-map created earlier which will be used in the new message, along with its contents, to contain the message headers. - The rest of the test verifies the different qualities of the new message.
As with immutable messages earlier, the id and timestamp message headers are added when the message is created.
Creating Immutable Messages Using a Message Builder
Creating Spring Integration messages can also be accomplished using message builders. In the first example, from the class GenericMessageTests, we will see how to create a message using the message builder that creates immutable messages:
/** * Tests creating an immutable message using the {@code MessageBuilder} message builder. * * Expected result: * A message should be created with the expected payload and with one expected * message header having the expected key and value. In addition, there will be * an id and a timestamp message headers that are set on all messages upon creation. */ @Test public void createMessageUsingMessageBuilder() { final Message<String> theMessage; /* Create the message. */ theMessage = MessageBuilder .withPayload(GREETING_STRING) .setHeader(MESSAGE_HEADER_NAME, MESSAGE_HEADER_VALUE) .build(); /* Verify the created message. */ Assert.assertTrue("Message should be a GenericMessage", theMessage instanceof GenericMessage); Assert.assertEquals("Message payload should be the greeting string", GREETING_STRING, theMessage.getPayload()); Assert.assertEquals("Message should contain three message headers", 3, theMessage.getHeaders().size()); Assert.assertTrue("Message should contain the expected header", theMessage.getHeaders().containsKey(MESSAGE_HEADER_NAME)); Assert.assertEquals("Message header value should be expected value", MESSAGE_HEADER_VALUE, theMessage.getHeaders().get(MESSAGE_HEADER_NAME)); assertContainsTimestampAndIdHeaders(theMessage); }
Note that:
- The message is created with the same payload and the same header as in the examples in which messages were created using new.
- The withPayload static method in the MessageBuilder class creates an instance of the MessageBuilder class and sets what will become the payload of the message created.
- The setHeader method is invoked on the instance of MessageBuilder to set one what will become one message header on the message created.
- The build method is invoked on the MessageBuilder instance to create the message.
- The created message is verified in the same way as when an immutable message was created with new.
As in the previous examples of message creation, id and timestamp message headers are added when the message is created.
Creating Mutable Messages Using a Message Builder
The final example on message creation shows how to create mutable messages using a message builder. This example is from the MutableMessageTests class.
/** * Tests creating a mutable message using the {@code MutableMessageBuilder} message builder. * * Expected result: * A message should be created with the expected payload and with one expected * message header having the expected key and value. In addition, there will be * an id and a timestamp message headers that are set on all messages upon creation. */ @Test public void createMessageUsingMessageBuilder() { final Message<String> theMessage; /* Create the message. */ theMessage = MutableMessageBuilder .withPayload(GREETING_STRING) .setHeader(MESSAGE_HEADER_NAME, MESSAGE_HEADER_VALUE) .build(); /* Verify the created message. */ Assert.assertTrue("Message should be a MutableMessage", theMessage instanceof MutableMessage); Assert.assertEquals("Message payload should be the greeting string", GREETING_STRING, theMessage.getPayload()); Assert.assertEquals("Message should contain three message headers", 3, theMessage.getHeaders().size()); Assert.assertTrue("Message should contain expected header", theMessage.getHeaders().containsKey(MESSAGE_HEADER_NAME)); Assert.assertEquals("Message header value should be expected value", MESSAGE_HEADER_VALUE, theMessage.getHeaders().get(MESSAGE_HEADER_NAME)); assertContainsTimestampAndIdHeaders(theMessage); }
Note that:
- The message creation is identical to that we just saw when creating an immutable message using a message builder except for the name of the message builder, which in this case is MutableMessageBuilder.
- The created message is verified in the same way as when an immutable message was created with new.
As in the previous examples of message creation, id and timestamp message headers are added when the message is created.
The message builders contain many more methods to assist in message creation, which will not be explored here.
Stay tuned for next part in this series, in which I will look more closely at cloning messages.
Happy coding!