简体   繁体   中英

Java: Azure Service Bus Queue Receiving messsages with sessions

I'm writing code in java (using Azure SDK for Java), I have a Service bus queue that contains sessionful messages. I want to receive those messages and process them to another place.

I make a connection to the Queue by using QueueClient, and then I use registerSessionHandler to process through the messages (code below).

The problem is that whenever a message is received, I can print all details about it including the content, but it is printed 10 times and after each time it prints an Exception. (printing 10 times: I understand that this is because there is a 10 times retry policy before it throws the message to the Dead letter queue and goes to the next message.)

The Exception says

> USERCALLBACK-Receiver not created. Registering a MessageHandler creates a receiver.

The output with the Exception

But I'm sure that the SessionHandler does the same thing as MessageHandler but includes support for sessions, so it should create a receiver since it receives messages. I have tried to use MessageHandler but it won't even work and stops the whole program because it doesn't support sessionful messages, and the ones I receive have sessions.

My problem is understanding what the Exception wants me to do, and how can I fix the code so it won't give me any exceptions? Does anyone have suggestions on how to improve the code? or other methods that do the same thing?

QueueClient qc = new QueueClient(
            new ConnectionStringBuilder(connectionString),
            ReceiveMode.PEEKLOCK);

qc.registerSessionHandler(
            new ISessionHandler() {
                @Override
                public CompletableFuture<Void> onMessageAsync(IMessageSession messageSession, IMessage message) {
                    System.out.printf(
                            "\nMessage received: " +
                                    "\n --> MessageId = %s " +
                                    "\n --> SessionId = %s" +
                                    "\n --> Content Type = %s" +
                                    "\n --> Content = \n\t\t %s",
                            message.getMessageId(),
                            messageSession.getSessionId(),
                            message.getContentType(),
                            getMessageContent(message)
                    );

                    return qc.completeAsync(message.getLockToken());
            }
                @Override
                public CompletableFuture<Void> OnCloseSessionAsync(IMessageSession iMessageSession) {
                    return CompletableFuture.completedFuture(null);
                }

                @Override
                public void notifyException(Throwable throwable, ExceptionPhase exceptionPhase) {
                    System.out.println("\n Exception " + exceptionPhase + "-" + throwable.getMessage());
                }
            },
            new SessionHandlerOptions(1, true, Duration.ofMinutes(1)),
            Executors.newSingleThreadExecutor()
);

(The getMessageContent(message) method is a separate method, for those interested:)

public String getMessageContent(IMessage message){
    List<byte[]> content = message.getMessageBody().getBinaryData();
    StringBuilder sb = new StringBuilder();
    for (byte[] b : content) {
        sb.append(new String(b)
        );
    }
    return sb.toString();
}

For those who wonder, I managed to solve the problem!

It was simply done by using Azure Functions ServiceBusQueueTrigger, it will then listen to the Service bus Queue and process the messages. By setting isSessionsEnabled to true, it will accept sessionful messages as I wanted :)

So instead of writing more than 100 lines of code, the code looks like this now:

public class Function {

@FunctionName("QueueFunction")
public void run(
        @ServiceBusQueueTrigger(
               name = "TriggerName", //Any name you choose
               queueName = "queueName", //QueueName from the portal
               connection = "ConnectionString", //ConnectionString from the portal
               isSessionsEnabled = true
        ) String message,
        ExecutionContext context
) {
    // Write the code you want to do with the message here
    // Using the variable messsage which contains the messageContent, messageId, sessionId etc.
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM