Use message session state in Azure Service Bus

Akihiro Nishikawa
Microsoft Azure
Published in
3 min readFeb 27, 2023

Please note that this entry was written on February 9, 2023. And the original entry is in Japanese.

Enquiries

The following query was received from an unusual enquirer.

Can we check the message session states, which can be assigned to an Azure Service Bus Queue or Topic message session, in Azure Portal or elsewhere?

If you don’t know what a message session state is, please check the following document.

Plainly, it is a binary opaque object that can hold a variety of writable data. The size of the object depends upon SKUs, 256 KB for Service Bus Standard and 100 MB for Service Bus Premium.

The person was wondering where we could check/view contents in message session state.

Azure Portal

Unfortunately, this is not visible in Azure Portal, nor in Service Bus Explorer built into Azure Portal.

Service Bus Explorer in Azure Portal

Classic Service Bus Explorer (application running on local machine)

Classic Service Bus Explorer allows us to check the state. This application is available via the following URL.

Please note that the classic Service Bus Explorer does not support Azure AD authentication. We can check the state as follows.

Classic Azure Service Bus Explorer

APIs created with Azure Functions to view message session states

Yes, we can create them :-). We can also configure RBAC with managed identities, so we can securely connect Blob storages from the APIs. Needless to say, however, we should restrict access to the APIs, such as IP address filtering, or others.

Implementation Point

[1] Message session state can be obtained and set only from receiver client.

Message session states are set by methods of the ServiceBusReceiverClient and the ServiceBusReceiverAsyncClient classes. This is because sessions are set in the ServiceBusReceiverClient and the ServiceBusReceiverAsyncClient client classes. In other words, there are no method to set/obtain session states in the ServiceBusReceivedMessage or the ServiceBusMessage classes.

In addition, session states cannot be set by the methods of the sender client, i.e. ServiceBusSenderClient or ServiceBusSenderAsyncClient.

The following code is to read message session states from a Queue.

DefaultAzureCredential defaultAzureCredential = new DefaultAzureCredentialBuilder().build();
try (var sessionReceiverClient = new ServiceBusClientBuilder()
.credential(namespace+".servicebus.windows.net", defaultAzureCredential)
.sessionReceiver()
.queueName(queueName)
.receiveMode(ServiceBusReceiveMode.PEEK_LOCK)
.buildClient()) {
try (var receiverClient = sessionReceiverClient.acceptSession(sessionId)) {
IterableStream<ServiceBusReceivedMessage> messages
= receiverClient.receiveMessages(100, Duration.ofSeconds(1));
for (ServiceBusReceivedMessage message : messages) {
logger.log(Level.INFO,
String.format("ID [%s] SessionId [%s] State[%s] Message [%s]\n",
message.getMessageId(),
message.getSessionId(),
new String(Optional.ofNullable(receiverClient.getSessionState())
.orElse("NULL".getBytes(StandardCharsets.UTF_8))),
message.getBody().toString()));

// Unlock
receiverClient.abandon(message, new AbandonOptions());
}
}
}
catch (IllegalArgumentException | ServiceBusException e) {
logger.log(Level.SEVERE,
String.format("ServiceBus exception\n\tMessage [%s]\n\n%s",
e.getLocalizedMessage(),
Arrays.toString(e.getStackTrace())));
}

Message session states are obtained between lines 14 and 18 of the code. Message ID and session ID (and the message itself, of course) can be obtained using methods of the ServiceReceivedMessage class, while the session state is handled by the following methods.

Sync clients

  • ServiceBusReceiverClient#getSessionState()
  • ServiceBusReceiverClient#setSessionState()

Async clients

  • ServiceBusReceiverAsyncClient#getSessionState()
  • ServiceBusReceiverAsyncClient#setSessionState()

[2] Receive mode

When creating a ServiceBusReceverClient instance, either PEEK_LOCK or RECEIVE_AND_DELETE mode can be set. If you only want to change the state, you must

  • set PEEK_LOCK mode instead of RECEIVE_AND_DELETE, and
  • release the lock with abandon instead of complete

so that messages are not taken out of the Queue/Topic.

When using receiveMessages to receive and abandon to release the lock, the delivery count is incremented. Therefore, Queue/Topic configuration around delivery count should be done properly so that messages are not delivered to the Dead Letter Queue.

--

--

Akihiro Nishikawa
Microsoft Azure

Cloud Solution Architect @ Microsoft, and JJUG (Japan Java Users Group) board member. ♥Java (JVM/GraalVM) and open-source technologies. All views are my own.