Error Handling in Service Broker procedures
October 31, 2007Error handling in T-SQL traditionally has been a sort of misterious voo-doo for most developers, with it’s mixture of error severities, SET settings like <a _\_designer:dtid="844424930131970" href="http://msdn2.microsoft.com/en-us/library/ms188792.aspx">XACT\_ABORT</a>, ARITHABORT or ARITHIGNORE and the options to handle the error on the server or at the client. For a long time now the best resource I know on this subject was, and perhaps still is, Erland Sommarskog set of articles at http://www.sommarskog.se/error-handling-I.html and http://www.sommarskog.se/error-handling-II.html. But the introduction of Service Broker activated procedures adds some new issues to consider when designing your application and this post is about what these issues are these and how to best cope with them.
@@ERROR or TRY…CATCH?
Well first things first, lets get this out of our way: check @@error or use BEGIN TRY… BEGIN CATCH? In my opinion, the advantages offered by the TRY… CATCH blocks are overwhelming and you should steer away from checking @@ERROR after each statement. Even if you may find some immediate scenario that would seem simpler using an explicit check for @@error, writing code using TRY…CATCH blocks pays of on the long run. For me the most important differentiatin factor between the two is actually the human factor: code writen with @@error checks is difficult to read and impossible to maintain. Keeping the discipline in writing code to check for @@error after each statement is tedious and errorprone. @@error checks are not ‘<a _\_designer:dtid="844424930131980" href="http://www.amazon.com/Effective-C%2B%2B-Addison-Wesley-Professional-Computing/dp/0321334876/ref=pd\_bbs\_sr\_1/002-9386102-7810448?ie=UTF8&s=books&qid=1193824559&sr=8-1">programming in the future tense</a>‘ as Scott Meyers would put it: future versions in the database engine could introduce behavior changes that raise new errors your application is not prepared to deal with. The TRY…CATCH blocks solve so many of these issues that they are clearly the winner in my book.
Service Broker Error Handling
Why is Service Broker error handling something special? Shouldn’t the normal common wisdom of writing Transact-SQL apply to Service Broker as well? Well yes, but as it turns out there is a twist to the story. Service Broker is an integrated part of the SQL Server database engine and it follows all the normal Transact-SQL language parsing, compilation and execution rules like any other database engine componet, including everything related to errors and exception handling. But the typical Service Broker application is deployed in a quite different fashion than the non-broker applications: it’s an activated procedure that runs in the server background threads. The first major difference is that there is no client application to surface the error to, so any error that happens will have to be dealt with by the procedure. This means that the very purpose of error handling in a Service Broker application is different than in an ordinary procedure: Service Broker error handling has to capture any error and somehow react to this error at the level of Service Broker semantics, namely conversations. Most times this means that the conversation that received the message that triggered the error has to be ended with an error so that the partener service is notified about this problem and, sometimes, some compensation logic has to be run to undo the effects of this conversation had so far. The partener will receive the error message and in turn run its own compensation to complete (with error) the business transaction represented by the conversation..
Lets roll a quick example. Supose we have a trivial service whose role is to insert received message content into a target table (similar to what an audit service perhaps would do). Lets go ahead and build our DDL objects:
use tempdb;
go
— A table for the purpose of the demo
create table [target_table] (
[id] int not null primary key,
[key] nvarchar(256),
[value] nvarchar(256));
go
— Our initiator service
create queue [sender_queue];
create service [sender_service]
on queue [sender_queue];
go
— Our target service
create queue [target_queue];
create service [target_service]
on queue [target_queue]
([DEFAULT]);
go
<p __designer:dtid="844424930132095" style="margin: 0in 0in 0pt" class="MsoNormal">create procedure<span __designer:dtid=”844424930132100” style=”color: #000000”> [usp_target]</p> <p __designer:dtid="844424930132102" style="margin: 0in 0in 0pt" class="MsoNormal">as</p> <p __designer:dtid="844424930132105" style="margin: 0in 0in 0pt" class="MsoNormal">begin</p> <p __designer:dtid="844424930132108" style="margin: 0in 0in 0pt" class="MsoNormal"> set nocount on;</p> <p __designer:dtid="844424930132118" style="margin: 0in 0in 0pt" class="MsoNormal"> declare @handle uniqueidentifier;</p> <p __designer:dtid="844424930132126" style="margin: 0in 0in 0pt" class="MsoNormal"> declare @messageType sysname;</p> <p __designer:dtid="844424930132134" style="margin: 0in 0in 0pt" class="MsoNormal"> declare @payload xml;</p> <p __designer:dtid="844424930132142" style="margin: 0in 0in 0pt" class="MsoNormal"> </p> <p __designer:dtid="844424930132146" style="margin: 0in 0in 0pt" class="MsoNormal"> begin try</p> <p __designer:dtid="844424930132153" style="margin: 0in 0in 0pt" class="MsoNormal"> begin transaction;</p> <p __designer:dtid="844424930132161" style="margin: 0in 0in 0pt" class="MsoNormal"> waitfor (receive top (1)</p> <p __designer:dtid="844424930132175" style="margin: 0in 0in 0pt" class="MsoNormal"> @handle = <span __designer:dtid=”844424930132181” style=”color: blue”>conversation_handle,</span></p> <p __designer:dtid="844424930132184" style="margin: 0in 0in 0pt" class="MsoNormal"> @messageType =<span __designer:dtid=”844424930132189” style=”color: #000000”> message_type_name,</span></p> <p __designer:dtid="844424930132192" style="margin: 0in 0in 0pt" class="MsoNormal"> @payload = cast(<span __designer:dtid=”844424930132200” style=”color: #000000”>message_body as xml)</span></p> <p __designer:dtid="844424930132206" style="margin: 0in 0in 0pt" class="MsoNormal"> from<span __designer:dtid=”844424930132210” style=”color: #000000”> [target_queue]), timeout 1000;</span></p> <p __designer:dtid="844424930132217" style="margin: 0in 0in 0pt" class="MsoNormal"> if (0 != @@rowcount)</p> <p __designer:dtid="844424930132229" style="margin: 0in 0in 0pt" class="MsoNormal"> begin</p> <p __designer:dtid="844424930132234" style="margin: 0in 0in 0pt" class="MsoNormal"> if (@messageType = ‘DEFAULT’)</p> <p __designer:dtid="844424930132246" style="margin: 0in 0in 0pt" class="MsoNormal"> begin</p> <p __designer:dtid="844424930132251" style="margin: 0in 0in 0pt" class="MsoNormal"> insert into<span __designer:dtid=”844424930132257” style=”color: #000000”> [target_table] (</span></p> <p __designer:dtid="844424930132260" style="margin: 0in 0in 0pt" class="MsoNormal"> [id], [key], [value]) </p> <p __designer:dtid="844424930132271" style="margin: 0in 0in 0pt" class="MsoNormal"> select e.value(‘@id’, ‘int’) as [id],</p> <p __designer:dtid="844424930132289" style="margin: 0in 0in 0pt" class="MsoNormal"> e.value(‘@key’, ‘nvarchar(256)’) as [key],</p> <p __designer:dtid="844424930132306" style="margin: 0in 0in 0pt" class="MsoNormal"> e.value(‘@value’, ‘nvarchar(256)’) as [value]</p> <p __designer:dtid="844424930132322" style="margin: 0in 0in 0pt" class="MsoNormal"> from @payload.nodes(‘//payload/entry’) p(e);</p> <p __designer:dtid="844424930132337" style="margin: 0in 0in 0pt" class="MsoNormal"> end;</p> <p __designer:dtid="844424930132343" style="margin: 0in 0in 0pt" class="MsoNormal"> end conversation @handle;</p> <p __designer:dtid="844424930132352" style="margin: 0in 0in 0pt" class="MsoNormal"> end </p> <p __designer:dtid="844424930132358" style="margin: 0in 0in 0pt" class="MsoNormal"> commit;</p> <p __designer:dtid="844424930132364" style="margin: 0in 0in 0pt" class="MsoNormal"> end try</p> <p __designer:dtid="844424930132371" style="margin: 0in 0in 0pt" class="MsoNormal"> begin catch</p> <p __designer:dtid="844424930132378" style="margin: 0in 0in 0pt" class="MsoNormal"> declare @error int, @message nvarchar(4000);</p> <p __designer:dtid="844424930132391" style="margin: 0in 0in 0pt" class="MsoNormal"> select @error = <span __designer:dtid=”844424930132398” style=”color: fuchsia”>ERROR_NUMBER(), @message = <span __designer:dtid=”844424930132403” style=”color: fuchsia”>ERROR_MESSAGE</span>();</span></p> <p __designer:dtid="844424930132406" style="margin: 0in 0in 0pt" class="MsoNormal"> end conversation @handle with error = @error description = @message;</p> <p __designer:dtid="844424930132423" style="margin: 0in 0in 0pt" class="MsoNormal"> commit;</p> <p __designer:dtid="844424930132429" style="margin: 0in 0in 0pt" class="MsoNormal"> end catch;</p> <p __designer:dtid="844424930132437" style="margin: 0in 0in 0pt" class="MsoNormal">end</p> <p __designer:dtid="844424930132440" style="margin: 0in 0in 0pt" class="MsoNormal">go</p> <p __designer:dtid="844424930132444" style="margin: 0in 0in 0pt" class="MsoNormal"> </p>
</span><p __designer:dtid="844424930132447" style="margin: 0in 0in 0pt" class="MsoNormal"><span __designer:dtid=”844424930132448” style=”font-size: 10pt; color: green; font-family: ‘Courier New’”>— attach the procedure to the target_queue as an activated procedure</span></p> <p __designer:dtid="844424930132450" style="margin: 0in 0in 0pt" class="MsoNormal">alter queue [target_queue]</p> <p __designer:dtid="844424930132455" style="margin: 0in 0in 0pt" class="MsoNormal"> with activation (</p> <p __designer:dtid="844424930132461" style="margin: 0in 0in 0pt" class="MsoNormal"> status = on,</p> <p __designer:dtid="844424930132469" style="margin: 0in 0in 0pt" class="MsoNormal"> max_queue_readers = 1,</p> <p __designer:dtid="844424930132475" style="margin: 0in 0in 0pt" class="MsoNormal"> procedure_name = [usp_target],</p> <p __designer:dtid="844424930132481" style="margin: 0in 0in 0pt" class="MsoNormal"> execute as owner);</p> <p __designer:dtid="844424930132489" style="margin: 0in 0in 0pt" class="MsoNormal">go</p> <p __designer:dtid="844424930132492"> </p> <p __designer:dtid="844424930132493">As you can see, the error handling in the stored procedure is handled by a BEGIN TRY/BEGIN CATCH block, and the error handling consist of ending the conversation with an error, sending back the error number and message to the original sender. Of course, in a real application it would probably make sense to clearly define error numbers and messages reported by the target service, as is not really useful to send back to the sender some internal database engine codes and messages. So now lets go ahead and test our service:</p> <p __designer:dtid="844424930132494" style="margin: 0in 0in 0pt" class="MsoNormal">— send a message to the target service</p> <p __designer:dtid="844424930132497" style="margin: 0in 0in 0pt" class="MsoNormal">declare @handle uniqueidentifier, @payload xml;</p> <p __designer:dtid="844424930132505" style="margin: 0in 0in 0pt" class="MsoNormal">begin transaction;</p> <p __designer:dtid="844424930132511" style="margin: 0in 0in 0pt" class="MsoNormal">begin dialog conversation @handle</p> <p __designer:dtid="844424930132517" style="margin: 0in 0in 0pt" class="MsoNormal"> from service [sender_service]</p> <p __designer:dtid="844424930132523" style="margin: 0in 0in 0pt" class="MsoNormal"> to service <span __designer:dtid=”844424930132528” style=”color: red”>‘target_service’, ‘current database’</span></p> <p __designer:dtid="844424930132532" style="margin: 0in 0in 0pt" class="MsoNormal"> with encryption = off;</p> <p __designer:dtid="844424930132541" style="margin: 0in 0in 0pt" class="MsoNormal"> </p> <p __designer:dtid="844424930132544" style="margin: 0in 0in 0pt" class="MsoNormal">select @payload = N‘
<tt __designer:dtid=”844424930132784”>2007-10-31 16:31:52.57 spid52s The activated proc [dbo].[usp_target] running on queue tempdb.dbo.target_queue output the following: ‘The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction.’</tt> </blockquote> <p __designer:dtid="844424930132786">So our procedure wad run, had hit an exception, but our exception handler was not capable of dealing with the problem. The error in the ERRORLOG indicates that we are dealing with an uncommittable transaction issue. So apparently we need to augment our error handling CATCH block to deal with such problems, and the <a __designer:dtid=”844424930132787” href=”http://msdn2.microsoft.com/en-us/library/ms189797.aspx”>XACT_STATE</a> documentation shows how this can be achieved. So we’re gonna modify our CATCH block to deal with doomed transactions and we’re also gonna modify our RECEIVE code slightly not to cast to XML during the RECEIVE statement, since that apparently is fooling the activation machinery which behaves as if the RECEIVE never occured. Here is our modified procedure:</p> <p __designer:dtid="844424930132788" style="margin: 0in 0in 0pt" class="MsoNormal">— Our modified procedure
</span></p> <p __designer:dtid="844424930132791" style="margin: 0in 0in 0pt" class="MsoNormal">alter procedure [usp_target]</p> <p __designer:dtid="844424930132796" style="margin: 0in 0in 0pt" class="MsoNormal">as</p> <p __designer:dtid="844424930132799" style="margin: 0in 0in 0pt" class="MsoNormal">begin</p> <p __designer:dtid="844424930132802" style="margin: 0in 0in 0pt" class="MsoNormal"> set nocount on;</p> <p __designer:dtid="844424930132810" style="margin: 0in 0in 0pt" class="MsoNormal"> declare @handle uniqueidentifier;</p> <p __designer:dtid="844424930132817" style="margin: 0in 0in 0pt" class="MsoNormal"> declare @messageType sysname;</p> <p __designer:dtid="844424930132824" style="margin: 0in 0in 0pt" class="MsoNormal"> declare @messageBody varbinary(max);</p> <p __designer:dtid="844424930132833" style="margin: 0in 0in 0pt" class="MsoNormal"> declare @payload xml;</p> <p __designer:dtid="844424930132840" style="margin: 0in 0in 0pt" class="MsoNormal"> </p> <p __designer:dtid="844424930132844" style="margin: 0in 0in 0pt" class="MsoNormal"> begin try</p> <p __designer:dtid="844424930132850" style="margin: 0in 0in 0pt" class="MsoNormal"> begin transaction;</p> <p __designer:dtid="844424930132857" style="margin: 0in 0in 0pt" class="MsoNormal"> waitfor (receive top (1)</p> <p __designer:dtid="844424930132867" style="margin: 0in 0in 0pt" class="MsoNormal"> @handle = <span __designer:dtid=”844424930132871” style=”color: blue”>conversation_handle,</span></p> <p __designer:dtid="844424930132874" style="margin: 0in 0in 0pt" class="MsoNormal"> @messageType = message_type_name,</p> <p __designer:dtid="844424930132880" style="margin: 0in 0in 0pt" class="MsoNormal"> @messageBody = message_body</p> <p __designer:dtid="844424930132885" style="margin: 0in 0in 0pt" class="MsoNormal"> from [target_queue]), timeout 1000;</p> <p __designer:dtid="844424930132893" style="margin: 0in 0in 0pt" class="MsoNormal"> if (0 != @@rowcount)</p> <p __designer:dtid="844424930132902" style="margin: 0in 0in 0pt" class="MsoNormal"> begin</p> <p __designer:dtid="844424930132907" style="margin: 0in 0in 0pt" class="MsoNormal"> if (@messageType = ‘DEFAULT’)</p> <p __designer:dtid="844424930132916" style="margin: 0in 0in 0pt" class="MsoNormal"> begin</p> <p __designer:dtid="844424930132921" style="margin: 0in 0in 0pt" class="MsoNormal"> select @payload = cast(@messageBody as xml);</p> <p __designer:dtid="844424930132932" style="margin: 0in 0in 0pt" class="MsoNormal"> insert into [target_table] (</p> <p __designer:dtid="844424930132939" style="margin: 0in 0in 0pt" class="MsoNormal"> [id], [key], [value]) </p> <p __designer:dtid="844424930132946" style="margin: 0in 0in 0pt" class="MsoNormal"> select e.value(‘@id’, ‘int’) as [id],</p> <p __designer:dtid="844424930132959" style="margin: 0in 0in 0pt" class="MsoNormal"> e.value(‘@key’, ‘nvarchar(256)’) as [key],</p> <p __designer:dtid="844424930132971" style="margin: 0in 0in 0pt" class="MsoNormal"> e.value(‘@value’, ‘nvarchar(256)’) as [value]</p> <p __designer:dtid="844424930132982" style="margin: 0in 0in 0pt" class="MsoNormal"> from @payload.nodes(‘//payload/entry’) p(e);</p> <p __designer:dtid="844424930132993" style="margin: 0in 0in 0pt" class="MsoNormal"> end;</p> <p __designer:dtid="844424930132999" style="margin: 0in 0in 0pt" class="MsoNormal"> end conversation @handle;</p> <p __designer:dtid="844424930133006" style="margin: 0in 0in 0pt" class="MsoNormal"> end </p> <p __designer:dtid="844424930133011" style="margin: 0in 0in 0pt" class="MsoNormal"> commit;</p> <p __designer:dtid="844424930133017" style="margin: 0in 0in 0pt" class="MsoNormal"> end try</p> <p __designer:dtid="844424930133023" style="margin: 0in 0in 0pt" class="MsoNormal"> begin catch</p> <p __designer:dtid="844424930133029" style="margin: 0in 0in 0pt" class="MsoNormal"> <span __designer:dtid=”844424930133032” style=”color: green”>— Test XACT_STATE for 0, 1, or -1.</span></p> <p __designer:dtid="844424930133034" style="margin: 0in 0in 0pt" class="MsoNormal"> — If 1, the transaction is committable.</p> <p __designer:dtid="844424930133039" style="margin: 0in 0in 0pt" class="MsoNormal"> — If -1, the transaction is uncommittable and should </p> <p __designer:dtid="844424930133044" style="margin: 0in 0in 0pt" class="MsoNormal"> — be rolled back.</p> <p __designer:dtid="844424930133050" style="margin: 0in 0in 0pt" class="MsoNormal"> </p> <p __designer:dtid="844424930133053" style="margin: 0in 0in 0pt" class="MsoNormal"> — Test whether the transaction is uncommittable.</p> <p __designer:dtid="844424930133058" style="margin: 0in 0in 0pt" class="MsoNormal"> if (<span __designer:dtid=”844424930133063” style=”color: fuchsia”>XACT_STATE()) = –1</span></p> <p __designer:dtid="844424930133068" style="margin: 0in 0in 0pt" class="MsoNormal"> begin</p> <p __designer:dtid="844424930133073" style="margin: 0in 0in 0pt" class="MsoNormal"> rollback transaction;</p> <p __designer:dtid="844424930133080" style="margin: 0in 0in 0pt" class="MsoNormal"> end;</p> <p __designer:dtid="844424930133086" style="margin: 0in 0in 0pt" class="MsoNormal"> </p> <p __designer:dtid="844424930133089" style="margin: 0in 0in 0pt" class="MsoNormal"> — Test wether the transaction is active and valid.</p> <p __designer:dtid="844424930133094" style="margin: 0in 0in 0pt" class="MsoNormal"> if (<span __designer:dtid=”844424930133099” style=”color: fuchsia”>XACT_STATE()) = 1</span></p> <p __designer:dtid="844424930133103" style="margin: 0in 0in 0pt" class="MsoNormal"> begin</p> <p __designer:dtid="844424930133108" style="margin: 0in 0in 0pt" class="MsoNormal"> declare @error int, @message nvarchar(4000);</p> <p __designer:dtid="844424930133119" style="margin: 0in 0in 0pt" class="MsoNormal"> select @error = <span __designer:dtid=”844424930133124” style=”color: fuchsia”>ERROR_NUMBER(), @message = <span __designer:dtid=”844424930133127” style=”color: fuchsia”>ERROR_MESSAGE</span>();</span></p> <p __designer:dtid="844424930133130" style="margin: 0in 0in 0pt" class="MsoNormal"> end conversation @handle with error = @error description = @message;</p> <p __designer:dtid="844424930133141" style="margin: 0in 0in 0pt" class="MsoNormal"> commit;</p> <p __designer:dtid="844424930133147" style="margin: 0in 0in 0pt" class="MsoNormal"> end</p> <p __designer:dtid="844424930133152" style="margin: 0in 0in 0pt" class="MsoNormal"> end catch;</p> <p __designer:dtid="844424930133159" style="margin: 0in 0in 0pt" class="MsoNormal">end</p> <p __designer:dtid="844424930133162" style="margin: 0in 0in 0pt" class="MsoNormal">go</p> <p __designer:dtid=”844424930133164”>We alter the proceure, turn activation back on and… yet again nothig, the message is still sitting in the target_queue. This time though the queue was correctly disabled, we check the select [name], is_receive_enabled from <span __designer:dtid=”844424930133169” style=”color: green”>sys.service_queues </span>view and sure enough the queue is disabled. But wait a minute! I’m sure TRY/CATCH has its place, but this is not quite what we wanted to achieve, a simple common XML formatting error is taking down our service! How come?</p> <h2 __designer:dtid="844424930133170">Error severities</h2> <p __designer:dtid="844424930133171">As it turns out, XML casting and validation errors are raised with severity 16, and this severity will always put the transaction into an uncommittable state. For Service Broker, this is quite bad, as parsing and shreding XML is a day to day operation for most service applications. Unfortunately, there’s simply no workaround for this issue, which has the implication that one cannot use the SQL Server built-in XML methods to validate the received XML programmatically, one has to ensure that the XML is valid upfront. For XML payloads fortunately there is a solution: declare the message validation on the message type and even enforce an XML schema. This will cause validation to occur prior to the message being enqueued and will ensure that the activate dprocedure has to deal only with valid input. In our case, this means to change the contract of the service to use an XML well formatted validation message:</p> <p __designer:dtid="844424930133173" style="margin: 0in 0in 0pt" class="MsoNormal">create message type [valid_payload] validation = <span __designer:dtid=”844424930133179” style=”color: blue”>well_formed_xml;</span></p> <p __designer:dtid="844424930133182" style="margin: 0in 0in 0pt" class="MsoNormal">create contract [validated_contract] ([valid_payload] sent by initiator);</p> <p __designer:dtid="844424930133190" style="margin: 0in 0in 0pt" class="MsoNormal">go</p> <p __designer:dtid="844424930133193" style="margin: 0in 0in 0pt" class="MsoNormal"> </p> <p __designer:dtid="844424930133196" style="margin: 0in 0in 0pt" class="MsoNormal">alter service [target_service] (add contract [validated_contract]);</p> <p __designer:dtid="844424930133204"> </p> <p __designer:dtid=”844424930133205”>We also need to change our activated procedure to deal with the new message type name, the ‘valid_payload’ type:</p> <p __designer:dtid="844424930133206">…</p> <p __designer:dtid="844424930133207" style="margin: 0in 0in 0pt" class="MsoNormal"> if (0 != @@rowcount)</p> <p __designer:dtid="844424930133216" style="margin: 0in 0in 0pt" class="MsoNormal"> begin</p> <p __designer:dtid="844424930133221" style="margin: 0in 0in 0pt" class="MsoNormal"> if (@messageType = N<span __designer:dtid=”844424930133227” style=”color: red”>‘valid_payload’)</span></p> <p __designer:dtid="844424930133230" style="margin: 0in 0in 0pt" class="MsoNormal"> begin</p> <p __designer:dtid="844424930133235" style="margin: 0in 0in 0pt" class="MsoNormal"> select @payload = cast(@messageBody as xml);</p> <p __designer:dtid="844424930133246" style="margin: 0in 0in 0pt" class="MsoNormal"> insert into [target_table] (</p> <p __designer:dtid="844424930133253" style="margin: 0in 0in 0pt" class="MsoNormal"> [id], [key], [value]) </p> <p __designer:dtid="844424930133260" style="margin: 0in 0in 0pt" class="MsoNormal">…</p> <p __designer:dtid=”844424930133261”>We can now reset the broker in tempdb (to get rif of the erroneous message that would prevent the target_queue from ever becomming enabled) and enable back the target_queue:</p> <p __designer:dtid="844424930133262" style="margin: 0in 0in 0pt" class="MsoNormal">alter database tempdb set <span __designer:dtid=”844424930133267” style=”color: blue”>new_broker with rollback immediate;</span></p> <p __designer:dtid="844424930133272" style="margin: 0in 0in 0pt" class="MsoNormal">go</p> <p __designer:dtid="844424930133275" style="margin: 0in 0in 0pt" class="MsoNormal">alter queue target_queue with status = on;</p> <p __designer:dtid="844424930133285" style="margin: 0in 0in 0pt" class="MsoNormal">go</p> <p __designer:dtid="844424930133287">So now we can send again the erroneous message, this time using the validated contract and message type:</p> <p __designer:dtid="844424930133288" style="margin: 0in 0in 0pt" class="MsoNormal">— send a message to the target service</p> <p __designer:dtid="844424930133291" style="margin: 0in 0in 0pt" class="MsoNormal">declare @handle uniqueidentifier, @payload nvarchar(max);</p> <p __designer:dtid="844424930133301" style="margin: 0in 0in 0pt" class="MsoNormal">begin transaction;</p> <p __designer:dtid="844424930133307" style="margin: 0in 0in 0pt" class="MsoNormal">begin dialog conversation @handle</p> <p __designer:dtid="844424930133313" style="margin: 0in 0in 0pt" class="MsoNormal"> from service [sender_service]</p> <p __designer:dtid="844424930133319" style="margin: 0in 0in 0pt" class="MsoNormal"> to service <span __designer:dtid=”844424930133324” style=”color: red”>‘target_service’, ‘current database’</span></p> <p __designer:dtid="844424930133328" style="margin: 0in 0in 0pt" class="MsoNormal"> on contract [validated_contract]</p> <p __designer:dtid="844424930133334" style="margin: 0in 0in 0pt" class="MsoNormal"> with encryption = off;</p> <p __designer:dtid="844424930133343" style="margin: 0in 0in 0pt" class="MsoNormal"> </p> <p __designer:dtid="844424930133346" style="margin: 0in 0in 0pt" class="MsoNormal">select @payload = N‘