Overview
A Message represents an individual input or output of a service, the content of which is interpreted by service implementation logic. A Message does not carry context specific to a service invocation, which means that it can be copied and reused across service invocations.
Requirements
- Any type of content model can be used for the content of the message, provided that content can be serialized/deserialized.
- There is a single body representing the content of the message, the type of which correlates to the message type.
- There can be one or more attachments to a message, where each attachment can have a content type independent of the main body.
- All message types must be serializable.
- A message carries no state or context information relative to a given service invocation.
Message Structure
There are two distinct parts to a message:
Content : the main body, or payload, of the message. There is only one body per message instance. The message body is mutable, so message processing logic can access the content, change it (transform, enrich, etc.), and then set it back on the message.
Attachments : provide the ability to associate content with a message separate from the main body, allowing it to be parsed independently. One example would be a binary image that is referenced by the main body of the message. The attachment may be too large to be processed in certain services or the service implementation may not be able to parse/interpret it.
Building a Message
Messages are created using an instance of MessageBuilder. The core provides an Object-based MessageBuilder by default. Additional MessageBuilder implementations can be added as required.
A MessageBuilder instance has the following responsibilities for a given message type:
- Create new instances of a message
- Serialize a message instance to an output stream
- Deserialize a message instance from an input stream
Using the default MessageBuilder
MessageBuilder builder = MessageBuilder.newInstance(); Message message = builder.buildMessage();
Using a MessageBuilder for a specific type
MessageBuilder builder = MessageBuilder.newInstance(StreamMessage.class); FooMessage message = (FooMessage)builder.buildMessage();
Populating a Message
Getting and setting content on a message is super easy ...
// create a message and and a payload Message message = MessageBuilder.newInstance().buildMessage(); message.setContent("I love me some ..."); // get the content from a message, play with it, then update the content String message = message.getContent(String.class); message += "SwitchYard!"; message.setContent(message); // add a photo of me loving SwitchYard message.addAttachment("my-photo", new FileDataSource("MeAndSY.jpg"));
Serialization
Serialization refers to the ability to read and write a complete Message instance to a stream. This should not be confused with a service binding (such as HTTP/SOAP) reading and writing message content. In the former case, a MessageBuilder is used to marshal the entire Message instance with the intent of then unmarshaling into a new Message instance. In the latter (gateway) case, the content of the message is pulled out of the Message instance and encoded in the specific protocol format that the gateway handles.
There are three points at which a Message instance needs to be serialized:
- The message needs to be persisted.
- The message needs to be transmitted to a remote SwitchYard instance via a bridge.
- A deep copy of the message is required.
Interfaces
public abstract class MessageBuilder { public static final MessageBuilder newInstance() { ... } public static final MessageBuilder newInstance( Class<? extends Message> messageType) throws EsbException { ... } public abstract Message buildMessage(); public abstract void writeMessage(Message message, OutputStream out) throws java.io.IOException, EsbException; public abstract Message readMessage(InputStream in) throws java.io.IOException, EsbException; }
public interface Message { void setContent(Object content); Object getContent(); <T> T getContent(Class<T> type); void addAttachment(String name, DataSource attachment); DataSource getAttachment(String name); DataSource removeAttachment(String name); Map<String, DataSource> getAttachmentMap(); }
Comments