"The notification message type <MessageType> was unexpected." is logged by SSBEA and my app is never called
I am running SQL Server 2005 Standard Edition with External Activator installed. I have the following code in an SSMS tab:
-- Begin a conversation and send a request message
DECLARE @InitDlgHandle UNIQUEIDENTIFIER;
DECLARE @RequestMsg NVARCHAR(100);
BEGIN TRANSACTION;
BEGIN DIALOG @InitDlgHandle
FROM SERVICE [//abc/XYZ/InitiatorPostService]
TO SERVICE N'//abc/XYZ/TargetPostService'
ON CONTRACT [//abc/XYZ/PostContract]
WITH ENCRYPTION = OFF;
SELECT @RequestMsg = N'<RequestMsg>Message for Target service.</RequestMsg>';
SEND ON CONVERSATION @InitDlgHandle
MESSAGE TYPE [//abc/XYZ/RequestPostMessage](@RequestMsg);
SELECT @RequestMsg AS SentRequestMsg, @InitDlgHandle AS ConversationHandle;
COMMIT TRANSACTION;
GO
When I run it, I get the expected output in the results pane. In the EATrace.log, I get the error message "The notification message type //abc/XYZ/RequestPostMessage was unexpected."
-- Create message types
CREATE MESSAGE TYPE [//abc/XYZ/RequestPostMessage] VALIDATION = WELL_FORMED_XML;
CREATE MESSAGE TYPE [//abc/XYZ/ReplyPostMessage] VALIDATION = WELL_FORMED_XML;
GO
-- Create contract
CREATE CONTRACT [//abc/XYZ/PostContract]
([//abc/XYZ开发者_开发技巧/RequestPostMessage] SENT BY INITIATOR,
[//abc/XYZ/ReplyPostMessage] SENT BY TARGET
);
GO
-- Create target queue and service
CREATE QUEUE TargetPostQueue WITH RETENTION = ON;
CREATE SERVICE [//abc/XYZ/TargetPostService]
ON QUEUE TargetPostQueue([//abc/XYZ/PostContract]);
GO
-- Create the initiator queue and service
CREATE QUEUE InitiatorPostQueue WITH RETENTION = ON;
CREATE SERVICE [//abc/XYZ/InitiatorPostService]
ON QUEUE InitiatorPostQueue([//abc/xyz/PostContract]);
GO
-- Create a notification for External Activator
CREATE QUEUE NotificationPostQueue
CREATE SERVICE [//abc/xyz/NotificationPostService]
ON QUEUE NotificationPostQueue([http://schemas.microsoft.com/SQL/Notifications/PostEventNotification])
CREATE EVENT NOTIFICATION EventQueueActivation
ON QUEUE [TargetPostQueue]
FOR QUEUE_ACTIVATION
TO SERVICE '//abc/xyz/NotificationPostService', 'current_database';
GO
-- Security
GRANT CONNECT TO [**Company**\**Machine**$] -- allow CONNECT to the notification database
GRANT RECEIVE ON TargetPostQueue TO [**Company**\**Machine**$] -- allow RECEIVE from the service queue
GRANT RECEIVE ON NotificationPostQueue TO [**Company**\**Machine**$] -- allow RECEIVE from the notifcation queue
GRANT REFERENCES ON SCHEMA::dbo TO [**Company**\**Machine**$] -- allow REFRENCES right on the notification queue schema
-- allow VIEW DEFINITION on the target service
GRANT VIEW DEFINITION ON SERVICE::[//abc/xyz/TargetPostService] TO [**Company**\**Machine**$]
-- allow VIEW DEFINITION on the notification service
GRANT VIEW DEFINITION ON SERVICE::[//abc/xyz/NotificationPostService] TO [**Company**\**Machine**$]
GO
There is nothing in EAService.config that tells EA what message types to expect. Why am I getting this error instead of EA executing the application specified in its config file? Do I have the contract set up incorrectly?
** Newly added section below:**
Per Remus's suggestion, I added the following:
-- Create a notification for External Activator
CREATE QUEUE NotificationPostQueue
CREATE SERVICE [//abc/xyz/NotificationPostService]
ON QUEUE NotificationPostQueue([http://schemas.microsoft.com/SQL/Notifications/PostEventNotification])
CREATE EVENT NOTIFICATION EventQueueActivation
ON QUEUE [TargetPostQueue]
FOR QUEUE_ACTIVATION
TO SERVICE '//abc/xyz/NotificationPostService', 'current_database';
GO
But when I change the NotificationService name in the config file from "//abc/xyz/TargetPostService" to "//abc/xyz/NotificationPostService", I get the error "ERROR = 31, The notification service //abc/xyz/NotificationPostService does not exist" in the EATrace.log when I start the service. However, that service is listed in sys.services.
** Error 31 resolved, now the issue is that my app is not being called **
I used the sample app from the Service Broker Team Blog, adding logging for debug purposes. It writes a log file as soon as it is run, before doing anything else. I've tested it by running it from VS2010 and that works fine, but when I send a message using the code at the beginning of this question, no long is getting created. Therefore I know my app isn't run by EA. How can I diagnose why this is happening? The paths in my EAService.config file are correct. Here is the whole file:
<?xml version="1.0" encoding="utf-8"?>
<Activator xmlns="http://schemas.microsoft.com/sqlserver/2008/10/servicebroker/externalactivator"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.microsoft.com/sqlserver/2008/10/servicebroker/externalactivator EAServiceConfig.xsd"
>
<NotificationServiceList>
<NotificationService name="//abc/xyz/NotificationPostService" id="100" enabled="true">
<Description>My test notification service</Description>
<ConnectionString>
<!-- All connection string parameters except User Id and Password should be specificed here -->
<Unencrypted>server=**MyServer**\**MyInstance**;database=CompanyRehabManagement;Application Name=External Activator;Integrated Security=true;</Unencrypted>
</ConnectionString>
</NotificationService>
</NotificationServiceList>
<ApplicationServiceList>
<ApplicationService name="Company.xyz.EAProcessor" enabled="true">
<OnNotification>
<ServerName>**MyServer**\**MyInstance**</ServerName>
<DatabaseName>**MyDbName**</DatabaseName>
<SchemaName>dbo</SchemaName>
<QueueName>TargetPostQueue</QueueName>
</OnNotification>
<LaunchInfo>
<ImagePath>C:\Project\Pathway\Source\Company.xyz\Company.xyz.EAProcessor\bin\Debug\Company.xyz.EAProcessor.exe</ImagePath>
<CmdLineArgs> %sqlserver% %database% %schema% %queue% </CmdLineArgs>
<WorkDir>C:\Project\Pathway\Source\Company.xyz\Company.xyz.EAProcessor</WorkDir>
</LaunchInfo>
<Concurrency min="1" max="1" />
</ApplicationService>
</ApplicationServiceList>
<LogSettings>
<LogFilter>
<TraceFlag>All Levels</TraceFlag>
<TraceFlag>All Modules</TraceFlag>
<TraceFlag>All Entities</TraceFlag>
</LogFilter>
</LogSettings>
</Activator>
Am I using the correct QueueName? Are there any other possible errors in this file? What else can I do to diagnose this? This is the conversation that occurs:
conversation_id, is_initiator, conversation_handle, local_service, remote_service, service_contract, state_desc, far_broker_instance, security_timestamp, send_sequence, receive_sequence, end_dialog_sequence, system_sequence
411C6F74-B29F-4C47-A538-1B9C900F49BD, 1, 7E7DD27A-E102-E011-93D2-0004239AA238, //abc/xyz/InitiatorPostService, //abc/xyz/TargetPostService, //abc/xyz/PostContract, CONVERSING, 083E1179-A1C3-4414-A1A6-67238E3879CE, 1900-01-01 00:00:00.000, 1, 0, -1, 0
411C6F74-B29F-4C47-A538-1B9C900F49BD, 0, 817DD27A-E102-E011-93D2-0004239AA238, //abc/xyz/TargetPostService, //abc/xyz/InitiatorPostService, //abc/xyz/PostContract, CONVERSING, 083E1179-A1C3-4414-A1A6-67238E3879CE, 2010-12-08 16:10:59.260, 0, 1, -1, 0
When you create the event notification, you should use 'current database' (without the underscore) rather than 'current_database'. 'current database' is a special value, which will match whatever the broker ID of the current database is, whereas in your case the event notification tries to send a notification message to a service with broker ID = 'current_database'.
The external activator is not monitoring your queue, is instead monitoring a notifications queue. External activation is driven by an Event Notifications subscription, something like:
CREATE EVENT NOTIFICATION EventQueueActivation
ON QUEUE [TargetPostQueue]
FOR QUEUE_ACTIVATION
TO SERVICE '...','...';
So the SSBEA needs its own queue on which it will receive the QUEUE_ACTIVATION notification messages. This queue must have on it a service that supports the http://schemas.microsoft.com/SQL/Notifications/PostEventNotification
contract (the Event Notifications contract).
It appears that in your case the SSBEA is configured to listen for notifications on the TargetPostQueue
itself, and thus it getting your custom application messages instead of the expected Event Notification ones.
Regarding the problem with ERROR 31 mentioned at the end of your question, please make sure that the connection string in External Activator's configuration file explicitly sets the initial catalog to the database where the notification service is located. Otherwise it will try to find it in master db, which will obviously fail.
An example is available on the Service Broker Team Blog.
I would just like to add that the ApplicationService name attibute in EAConfig needs to be the same as the TargetService in SQL. So if your target service is called PostInsertedRecordsService, then the ApplicationService name attribute will also be PostInsertedRecordsService.
精彩评论