All Products
Search
Document Center

Simple Message Queue (formerly MNS):Receive messages from a queue

Last Updated:Feb 27, 2026

This topic describes how to use Simple Message Queue (formerly MNS) SDK for Java to receive messages from a queue, process them, and delete them after successful consumption.

Prerequisites

Before you begin, make sure that you have:

Authorization information

By default, only an Alibaba Cloud account can call this operation. You can call this operation as a Resource Access Management (RAM) user only after you grant the required permissions to the RAM user.

NameValue
APIReceiveMessage
Actionmns:ReceiveMessage
Resourceacs:mns:$region:$accountid:/queues/$queueName/messages

How message receiving works

When a consumer calls the ReceiveMessage operation, the message state changes from Active to Inactive. The message remains in the Inactive state for the duration specified by the VisibilityTimeout parameter of the queue.

The consumer must call the DeleteMessage operation to delete the message within the visibility timeout period. Otherwise, the message returns to the Active state and becomes available for consumption again.

Message body encoding

If the message body does not contain special characters, skip Base64 encoding and use the raw string methods instead:

  • Send a message: Call the message.setMessageBodyAsRawString method.

  • Receive a message: Call the message.getMessageBodyAsRawString method.

The Base64 encoding behavior is controlled by the msgBodyBase64Switch property in your configuration file (default: false).

Two ways to receive messages

The sample code demonstrates two approaches:

MethodAPI callDescription
Single receive (basic)queue.popMessage()Receives one message at a time from the queue. Suitable for low-throughput scenarios.
Long polling batch receive (recommended)queue.batchPopMessage(batchSize, waitSeconds)Receives multiple messages at a time using long polling. Provides higher throughput and fewer API calls, which reduces costs.

Long polling keeps the connection open for a specified duration (waitSeconds) and returns messages as soon as they become available, rather than returning an empty response immediately. This reduces the number of empty responses and API calls compared to short polling.

Sample code

For the complete source code, see ReceiveMessageDemo on GitHub.

Configuration

Before running the sample code, configure the following file:

File path: ${"user.home"}/.aliyun-mns.properties

mns.endpoint=http://xxxxxxx
mns.msgBodyBase64Switch=true/false

Configure your AccessKey ID and AccessKey secret as environment variables according to Alibaba Cloud security best practices.

Code

package com.aliyun.mns.sample.queue;

import com.aliyun.mns.client.CloudAccount;
import com.aliyun.mns.client.CloudQueue;
import com.aliyun.mns.client.MNSClient;
import com.aliyun.mns.common.ClientException;
import com.aliyun.mns.common.ServiceException;
import com.aliyun.mns.common.ServiceHandlingRequiredException;
import com.aliyun.mns.common.utils.ServiceSettings;
import com.aliyun.mns.model.Message;
import java.util.List;

/**
 * 1. Configure the AccessKey ID and AccessKey secret in the environment based on Alibaba Cloud specifications.
 * 2.Configure the ${"user.home"}/.aliyun-mns.properties file based on the following content:
 *           mns.endpoint=http://xxxxxxx
 *           mns.msgBodyBase64Switch=true/false
 */
public class ReceiveMessageDemo {
    /**
     * Specify whether to encode the message body in Base64.
     */
    private static final Boolean IS_BASE64 = Boolean.valueOf(ServiceSettings.getMNSPropertyValue("msgBodyBase64Switch","false"));

    public static void main(String[] args) {
        String queueName = "cloud-queue-demo";

        // Configure the AccessKey ID and AccessKey secret in the environment based on Alibaba Cloud specifications.
        CloudAccount account = new CloudAccount(ServiceSettings.getMNSAccountEndpoint());
        //this client need only initialize once
        MNSClient client = account.getMNSClient();
        CloudQueue queue = client.getQueueRef(queueName);

        // Obtain and process messages in a round-robin manner.
        loopReceive(queue, client);

        // Disable the client after message processing.
        client.close();
    }

    private static void loopReceive(CloudQueue queue, MNSClient client) {
        while (true) {
            // Receive messages in round-robin manner.
            try {
                // Receive a message from the queue. This is the basic method.
                singleReceive(queue);

                // Receive multiple messages at a time by using the long polling mechanism. This is the recommended method.
                longPollingBatchReceive(queue);
            } catch (ClientException ce) {
                System.out.println("Something wrong with the network connection between client and MNS service."
                    + "Please check your network and DNS availablity.");
                // Client exception: retry is triggered due to network jitter.
            } catch (ServiceException se) {
                if (se.getErrorCode().equals("QueueNotExist")) {
                    System.out.println("Queue is not exist. Please create queue before use");
                    client.close();
                    return;
                } else if (se.getErrorCode().equals("TimeExpired")) {
                    System.out.println("The request is time expired. Please check your local machine timeclock");
                    return;
                }
                // Server exception: retry is triggered due to network jitter.
            } catch (Exception e) {
                System.out.println("Unknown exception happened!e:"+e.getMessage());
                // Other exception: retry is triggered due to network jitter.
            }

        }
    }

    private static void longPollingBatchReceive(CloudQueue queue) throws ServiceHandlingRequiredException {

        System.out.println("=============start longPollingBatchReceive=============");

        // The maximum number of messages that can be received at a time.
        int batchSize = 15;
        // The long polling period. Unit: seconds.
        int waitSeconds = 15;

        List<Message> messages = queue.batchPopMessage(batchSize, waitSeconds);
        if (messages != null && messages.size() > 0) {

            for (Message message : messages) {
                printMsgAndDelete(queue,message);
            }
        }

        System.out.println("=============end longPollingBatchReceive=============");

    }

    private static void singleReceive(CloudQueue queue) throws ServiceHandlingRequiredException {
        System.out.println("=============start singleReceive=============");

        Message popMsg = queue.popMessage();
        printMsgAndDelete(queue, popMsg);

        System.out.println("=============end singleReceive=============");
    }

    private static void printMsgAndDelete(CloudQueue queue, Message popMsg) throws ServiceHandlingRequiredException {
        if (popMsg != null) {
            System.out.println("message handle: " + popMsg.getReceiptHandle());
            System.out.println("message body: " + (IS_BASE64 ? popMsg.getMessageBody() : popMsg.getMessageBodyAsRawString()));
            System.out.println("message id: " + popMsg.getMessageId());
            System.out.println("message dequeue count:" + popMsg.getDequeueCount());
            //<<to add your special logic.>>

            //remember to delete message when consume message successfully.
            queue.deleteMessage(popMsg.getReceiptHandle());
            System.out.println("delete message successfully.\n");
        }
    }

}

Error handling

The sample code handles three types of exceptions:

Exception typeCauseRecovery action
ClientExceptionNetwork connection issues between the client and the SMQ serviceRetry. Check your network and DNS settings.
ServiceException (QueueNotExist)The specified queue does not existCreate the queue before calling ReceiveMessage.
ServiceException (TimeExpired)The request has expiredCheck your local machine clock for time synchronization issues.
Generic ExceptionUnknown errorsRetry. Log the error for further investigation.

Expected output

When the sample code runs successfully, the console output is similar to the following:

=============start singleReceive=============
message handle: 1-ODU4OTkzNDU5My0xNDMyNzI3ODI3LTItOA==
message body: This is a test message
message id: 5F290C926D472878-2-14D9529A8FA-20000****
message dequeue count:1
delete message successfully.

=============end singleReceive=============
=============start longPollingBatchReceive=============
message handle: 1-ODU4OTkzNDU5My0xNDMyNzI3MzI3LTItOA==
message body: Batch message 1
message id: 5F290C926D472878-2-14D9529A8FA-20001****
message dequeue count:1
delete message successfully.

message handle: 1-ODU4OTkzNDU5My0xNDMyNzI3NDI3LTItOA==
message body: Batch message 2
message id: 5F290C926D472878-2-14D9529A8FA-20002****
message dequeue count:1
delete message successfully.

=============end longPollingBatchReceive=============

References