Messages

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();
    
}