Use message session state in Azure Service Bus
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.
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.
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 ofRECEIVE_AND_DELETE
, and - release the lock with
abandon
instead ofcomplete
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.