Exchange
Using the VLINGO XOOM message and event exchange across Bounded Contexts.
This XOOM LATTICE component provides an Exchange
abstraction over Publish-Subscribe messaging for exchanges or topics. This is a means to publish messages to exchanges/topics inside or outside your current application/service, and to subscribe to such messages. The Exchange
provides translators from internal to external message types, and from external to internal message types.
Understanding the Exchange
There are a few key abstractions. The following subsections describe each.
Exchange
The Exchange
itself is the primary protocol. It defines a message exchange, such as a queue or topic, through which any number of related ExchangeSender
, ExchangeReceiver
, and ExchangeAdapter
components are registered, and messages are sent. The protocol is defined as follows.
The defined behaviors are described next.
Close the Exchange
and any underlying resources. Given that the Exchange
is backed by some middleware messaging mechanism, and connections and other allocated resources to the mechanism are closed.
Answers the underlying channel, which is implementation dependent. The T
type is a parameter that determines the dynamic cast to the runtime type.
Answers the underlying connection, which is implementation dependent. The T
type is a parameter that determines the dynamic cast to the runtime type.
Answers the name of this Exchange
as a String
.
Registers a Covey
with the Exchange
. A Covey
is a set of Exchange
components used to send, receive, and translate messages. The Covey
is explained in a below subsection.
Sends the local
message to the Exchange
after first adapting it to an Exchange
-compatible message. Any given message has three forms:
Local—The type used by the local system to represent the message sent or received
External—The type the message will have when it is received on the external service
Exchange—The type used to transport the message on the Exchange from sender to receiver(s). The Exchange type holds an instance of the External type.
ConnectionSettings
The ConnectionSettings
is a configuration for making a connection to the underlying messaging mechanism, including information for the host, port, virtual host, and user.
There are also a number of factory methods for creating the value state.
Covey
A covey by definition is a group or set. We use a Covey
as a set of Exchange
components used for translating, sending, and receiving messages. A given Exchange
will have one Covey
for each local message type, either as a sender or a receiver of that message type.
The adapter
is an ExchangeAdapter
that is capable of adapting messages to their three forms, Local, External, and Exchange.
The receiver
is an ExchangeReceiver
of messages of local type, meaning that the ExchangeAdapter
has already adapted the incoming message to the local type.
The sender
is an ExchangeSender
of messages of exchange type through the Exchange
, meaning that the ExchangeAdapter
has already adapted the local message to an outgoing type.
Each of the Class
instances is the type of a message form: localClass
, externalClass
, exchangeClass
.
Queue
A Queue
is just a specialized Exchange
. It is expected that a Queue
is not a fanout type but one that is point-to-point. Being point-to-point does not prevent the receiver end from enlisting multipleQueue
competing consumers. The Queue
protocol is identical to the Exchange
.
ExchangeSender
A sender of messages to an Exchange
or Queue
.
The single protocol operation is as follows.
Sends the E
exchange typed message through the underlying exchange or queue, meaning that the ExchangeAdapter
has already adapted the local message to an outgoing type.
From this it may be apparent that the Exchange#send()
does not actually send the message. Instead it dispatches the local message through the Forwarder
for translation to the exchange type, and then the Forwarder
dispatches the message to the ExchangeSender
.
Forwarder
The forwarder of all local and exchange messages, forwarding local messages through an ExchangeSender
and exchange messages through the ExchangeReceiver
. It is the Forwarder
that holds the Covey
instances in behalf of the Exchange
or Queue
, and thus manages translation from local to exchange types and from exchange to local types.
MessageParameters
A builder of message parameters and set of metadata attributes, any number of which are common to associate with messages as parameters. These are to be used as appropriate or ignored if unneeded. The chosen parameters are built using the fluent interface.
There are factory methods and builder methods, as well as public accessors for each parameter. Many of the metadata parameters are common to AMQP, but may also be useful for any type of messaging protocol.
ExchangeReceiver
A receiver of messages from an Exchange
, which may be implemented for each unique message type. The message type received has already been mapped and adapted from the exchange-typed message, and this is in the form of a local message.
The single protocol operation is as follows.
The implementor receives the delivered L
local typed message from the Exchange
. The message is of local type L
having already been mapped and adapted from the exchange-typed message.
ExchangeAdapter
Adapts local messages of type L
to exchange messages of type EX
that hold external type E
. This may involve mapping, in which case the underlying implementation must arrange for an ExchangeMapper
to be registered and used. Note that the L and E types may be different between ExchangeAdapter
and ExchangeMapper
.
The parameters of L
, E
, and EX
are the local form, the external form, and the exchange form types, respectively. The operations of this protocol work as follows.
Answers the L
typed local message from the exchangeMessage
of type EX
.
Answers the EX
typed exchange message from the localMessage
of type L
.
Answers whether or not the adapter supports the exchangeMessage
. This is used by the Forwarder
to find the Covey
used for the type of exchangeMessage
.
ExchangeMapper
Supports mapping a local type message to external type, and a external type message to local type.
The parameters of L
and E
are the local form type and the external form type, respectively. The mapper operations are used as follows.
Answers the external typed message given the local typed message.
Answers the local typed message given the external typed message.
Usage
This section demonstrates how to use the Exchange
. It provides a very simple usage example based on the RabbitMQ implementation.
To use the RabbitMQ implementation you first get connection to an Exchange
.
This factory method is specific to the RabbitMQ implementation. The settings()
is defined as:
The connection is to RabbitMQ on localhost
and uses the default port by passing the value of UndefinedPort
, which is -1
. The virtualHost
is "/"
and the username
and password
are both "guest"
.
Now that the Exchange
is open we can register a Covey
to handle a given set of message types.
To keep the example simple, both the local and external message types are String
. The exchange message type is Message
, which is a specialized RabbitMQ type.
The Message
holds a byte[] payload
and an instance of MessageParameters
as metadata. The Message
may be constructed using a byte[]
or a String
, which is converted to a byte[]
, along with MessageParameters
.
Now here is more specific detail on the Covey
registration on the Exchange
. The MessageSender
is a predefined implementation of ExchangeSender
specifically for RabbitMQ. You instantiate the MessageSender
with the Exchange
's connection.
The TextMessageReceiver
and TextExchangeAdapter
are specifically for String
messages. The TextMessageReceiver
is implemented as follows.
Your receive()
method will apply the message as appropriate for your service/application. The following is the TextExchangeAdapter
.
This specific adapter supports any Message
received from the Exchange
. To adapt from an Exchange
-received Message
to a String
, the adapter calls on the TextExchangeMapper
. To get a String
from the byte[] payload
, the adapter uses Message#payloadAsText()
.
Going from a localMessage
to a Message
for the Exchange
requires constructing with the localMessage
that is converted into a byte[]
, and providing a MessageParameters
instance indicating that the Message
must be sent as durable.
This is the mapper implementation.
Unsurprisingly this mapper, in mapping from String
to String
, has almost no heavy-lifting functionality. Note that a new String
is created from both local and external String
messages to ensure the instances are different.
That's all that is required for a simple text-based message exchange between a sending service and a receiving service.
A more sophisticated set of message types, adapters, and mappers are shown next. Note that the following message types all have equals()
, hashCode()
, and toString()
, but are excluded here for clarity.
The external message types are corresponding to the similarly named local types are as follows.
The local types hold String
, int
, and float
types, while the external types hold only String
attribute types. Also the attribute names are different. This justifies the need for an adapter and mapper for each local to external type. First are the adapter and mapper for LocalType1
and ExternalType1
.
Next are the adapter and mapper for LocalType2
and ExternalType2
.
You may define any number of adapters and mappers to deal with the translations between local and external message types. Each of the sets will be held by a separate Covey
and registered with the Exchange
or Queue
.
Last updated