Version

1.1.2

Next

RabbitMQ Transport

Previous

TCP Transport

Azure Service Bus Transport


Note! For the moment, Jasper requires all queues and subscriptions in Azure Service Bus to be configured with sessions enabled.

Quick Start

Note! Jasper uses the Microsoft.Azure.ServiceBus Nuget library for accessing Azure Service Bus.

If you're starting a fresh project, you can quickly spin up a new Jasper project using Azure Service Bus with a dotnet new template.

First install the JasperTemplates nuget like so:

dotnet new --install JasperTemplates

Then build out the directory for your intended project, and use:

dotnet new jasper.azureservicebus

Then check the README.md file in the generated directory for an overview of what was generated for you.

Getting Started

All the sample code in this section is available on GitHub in the sample projects.

The only thing you need to do is to install the Jasper.AzureServiceBus Nuget to your Jasper application. This will add the client libraries for Azure Service Bus access and add the transport to your application automatically.

In terms of configuration, there's a few things to worry about:

  1. The Azure Service Bus connection string
  2. Configuring Jasper listeners and subscribers
  3. Optionally, you can also override how Jasper maps Envelope properties to Azure Service Bus messages in the case of communicating with a non-Jasper application

Here's a sample of a basic ping/pong application that uses Jasper's Azure Service Bus support:


internal class JasperConfig : JasperOptions
{
    public JasperConfig()
    {
        // Publish all messages to an Azure Service Bus queue
        Endpoints
            .PublishAllMessages()
            .ToAzureServiceBusQueue("pings");

        // Listen to incoming messages from an Azure Service Bus
        // queue
        Endpoints.ListenToAzureServiceBusQueue("pongs");

        // Because Jasper rides on top of the built in
        // .Net Core generic host, you can use the
        // IHostedService
        Services.AddHostedService<PingerService>();
    }
}

For more information about Azure Service Bus connection strings, see Get started with Service Bus queues.

The Azure Service Bus connection string is the only required configuration, but you can also exert some fine grained control over the underlying Azure Service Bus client objects like so:


public class JasperWithAzureServiceBusApp : JasperOptions
{
    public JasperWithAzureServiceBusApp()
    {
        Endpoints.ConfigureAzureServiceBus(asb =>
        {

            asb.ConnectionString = "an Azure Service Bus connection string";

            // The following properties would be set on all
            // TopicClient, QueueClient, or SubscriptionClient
            // objects created at runtime
            asb.TransportType = TransportType.AmqpWebSockets;
            asb.TokenProvider = new ManagedServiceIdentityTokenProvider();
            asb.ReceiveMode = ReceiveMode.ReceiveAndDelete;
            asb.RetryPolicy = RetryPolicy.NoRetry;
        });

        // Configure endpoints
        Endpoints.PublishAllMessages().ToAzureServiceBusQueue("outgoing");
        Endpoints.ListenToAzureServiceBusQueue("incoming");
    }


}

If all you care about is the Azure Service Bus connection string, there is an overload shortcut like this example:


internal class JasperConfig : JasperOptions
{
    public JasperConfig()
    {
        // Publish all messages to an Azure Service Bus queue
        Endpoints
            .PublishAllMessages()
            .ToAzureServiceBusQueue("pings")

            // Optionally use the store and forward
            // outbox mechanics against this endpoint
            .Durably();

        // Listen to incoming messages from an Azure Service Bus
        // queue
        Endpoints
            .ListenToAzureServiceBusQueue("pongs");
    }

    public override void Configure(IHostEnvironment hosting, IConfiguration config)
    {
        var connectionString = config.GetConnectionString("azureservicebus");
        Endpoints.ConfigureAzureServiceBus(connectionString);
    }
}

Subscribe and Publish Messages to a named Queue

Below is a sample of configuring both a listener and a publisher endpoint to a named Azure Service Bus queue:


internal class JasperConfig : JasperOptions
{
    public JasperConfig()
    {
        // Publish all messages to an Azure Service Bus queue
        Endpoints
            .PublishAllMessages()
            .ToAzureServiceBusQueue("pings")

            // Optionally use the store and forward
            // outbox mechanics against this endpoint
            .Durably();

        // Listen to incoming messages from an Azure Service Bus
        // queue
        Endpoints
            .ListenToAzureServiceBusQueue("pongs");
    }

    public override void Configure(IHostEnvironment hosting, IConfiguration config)
    {
        var connectionString = config.GetConnectionString("azureservicebus");
        Endpoints.ConfigureAzureServiceBus(connectionString);
    }
}

Alternatively, you could use Uri values instead like so:


internal class JasperConfig2 : JasperOptions
{
    public JasperConfig2()
    {
        // Publish all messages to an Azure Service Bus queue
        Endpoints
            .PublishAllMessages()
            .To("asb://queue/pings");


        // Listen to incoming messages from an Azure Service Bus
        // queue
        Endpoints
            .ListenForMessagesFrom("asb://queue/pongs")
            .UseForReplies();
    }

    public override void Configure(IHostEnvironment hosting, IConfiguration config)
    {
        var connectionString = config.GetConnectionString("azureservicebus");
        Endpoints.ConfigureAzureServiceBus(connectionString);
    }
}

Just note that there are some Azure Service Bus specific settings for listeners and senders that won't be exposed through the generic register by Uri mechanisms.

Subscribe and Publish Messages for a specific Topic

To publish or subscribe to a specific, named Azure Service Bus topic, use the syntax shown below:


internal class JasperConfig3 : JasperOptions
{
    public JasperConfig3()
    {
        // Publish all messages to an Azure Service Bus queue
        Endpoints
            .PublishAllMessages()
            .ToAzureServiceBusTopic("pings")

            // Optionally use the store and forward
            // outbox mechanics against this endpoint
            .Durably();

        // Listen to incoming messages from an Azure Service Bus
        // queue
        Endpoints
            .ListenToAzureServiceBusTopic("pongs", "pong-subscription");
    }

    public override void Configure(IHostEnvironment hosting, IConfiguration config)
    {
        var connectionString = config.GetConnectionString("azureservicebus");
        Endpoints.ConfigureAzureServiceBus(connectionString);
    }
}

Alternatively, you could use Uri values instead like so:


internal class JasperConfig4 : JasperOptions
{
    public JasperConfig4()
    {
        // Publish all messages to an Azure Service Bus queue
        Endpoints
            .PublishAllMessages()
            .To("asb://topic/pings");


        // Listen to incoming messages from an Azure Service Bus
        // queue
        Endpoints
            .ListenForMessagesFrom("asb://topic/pongs/subscription/pong-subscription")
            .UseForReplies();
    }

    public override void Configure(IHostEnvironment hosting, IConfiguration config)
    {
        var connectionString = config.GetConnectionString("azureservicebus");
        Endpoints.ConfigureAzureServiceBus(connectionString);
    }
}

Just note again that there are some Azure Service Bus specific settings for listeners and senders that won't be exposed through the generic register by Uri mechanisms.

See Get started with Service Bus topics for more information;

Scheduled Messages

Jasper happily uses Azure Service Bus scheduled messaging functionality behind the scenes when you use Jasper's ScheduleSend() functionality. See Scheduled Message Delivery and Execution for more information.

Connecting to non-Jasper Applications

Lastly, you may want to use the Azure Service Bus transport to integrate with other applications that aren't using Jasper. To make that work, you may need to do some mapping between Jasper's Envelope structure and Azure Service Bus's Message structure using a custom implementation of Jasper.AzureServiceBus.IAzureServiceBusProtocol.

That interface is shown below:


public interface IAzureServiceBusProtocol
{
    Message WriteFromEnvelope(Envelope envelope);

    Envelope ReadEnvelope(Message message);
}

And here's what the default protocol looks like because it's likely easier to start with this than build something all new:



public class SpecialAzureServiceBusProtocol : DefaultAzureServiceBusProtocol
{
    public override Message WriteFromEnvelope(Envelope envelope)
    {
        var message = base.WriteFromEnvelope(envelope);

        // Override some properties from how
        // Jasper itself would write them out
        message.ReplyTo = "replies";

        return message;
    }

    public override Envelope ReadEnvelope(Message message)
    {
        var envelope = base.ReadEnvelope(message);

        if (message.ReplyTo.IsNotEmpty())
        {
            var uriString = "asb://topic/" + message.ReplyTo;
        }

        return envelope;
    }
}

Lastly, to apply the protocol, use the mechanism shown below:


internal class JasperConfig5 : JasperOptions
{
    public JasperConfig5()
    {
        // Publish all messages to an Azure Service Bus queue
        Endpoints
            .PublishAllMessages()
            .ToAzureServiceBusTopic("pings")

            // Override the Azure Service Bus protocol
            // because it's not a Jasper application on the other end
            .Protocol<SpecialAzureServiceBusProtocol>()

            // Optionally use the store and forward
            // outbox mechanics against this endpoint
            .Durably();

        // Listen to incoming messages from an Azure Service Bus
        // queue
        Endpoints
            .ListenToAzureServiceBusTopic("pongs", "pong-subscription");
    }

    public override void Configure(IHostEnvironment hosting, IConfiguration config)
    {
        var connectionString = config.GetConnectionString("azureservicebus");
        Endpoints.ConfigureAzureServiceBus(connectionString);
    }
}