Let us understand service broker concepts with an example. This is a simple local instance based example which explains how service broker can be used to communicate between two databases.
Create Database DB-Initiator
Use Master create WITH GO |
When TRUSTWORTHY
ON is specified, database modules (for example, views, user-defined functions, or stored procedures) that use an impersonation context can access resources outside the database
Create a Master Key
use DBInitiator Go CREATE ENCRYPTION GO |
Create a logging Table for our Example
CREATE [ID] [int] IDENTITY(1,1) [Data] [varchar](max) [Message] [xml] NULL) GO |
So far so good! I am the master key creation would be puzzling. Hold on to it. It isn't that complicated.
Let us setup the second database.
We will create the similar entities in DBTarget as well.
create WITH GO
use DBTarget Go
CREATE ENCRYPTION GO
-- Creating Database table to be used for logging data CREATE [ID] [int] IDENTITY(1,1) [Data] [varchar](max) [Message] [xml] NULL) GO |
Service Broker Setup on Both Databases
We need to setup service broker components on both the databases. These components are self-explanatory and easy to understand. You can create analogies to the normal conversation protocols human follow to understand these concepts.
How to say?
CREATE VALIDATION |
How to Reply?
CREATE VALIDATION |
Auto Check Message?
VALIDATION : Specifies how Service Broker validates the message body for messages of this type. When this clause is not specified, validation defaults to NONE. WELL_FORMED_XML Specifies that the message body must contain well-formed XML.
Specifying Request Reply Handshake – Called Contract.
CREATE ( [SendMessageType] SENT [ReceiveMessageType] SENT ); |
Where to put the message? - Queue
Every message goes into the queue. Before we create the queues let us create a dummy stored procedure. This stored procedure will process the messages that come into the queue. After you create the procedure, create the Initiator queue.
use DBInitiator go
CREATE As declare @msg_type int declare @dialog uniqueidentifier, @ErrSave int @ErrDesc nvarchar(150), @msg_body xml SELECT @msg_type, @dialog GO
CREATE
Execute |
Please note: The signature that is expected for the activation clause needs to match your stored procedure definition. Also, use the appropriate user for the execute as clause.
Do the same on the other database as well.
use DBTarget go
CREATE As declare @msg_type int declare @dialog uniqueidentifier, @ErrSave int @ErrDesc nvarchar(150), @msg_body xml SELECT @msg_type, @dialog GO
CREATE
Execute |
Who will send to whom?
These will be the services that will communicate.
use DBInitiator go -- Create a Service to be used CREATE ON ( [MainContract] ); GO use DBTarget go -- Create a Service to be used CREATE ON ( [MainContract] ); GO |
Stored Procedure that will process the message (thanks to Akram Hussein)
I created a dummy stored procedure ProcessMessage before. This was needed to create the queue. Now I will alter the stored procedure to put the actual logic.
The actual logic is simple.
- Check the queue for message.
- If you find a message and this is not an end of conversation message..
- Respond
- Respond
- Else
- Close the conversation.
- Close the conversation.
In all the above process, log into the table.
use DBTarget go
Alter As declare @msg_type int declare @dialog uniqueidentifier, @ErrSave int @ErrDesc nvarchar(150), @msg_body xml -- While loop to check the queue. while (1 = 1) begin begin -- Receive the next available message from the queue WAITFOR ( RECEIVE @msg_type=message_type_id, @msg_body=message_body, @dialog = FROM ),
-- If we didnt recieve anything, just rollback. if (@@ROWCOUNT = 0) BEGIN Rollback BREAK END
-- look for errors. SET @ErrSave =
IF (@ErrSave <> 0) BEGIN ROLLBACK SET @ErrDesc = END WITH ERROR = @ErrSave DESCRIPTION
INSERT END ELSE
-- Check for the End Dialog message. If (@msg_type <> 2) BEGIN -- Log Message in Database INSERT -- Send the message back to the sender. SET @msg_body = SEND MESSAGE (@msg_body); END ELSE BEGIN
-- End Conversation and Notify other side of the conversation END
END commit end GO |
Let us try now…
The script snippet will send a message. We will read the table to find out how messages have transmitted. All conversations need to happen through a dialog
Service Broker dialog security lets your application use authentication, authorization, or encryption for an individual dialog conversation (or dialog). By default, all dialog conversations use dialog security. When you begin a dialog, you can explicitly allow a dialog to proceed without dialog security by including the ENCRYPTION = OFF clause on the BEGIN DIALOG CONVERSATION statement. However, if a remote service binding exists for the service that the conversation targets, the dialog uses security even when ENCRYPTION = OFF. This explains why I created the master key before.
use DBInitiator go
DECLARE @dialog_handle uniqueidentifier, @msg XML
BEGIN DIALOG CONVERSATION @dialog_handle
set @msg =
-- Now Sending a message note we are using -- SendMessageType since it is defined in the contract -- that it is to be sent only by initiater
SEND MESSAGE |
