Skip to content

The search box in the website knows all the secrets—try it!

For any queries, join our Discord Channel to reach us faster.

JasperFx Logo

JasperFx provides formal support for Wolverine and other JasperFx libraries. Please check our Support Plans for more details.

Conventional Message Routing

Lastly, you can have Wolverine automatically determine message routing to Azure Service Bus based on conventions as shown in the code snippet below. By default, this approach assumes that each outgoing message type should be sent to queue named with the message type name for that message type.

Likewise, Wolverine sets up a listener for a queue named similarly for each message type known to be handled by the application.

cs
var builder = Host.CreateApplicationBuilder();
builder.UseWolverine(opts =>
{
    // One way or another, you're probably pulling the Azure Service Bus
    // connection string out of configuration
    var azureServiceBusConnectionString = builder
        .Configuration
        .GetConnectionString("azure-service-bus")!;

    // Connect to the broker in the simplest possible way
    opts.UseAzureServiceBus(azureServiceBusConnectionString).AutoProvision()
        .UseConventionalRouting(convention =>
        {
            // Optionally override the default queue naming scheme
            convention.QueueNameForSender(t => t.Namespace)

                // Optionally override the default queue naming scheme
                .QueueNameForListener(t => t.Namespace)

                // Fine tune the conventionally discovered listeners
                .ConfigureListeners((listener, builder) =>
                {
                    var messageType = builder.MessageType;
                    var runtime = builder.Runtime; // Access to basically everything

                    // customize the new queue
                    listener.CircuitBreaker(queue => { });

                    // other options...
                })

                // Fine tune the conventionally discovered sending endpoints
                .ConfigureSending((subscriber, builder) =>
                {
                    // Similarly, use the message type and/or wolverine runtime
                    // to customize the message sending
                });
        });
});

using var host = builder.Build();
await host.StartAsync();

snippet source | anchor

Route to Topics and Subscriptions 1.6.0

You can also opt into conventional routing using topics and subscriptions named after the message type names like this:

cs
opts.UseAzureServiceBusTesting()
    .UseTopicAndSubscriptionConventionalRouting(convention =>
    {
        // Optionally control every aspect of the convention and
        // its applicability to types
        // as well as overriding any listener, sender, topic, or subscription
        // options

        // Can't use the full name because of limitations on name length
        convention.SubscriptionNameForListener(t => t.Name.ToLowerInvariant());
        convention.TopicNameForListener(t => t.Name.ToLowerInvariant());
        convention.TopicNameForSender(t => t.Name.ToLowerInvariant());
    })

    .AutoProvision()
    .AutoPurgeOnStartup();

snippet source | anchor

Handler Type Naming 5.25

By default, conventional routing names queues after the message type. In modular monolith scenarios where you have more than one handler for a given message type and want each handler to receive messages on its own dedicated queue, you can opt into naming queues after the handler type instead:

cs
opts.UseAzureServiceBus(connectionString)
    // Name listener queues after the handler type instead of the message type
    .UseConventionalRouting(NamingSource.FromHandlerType);

This also works with the topic/subscription variant:

cs
opts.UseAzureServiceBus(connectionString)
    .UseTopicAndSubscriptionConventionalRouting(NamingSource.FromHandlerType);

With NamingSource.FromHandlerType, each handler class gets its own dedicated queue or subscription named after the handler type. This ensures that each handler independently receives a copy of every message. Outgoing queue/topic names are still derived from the message type.

Separated Handler Behavior 4.12

In the case of using the MultipleHandlerBehavior.Separated mode, this convention will create a subscription for each separate handler using the handler type to derive the subscription name and the message type to derive the topic name. Both the topic and subscription are declared by the transport if using the AutoProvision() setting.

Released under the MIT License.