Demystifying Direct Bound Ports - Part 2
Message Box Direct Bound Ports
Message box direct bound ports, as its name implies, allows you to drop messages directly into the message box without an explicit recipient and it allows you to subscribe to messages, not from any particular sender, which meet certain criteria. To configure a message box direct bound port set the ‘Partner Orchestration Port’ property to ‘Message Box’.
Sending a message on a message box direct bound port is equivalent to publishing the message to a message bus, in this case the message box. For any published message there can be any number of subscribers for that message. If there are no subscribers interested in the message at the time you publish it a persistence exception is thrown with an inner exception of subscription not found.
Sometimes when sending a message through a message box direct bound port you may have an implicit recipient in mind and will set properties to particular values that you know a subscriber(s) is looking for and is therefore used as a method for loose-coupling.
Recipients of the message can be any type of service that can subscribe to messages which include orchestrations and send ports.
Receiving a message through a message box direct bound port is equivalent to subscribing to a message bus with filter criteria. For an activating receive shape the subscription will be the message type and the filter and for non-activating receive shapes the subscription will be the message type and the correlation set.
Every receive shape always includes the message type as part of its subscription.
If you don’t add any filter criteria to the activating receive shape connected to a message box direct bound port then the subscription will be:
Which can be read as, “Give me every message whose message-type is MyMessageType”. This is what differentiates a send port subscription from an orchestration subscription. A send port subscription, if you don’t provide it with a filter, will only handle messages sent directly to it via a bound (specify-now or specify-later) logical orchestration port (i.e. the subscription for a send port includes its send port id as a clause OR’ed with it’s filter). A message box direct bound receive port that does not have a filter explicitly added will receive every message that matches the message type that the port’s operation is configured for. [Note: If the message-type is XmlDocument then this is a type-agnostic port. Type-agnostic ports accept any message type. To accomplish this the subscription won't include a message-type, implying that it is not filtering based on message-type. So if there is no filter on the port and the port is type-agnostic then the subscription will be empty and in this case will not match any incoming message as there are no predicates for the routing engine to match against.]
When using message box direct bound receive ports be careful to make the filter as specific as possible. I typically caution developers to only use receive message box direct bound ports only when it is absolutely necessary or the benefits (e.g. loose-coupling) out-weigh the risks, as many developers make the mistake of not making their filter distinguishing enough. The side effect of not having a distinguishing enough filter is that the orchestration can receive messages it didn’t intend to.
An example of a mistake that is commonly made is the following; an activating receive shape with a filter using some custom property followed sometime later by a send shape sending the same message to a send port physically bound to an endpoint. In this case the developer assumes that since the logical send port is bound to a physical send port then only that physical send port will get the message. This is not the case. What will happen is that after the first message is published to the message box an infinite number of orchestrations will be activated. This will happen because the message being sent to the send port endpoint is published to the message box and, because every time a message is sent to the message box all subscriptions are checked for a match, the activation filter of the orchestration will match the message and a new orchestration instance will be started, then recurse to infinity. If the orchestration is more complex and/or if the receive is using a correlation set as its subscription then the difficulty of trying to debug a similar scenario increases dramatically.
Figure 5 Orchestration that will consume its own messages
In this case the only way to not have the orchestration pick-up the same messages it is sending (i.e. incorrectly activate a new instance of the same orchestration) is to either construct a new message and change MyProp property to some other value or send a message of a different message-type.