### Start Local Development Server Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/website/README.md Starts a local development server for live preview. Changes are reflected without server restart. ```bash $ yarn start ``` -------------------------------- ### Add ArtemisNetClient.Testing NuGet Package Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/testing.md Install the testing package using the .NET CLI. ```bash dotnet add package ArtemisNetClient.Testing ``` -------------------------------- ### Install Dependencies Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/website/README.md Installs project dependencies using Yarn. ```bash $ yarn ``` -------------------------------- ### Add ArtemisNetClient.Extensions.DependencyInjection Package Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/src/ArtemisNetClient.Extensions.DependencyInjection/README.md Installs the ArtemisNetClient.Extensions.DependencyInjection package using the .NET CLI. ```bash dotnet add package ArtemisNetClient.Extensions.DependencyInjection ``` -------------------------------- ### Complete Example: Multi-Criteria Filtering Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Demonstrates creating a consumer with a complex filter expression and sending messages to test the filtering logic. ```csharp await using var connection = await connectionFactory.CreateAsync(endpoint); var address = "orders"; // Create consumer that only receives high-priority, pending orders for the premium tier await using var consumer = await connection.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Anycast, FilterExpression = "AMQPriority >= 7 AND status = 'pending' AND tier = 'premium'" }); // Create producer and send various messages await using var producer = await connection.CreateProducerAsync(address, RoutingType.Anycast); // This message will be received (matches all criteria) await producer.SendAsync(new Message("order1") { Priority = 9, ApplicationProperties = { ["status"] = "pending", ["tier"] = "premium" } }); // This message will NOT be received (priority too low) await producer.SendAsync(new Message("order2") { Priority = 4, ApplicationProperties = { ["status"] = "pending", ["tier"] = "premium" } }); // This message will NOT be received (wrong status) await producer.SendAsync(new Message("order3") { Priority = 8, ApplicationProperties = { ["status"] = "completed", ["tier"] = "premium" } }); var message = await consumer.ReceiveAsync(cancellationToken); Console.WriteLine(message.GetBody()); // Output: "order1" ``` -------------------------------- ### Start Docker Compose for Broker Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/CLAUDE.md Starts the ActiveMQ Artemis broker using Docker Compose. This is a prerequisite for running integration tests. ```bash cd test/artemis && docker-compose up -V -d ``` -------------------------------- ### Minimal ASP.NET Core Setup with ArtemisNetClient Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/dependency-injection.md Demonstrates registering and configuring ArtemisNetClient services, including a connection, a consumer, and a producer, within an ASP.NET Core application's dependency injection container. ```csharp var builder = WebApplication.CreateBuilder(args); builder.Services.AddActiveMqHostedService(); var endpoint = Endpoint.Create( host: "localhost", port: 5672, user: "artemis", password: "artemis"); var activeMq = builder.Services.AddActiveMq( name: "my-artemis", endpoints: new[] { endpoint }); activeMq.AddConsumer( address: "orders.incoming", routingType: RoutingType.Anycast, handler: async (message, consumer, serviceProvider, cancellationToken) => { var publisher = serviceProvider.GetRequiredService(); var orderId = message.GetBody(); await publisher.AcceptAsync(orderId, cancellationToken); await consumer.AcceptAsync(message); }); activeMq.AddProducer("orders.events", RoutingType.Multicast); var app = builder.Build(); app.Run(); public sealed class OrderEventsProducer { private readonly IProducer _producer; public OrderEventsProducer(IProducer producer) => _producer = producer; public Task PublishAccepted(string orderId, CancellationToken cancellationToken) { return _producer.SendAsync(new Message($"accepted:{orderId}"), cancellationToken); } } ``` -------------------------------- ### Add ArtemisNetClient NuGet Package Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Install the ActiveMQ.Artemis.Client NuGet package using the dotnet CLI. ```bash dotnet add package ArtemisNetClient ``` -------------------------------- ### Add Dependency Injection Packages Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/README.md Install NuGet packages for integrating ArtemisNetClient with Microsoft.Extensions.DependencyInjection and ASP.NET Core. ```bash dotnet add package ArtemisNetClient.Extensions.DependencyInjection dotnet add package ArtemisNetClient.Extensions.Hosting ``` -------------------------------- ### Add ArtemisNetClient.Extensions.Hosting Package Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/src/ArtemisNetClient.Extensions.DependencyInjection/README.md Installs the ArtemisNetClient.Extensions.Hosting package using the .NET CLI. This is often used in conjunction with the dependency injection package for hosted applications. ```bash dotnet add package ArtemisNetClient.Extensions.Hosting ``` -------------------------------- ### Configure Connection Events Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/dependency-injection.md Use ConfigureConnection to register event handlers for the created IConnection. This example shows how to log connection closure events. ```csharp activeMq.ConfigureConnection((_, connection) => { connection.ConnectionClosed += (_, args) => { Console.WriteLine($"Connection closed. Error={args.Error}"); }; }); ``` -------------------------------- ### Response Side: Dependency Injection Setup for Request Reply Consumer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/request-reply.md Configure a consumer with a message handler that uses an anonymous producer to send replies. Ensure the CorrelationId and ReplyTo address are correctly handled. ```csharp var builder = WebApplication.CreateBuilder(args); builder.Services.AddActiveMqHostedService(); var endpoint = Endpoint.Create("localhost", 5672, "guest", "guest"); var activeMq = builder.Services.AddActiveMq("bookstore-cluster", new[] { endpoint }); activeMq.AddAnonymousProducer(); activeMq.AddConsumer( address: "bookstore.requests", routingType: RoutingType.Anycast, handler: async (message, consumer, serviceProvider, cancellationToken) => { var replyProducer = serviceProvider.GetRequiredService(); await replyProducer.SendAsync( message.ReplyTo, new Message("accepted") { CorrelationId = message.CorrelationId }, cancellationToken); await consumer.AcceptAsync(message); }); public sealed class ReplyProducer { private readonly IAnonymousProducer _producer; public ReplyProducer(IAnonymousProducer producer) { _producer = producer; } public Task SendAsync(string address, Message message, CancellationToken cancellationToken) { return _producer.SendAsync(address, message, cancellationToken); } } ``` -------------------------------- ### Run Integration Tests (Requires Broker) Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/CLAUDE.md Execute integration tests that require a running ActiveMQ Artemis broker. Ensure the broker is started before running this command. ```bash dotnet test --filter "FullyQualifiedName~IntegrationTests" ``` -------------------------------- ### Demonstrate NoLocal Filter with Multiple Connections Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md This example shows how the NoLocal filter prevents a consumer on `connection1` from receiving messages produced by `producer1` on the same connection, while still receiving messages from `producer2` on `connection2`. Requires `RoutingType.Multicast`. ```csharp var address = "news.updates"; // Create first connection with producer and consumer await using var connection1 = await connectionFactory.CreateAsync(endpoint); await using var producer1 = await connection1.CreateProducerAsync(address, RoutingType.Multicast); await using var consumer = await connection1.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Multicast, NoLocalFilter = true }); // Create second connection with producer await using var connection2 = await connectionFactory.CreateAsync(endpoint); await using var producer2 = await connection2.CreateProducerAsync(address, RoutingType.Multicast); // Send messages from both connections await producer1.SendAsync(new Message("from connection 1")); await producer2.SendAsync(new Message("from connection 2")); // Consumer will only receive the message from connection 2 var message = await consumer.ReceiveAsync(cancellationToken); Console.WriteLine(message.GetBody()); // Output: "from connection 2" ``` -------------------------------- ### Request Side: Dependency Injection Setup for RequestReplyClient Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/request-reply.md Register IRequestReplyClient using AddRequestReplyClient and ensure ActiveMQ hosted service is added for ASP.NET Core applications. ```csharp var builder = WebApplication.CreateBuilder(args); builder.Services.AddActiveMqHostedService(); var endpoint = Endpoint.Create("localhost", 5672, "guest", "guest"); var activeMq = builder.Services.AddActiveMq("bookstore-cluster", new[] { endpoint }); activeMq.AddRequestReplyClient(); public sealed class BookstoreRequestClient { private readonly IRequestReplyClient _requestReplyClient; public BookstoreRequestClient(IRequestReplyClient requestReplyClient) { _requestReplyClient = requestReplyClient; } public Task SendAsync(string payload, CancellationToken cancellationToken) { return _requestReplyClient.SendAsync( "bookstore.requests", RoutingType.Anycast, new Message(payload), cancellationToken); } } ``` -------------------------------- ### Configure Consumer Message Credit Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/consumer-credit.md Set the message credit for a new consumer to control the number of messages that can be received before acknowledgment. The default credit is 200, but this example sets it to 2. Credit must be at least 1. ```csharp var consumer = await connection.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Multicast, Credit = 2 // Set message credit to 2 }); ``` -------------------------------- ### Retrieve Message Payload Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-payload.md Get the message body by specifying the expected type T. Returns default(T) if the type does not match. ```csharp var body = message.GetBody(); ``` -------------------------------- ### Send Durable Message Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-durability.md Example of sending a durable message. By default, messages sent with SendAsync are durable. Awaiting this call implies the message has been persisted. ```csharp await producer.SendAsync(new Message("foo") ``` -------------------------------- ### Build the .NET Solution Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/CLAUDE.md Use this command to build the entire ActiveMQ Artemis .NET client solution. ```bash dotnet build ActiveMQ.Artemis.Client.sln ``` -------------------------------- ### Declare Topology on Startup Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/dependency-injection.md Enable queue and address declarations on startup when configuring consumers. This ensures the necessary broker objects are created or updated. ```csharp activeMq .AddConsumer( address: "orders.incoming", routingType: RoutingType.Anycast, queue: "orders-service", handler: async (message, consumer, serviceProvider, cancellationToken) => { await consumer.AcceptAsync(message); }) .EnableQueueDeclaration() .EnableAddressDeclaration(); ``` -------------------------------- ### Configure ASP.NET Core Application with Artemis Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/testing.md Sets up the Artemis client with dependency injection for an ASP.NET Core application. Assumes the hosted startup model. ```csharp var builder = WebApplication.CreateBuilder(args); builder.Services.AddActiveMqHostedService(); var endpoint = Endpoint.Create( host: "localhost", port: 5672, "artemis", "artemis" ); var activeMqBuilder = builder.Services.AddActiveMq(name: "my-artemis", endpoints: new[] {endpoint}); activeMqBuilder.AddConsumer(address: "foo", routingType: RoutingType.Anycast, handler: async (message, consumer, serviceProvider, cancellationToken) => { var body = message.GetBody(); var bar = body + "-" + "bar"; var producer = serviceProvider.GetRequiredService(); await producer.Publish(bar, cancellationToken); await consumer.AcceptAsync(message); }); activeMqBuilder.AddProducer("bar", RoutingType.Multicast); var app = builder.Build(); app.Run(); // this is required so we can use WebApplicationFactory to run the test server public partial class Program { } ``` -------------------------------- ### Build Static Website Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/website/README.md Generates static content for hosting. The output is placed in the 'build' directory. ```bash $ yarn build ``` -------------------------------- ### Deploy Website to GitHub Pages Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/website/README.md Builds the website and deploys it to the 'gh-pages' branch, suitable for GitHub Pages hosting. ```bash $ GIT_USER= USE_SSH=true yarn deploy ``` -------------------------------- ### Import ArtemisNetClient DI Namespaces Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/dependency-injection.md Import the necessary namespaces for using ArtemisNetClient with dependency injection and hosting extensions. ```csharp using ActiveMQ.Artemis.Client; using ActiveMQ.Artemis.Client.Extensions.DependencyInjection; using ActiveMQ.Artemis.Client.Extensions.Hosting; ``` -------------------------------- ### Create an IConsumer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Create an IConsumer instance to receive messages from a specified queue. Ensure the connection is established before creating the consumer. ```csharp var consumer = await connection.CreateConsumerAsync("a1", RoutingType.Anycast); ``` -------------------------------- ### Handling Request-Reply with a Consumer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/dependency-injection.md Demonstrates how to handle incoming requests, send a reply using a registered producer, and acknowledge the message. Ensure the reply preserves the CorrelationId. ```csharp activeMq.AddAnonymousProducer(); activeMq.AddConsumer( address: "bookstore.requests", routingType: RoutingType.Anycast, handler: async (message, consumer, serviceProvider, cancellationToken) => { var replyProducer = serviceProvider.GetRequiredService(); await replyProducer.SendAsync( message.ReplyTo, new Message("ok") { CorrelationId = message.CorrelationId }, cancellationToken); await consumer.AcceptAsync(message); }); ``` -------------------------------- ### Establish Connection to Artemis Broker Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Instantiate a ConnectionFactory and use it to asynchronously create a connection to the Artemis broker using the specified endpoint. ```csharp var connectionFactory = new ConnectionFactory(); var endpoint = Endpoint.Create("localhost", 5672, "guest", "guest"); var connection = await connectionFactory.CreateAsync(endpoint); ``` -------------------------------- ### Configure Failover with Multiple Endpoints Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Set up a `ConnectionFactory` to connect to multiple broker endpoints for high availability. The client will attempt to reconnect to other endpoints if the current one fails. ```csharp var masterEndpoint = Endpoint.Create( host: "master", port: 5672, user: "guest", password: "guest", scheme: Scheme.Amqp); var slaveEndpoint = Endpoint.Create( host: "slave", port: 5672, user: "guest", password: "guest", scheme: Scheme.Amqp); var connectionFactory = new ConnectionFactory(); var connection = await connectionFactory.CreateAsync(new[] { masterEndpoint, slaveEndpoint }); ``` -------------------------------- ### Enable Fast First Recovery Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Configure an exponential backoff recovery policy to attempt recovery immediately after the first connection failure. This counts as one retry. ```csharp var recoveryPolicy = RecoveryPolicyFactory.ExponentialBackoff( initialDelay: TimeSpan.FromMilliseconds(100), retryCount: 5, factor: 4.0, fastFirst: true); ``` -------------------------------- ### Import Client Namespace Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Import the ActiveMQ.Artemis.Client namespace to access the API interfaces and classes. ```csharp using ActiveMQ.Artemis.Client; ``` -------------------------------- ### Response Side: Receiving a Request and Sending a Reply Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/request-reply.md Set up a consumer to receive requests. When a reply is sent, ensure the ReplyTo address and CorrelationId from the request are used. ```csharp var connectionFactory = new ConnectionFactory(); var endpoint = Endpoint.Create("localhost", 5672, "guest", "guest"); var connection = await connectionFactory.CreateAsync(endpoint); await using var consumer = await connection.CreateConsumerAsync("my-address", RoutingType.Anycast); var request = await consumer.ReceiveAsync(); await using var producer = await connection1.CreateAnonymousProducerAsync(); await producer.SendAsync(request.ReplyTo, new Message("bar") { CorrelationId = request.CorrelationId }); await consumer.AcceptAsync(request); ``` -------------------------------- ### Send and Filter by Custom Application Property Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Demonstrates sending a message with custom application properties and then creating a consumer to filter messages based on one of those properties. ```csharp // Sending a message with custom properties await producer.SendAsync(new Message("order data") { ApplicationProperties = { ["color"] = "red", ["size"] = "large", ["quantity"] = 10 } }); // Filtering by custom property var consumer = await connection.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Anycast, FilterExpression = "color = 'red'" }); ``` -------------------------------- ### Receive a Message Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/README.md Create a message consumer and receive a message from a specified queue. ```csharp var consumer = await connection.CreateConsumerAsync("a1", RoutingType.Anycast); var message = await consumer.ReceiveAsync(); ``` -------------------------------- ### Send a Message Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/README.md Create a message producer and send a message to a specified queue. ```csharp var producer = await connection.CreateProducerAsync("a1", RoutingType.Anycast); await producer.SendAsync(new Message("foo")); ``` -------------------------------- ### Creating a Producer for a Specific Address Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Create an IProducer by specifying the address name and routing type. Use this for sending messages to a known destination. ```csharp var producer = await connection.CreateProducerAsync("a1", RoutingType.Anycast); ``` -------------------------------- ### Create Consumer with Combined Filters Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Use this configuration to create a consumer that filters messages based on a property ('priority' > 5) and excludes messages originating from the same connection. ```csharp var consumer = await connection.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Multicast, FilterExpression = "priority > 5", NoLocalFilter = true }); ``` -------------------------------- ### Registering a Request-Reply Client Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/dependency-injection.md Register a typed wrapper for the IRequestReplyClient. This facilitates implementing request-reply patterns by abstracting the underlying client. ```csharp activeMq.AddRequestReplyClient(); public sealed class BookstoreRequestClient { private readonly IRequestReplyClient _client; public BookstoreRequestClient(IRequestReplyClient client) => _client = client; public Task SendAsync(string address, string payload, CancellationToken cancellationToken) { return _client.SendAsync( address, RoutingType.Anycast, new Message(payload), cancellationToken); } } ``` -------------------------------- ### Add Basic Consumer with Handler Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/dependency-injection.md Registers a consumer for a specified address and routing type. The handler processes incoming messages and accepts them. ```csharp activeMq.AddConsumer( address: "orders.incoming", routingType: RoutingType.Anycast, handler: async (message, consumer, serviceProvider, cancellationToken) => { var logger = serviceProvider.GetRequiredService>(); logger.LogInformation("Received order {OrderId}", message.GetBody()); await consumer.AcceptAsync(message); }); ``` -------------------------------- ### Create a New Message Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-payload.md Instantiate a new Message object with a string payload. ```csharp var message = new Message("foo"); ``` -------------------------------- ### Create Consumer with Basic Filter Expression Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Use this to create a consumer that only receives messages matching a specific property value. The filter expression uses SQL-like syntax. ```csharp var consumer = await connection.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Multicast, FilterExpression = "color = 'red'" }); ``` -------------------------------- ### Sending a Message with a Producer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Send a message using a pre-configured producer. The message will be routed to the address specified during producer creation. ```csharp await producer.SendAsync(new Message("foo")); ``` -------------------------------- ### Using CancellationToken with CreateAsync Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Pass a CancellationToken to CreateAsync to prevent indefinite waiting if connection recovery fails permanently. This allows for timely cancellation of the connection attempt. ```csharp await connectionFactory.CreateAsync(endpoint, cancellationToken); ``` -------------------------------- ### Pattern Matching with LIKE Operator Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Utilize the LIKE operator with wildcards ('%' for multiple characters, '_' for a single character) for flexible string matching. ```csharp // Match departments starting with 'sales' FilterExpression = "department LIKE 'sales%'" ``` ```csharp // Match emails ending with '@example.com' FilterExpression = "email LIKE '%@example.com'" ``` ```csharp // Match code patterns: 'A', any character, then 'B' (e.g., 'AXB', 'A1B') FilterExpression = "code LIKE 'A_B'" ``` -------------------------------- ### Create AMQP Endpoint Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Create an Endpoint object to represent the AMQP broker endpoint. This includes host, port, user, password, and scheme for connection. ```csharp Endpoint.Create( host: "localhost", port: 5672, user: "guest", password: "guest", scheme: Scheme.Amqp); ``` -------------------------------- ### Configure Connection Factory Settings Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/dependency-injection.md Use ConfigureConnectionFactory to set transport, logging, recovery, or message ID settings for the connection factory. It requires a service provider and the factory instance. ```csharp activeMq.ConfigureConnectionFactory((serviceProvider, factory) => { factory.LoggerFactory = serviceProvider.GetRequiredService(); factory.AutomaticRecoveryEnabled = true; }); ``` -------------------------------- ### Linear Backoff Recovery Policy with Default Factor Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Sets up a recovery policy where the delay between retries increases linearly. The default linear factor is 1.0. ```csharp var linearBackoff = RecoveryPolicyFactory.LinearBackoff( initialDelay: TimeSpan.FromMilliseconds(100), retryCount: 5); ``` -------------------------------- ### Run a Single Integration Test Class Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/CLAUDE.md Execute integration tests for a specific test class. Replace 'FilterExpressionsSpec' with the desired test class name. ```bash dotnet test --filter "FullyQualifiedName~FilterExpressionsSpec" ``` -------------------------------- ### Request Side: Sending a Request with IRequestReplyClient Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/request-reply.md Use IRequestReplyClient to send messages and asynchronously listen for responses. Ensure the connection and client are properly initialized. ```csharp var connectionFactory = new ConnectionFactory(); var endpoint = Endpoint.Create("localhost", 5672, "guest", "guest"); var connection = await connectionFactory.CreateAsync(endpoint); await using var requestReplyClient = await connection.CreateRequestReplyClientAsync(); var response = await requestReplyClient.SendAsync("my-address", RoutingType.Anycast, new Message("foo"), default); var test = response.GetBody(); // bar ``` -------------------------------- ### Integration Test for ASP.NET Core Application with Artemis Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/testing.md An integration test using TestKit and WebApplicationFactory to verify messaging functionality. It sets up an in-memory broker, subscribes to a topic, sends a message, and asserts the response. ```csharp public class MyTests { [Fact] public async Task Test() { // setup the test kit var endpoint = Endpoint.Create( host: "localhost", port: 5672, "artemis", "artemis" ); using var testKit = new TestKit(endpoint); // setup the application await using var application = new WebApplicationFactory(); // trigger the app to start application.CreateClient(); // subscribe to the bar address using var subscription = testKit.Subscribe("bar"); // send a message to the application await testKit.SendMessageAsync("foo", new Message("my-payload")); // wait for a message sent from the application var message = await subscription.ReceiveAsync(); Assert.Equal("my-payload-bar", message.GetBody()); } } ``` -------------------------------- ### Run Unit Tests (No Broker) Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/CLAUDE.md Execute unit tests that do not require a running ActiveMQ Artemis broker. This command filters out integration tests. ```bash dotnet test --filter "FullyQualifiedName!~IntegrationTests" ``` -------------------------------- ### Check if Connection is Opened Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/connection-lifecycle.md Verify the current status of the connection by inspecting the IsOpened property. This helps in determining if the connection to the broker is still active. ```csharp var connectionFactory = new ConnectionFactory(); var connection = await connectionFactory.CreateAsync(endpoint); if (connection.IsOpened) { // connection is still opened } else { // connection to the broker has been lost } ``` -------------------------------- ### Exponential Backoff Recovery Policy with Custom Factor Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Configures an exponential backoff recovery policy with a custom growth factor, leading to faster increases in retry delays. The factor must be >= 1. ```csharp var exponentialBackoff = RecoveryPolicyFactory.ExponentialBackoff( initialDelay: TimeSpan.FromMilliseconds(100), retryCount: 5, factor: 4.0); ``` -------------------------------- ### Linear Backoff Recovery Policy with Custom Factor Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Configures a linear backoff recovery policy with a custom growth factor, resulting in a steeper increase in retry delays. The factor must be >= 0. ```csharp var linearBackoff = RecoveryPolicyFactory.LinearBackoff( initialDelay: TimeSpan.FromMilliseconds(100), retryCount: 5, factor: 2); ``` -------------------------------- ### Exponential Backoff Recovery Policy with Default Factor Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Implements an exponential backoff recovery policy where delays increase exponentially based on the attempt number. The default growth factor is 2.0. ```csharp var exponentialBackoff = RecoveryPolicyFactory.ExponentialBackoff( initialDelay: TimeSpan.FromMilliseconds(100), retryCount: 5); ``` -------------------------------- ### Accept a Message Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-acknowledgment.md Use AcceptAsync to signal successful message processing to the broker. This typically results in the message being removed from the queue for destructive queues. ```csharp var message = await consumer.ReceiveAsync(); // process message... await consumer.AcceptAsync(message); ``` -------------------------------- ### Configure NoLocal Filter in Consumer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Set the `NoLocalFilter` property to `true` in the `ConsumerConfiguration` to enable the NoLocal filter. ```csharp var consumer = await connection.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Multicast, NoLocalFilter = true }); ``` -------------------------------- ### Creating an Anonymous Producer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Instantiate an IAnonymousProducer when the destination address is not known at producer creation time. This allows specifying the address per message. ```csharp var anonymousProducer = await connection.CreateAnonymousProducer(); ``` -------------------------------- ### Constant Backoff Recovery Policy Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Configures a recovery policy to wait a fixed amount of time between retry attempts. Use this when a predictable delay is desired. ```csharp var constantBackoff = RecoveryPolicyFactory.ConstantBackoff( delay: TimeSpan.FromSeconds(1), retryCount: 5); ``` -------------------------------- ### Registering an Anonymous Producer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/dependency-injection.md Register a custom anonymous producer class. This is useful when the producer needs to publish messages to multiple addresses dynamically. ```csharp activeMq.AddAnonymousProducer(); public sealed class ReplyProducer { private readonly IAnonymousProducer _producer; public ReplyProducer(IAnonymousProducer producer) => _producer = producer; public Task SendAsync(string address, Message message, CancellationToken cancellationToken) { return _producer.SendAsync(address, message, cancellationToken); } } ``` -------------------------------- ### Linear Backoff Recovery Policy with Max Delay Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Defines a linear backoff recovery policy for an infinite number of retries, specifying a maximum delay to prevent excessively long waits. The factor must be >= 0. ```csharp var linearBackoff = RecoveryPolicyFactory.LinearBackoff( initialDelay: TimeSpan.FromMilliseconds(100), maxDelay: TimeSpan.FromSeconds(15)); ``` -------------------------------- ### Filter by AMQTimestamp Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Create a consumer that filters messages based on their creation timestamp. The filter uses milliseconds since the Unix epoch. ```csharp var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); var consumer = await connection.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Anycast, FilterExpression = $"AMQTimestamp > {timestamp}" }); ``` -------------------------------- ### Filter by AMQPriority Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Create a consumer that filters messages based on their priority level. Priority ranges from 0 (lowest) to 9 (highest). ```csharp var consumer = await connection.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Anycast, FilterExpression = "AMQPriority = 9" }); ``` ```csharp FilterExpression = "AMQPriority > 5" // Only high-priority messages ``` -------------------------------- ### Filter by AMQDurable Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Create a consumer that filters messages based on their durability mode. Valid values are 'DURABLE' or 'NON_DURABLE'. ```csharp var consumer = await connection.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Anycast, FilterExpression = "AMQDurable = 'DURABLE'" }); ``` -------------------------------- ### Configure TCP Keep-Alive Settings Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/connection-lifecycle.md Configure TCP Keep-Alive settings on the ConnectionFactory to enhance connection stability. This sends periodic signals to ensure the connection remains active. ```csharp var factory = new ConnectionFactory(); // Configure TCP Keep-Alive settings factory.TCP.KeepAliveTime = 30000; // 30 seconds factory.TCP.KeepAliveInterval = 1000; // 1 second ``` -------------------------------- ### Registering a Typed Producer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/dependency-injection.md Register a custom typed producer class with the ActiveMQ Artemis client. This allows for type-safe message publishing and keeps application code decoupled from raw Artemis primitives. ```csharp activeMq.AddProducer("orders.events", RoutingType.Multicast); public sealed class OrderEventsProducer { private readonly IProducer _producer; public OrderEventsProducer(IProducer producer) => _producer = producer; public Task PublishAccepted(string orderId, CancellationToken cancellationToken) { return _producer.SendAsync(new Message($"accepted:{orderId}"), cancellationToken); } } ``` -------------------------------- ### Combine Multiple Filter Operators Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Create sophisticated filters by combining logical operators and comparison operators. ```csharp FilterExpression = "AMQPriority > 5 AND (color = 'red' OR color = 'blue')" ``` ```csharp FilterExpression = "quantity BETWEEN 10 AND 100 AND status = 'pending'" ``` -------------------------------- ### Sending a Message with an Anonymous Producer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Send a message using an anonymous producer, specifying the address, routing type, and message content at the time of sending. ```csharp await anonymousProducer.SendAsync("a2", RoutingType.Multicast, new Message("foo")); ``` -------------------------------- ### Receive a Message Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Retrieve a message from the consumer's buffer. If no messages are available, this method will asynchronously wait until a new message arrives. ```csharp var message = await consumer.ReceiveAsync(); ``` -------------------------------- ### Send Multiple Messages Transactionally Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/transactions.md Use this snippet to send a series of messages as an all-or-nothing operation. Ensure that all messages are either successfully sent or none are. ```csharp var connectionFactory = new ConnectionFactory(); var endpoint = Endpoint.Create("localhost", 5672, "guest", "guest"); var connection = await connectionFactory.CreateAsync(endpoint); await using (var transaction = new Transaction()) { await producer.SendAsync( address: "credit-queue", message: new Message("credit:500,account:a"), transaction: transaction ); await producer.SendAsync( address: "debit-queue", message: new Message("debit:500,account:b"), transaction: transaction); await transaction.CommitAsync(); } ``` -------------------------------- ### Configure Producer for Nondurable Messages Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-durability.md Configures a producer to send only nondurable messages. This setting can be overridden on a per-message basis. ```csharp var producer = await connection.CreateProducerAsync(new ProducerConfiguration { Address = "a1", RoutingType = RoutingType.Anycast, MessageDurabilityMode = DurabilityMode.Nondurable }); ``` -------------------------------- ### Set Default Message Priority on Producer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-priority.md Configure a message producer to send all messages with a specific priority level. This sets the default priority for messages sent through this producer. ```csharp var producer = await connection.CreateProducerAsync(new ProducerConfiguration { Address = "a1", RoutingType = RoutingType.Anycast, MessagePriority = 9 }); ``` -------------------------------- ### Reject a Message Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-acknowledgment.md Use Reject to inform the broker that a message cannot be processed. Rejected messages may be routed to a Dead Letter Queue (DLQ) if configured. ```csharp var message = await consumer.ReceiveAsync(); consumer.Reject(message); ``` -------------------------------- ### Indefinite Retry Configuration Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Configure the IRecoveryPolicy to retry recovery indefinitely by returning int.MaxValue for RetryCount. Use with caution as it may lead to long waits if the server remains unavailable. ```csharp int.MaxValue ``` -------------------------------- ### Receive a Message with Cancellation Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Receive a message with a CancellationToken. This is useful for gracefully shutting down the application by signaling cancellation. ```csharp var cts = new CancellationTokenSource(); var message = await consumer.ReceiveAsync(cts.Token); ``` -------------------------------- ### Inspect Connection Closed Error Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/connection-lifecycle.md When the ConnectionClosed event is raised, inspect the ConnectionClosedEventArgs to determine the specific error that caused the connection termination. ```csharp connection.ConnectionClosed += (sender, eventArgs) => { // reason the connection was closed string reason = eventArgs.Error; _logger.LogWarning(reason); }; ``` -------------------------------- ### Filter by AMQExpiration Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Create a consumer that filters messages based on their expiration time. The filter uses an absolute timestamp in milliseconds. ```csharp var messageExpiryTime = DateTimeOffset.UtcNow.AddMinutes(10).ToUnixTimeMilliseconds(); var consumer = await connection.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Anycast, FilterExpression = $"AMQExpiration > {messageExpiryTime}" }); ``` -------------------------------- ### IRecoveryPolicy Interface Definition Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Defines the retry count and delay strategy for automatic recovery attempts. Implement this interface to customize recovery behavior. ```csharp public interface IRecoveryPolicy { int RetryCount { get; } TimeSpan GetDelay(int attempt); } ``` -------------------------------- ### Subscribing to Connection Recovery Errors Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Attach a handler to the ConnectionRecoveryError event to react when automatic recovery attempts fail. This allows for custom error handling or notification. ```csharp var connectionFactory = new ConnectionFactory(); var connection = await connectionFactory.CreateAsync(endpoint); connection.ConnectionRecoveryError += (sender, eventArgs) => { // react accordingly }; ``` -------------------------------- ### Handle Connection Closed Event Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/connection-lifecycle.md Subscribe to the ConnectionClosed event to be notified when the connection to the broker is lost. This allows your application to react to disconnections. ```csharp var connectionFactory = new ConnectionFactory(); var connection = await connectionFactory.CreateAsync(endpoint); connection.ConnectionClosed += (sender, eventArgs) => { // react accordingly }; ``` -------------------------------- ### Acknowledge and Send Messages Transactionally Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/transactions.md This snippet demonstrates how to ensure a received message is acknowledged only if a new message is successfully sent as a result of processing. Both operations are committed together. ```csharp var endpoint = Endpoint.Create("localhost", 5672, "guest", "guest"); var connectionFactory = new ConnectionFactory(); await using var connection = await connectionFactory.CreateAsync(endpoint); await using var producer = await connection.CreateProducerAsync("my-address-2", RoutingType.Anycast); await using var consumer = await connection.CreateConsumerAsync("my-address-1", RoutingType.Anycast); var msg1 = await consumer.ReceiveAsync(); await using (var transaction = new Transaction()) { // transactionally acknowledge message await consumer.AcceptAsync(msg1, transaction); var result = DoSomeProcessing(msg1); var msg2 = new Message(result); // transactionally send another message await producer.SendAsync(msg2, transaction); // commit the two operations await transaction.CommitAsync(); } ``` -------------------------------- ### Override Producer Priority with Message Priority Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-priority.md Set a specific priority for an individual message, which will take precedence over the priority defined at the producer level. This allows for fine-grained control over message importance. ```csharp await producer.SendAsync(new Message("foo") { Priority = 0 // takes precedence over priority specified on producer level }); ``` -------------------------------- ### Handle Message Delivery Count Threshold Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-acknowledgment.md Check the DeliveryCount property to manage retries. If a message has been redelivered too many times, reject it; otherwise, modify it for another retry. ```csharp var message = await consumer.ReceiveAsync(); if (message.DeliveryCount >= 3) { // too many retries, reject to DLQ consumer.Reject(message); } else { // retry later consumer.Modify(message, deliveryFailed: true, undeliverableHere: false); } ``` -------------------------------- ### Modify Message: Redirect to Different Consumer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-acknowledgment.md Use Modify with deliveryFailed: true and undeliverableHere: true to requeue a message, increment its delivery count, and prevent it from being redelivered to the current consumer. ```csharp var message = await consumer.ReceiveAsync(); consumer.Modify(message, deliveryFailed: true, undeliverableHere: true); ``` -------------------------------- ### Filter Messages with AND Operator Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Use the AND operator to receive messages that satisfy all specified conditions. ```csharp FilterExpression = "color = 'red' AND size = 'large'" ``` -------------------------------- ### Disable Automatic Recovery Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/auto-recovery.md Set the `AutomaticRecoveryEnabled` property to `false` on the `ConnectionFactory` to prevent automatic recovery attempts. ```csharp var connectionFactory = new ConnectionFactory(); connectionFactory.AutomaticRecoveryEnabled = false; // connection that will not recover automatically var connection = await connectionFactory.CreateAsync(endpoint); ``` -------------------------------- ### Disconnecting from ActiveMQ Artemis Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/getting-started.md Call DisposeAsync on the connection object to asynchronously close the connection. Connections should be long-lived. ```csharp await connection.DisposeAsync(); ``` -------------------------------- ### Unacknowledged Message Redelivery on Consumer Close Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-acknowledgment.md Messages received but not acknowledged (Accept, Reject, Modify) before a consumer is closed or disposed will be redelivered. This applies to both durable and non-durable consumers. ```csharp { await using var consumer = await connection.CreateConsumerAsync("a1", RoutingType.Anycast); var message = await consumer.ReceiveAsync(); // consumer disposed here without AcceptAsync/Reject/Modify // message is not acknowledged and will be redelivered } ``` -------------------------------- ### Modify Message: Retry on Same Consumer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-acknowledgment.md Use Modify with deliveryFailed: true and undeliverableHere: false to return a message to the queue for redelivery to the same consumer, incrementing its delivery count. ```csharp var message = await consumer.ReceiveAsync(); consumer.Modify(message, deliveryFailed: true, undeliverableHere: false); ``` -------------------------------- ### Handle NULL Values in Filters Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Filter messages based on whether a property is explicitly NULL or IS NOT NULL. ```csharp var consumer = await connection.CreateConsumerAsync(new ConsumerConfiguration { Address = address, RoutingType = RoutingType.Multicast, FilterExpression = "optionalField IS NULL" }); ``` ```csharp FilterExpression = "requiredField IS NOT NULL" ``` -------------------------------- ### Send Nondurable Message Individually Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-durability.md Sends a single nondurable message, overriding any producer-level durability settings. This ensures the message is not persisted by the broker. ```csharp await producer.SendAsync(new Message("foo") { DurabilityMode = DurabilityMode.Nondurable // takes precedence over durability // mode specified on the producer level }); ``` -------------------------------- ### Check if Connection Closed by Peer Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/connection-lifecycle.md Determine if the connection was closed by the remote peer (broker) or by the client itself by checking the ClosedByPeer property in ConnectionClosedEventArgs. ```csharp connection.ConnectionClosed += (sender, eventArgs) => { bool closedByPeer = eventArgs.ClosedByPeer; if (closedByPeer) { _logger.LogWarning("connection was closed by the broker"); } else { _logger.LogWarning("connection was closed by the client"); } }; ``` -------------------------------- ### Filter Messages with OR Operator Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Use the OR operator to receive messages that satisfy at least one of the specified conditions. ```csharp FilterExpression = "color = 'red' OR color = 'blue'" ``` -------------------------------- ### Filter Messages with IN Operator Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-filtering.md Use the IN operator to filter messages where a property matches any value within a specified list. ```csharp FilterExpression = "color IN ('red', 'blue', 'green')" ``` -------------------------------- ### Modify Message: Requeue Without Incrementing Delivery Count Source: https://github.com/havret/dotnet-activemq-artemis-client/blob/master/docs/message-acknowledgment.md Use Modify with deliveryFailed: false and undeliverableHere: true to requeue a message without incrementing its delivery count, typically for handing off to another consumer. ```csharp var message = await consumer.ReceiveAsync(); consumer.Modify(message, deliveryFailed: false, undeliverableHere: true); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.