Service Broker "initiators" adhere to the rules for object identifiers. But "target" service objects are simple string literals. This leads to goofy syntax and confusion. This is really no big deal and in this post I'll cover in detail why it works this way.
I've heard that people don't want to use Service Broker because it is too confusing. I started a blog series called Service Broker Demystified because SSB really isn't that confusing after you account for some of its idiosyncracies. Today we are going to cover why Initiator services are object identifiers (listed in square brackets) and Target services are string literals in the
BEGIN DIALOG statement.
First, it's probably good to take a look at the (abridged) syntax for
BEGIN DIALOG. Note that
TO SERVICE is indeed a string literal (note the single quotes) and the
FROM SERVICE is a standard object (although the brackets aren't shown, you should use them). Remember that SSB was designed for reliable asynchronous message delivery across SQL Server instance boundaries. The
FROM SERVICE is always local to the database where you are starting the DIALOG. It can never be a remote instance. The
TO SERVICE, however, can be either local to the
'CURRENT DATABASE' or it can be remote. Due to this we can never specify the target service as an object, it must always be a string literal. If you attempt to use an object identifier for the TO SERVICE it will fail, even if your SSB design is contained within a single database. The reasoning is that at any future point you may decide to make the service remote and use a route. At that point the syntax would no longer be valid if an object identifier was used. So the SSB designers chose to use the least common denominator...a string literal. Let's look at an example to prove this (click here for the repro script).
First let's build a very simple SSB design:
Here we have two services and we know that Service B is a target service because it is bound to a contract. Next we create a simple dialog, where we name our initiator and target services properly, and this works flawlessly.
Now let's try naming the target service using an object identifier:
Notice that Intellisense doesn't even like this syntax.
Even if we specify
'CURRENT DATABASE' on the
TO SERVICE line we will get the same syntax error.
The rule is that when you begin a dialog SSB will create a conversation endpoint (
sys.conversation_endpoints) in the database of the sending service. But no network connection to the target is established. Therefore no verification of objects can occur. SSB establishes communication with the target only after the first message is sent.
This should logically make sense because we wouldn't want to needlessly traverse the network until we actually had a message to send. Then we could also validate the message and message type at the target simultaneously.
Let's see if we can prove that statement. Download the repro script to follow along.
Here we are going to create two databases on the same instance:
And then in each database we are going to create the most basic set of SSB services:
Now we want to fool SQL Server into thinking that our remote database does not live on our local instance. We do this by creating a SSB route to our target service. (You can of course demo this using a second instance of SQL Server on another machine, but this "trick" works just as well).
Let's quickly confirm that there are no SSB connections to any remote services.
When you begin a dialog conversation SSB creates a conversation endpoint (in
sys.conversation_endpoints) in the database of the initiating service. But no network connection to the target is established. Therefore no verification of objects can occur. SSB establishes communication with the target only after the first message is sent. We demo that here by showing that beginning a dialog will create a
conversation_endpoint, but no network traffic.
Now let's send the message. Note that the status changes to
CONVERSING which means a network connection is being made to the
When the target replies to the message it does not need to call
BEGIN DIALOG CONVERSATION again. It will simply continue the dialog using the existing
conversation_handle already established. When the first message arrives on the target database a conversation endpoint is established in that database which persists all of the routing information to reply to the Initiator.
When I first learned SSB I didn't understand why nitiator services were object identifiers but target services were not. When you remember that targets can *eventually* be remote to your SQL Server instance then it becomes clear that they must be coded as string literals. It's the little peccadilloes like this that make SSB scary. However, once you fully understand why it works this way you start to realize the true power of Service Broker.
You have just read "Service Broker Demystified - [Initiators] and 'Targets'" on davewentzel.com. If you found this useful please feel free to subscribe to the RSS feed.
sql server service broker service broker demystified