We are using Azure Service Bus Queues for exchanging messages between different systems. We would like to move the invalid messages to Dead Letter Queue using Java code.
<There are many reasons why a message may be automatically moved to the dead letter queue by the Azure Service bus runtime, such as:
Find more details at https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dead-letter-queues, including a full list of reasons why messages are moved to the dead letter queue.
In addition, it is possible for the application to move messages to the dead letter queue. Find a sample Java 8 Console Application code and the pom.xml file further below.
Please note The following properties are automatically filled up by the Azure Service Bus runtime when moving messages to the dead letter queue, it is a good idea to also provides those when the application it performing the same action:
DeadLetterReason
DeadLetterErrorDescription
-- Java Version --
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)
--- Azure Service Bus Dependency for pom.xml ---
<dependencies>
<!-- https://mvnrepository.com/artifact/com.microsoft.azure/azure-servicebus -->
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-servicebus</artifactId>
<version>2.0.0-preview1</version>
</dependency>
</dependencies>
-- Java 8 Console Application --
import java.time.Duration;
import java.util.Scanner;
import com.microsoft.azure.servicebus.MessageHandlerOptions;
import com.microsoft.azure.servicebus.QueueClient;
import com.microsoft.azure.servicebus.ReceiveMode;
import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder;
import com.microsoft.azure.servicebus.primitives.ServiceBusException;
public class Main {
public static void main(String[] args)
{
final String CONNECTION_STRING = "{Azure Service Bus Connection String}";
final String QUEUE_NAME = "{Azure Service Bus Queue Name}";
try {
moveMessageToDlq(CONNECTION_STRING, QUEUE_NAME);
}catch (Exception ex) {
System.out.println(String.format("An exception occurred. Details: %s.", ex.toString()));
}
}
private static void moveMessageToDlq(String connectionString, String queueName)
throws ServiceBusException, InterruptedException {
ConnectionStringBuilder connectionStringBuilder = new ConnectionStringBuilder(connectionString, queueName);
QueueClient queueClient = new QueueClient(connectionStringBuilder, ReceiveMode.PEEKLOCK);
MessageHandler messageHandler = new MessageHandler(queueClient);
MessageHandlerOptions messageHandlerOptions = new MessageHandlerOptions(
1,
false,
Duration.ofMinutes(1));
queueClient.registerMessageHandler(messageHandler, messageHandlerOptions);
final String QUIT_COMMAND_NAME = "quit";
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println(String.format("Enter '%s' and press <ENTER> to exit...", QUIT_COMMAND_NAME));
String input = scanner.nextLine();
if (input.equalsIgnoreCase(QUIT_COMMAND_NAME)){
System.out.println("Exiting...");
break;
}
}
scanner.close();
queueClient.close();
}
}
--- Message Handler ---
import java.util.concurrent.CompletableFuture;
import com.microsoft.azure.servicebus.ExceptionPhase;
import com.microsoft.azure.servicebus.IMessage;
import com.microsoft.azure.servicebus.IMessageHandler;
import com.microsoft.azure.servicebus.IQueueClient;
public class MessageHandler implements IMessageHandler {
private final IQueueClient _client;
public MessageHandler(IQueueClient client) {
if (client == null){
throw new IllegalArgumentException("Queue client cannot be null.");
}
_client = client;
}
@Override
public CompletableFuture<Void> onMessageAsync(IMessage message) {
System.out.println(String.format("Received message id '%s' (DeliveryCount=%d).",
message.getMessageId(),
message.getDeliveryCount()));
if (message.getLabel().equalsIgnoreCase("dlq")){ // Send message to DLQ if label id dlq
System.out.println("Sending message to the dead letter queue...");
return _client.deadLetterAsync(
message.getLockToken(),
"InvalidMessage", // DeadLetterReason
"Message invalid due to..."); // DeadLetterErrorDescription
}
else { // Otherwise, complete message
System.out.println("Completing message...");
return _client.completeAsync(message.getLockToken());
}
}
@Override
public void notifyException(Throwable throwable, ExceptionPhase exceptionPhase) {
System.out.println("An exception occurred. Details: " + exceptionPhase + "-" + throwable.getMessage());
}
}
GitHub Azure Service Bus Java Samples: https://github.com/Azure/azure-service-bus-java/tree/e3d163eac92213d34dce059f3353d2c819d31fbf.