Bootstrapping & Configuration
As of the 1.0 release, Jasper plays entirely within the existing .Net Core ecosystem and depends on the generic hosting released as part of .Net Core 3.0 (IHostBuilder
) for bootstrapping.
All Jasper configuration starts with the JasperOptions class and the UseJasper()
extension method that hangs off of IHostBuilder
.
Say that you are starting with the dotnet new worker
template to build a headless Jasper
application (i.e., no HTTP endpoints and no user interface of any kind). After adding a reference to the Jasper nuget,
the Program
class would look like this:
public class Program
{
// The Jasper-ified version
public static Task<int> Main(string[] args)
{
return CreateHostBuilder().RunJasper(args);
}
public static IHostBuilder CreateHostBuilder() =>
Host.CreateDefaultBuilder()
// This adds Jasper with a default JasperOptions
.UseJasper()
.ConfigureServices((hostContext, services) =>
{
// If you're not familiar with IHostedService,
// it's a .Net Core mechanism to start and stop
// long running routines within a .Net Core application
services.AddHostedService<Worker>();
});
}
Do be aware that Jasper can only function with Lamar as the underlying IoC container and
the call to UseJasper()
quietly replaces the built in ASP.Net Core DI container with Lamar.
See IoC Container Integration for more information.
Applying Jasper to a .Net Generic Host
We already saw above how to call UseJasper()
with no arguments to add Jasper with all the defaults, but outside of using Jasper as just an in memory mediator, you'll need some further configuration.
If your Jasper configuration is relatively simple, you can modify the JasperOptions
directly as shown in this overload of UseJasper(Action<JasperOptions>)
:
public static IHostBuilder CreateHostBuilder() =>
Host.CreateDefaultBuilder()
// This adds Jasper with inline configuration
// of JasperOptions
.UseJasper(opts =>
{
opts.Extensions.UseMessageTrackingTestingSupport();
});
If you need to lookup configuration items like connection strings, ports, file paths, and other similar items from application configuration -- or need to vary the Jasper configuration by hosting environment -- you can use this overload:
public static IHostBuilder CreateHostBuilder() =>
Host.CreateDefaultBuilder()
// This adds Jasper with inline configuration
// of JasperOptions
.UseJasper((context, opts) =>
{
// This is an example usage of the application's
// IConfiguration inside of Jasper bootstrapping
var port = context.Configuration.GetValue<int>("ListenerPort");
opts.Endpoints.ListenAtPort(port);
// If we're running in development mode and you don't
// want to worry about having all the external messaging
// dependencies up and running, stub them out
if (context.HostingEnvironment.IsDevelopment())
{
// This will "stub" out all configured external endpoints
opts.Endpoints.StubAllExternallyOutgoingEndpoints();
opts.Extensions.UseMessageTrackingTestingSupport();
}
});
Lastly, if you have more complex Jasper configuration, you may want to opt for a custom JasperOptions
type. Let's say we have a class called CustomJasperOptions
that inherits from JasperOptions
like this:
public class MyJasperApp : JasperOptions
{
public MyJasperApp()
{
ServiceName = "My Jasper App";
Endpoints.ListenAtPort(2111).Durable();
}
}
That can be applied to a .Net Core application like this:
public static IHostBuilder CreateHostBuilder() =>
Host.CreateDefaultBuilder()
.UseJasper<CustomJasperOptions>();
Jasper with ASP.Net Core
Adding Jasper to an ASP.Net Core application -- with or without MVC -- isn't really any different. You still use the UseJasper()
extension method like in this example:
public class Program
{
// Change the return type to Task<int> to communicate
// success/failure codes
public static Task<int> Main(string[] args)
{
return CreateHostBuilder(args)
// This replaces Build().Start() from the default
// dotnet new templates
.RunJasper(args);
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
// You can do the Jasper configuration inline with a
// Lambda, but here I've centralized the Jasper
// configuration into a separate class
.UseJasper<JasperConfig>()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
JasperOptions
The custom JasperOptions
class shown below demonstrates the main features you can configure or extend for a Jasper application:
public class JasperOptionsWithEverything : JasperOptions
{
public JasperOptionsWithEverything()
{
// This is strictly for logging and diagnostics identification
// By default, this is just the name of the main application
// assembly
ServiceName = "MyService";
// Extensions lets you apply or query Jasper extensions
Extensions.UseMessageTrackingTestingSupport();
// Idiomatic Lamar service registrations to be applied to the
// application's underlying IoC container
Services.For<IClock>().Use<Clock>();
// Fine-tune how message handler types are discovered
// and built. Also allows you to add middleware policies
Handlers.DisableConventionalDiscovery();
}
// This method is an optional override for additional
// Jasper configuration that is dependent upon either the
// hosting environment name or the application configuration
public override void Configure(IHostEnvironment hosting, IConfiguration config)
{
// Endpoints controls everything about where and how
// Jasper receives incoming or sends outgoing messages
// For the moment, this also gives you access to fine-tuning
// the in-process worker queues for the local transport
var incomingPort = config.GetValue<int>("incoming_port");
Endpoints.ListenAtPort(incomingPort);
var outgoingPort = config.GetValue<int>("outgoing_port");
Endpoints.PublishAllMessages().ToPort(outgoingPort);
Endpoints.LocalQueue("worker1").Sequential();
}
}
The major areas are:
ServiceName
-- see the section belowExtensions
-- see ExtensionsAdvanced
-- most of these properties are related to message persistence. See Durable Messaging and Command Processing for more informationServices
-- see IoC Container IntegrationHandlers
-- see Execution PipelineEndpoints
-- see Messaging Transports