Enviar mensagens para um tópico do Barramento de Serviço do Azure e receber mensagens de assinaturas para o tópico (Java)

Neste guia de início rápido, você escreverá um código Java usando o pacote azure-messaging-servicebus para enviar mensagens para um tópico do Barramento de Serviço do Azure e receber mensagens de assinaturas para esse tópico.

Observação

Este guia de início rápido apresenta instruções passo a passo para um cenário simples de envio de um lote de mensagens para um tópico de Barramento de Serviço e recebimento dessas mensagens de uma assinatura do tópico. Você pode encontrar exemplos do Java predefinidos para o Barramento de Serviço do Azure no SDK do Azure para repositório do Java no GitHub.

Dica

Se você estiver trabalhando com recursos do Barramento de Serviço do Azure em um aplicativo Spring, recomendamos considerar o Spring Cloud Azure como alternativa. O Spring Cloud Azure é um projeto de software livre que fornece integração perfeita do Spring com os serviços do Azure. Para saber mais sobre o Spring Cloud Azure e ver um exemplo usando o Barramento de Serviço, confira Spring Cloud Stream com o Barramento de Serviço do Azure.

Pré-requisitos

Criar um namespace no Portal do Azure

Para começar a usar as entidades de mensagens do Barramento de Serviço no Azure, primeiro é necessário criar um namespace com um nome exclusivo no Azure. Um namespace fornece um contêiner de escopo para recursos do Barramento de Serviço (filas, tópicos, etc.) dentro de seu aplicativo.

Para criar um namespace:

  1. Entre no portal do Azure.

  2. Navegue até Página Todos os serviços.

  3. Na barra de navegação à esquerda, selecione Integração na lista de categorias. Passe o mouse sobre Barramento de Serviço e, em seguida, selecione o botão + no bloco do Barramento de Serviço.

    Imagem mostrando a seleção de Criar um recurso, Integração e, por fim, Barramento de Serviço no menu.

  4. Na marca Informações Básicas da página Criar namespace, siga estas etapas:

    1. Em Assinatura, escolha uma assinatura do Azure na qual criar o namespace.

    2. Em Grupo de recursos, escolha um grupo de recursos existente no qual o namespace residirá ou então crie um novo.

    3. Insira um nome para o namespace. O nome do namespace deve estar de acordo com as convenções de nomenclatura abaixo:

      • O nome deve ser exclusivo em todo o Azure. O sistema imediatamente verifica para ver se o nome está disponível.
      • O nome deve ter no mínimo seis e no máximo 50 caracteres.
      • O campo pode conter apenas letras, números e hifens "-".
      • O nome precisa começar com uma letra e terminar com uma letra ou um número.
      • O nome não termina com “-sb“ nem “-mgmt“.
    4. Em Localização, escolha a região na qual o namespace deve ser hospedado.

    5. Selecione o Tipo de preço (Básico, Standard ou Premium) do namespace. Para esse início rápido, selecione Padrão.

      Importante

      Se você quiser usar tópicos e assinaturas, escolha Standard ou Premium. Não há suporte para os tópicos/assinaturas no tipo de preço básico.

      Se você selecionou o tipo de preço Premium, especifique o número de unidades do sistema de mensagens. A camada Premium fornece isolamento de recursos no nível de CPU e memória, de modo que cada carga de trabalho seja executada isoladamente. Esse contêiner de recursos é chamado de unidade do sistema de mensagens. Um namespace premium tem pelo menos uma unidade do sistema de mensagens. Você pode selecionar 1, 2, 4, 8 ou 16 unidades do sistema de mensagens para cada namespace Premium do Barramento de Serviço. Para saber mais, confira Sistema de Mensagens Premium do Barramento de Serviço.

    6. Selecione Revisar + criar na parte inferior da página.

      Imagem mostrando a página Criar um namespace

    7. Na páginaRevisar + criar,revise as configurações e selecioneCriar.

  5. Depois que a implantação do recurso for bem-sucedida, selecione Ir para o recurso na página de implantação.

    Imagem mostrando a página implantação bem-sucedida com o link Ir para o recurso.

  6. Você verá a home page do namespace do barramento de serviço.

    Imagem mostrando a home page do namespace Barramento de Serviço criado.

Criar um tópico usando o portal do Azure

  1. Na página Namespace de Barramento de Serviço, selecione Tópicos no menu à esquerda.

  2. Selecione + Tópico na barra de ferramentas.

  3. Insira um nome para o tópico. Deixe as outras opções com os valores padrão.

  4. Selecione Criar.

    Imagem mostrando a página Criar um Tópico.

Criar uma assinatura para o tópico

  1. Selecione o tópico que você criou na seção anterior.

    Imagem mostrando a seleção de tópico na lista de tópicos.

  2. Na página Tópico de Barramento de Serviço, selecione + Assinatura na barra de ferramentas.

    Imagem mostrando o botão Adicionar assinatura.

  3. Na página Criar assinatura, siga estas etapas:

    1. Insira S1 em Nome da assinatura.

    2. Insira 3 em Contagem máxima de entregas.

    3. Em seguida, selecione Criar para criar a assinatura.

      Imagem mostrando a página Criar assinatura.

Autenticar o aplicativo no Azure

Este início rápido mostra duas maneiras de se conectar ao Barramento de Serviço do Azure: sem senha e cadeia de conexão.

A primeira opção mostra como usar sua entidade de segurança no Microsoft Entra ID e o RBAC (controle de acesso baseado em função) para se conectar a um namespace do Barramento de Serviço. Você não precisa se preocupar em ter uma cadeia de conexão embutida no código, em um arquivo de configuração ou em um armazenamento seguro, como o Azure Key Vault.

A segunda opção mostra como usar uma cadeia de conexão para se conectar a um namespace do Barramento de Serviço. Se você for novo no Azure, poderá achar a opção de cadeia de conexão mais fácil de ser seguida. É recomendável usar a opção sem senha em aplicativos do mundo real e ambientes de produção. Para obter mais informações, confira Autenticação e autorização. Você também pode ler mais sobre a autenticação sem senha na página de visão geral.

Atribuir funções ao usuário do Microsoft Entra

Ao desenvolver localmente, a conta de usuário que se conecta ao Barramento de Serviço do Azure deve ter as permissões corretas. Você precisará da função Proprietário de Dados do Barramento de Serviço do Azure para enviar e receber mensagens. Para atribuir essa função a si mesmo, você precisará da função Administrador de acesso do usuário ou de outra função que inclua a ação Microsoft.Authorization/roleAssignments/write. É possível atribuir funções RBAC do Azure a um usuário usando o portal do Azure, a CLI do Azure ou o Azure PowerShell. Saiba mais sobre os escopos disponíveis para atribuições de função na página de visão geral do escopo.

O exemplo a seguir atribui a função Azure Service Bus Data Owner à sua conta de usuário, que fornece acesso completo aos recursos do Barramento de Serviço do Azure. Em um cenário real, siga o Princípio do Privilégio Mínimo para dar aos usuários apenas as permissões mínimas necessárias para um ambiente de produção mais seguro.

Funções internas do Azure para o Barramento de Serviço do Azure

Para o Barramento de Serviço do Azure, o gerenciamento de namespaces e de todos os recursos relacionados por meio do portal do Azure e da API de gerenciamento de recursos do Azure já está protegido pelo modelo RBAC do Azure. O Azure fornece as funções internas do Azure abaixo para autorizar o acesso a um namespace do Barramento de Serviço:

Se você quiser criar uma função personalizada, consulte Direitos exigidos para operações do Barramento de Serviço.

Adicionar usuário do Microsoft Entra à função Proprietário do Barramento de Serviço do Azure

Adicione seu nome de usuário do Microsoft Entra à função de Proprietário de Dados do Barramento de Serviço do Azure no nível do namespace do Barramento de Serviço. Ele permitirá que um aplicativo em execução no contexto de sua conta de usuário envie mensagens para uma fila ou um tópico e receba mensagens de uma fila ou assinatura de um tópico.

Importante

Na maioria dos casos, levará um ou dois minutos para a atribuição de função se propagar no Azure. Em casos raros, poderá levar até oito minutos. Se você receber erros de autenticação ao executar o código pela primeira vez, aguarde alguns instantes e tente novamente.

  1. Se você a página Namespace do Barramento de Serviço não estiver aberta no portal do Azure, localize o namespace do Barramento de Serviço usando a barra de pesquisa principal ou a navegação à esquerda.

  2. Na página de visão geral, selecione Controle de acesso (IAM) no menu à esquerda.

  3. Na página Controle de acesso (IAM), selecione a guia Atribuições de função.

  4. Selecione + Adicionar no menu superior e, em seguida, Adicionar atribuição de função no menu suspenso resultante.

    Captura de tela mostrando como atribuir uma função.

  5. Use a caixa de pesquisa para filtrar os resultados para a função desejada. Neste exemplo, pesquise Azure Service Bus Data Owner e selecione o resultado correspondente. Em seguida, escolha Avançar.

  6. Em Atribuir acesso a, selecione Usuário, grupo ou entidade de serviço e, em seguida, selecione + Selecionar membros.

  7. No diálogo, pesquise seu nome de usuário do Microsoft Entra (geralmente seu endereço de email user@domain) e escolha Selecionar na parte inferior do diálogo.

  8. Selecione Revisar + atribuir para ir para a página final e, em seguida, Revisar + atribuir novamente para concluir o processo.

Enviar mensagens para um tópico

Nesta seção, você criará um projeto de console Java e adicionará um código para enviar mensagens para o tópico criado.

Criar um projeto de console Java

Crie um projeto Java usando o Eclipse ou uma ferramenta de sua preferência.

Configurar seu aplicativo para usar o Barramento de serviço

Adicione referências às bibliotecas do Azure Core e do Barramento de Serviço do Azure.

Se você estiver usando o Eclipse e criado um aplicativo de console Java, converta seu projeto Java em um Maven: clique com o botão direito do mouse no projeto na janela Explorador de Pacotes, selecione Configurar ->Converter para projeto Maven. Em seguida, adicione dependências a essas duas bibliotecas, conforme mostrado no exemplo a seguir.

Atualize o arquivo pom.xml para adicionar dependências ao Barramento de Serviço do Azure e a pacotes de Identidade do Azure.

    <dependencies>
        <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-messaging-servicebus</artifactId>
            <version>7.13.3</version>
        </dependency>
        <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-identity</artifactId>
            <version>1.8.0</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

Adicionar um código para enviar mensagens para o tópico

  1. Adicione as instruções import a seguir ao tópico do arquivo Java.

    import com.azure.messaging.servicebus.*;
    import com.azure.identity.*;
    
    import java.util.concurrent.TimeUnit;
    import java.util.Arrays;
    import java.util.List;
    
  2. Na classe, defina variáveis para manter a cadeia de conexão (o que não é necessário para o cenário sem senha), o nome do tópico e o nome da assinatura.

    static String topicName = "<TOPIC NAME>";
    static String subName = "<SUBSCRIPTION NAME>";
    

    Importante

    Substitua <TOPIC NAME> pelo nome do tópico e <SUBSCRIPTION NAME> pelo nome da assinatura do tópico.

  3. Adicione um método chamado sendMessage à classe para enviar uma mensagem ao tópico.

    Importante

    Substitua NAMESPACENAME pelo nome do seu namespace do Barramento de Serviço.

    static void sendMessage()
    {
        // create a token using the default Azure credential
        DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
                .build();
    
        ServiceBusSenderClient senderClient = new ServiceBusClientBuilder()
                .fullyQualifiedNamespace("NAMESPACENAME.servicebus.windows.net")
                .credential(credential)
                .sender()
                .topicName(topicName)
                .buildClient();
    
        // send one message to the topic
        senderClient.sendMessage(new ServiceBusMessage("Hello, World!"));
        System.out.println("Sent a single message to the topic: " + topicName);
    }
    
    
  4. Adicione um método chamado createMessages à classe para criar uma lista de mensagens. Normalmente, você obtém essas mensagens de diferentes partes do seu aplicativo. Aqui, criamos uma lista de mensagens de exemplo.

    static List<ServiceBusMessage> createMessages()
    {
        // create a list of messages and return it to the caller
        ServiceBusMessage[] messages = {
                new ServiceBusMessage("First message"),
                new ServiceBusMessage("Second message"),
                new ServiceBusMessage("Third message")
        };
        return Arrays.asList(messages);
    }
    
  5. Adicione um método chamado sendMessageBatch para enviar mensagens ao tópico criado. Esse método cria uma ServiceBusSenderClient para o tópico, invoca o método createMessages para obter a lista de mensagens, prepara um ou mais lotes e envia os lotes ao tópico.

    Importante

    Substitua NAMESPACENAME pelo nome do seu namespace do Barramento de Serviço.

    static void sendMessageBatch()
    {
        // create a token using the default Azure credential
        DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
                .build();
    
        ServiceBusSenderClient senderClient = new ServiceBusClientBuilder()
                .fullyQualifiedNamespace("NAMESPACENAME.servicebus.windows.net")
                .credential(credential)
                .sender()
                .topicName(topicName)
                .buildClient();
    
        // Creates an ServiceBusMessageBatch where the ServiceBus.
        ServiceBusMessageBatch messageBatch = senderClient.createMessageBatch();
    
        // create a list of messages
        List<ServiceBusMessage> listOfMessages = createMessages();
    
        // We try to add as many messages as a batch can fit based on the maximum size and send to Service Bus when
        // the batch can hold no more messages. Create a new batch for next set of messages and repeat until all
        // messages are sent.
        for (ServiceBusMessage message : listOfMessages) {
            if (messageBatch.tryAddMessage(message)) {
                continue;
            }
    
            // The batch is full, so we create a new batch and send the batch.
            senderClient.sendMessages(messageBatch);
            System.out.println("Sent a batch of messages to the topic: " + topicName);
    
            // create a new batch
            messageBatch = senderClient.createMessageBatch();
    
            // Add that message that we couldn't before.
            if (!messageBatch.tryAddMessage(message)) {
                System.err.printf("Message is too large for an empty batch. Skipping. Max size: %s.", messageBatch.getMaxSizeInBytes());
            }
        }
    
        if (messageBatch.getCount() > 0) {
            senderClient.sendMessages(messageBatch);
            System.out.println("Sent a batch of messages to the topic: " + topicName);
        }
    
        //close the client
        senderClient.close();
    }
    

Receber mensagens de uma assinatura

Nesta seção, você adicionará o código para recuperar mensagens de uma assinatura para o tópico.

  1. Adicione um método chamado receiveMessages para receber mensagens da assinatura. Esse método cria um ServiceBusProcessorClient para a assinatura especificando um manipulador para o processamento de mensagens e outro para o tratamento de erros. Em seguida, ele inicia o processador, aguarda alguns segundos, imprime as mensagens recebidas e, por fim, interrompe e fecha o processador.

    Importante

    • Substitua NAMESPACENAME pelo nome do seu namespace do Barramento de Serviço.
    • Substitua ServiceBusTopicTest em ServiceBusTopicTest::processMessage no código pelo nome da sua classe.
    // handles received messages
    static void receiveMessages() throws InterruptedException
    {
        DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
                .build();
    
        // Create an instance of the processor through the ServiceBusClientBuilder
        ServiceBusProcessorClient processorClient = new ServiceBusClientBuilder()
            .fullyQualifiedNamespace("NAMESPACENAME.servicebus.windows.net")
            .credential(credential)
            .processor()
            .topicName(topicName)
            .subscriptionName(subName)
            .processMessage(context -> processMessage(context))
            .processError(context -> processError(context))
            .buildProcessorClient();
    
        System.out.println("Starting the processor");
        processorClient.start();
    
        TimeUnit.SECONDS.sleep(10);
        System.out.println("Stopping and closing the processor");
        processorClient.close();
    }
    
  2. Adicione o método processMessage para processar uma mensagem recebida da assinatura do Barramento de Serviço.

    private static void processMessage(ServiceBusReceivedMessageContext context) {
        ServiceBusReceivedMessage message = context.getMessage();
        System.out.printf("Processing message. Session: %s, Sequence #: %s. Contents: %s%n", message.getMessageId(),
            message.getSequenceNumber(), message.getBody());
    }
    
  3. Adicione o método processError para manipular mensagens de erro.

    private static void processError(ServiceBusErrorContext context) {
        System.out.printf("Error when receiving messages from namespace: '%s'. Entity: '%s'%n",
            context.getFullyQualifiedNamespace(), context.getEntityPath());
    
        if (!(context.getException() instanceof ServiceBusException)) {
            System.out.printf("Non-ServiceBusException occurred: %s%n", context.getException());
            return;
        }
    
        ServiceBusException exception = (ServiceBusException) context.getException();
        ServiceBusFailureReason reason = exception.getReason();
    
        if (reason == ServiceBusFailureReason.MESSAGING_ENTITY_DISABLED
            || reason == ServiceBusFailureReason.MESSAGING_ENTITY_NOT_FOUND
            || reason == ServiceBusFailureReason.UNAUTHORIZED) {
            System.out.printf("An unrecoverable error occurred. Stopping processing with reason %s: %s%n",
                reason, exception.getMessage());
        } else if (reason == ServiceBusFailureReason.MESSAGE_LOCK_LOST) {
            System.out.printf("Message lock lost for message: %s%n", context.getException());
        } else if (reason == ServiceBusFailureReason.SERVICE_BUSY) {
            try {
                // Choosing an arbitrary amount of time to wait until trying again.
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                System.err.println("Unable to sleep for period of time");
            }
        } else {
            System.out.printf("Error source %s, reason %s, message: %s%n", context.getErrorSource(),
                reason, context.getException());
        }
    }
    
  4. Atualize o método main para invocar os métodos sendMessage, sendMessageBatch e receiveMessages e gerar InterruptedException.

    public static void main(String[] args) throws InterruptedException {
        sendMessage();
        sendMessageBatch();
        receiveMessages();
    }
    

Executar o aplicativo

Execute o programa para ver a saída semelhante à seguinte saída:

  1. Se você estiver usando o Eclipse, clique com o botão direito do mouse no projeto, selecione Exportar, expanda Java, selecione Arquivo JAR executável e siga as etapas para criar um arquivo JAR executável.

  2. Se você estiver conectado ao computador usando uma conta de usuário diferente da conta de usuário adicionada à função Proprietário de Dados do Barramento de Serviço do Azure, siga estas etapas. Caso contrário, ignore esta etapa e siga em frente para executar o arquivo Jar na próxima etapa.

    1. Instale a CLI do Azure no seu computador.

    2. Execute o comando da CLI a seguir para entrar no Azure. Use a mesma conta de usuário que você adicionou à função proprietário de dados do Barramento de Serviço do Azure.

      az login
      
  3. Execute o arquivo Jar usando o comando a seguir.

    java -jar <JAR FILE NAME>
    
  4. Você verá a saída a seguir na janela do console.

    Sent a single message to the topic: mytopic
    Sent a batch of messages to the topic: mytopic
    Starting the processor
    Processing message. Session: e0102f5fbaf646988a2f4b65f7d32385, Sequence #: 1. Contents: Hello, World!
    Processing message. Session: 3e991e232ca248f2bc332caa8034bed9, Sequence #: 2. Contents: First message
    Processing message. Session: 56d3a9ea7df446f8a2944ee72cca4ea0, Sequence #: 3. Contents: Second message
    Processing message. Session: 7bd3bd3e966a40ebbc9b29b082da14bb, Sequence #: 4. Contents: Third message
    

Na página Visão geral do namespace do Barramento de Serviço no portal do Azure, você poderá ver a contagem de mensagens de entrada e saída. Aguarde alguns minutos e atualizar a página para ver os valores mais recentes.

Contagem de mensagens de entrada e saída

Alterne para a guia Tópicos no painel da metade inferior e selecione o tópico para ver a página Tópico do Barramento de Serviço do tópico. Nessa página, você verá quatro mensagens de entrada e quatro mensagens de saída no gráfico Mensagens.

Mensagens de entrada e saída

Se você comentar a chamada receiveMessages no método main e executar o aplicativo novamente, na página Tópico do Barramento de Serviço, verá oito mensagens de entrada (quatro novas), mas quatro mensagens de saída.

Página do tópico atualizada

Nessa página, se você selecionar uma assinatura, chegará à página Assinatura do Barramento de Serviço. Você poderá ver a contagem de mensagens ativas, a contagem de mensagens mortas, entre outros nessa página. Neste exemplo, há quatro mensagens ativas que ainda não foram recebidas pelo destinatário.

Contagem de mensagens ativas

Próximas etapas

Confira os seguintes exemplos e a documentação: