コード例 #1
0
        public void Serialize_Deserialize_TransportMessage()
        {
            var types = new List<Type> { typeof(C1), typeof(C2) };
            var mapper = new MessageMapper();
            mapper.Initialize(types);
            var serializer = new XmlMessageSerializer(mapper);
            serializer.Initialize(types);

            var transportMessage = new TransportMessage();
            transportMessage.Id = Guid.NewGuid().ToString();
            transportMessage.IdForCorrelation = Guid.NewGuid().ToString();
            transportMessage.ReturnAddress = Guid.NewGuid().ToString();
            transportMessage.WindowsIdentityName = string.Empty;
            transportMessage.TimeSent = DateTime.Now;
            transportMessage.Headers = new List<HeaderInfo>();
            transportMessage.Body = new object[] { new C1() { Data = "o'tool" }, new C2() { Data = "Timmy" } };

            var newTransportMessage = Execute(transportMessage, serializer);

            var messages = newTransportMessage.Body;
            Assert.AreEqual(2, messages.Count());
            Assert.AreEqual(1, messages.Count(x => x is C1));
            Assert.AreEqual(1, messages.Count(x => x is C2));
            Assert.AreEqual("o'tool", ((C1)messages.First(x => x is C1)).Data);
            Assert.AreEqual("Timmy", ((C2)messages.First(x => x is C2)).Data);
            Assert.AreEqual(transportMessage.Id, newTransportMessage.Id);
            Assert.AreEqual(transportMessage.IdForCorrelation, newTransportMessage.IdForCorrelation);
            Assert.AreEqual(transportMessage.ReturnAddress, newTransportMessage.ReturnAddress);
            Assert.AreEqual(transportMessage.TimeSent, newTransportMessage.TimeSent);
            Assert.AreEqual(transportMessage.Headers, newTransportMessage.Headers);
            Assert.AreNotSame(transportMessage, newTransportMessage);
        }
コード例 #2
0
        public void Serialize(TransportMessage transportMessage, Stream outputStream)
        {
            var xs = GetXmlSerializer();
            var doc = new XmlDocument();

            using (var tempstream = new MemoryStream())
            {
                xs.Serialize(tempstream, transportMessage);
                tempstream.Position = 0;

                doc.Load(tempstream);
            }

            if (transportMessage.Body != null && transportMessage.BodyStream == null)
            {
                transportMessage.BodyStream = new MemoryStream();
                this.messageSerializer.Serialize(transportMessage.Body, transportMessage.BodyStream);
            }

            // Reset the stream, so that we can read it back out as data
            transportMessage.BodyStream.Position = 0;

            var data = new StreamReader(transportMessage.BodyStream).ReadToEnd();
            var bodyElement = doc.CreateElement("Body");
            bodyElement.AppendChild(doc.CreateCDataSection(data));
            doc.DocumentElement.AppendChild(bodyElement);

            doc.Save(outputStream);
            outputStream.Position = 0;
        }
コード例 #3
0
 public void OnMessageHandled(ITransport transport, TransportMessage transportMessage, double elapsedMilliseconds)
 {
     var tr = (long)Math.Round(elapsedMilliseconds);
     Metrics.Default.SendBatch()
                 .AddTiming("CWServiceBus.MessageHandled.Destination." + transport.ListenerQueue, tr)
                 .AddTiming("CWServiceBus.MessageHandled.Message." + transportMessage.Body[0].GetType().Name, tr)
                 .Send();
 }
コード例 #4
0
        public static TransportMessage Execute(TransportMessage transportMessage, IMessageSerializer messageSerializer)
        {
            var serializer = new XmlTransportMessageSerializer(messageSerializer);

            using (var stream = new MemoryStream())
            {
                serializer.Serialize(transportMessage, stream);
                Debug.WriteLine(Encoding.ASCII.GetString(stream.ToArray()));
                stream.Position = 0;
                return serializer.Deserialize(stream, true);
            }
        }
コード例 #5
0
        private bool HandledMaxRetries(TransportMessage message, out Exception lastException)
        {
            string messageId = message.Id;
            failuresPerMessageLocker.EnterReadLock();

            if (failuresPerMessage.ContainsKey(messageId) &&
                (failuresPerMessage[messageId] >= maxRetries))
            {
                failuresPerMessageLocker.ExitReadLock();
                failuresPerMessageLocker.EnterWriteLock();

                lastException = exceptionsForMessages[messageId];
                failuresPerMessage.Remove(messageId);
                exceptionsForMessages.Remove(messageId);

                failuresPerMessageLocker.ExitWriteLock();

                return true;
            }

            lastException = null;
            failuresPerMessageLocker.ExitReadLock();
            return false;
        }
コード例 #6
0
        /// <summary>
        /// This is a special helper method which will cause the transport to receive messages as if they came off the bus
        /// </summary>
        public void ReceiveMessages(object[] messages, IEnumerable<HeaderInfo> headers)
        {
            needToAbort = false;
            messageId = string.Empty;
            try
            {
                TransactionWrapper.RunInTransaction(transaction =>
                {

                    var transportMessage = new TransportMessage()
                    {
                        Id = Guid.NewGuid().ToString(),
                        IdForCorrelation = Guid.NewGuid().ToString(),
                        Body = messages,
                        TimeSent = DateTime.UtcNow,
                        MessageIntent = MessageIntentEnum.Send,
                        Headers = headers.ToList(),
                    };

                    //care about failures here
                    var exceptionFromMessageHandling = OnTransportMessageReceived(transportMessage);

                    //and here
                    var exceptionFromMessageModules = OnFinishedMessageProcessing();

                    //but need to abort takes precedence - failures aren't counted here,
                    //so messages aren't moved to the error queue.
                    if (needToAbort)
                        throw new AbortHandlingCurrentMessageException();

                    if (exceptionFromMessageHandling != null) //cause rollback
                        throw exceptionFromMessageHandling;

                    if (exceptionFromMessageModules != null) //cause rollback
                        throw exceptionFromMessageModules;
                });
            }
            catch (AbortHandlingCurrentMessageException)
            {
                //in case AbortHandlingCurrentMessage was called
                //don't increment failures, we want this message kept around.
                return;
            }
            catch (Exception e)
            {
                var originalException = e;
                if (originalException is TransportMessageHandlingFailedException)
                    originalException = ((TransportMessageHandlingFailedException)e).OriginalException;
                OnFailedMessageProcessing(originalException);
                throw;
            }
        }
コード例 #7
0
        private void ProcessMessage(TransportMessage transportMessage)
        {
            messageId = transportMessage.Id;

            var exceptionFromStartedMessageHandling = OnStartedMessageProcessing(transportMessage);

            Exception lastException = null;
            if (HandledMaxRetries(transportMessage, out lastException))
            {
                try
                {
                    this.WriteFailedMessage(transportMessage, lastException, transportMessage.BodyString, transportMessage.HeadersString);
                    if (MessageFault != null)
                        MessageFault(this, new TransportMessageFaultEventArgs(transportMessage, lastException, "ProcessingFailed"));
                    SendFailureMessage(transportMessage, lastException, "ProcessingFailed");
                }
                catch (Exception e)
                {
                    Logger.FatalFormat("Fault manager failed to process the failed message {0}", e, transportMessage);
                    // TODO critical error will stop the transport from handling new messages
                    //Configure.Instance.OnCriticalError();
                }
                Logger.Error(string.Format("Message has failed the maximum number of times allowed, ID={0}.", transportMessage.Id));
                OnFinishedMessageProcessing();
                return;
            }

            if (exceptionFromStartedMessageHandling != null)
                throw exceptionFromStartedMessageHandling; //cause rollback 

            //care about failures here
            var exceptionFromMessageHandling = OnTransportMessageReceived(transportMessage);

            //and here
            var exceptionFromMessageModules = OnFinishedMessageProcessing();

            //but need to abort takes precedence - failures aren't counted here,
            //so messages aren't moved to the error queue.
            if (needToAbort)
                throw new AbortHandlingCurrentMessageException();

            if (exceptionFromMessageHandling != null) //cause rollback
                throw exceptionFromMessageHandling;

            if (exceptionFromMessageModules != null) //cause rollback
                throw exceptionFromMessageModules;
        }
コード例 #8
0
 private void OnSerializationFailed(Guid messageId, TransportMessage transportMessage, string body, string headers, Exception exception)
 {
     try
     {
         this.WriteFailedMessage(transportMessage, exception, body, headers);
         if (MessageFault != null)
             MessageFault(this, new TransportMessageFaultEventArgs(transportMessage, exception, "SerializationFailed"));
         SendFailureMessage(transportMessage, exception, "SerializationFailed");
     }
     catch (Exception e)
     {
         Logger.FatalFormat("Fault manager failed to process the failed message {0}", e);
         // TODO critical error will stop the transport from handling new messages
         //Configure.Instance.OnCriticalError();
     }
 }
コード例 #9
0
        public void ReceiveMessage(SqlTransaction transaction)
        {
            TransportMessage message = null;
            Guid id;
            try
            {
                using (var cmd = transaction.Connection.CreateCommand())
                {
                    cmd.Transaction = transaction;
                    cmd.CommandText = string.Format(SqlCommands.SelectMessage, ListenerQueue);
                    var backoff = new BackOff(1000);
                    while (message == null)
                    {
                        using (var reader = cmd.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                message = new TransportMessage();
                                id = reader.GetGuid(0);
                                message.Id = id.ToString();
                                message.CorrelationId = reader.GetString(1) ?? string.Empty;
                                message.ReturnAddress = reader.GetString(2);
                                message.MessageIntent = (MessageIntentEnum)reader.GetByte(3);
                                message.HeadersString = reader.GetString(4) ?? string.Empty;
                                message.BodyString = reader.GetString(5) ?? string.Empty;
                                try
                                {
                                    using (var bodyStream = new MemoryStream(Encoding.UTF8.GetBytes(message.BodyString)))
                                    {
                                        message.Body = MessageSerializer.Deserialize(bodyStream);
                                    }
                                    if (message.HeadersString.Length > 0)
                                    {
                                        using (var headersStream = new MemoryStream(Encoding.UTF8.GetBytes(message.HeadersString)))
                                        {
                                            message.Headers = MessageSerializer.Deserialize(headersStream).Cast<HeaderInfo>().ToList();
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Logger.Error("Could not extract message data.", ex);
                                    OnSerializationFailed(id, message, message.BodyString, message.HeadersString, ex);
                                    return; // deserialization failed - no reason to try again, so don't throw
                                }
                            }
                        }
                        if (message == null)
                        {
                            backoff.Wait(() => true);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Error("Error in receiving message from queue.", e);
                throw; // Throw to rollback 
            }
            finally
            {
                transactionWaitPool.Release(1);
                releasedWaitLock = true;
            }

            // No message? That's okay
            if (message == null)
            {
                return;
            }

            // Set the correlation Id
            if (string.IsNullOrEmpty(message.IdForCorrelation))
            {
                message.IdForCorrelation = message.Id;
            }
            ProcessMessage(message);
        }
コード例 #10
0
 private void WriteFailedMessage(Guid messageId, Message serviceBrokerMessage, TransportMessage transportMessage, Exception exception, int status) {
     try {
         // Write a failed message
         TransactionWrapper.RunInTransaction(transaction => {
             using (var command = transaction.Connection.CreateCommand()) {
                 command.CommandText = "cw_InsertFailedMessage";
                 command.CommandType = CommandType.StoredProcedure;
                 if (transportMessage != null)
                     command.Parameters.AddWithValue("@originService", transportMessage.ReturnAddress);
                 else
                     command.Parameters.AddWithValue("@originService", string.Empty);
                 command.Parameters.AddWithValue("@queueName", this.ListenerQueue);
                 command.Parameters.AddWithValue("@queueService", this.ReturnAddress);
                 command.Parameters.AddWithValue("@messageId", messageId);
                 command.Parameters.AddWithValue("@messageStatus", (int)status);
                 command.Parameters.AddWithValue("@messageData", serviceBrokerMessage.Body);
                 if (exception != null)
                     command.Parameters.AddWithValue("@errorMessage", FormatErrorMessage(exception));
                 else
                     command.Parameters.AddWithValue("@errorMessage", DBNull.Value);
                 command.Transaction = transaction;
                 command.ExecuteNonQuery();
             }
         });
     } catch (Exception e) {
         Logger.Fatal("Failed to write ServiceBroker Error Message", e);
         // suppress -- don't let this exception take down the process
     }
 }
コード例 #11
0
 private void SendFailureMessage(TransportMessage message, Exception e, string reason)
 {
     if (message == null)
         return;
     message.MessageIntent = MessageIntentEnum.FaultNotification;
     SetExceptionHeaders(message, e, reason);
     try
     {
         Send(message, this.faultForwardDestinations);
     }
     catch (Exception exception)
     {
         var errorMessage = string.Format("Could not forward failed message to error queue, reason: {0}.", exception.ToString());
         Logger.Fatal(errorMessage, exception);
         throw new InvalidOperationException(errorMessage, exception);
     }
 }
コード例 #12
0
        public void Send(TransportMessage toSend, IEnumerable<string> destinations)
        {
            var destinationQueue = string.Empty;
            try
            {
                TransactionWrapper.RunInTransaction(transaction =>
                {
                    var id = Guid.NewGuid();
                    toSend.Id = id.ToString();
                    toSend.TimeSent = DateTime.UtcNow;
                    toSend.ReturnAddress = this.ListenerQueue;
                    var serializedMessage = string.Empty;
                    var messages = "";
                    var headers = "";
                    using (var stream = new MemoryStream())
                    {
                        MessageSerializer.Serialize(toSend.Body, stream);
                        messages = Encoding.UTF8.GetString(stream.ToArray());
                    }
                    if (toSend.Headers != null && toSend.Headers.Count > 0)
                    {
                        using (var stream = new MemoryStream())
                        {
                            MessageSerializer.Serialize(toSend.Headers.ToArray(), stream);
                            headers = Encoding.UTF8.GetString(stream.ToArray());
                        }
                    }
                    using (var cmd = transaction.Connection.CreateCommand())
                    {
                        cmd.Transaction = transaction;
                        cmd.Parameters.AddWithValue("@Id", id);
                        var paramCorrelationId = cmd.Parameters.AddWithValue("@CorrelationId", toSend.CorrelationId ?? string.Empty);
                        paramCorrelationId.SqlDbType = SqlDbType.VarChar;
                        paramCorrelationId.Size = 255;
                        var paramReplyToAddress = cmd.Parameters.AddWithValue("@ReplyToAddress", this.ListenerQueue);
                        paramReplyToAddress.SqlDbType = SqlDbType.VarChar;
                        paramReplyToAddress.Size = 255;
                        cmd.Parameters.AddWithValue("@MessageIntent", (byte)toSend.MessageIntent);

                        var paramHeaders = cmd.Parameters.AddWithValue("@Headers", headers);
                        paramHeaders.Size = -1;
                        var paramBody = cmd.Parameters.AddWithValue("@Body", messages);
                        paramBody.Size = -1;
                        foreach (var destination in destinations)
                        {
                            destinationQueue = destination;
                            cmd.CommandText = string.Format(SqlCommands.InsertMessage, destination);
                            cmd.ExecuteNonQuery();
                            if (Logger.IsDebugEnabled)
                                Logger.Debug(string.Format("Sending message {0} with ID {1} to destination {2}.\n" +
                                                   "ToString() of the message yields: {3}\n" +
                                                   "Message headers:\n{4}",
                                                   toSend.Body[0].GetType().AssemblyQualifiedName,
                                                   toSend.Id,
                                                   destination,
                                                   toSend.Body[0],
                                                   string.Join(", ", toSend.Headers.Select(h => h.Key + ":" + h.Value).ToArray())
                            ));
                        }
                    }
                });
            }
            catch (SqlException ex)
            {
                if (ex.Number == 208)
                {
                    var msg = string.Format("Failed to send message to address: [{0}]", destinationQueue);
                    throw new QueueNotFoundException(toSend, msg, ex);
                }
            }
        }
コード例 #13
0
        private Exception OnStartedMessageProcessing(TransportMessage msg)
        {
            try
            {
                if (StartedMessageProcessing != null)
                    StartedMessageProcessing(this, new StartedMessageProcessingEventArgs(msg));
            }
            catch (Exception e)
            {
                Logger.Error("Failed raising 'started message processing' event.", e);
                return e;
            }

            return null;
        }
コード例 #14
0
 public MessageContext(TransportMessage transportMessage)
 {
     this.transportMessage = transportMessage;
 }
コード例 #15
0
 public TransportMessageReceivedEventArgs(TransportMessage m) {
     message = m;
 }
コード例 #16
0
 public QueueNotFoundException(TransportMessage transportMessage, string message, SqlException innerException)
     : base(message, innerException)
 {
     this.TransportMessage = transportMessage;
 }
コード例 #17
0
 public TransportMessageFaultEventArgs(TransportMessage m, Exception e, string reason)
 {
     Message   = m;
     Exception = e;
     Reason    = reason;
 }
コード例 #18
0
 public TransportMessageFaultEventArgs(TransportMessage m, Exception e, string reason) {
     Message = m;
     Exception = e;
     Reason = reason;
 }
コード例 #19
0
 private Exception OnTransportMessageReceived(TransportMessage msg)
 {
     try
     {
         if (TransportMessageReceived != null)
             TransportMessageReceived(this, new TransportMessageReceivedEventArgs(msg));
     }
     catch (Exception e)
     {
         var originalException = e;
         if (e is TransportMessageHandlingFailedException)
             originalException = ((TransportMessageHandlingFailedException)e).OriginalException;
         Logger.Warn("Failed raising 'transport message received' event for message with ID=" + msg.Id, originalException);
         return e;
     }
     return null;
 }
コード例 #20
0
 public StartedMessageProcessingEventArgs(TransportMessage m) {
     message = m;
 }
コード例 #21
0
 private void WriteFailedMessage(TransportMessage transportMessage, Exception exception, string originalBody, string originalHeaders)
 {
     try
     {
         // Write a failed message
         TransactionWrapper.RunInTransaction(transaction =>
         {
             using (var command = transaction.Connection.CreateCommand())
             {
                 command.CommandText = SqlCommands.InsertPoisonMessage;
                 var paramQueue = command.Parameters.AddWithValue("@Queue", this.ListenerQueue);
                 paramQueue.Size = 255;
                 command.Parameters.AddWithValue("@InsertDateTime", DateTime.UtcNow);
                 command.Parameters.AddWithValue("@Id", Guid.Parse(transportMessage.Id));
                 var paramCorrelationId = command.Parameters.AddWithValue("@CorrelationId", transportMessage.CorrelationId ?? string.Empty);
                 paramCorrelationId.SqlDbType = SqlDbType.VarChar;
                 paramCorrelationId.Size = 255;
                 var paramReplyToAddress = command.Parameters.AddWithValue("@ReplyToAddress", transportMessage.ReturnAddress);
                 paramReplyToAddress.SqlDbType = SqlDbType.VarChar;
                 paramReplyToAddress.Size = 255;
                 command.Parameters.AddWithValue("@MessageIntent", (byte)transportMessage.MessageIntent);
                 var paramHeaders = command.Parameters.AddWithValue("@Headers", originalHeaders ?? string.Empty);
                 paramHeaders.Size = -1;
                 var paramBody = command.Parameters.AddWithValue("@Body", originalBody ?? string.Empty);
                 paramBody.Size = -1;
                 if (exception != null)
                 {
                     var paramException = command.Parameters.AddWithValue("@Exception", FormatErrorMessage(exception));
                     paramException.Size = -1;
                 }
                 else
                 {
                     command.Parameters.AddWithValue("@Exception", DBNull.Value);
                 }
                 command.Transaction = transaction;
                 command.ExecuteNonQuery();
             }
         });
     }
     catch (Exception e)
     {
         Logger.Fatal("Failed to write ServiceBroker Error Message", e);
         // suppress -- don't let this exception take down the process
     }
 }
コード例 #22
0
 private TransportMessage MakeTransportMessage(params IMessage[] input)
 {
     var transportMessage = new TransportMessage();
     transportMessage.Id = Guid.NewGuid().ToString();
     transportMessage.IdForCorrelation = Guid.NewGuid().ToString();
     transportMessage.ReturnAddress = Guid.NewGuid().ToString();
     transportMessage.WindowsIdentityName = string.Empty;
     transportMessage.TimeSent = DateTime.Now;
     transportMessage.Headers = new List<HeaderInfo>();
     transportMessage.Body = input;
     return transportMessage;
 }
コード例 #23
0
        private void SetExceptionHeaders(TransportMessage message, Exception e, string reason)
        {
            if (message.Headers == null)
                message.Headers = new List<HeaderInfo>();
            message.Headers.Add(new HeaderInfo() { Key = "CWServiceBus.ExceptionInfo.Reason", Value = reason });
            message.Headers.Add(new HeaderInfo() { Key = "CWServiceBus.ExceptionInfo.ExceptionType", Value = e.GetType().FullName });

            if (e.InnerException != null)
                message.Headers.Add(new HeaderInfo() { Key = "CWServiceBus.ExceptionInfo.InnerExceptionType", Value = e.InnerException.GetType().FullName });

            message.Headers.Add(new HeaderInfo() { Key = "CWServiceBus.ExceptionInfo.HelpLink", Value = e.HelpLink });
            message.Headers.Add(new HeaderInfo() { Key = "CWServiceBus.ExceptionInfo.Message", Value = e.Message });
            message.Headers.Add(new HeaderInfo() { Key = "CWServiceBus.ExceptionInfo.Source", Value = e.Source });
            message.Headers.Add(new HeaderInfo() { Key = "CWServiceBus.ExceptionInfo.StackTrace", Value = e.StackTrace });

            message.Headers.Add(new HeaderInfo() { Key = "CWServiceBus.OriginalId", Value = message.Id });
            message.Headers.Add(new HeaderInfo() { Key = "CWServiceBus.FaultedAddress", Value = this.ListenerQueue });
            message.Headers.Add(new HeaderInfo() { Key = "CWServiceBus.SqlServer.FaultedQueue", Value = this.ListenerQueue });
            message.Headers.Add(new HeaderInfo() { Key = "CWServiceBus.TimeOfFailure", Value = DateTime.UtcNow.ToString("o") });

        }
コード例 #24
0
 public void Send(TransportMessage toSend, IEnumerable<string> destinations) {
     TransactionWrapper.RunInTransaction(transaction => {
         toSend.TimeSent = DateTime.UtcNow;
         toSend.ReturnAddress = this.ReturnAddress;
         var serializedMessage = string.Empty;
         using (var stream = new MemoryStream()) {
             TransportMessageSerializer.Serialize(toSend, stream);
             foreach (var destination in destinations) {
                 var conversationHandle = ServiceBrokerWrapper.SendOne(transaction, ReturnAddress, destination, NServiceBusTransportMessageContract, NServiceBusTransportMessage, stream.ToArray());
                 toSend.Id = conversationHandle.ToString();
                 if (Logger.IsDebugEnabled)
                     Logger.Debug(string.Format("Sending message {0} with ID {1} to destination {2}.\n" +
                                        "ToString() of the message yields: {3}\n" +
                                        "Message headers:\n{4}",
                                        toSend.Body[0].GetType().AssemblyQualifiedName,
                                        toSend.Id,
                                        destination,
                                        toSend.Body[0],
                                        string.Join(", ", toSend.Headers.Select(h => h.Key + ":" + h.Value).ToArray())
                 ));
             }
         }
     });
 }