Reputation: 1721
I'm trying to learn the basics of Service Broker, and have created an application originally based on the SSMS template. However I can't send a message to my queue. It just says the message type is not part of the service contract.
The absolute bare minimum I need to recreate this is the following batch:
USE [test_db]
GO
CREATE MESSAGE TYPE [test_message]
AUTHORIZATION [dbo]
VALIDATION = WELL_FORMED_XML
GO
CREATE CONTRACT [test_contract]
AUTHORIZATION [dbo] (
[test_message] SENT BY ANY
)
GO
CREATE QUEUE [dbo].[test_queue]
WITH STATUS = ON
,RETENTION = OFF
--,ACTIVATION (
-- STATUS = ON
-- ,PROCEDURE_NAME = [dbo].[test_activator]
-- ,MAX_QUEUE_READERS = 1
-- ,EXECUTE AS N'dbo'
--)
ON [PRIMARY]
GO
CREATE SERVICE [test_service]
AUTHORIZATION [dbo]
ON QUEUE [dbo].[test_queue] (
[test_contract]
)
GO
BEGIN TRANSACTION
DECLARE @dialog_handle UNIQUEIDENTIFIER
BEGIN DIALOG @dialog_handle
FROM SERVICE test_service
TO SERVICE N'test_service';
SEND ON CONVERSATION @dialog_handle
MESSAGE TYPE test_message (N'<test />');
END CONVERSATION @dialog_handle;
COMMIT TRANSACTION
GO
...which yields:
Msg 8431, Level 16, State 1, Line 10
The message type 'test_message' is not part of the service contract.
I only need to be able to send asynchronous messages within the same database. There are no remote connections to consider, and I don't strictly even need to handle a reply.
I've checked and double-checked that the message type, contract, queue and service all exist and the properties of the contract says that the message type is included
What am I missing?
Upvotes: 2
Views: 1803
Reputation: 294177
As Denis already answered, you're missing the ON CONTRACT test_contract
.
If you omit it then the DEFAULT
contract is used. Every database has a contract named DEFAULT
which has one message type, also named DEFAULT
. The DEFAULT
contract is used when you omit any contract in BEGIN DIALOG
and the DEFAULT
message type is used when you omit the message type in SEND
:
BEGIN DIALOG @dialog_handle
FROM SERVICE test_service
TO SERVICE N'test_service'; <-- will use the DEFAULT contract
SEND ON CONVERSATION @dialog_handle
(N'<test />'); <-- will use the DEFAULT message type
DEFAULT
message type has no validation. The DEFAULT
contract binds the DEFAULT
message type to both initiator and target (both can send the message in this contract, ie. SENT BY ANY
). Contract and message type names are always case sensitive, irrelevant of database collation, so the name DEFAULT
is case sensitive.
Upvotes: 4
Reputation: 6015
Try this:
BEGIN DIALOG @dialog_handle
FROM SERVICE test_service
TO SERVICE N'test_service'
ON CONTRACT test_contract;
Upvotes: 3