Question

How is NServiceBus maintaining consistency when the outgoing headers is static?

Does it mean if I were to set the outgoing headers for a particular message, it will affect all other outgoing messages since it's a singleton?

namespace NServiceBus.MessageHeaders
{
  [ComVisible(false)]
  public class MessageHeaderManager : IMutateOutgoingTransportMessages
  {
    private static IDictionary<string, string> staticOutgoingHeaders = (IDictionary<string, string>) new Dictionary<string, string>();
    private IUnicastBus bus;
    [ThreadStatic]
    private static IDictionary<object, IDictionary<string, string>> messageHeaders;
   .
   .
   .
 }

The incoming header seems to be correctly marked as [ThreadStatic] however.

Explain.

========================EDIT==============================

I guess I'm trying to understand because many examples show the code below:

Bus.OutgoingHeaders["Test"] = g.ToString("N");

Which's traced to:

IDictionary<string, string> IBus.OutgoingHeaders
{
  get
  {
    return ExtensionMethods.GetStaticOutgoingHeadersAction();
  }
}

Which's set at:

internal class Bootstrapper : INeedInitialization, IWantToRunWhenConfigurationIsComplete { public MessageHeaderManager Manager { get; set; }

void INeedInitialization.Init()
{
  Configure.Instance.Configurer.ConfigureComponent<MessageHeaderManager>(DependencyLifecycle.SingleInstance);
}

public void Run()
{
  ExtensionMethods.GetHeaderAction = (Func<object, string, string>) ((msg, key) => this.Manager.GetHeader(msg, key));
  ExtensionMethods.SetHeaderAction = (Action<object, string, string>) ((msg, key, val) => this.Manager.SetHeader(msg, key, val));
  ExtensionMethods.GetStaticOutgoingHeadersAction = (Func<IDictionary<string, string>>) (() => this.Manager.GetStaticOutgoingHeaders());
}

}

And of course the GetStaticOutgoingHeaders in the last line above goes to a static field.

I'm trying to figure out how to set the header, for the next message. But if I follow the examples, I end up setting the headers for ALL messages.

Was it helpful?

Solution

[Update by Udi] If you want to set a header on a specific message that you're sending, just call the .SetHeader(key, value); method on the message object. The static outgoing headers is useful for process-wide data like who the logged-in user is in a desktop application.[End update]

MessageHeaderManager is a IMutateOutgoingTransportMessages which means it only is concerned with messages on their way out. There are no incoming message headers on display here.

messageHeaders is concerned with headers that are set per-message, like time sent, or anything you would set manually from a message handler.

staticOutgoingHeaders is a place to cache all headers that are the same for every single message out of an endpoint so that their values don't need to be recalculated. This would include things like the source machine name.

If you look into the guts of that MutateOutgoing method, you will see that all of the key/value pairs from both messageHeaders and staticOutgoingHeaders are added to the transportMessage.Headers collection. Additionally, the static ones are added with Headers.Add(key, value) while the thread-static headers are added via Headers[key] = value so that an item from the thread-static collection would override a static header of the same name.

Here's a link to the full source for this class on GitHub, linked by the tag for V4.0.3 (current at time of writing) so hopefully that link won't expire.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top