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:
- The Azure Service Bus connection string
- Configuring Jasper listeners and subscribers
- 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);
}
}