Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este guia fornece informações detalhadas para o ajudar a ter sucesso na comunicação com o Azure Service Bus utilizando a API Java Message Service (JMS) 2.0.
Como programador Java, se és novo no Azure Service Bus, considera ler os seguintes artigos.
| Como Começar | Conceitos |
|---|---|
Modelo de programação Java Message Service (JMS)
O modelo de programação da API do Java Message Service é descrito nas seguintes secções:
Observação
A camada Premium do Barramento de Serviço do Azure suporta JMS 1.1 e JMS 2.0.
O Barramento de Serviço do Azure - camada Standard suporta funcionalidade limitada do JMS 1.1. Para mais detalhes, consulte esta documentação.
JMS - Blocos de construção
Use os seguintes blocos de construção para comunicar com a aplicação JMS.
Observação
Este guia é adaptado do tutorial Oracle Java EE 6 para Java Message Service (JMS).
Para uma melhor compreensão do Java Message Service (JMS), consulte este tutorial.
Fábrica de conexões
Observação
A azure-servicebus-jms biblioteca está disponível em duas variantes: com.azure:azure-servicebus-jms (versão 2.0.0+) para Jakarta EE (jakarta.jms.*) e com.microsoft.azure:azure-servicebus-jms (versão 1.0.x) para Java EE (javax.jms.*). Para orientações sobre como escolher o artefato certo, consulte Jakarta EE e suporte javax.
O cliente utiliza o objeto de fábrica de ligação para se ligar ao fornecedor JMS. A fábrica de ligação encapsula um conjunto de parâmetros de configuração de ligação que o administrador define.
Cada fábrica de ligações é uma instância da interface ConnectionFactory, QueueConnectionFactory ou TopicConnectionFactory.
Para simplificar a ligação a Azure Service Bus, estas interfaces são implementadas através de ServiceBusJmsConnectionFactory, ServiceBusJmsQueueConnectionFactory ou ServiceBusJmsTopicConnectionFactory, respetivamente.
Importante
As aplicações Java que utilizam a API JMS 2.0 podem ligar-se ao Azure Service Bus utilizando a cadeia de ligação ou um TokenCredential para tirar partido da autenticação suportada pelo Microsoft Entra. Quando usar a autenticação suportada pelo Microsoft Entra, certifique-se de atribuir funções e permissões à identidade, conforme necessário.
- Identidade gerenciada atribuída pelo sistema
- Identidade Gerida Atribuída pelo Utilizador
- Entidade de Serviço
Crie uma identidade gerida atribuída pelo sistema no Azure e use essa identidade para criar um TokenCredential.
TokenCredential tokenCredential = new DefaultAzureCredentialBuilder().build();
Pode instanciar a fábrica de ligação com os seguintes parâmetros:
- Credencial de token - Representa uma credencial capaz de fornecer um token OAuth.
- Host - O nome de host do namespace de nível Premium do Azure Service Bus.
- conjunto de propriedades ServiceBusJmsConnectionFactorySettings, que contém:
-
connectionIdleTimeoutMS- tempo limite da ligação inativa em milissegundos. -
traceFrames- sinalizador booleano para capturar tramas de rastreio AMQP para depuração. - Outros parâmetros de configuração.
-
Crie a fábrica como mostrado no exemplo seguinte. A credencial de token e o host são parâmetros necessários, mas as outras propriedades são opcionais.
String host = "<YourNamespaceName>.servicebus.windows.net";
ConnectionFactory factory = new ServiceBusJmsConnectionFactory(tokenCredential, host, null);
Destino JMS
Um destino é o objeto que um cliente usa para especificar o destino das mensagens que produz e a origem das mensagens que consome.
Destinos mapeados para entidades no Barramento de Serviço do Azure - filas (em cenários ponto a ponto) e tópicos (em cenários pub-sub).
Conexões
Uma conexão encapsula uma ligação virtual com um fornecedor de JMS. Com o Barramento de Serviço do Azure, ele representa uma conexão com monitoração de estado entre o aplicativo e o Barramento de Serviço do Azure sobre AMQP.
Crie uma conexão a partir da fábrica de conexões, conforme mostrado no exemplo seguinte:
Connection connection = factory.createConnection();
Sessões
Uma sessão é um contexto de thread único para produzir e consumir mensagens. Use-o para criar mensagens, produtores de mensagens e consumidores. Também fornece um contexto transacional para agrupar envios e receções numa unidade atómica de trabalho.
Crie uma sessão a partir do objeto de conexão, como mostrado no seguinte exemplo:
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Observação
A API JMS não suporta o recebimento de mensagens de filas de barramento de serviço ou tópicos com sessões de mensagens habilitadas.
Modos de sessão
Crie uma sessão com qualquer um dos seguintes modos.
| Modos de sessão | Comportamento |
|---|---|
| Session.AUTO_ACKNOWLEDGE | A sessão reconhece automaticamente a receção de uma mensagem por parte do cliente, seja quando a sessão regressa com sucesso de uma chamada para receber ou quando o ouvinte da mensagem que a sessão chama para processar a mensagem retorna com sucesso. |
| Session.CLIENT_ACKNOWLEDGE (Reconhecimento do Cliente) | O cliente reconhece uma mensagem consumida chamando o método de reconhecimento da mensagem. |
| Session.DUPS_OK_ACKNOWLEDGE | Este modo de confirmação instrui a sessão a reconhecer preguiçosamente a entrega de mensagens. |
| Session.SESSION_TRANSACTED | Passe este valor como argumento ao método createSession(int sessionMode) no objeto Connection para especificar que a sessão deve usar uma transação local. |
Se não especificares o modo de sessão, o padrão é Session.AUTO_ACKNOWLEDGE.
JMSContext
Observação
JMSContext é definido como parte da especificação JMS 2.0.
JMSContext combina a funcionalidade fornecida pelo objeto de conexão e sessão. Cria-se a partir do objeto connection factory.
JMSContext context = connectionFactory.createContext();
Modos JMSContext
Tal como acontece com o objeto Session, pode criar o JMSContext com os mesmos modos de confirmação referidos em modos de Session.
JMSContext context = connectionFactory.createContext(JMSContext.AUTO_ACKNOWLEDGE);
Se não especificares um modo, o padrão é JMSContext.AUTO_ACKNOWLEDGE.
Produtores de mensagens JMS
Um produtor de mensagens é um objeto que se cria usando um JMSContext ou uma Session. Use-o para enviar mensagens para um destino.
Pode criá-lo como um objeto autónomo, como mostrado no seguinte exemplo:
JMSProducer producer = context.createProducer();
Ou podes criá-lo em tempo de execução quando precisares de enviar uma mensagem.
context.createProducer().send(destination, message);
Consumidores de mensagens JMS
Um consumidor de mensagens é um objeto criado por um JMSContext ou uma Session. Use-o para receber mensagens enviadas para um destino. Crie-o como mostrado no seguinte exemplo:
JMSConsumer consumer = context.createConsumer(dest);
Recebimento síncrono via método receive()
O consumidor de mensagens fornece uma maneira síncrona de receber mensagens do destino por meio do receive() método.
Se não especificar argumentos nem um timeout, ou se especificar um timeout de 0, o consumidor fica bloqueado indefinidamente, a menos que a mensagem chegue ou que a ligação seja interrompida, consoante o que ocorrer primeiro.
Message m = consumer.receive();
Message m = consumer.receive(0);
Quando fornece um argumento positivo diferente de zero, o consumidor bloqueia até essa temporização terminar.
Message m = consumer.receive(1000); // time out after one second.
Receções assíncronas com ouvintes de mensagens JMS
Um recetor de mensagens é um objeto que utiliza para o processamento assíncrono de mensagens num destino. Implementa a interface MessageListener, que contém o método onMessage onde a lógica de negócios específica deve estar implementada.
Deve instanciar um objeto recetor de mensagens e associá-lo a um consumidor de mensagens específico utilizando o método setMessageListener.
Listener myListener = new Listener();
consumer.setMessageListener(myListener);
Consumir a partir de tópicos
Cria Consumidores de Mensagens JMS para um destino, que pode ser uma fila ou um tópico.
Os consumidores em filas são simplesmente objetos do lado do cliente que vivem no contexto da Sessão (e da Ligação) entre a aplicação cliente e o Azure Service Bus.
No entanto, os consumidores de tópicos têm duas partes -
- Um objeto do lado do cliente que vive no contexto da Sessão (ou JMSContext), e
- Uma assinatura que é uma entidade no Azure Service Bus.
As subscrições estão documentadas aqui e podem ser de um dos seguintes tipos:
- Subscrições duradouras partilhadas
- Subscrições partilhadas não duráveis
- Subscrições duradouras não partilhadas
- Subscrições não partilhadas não duradouras
Navegadores de fila JMS
A API JMS fornece um QueueBrowser objeto que a aplicação pode usar para navegar pelas mensagens na fila e mostrar os valores do cabeçalho de cada mensagem.
Pode criar um Navegador de Filas usando o JMSContext, como mostrado no seguinte exemplo:
QueueBrowser browser = context.createBrowser(queue);
Observação
A API JMS não fornece uma API para navegar em um tópico.
Esta limitação existe porque o próprio tema não armazena as mensagens. Assim que a mensagem é enviada para o tópico, ela é encaminhada para as assinaturas apropriadas.
Seletores de mensagens JMS
As aplicações recetoras podem usar seletores de mensagens para filtrar as mensagens que recebem. Ao usar seletores de mensagens, a aplicação recetora transfere o trabalho de filtragem das mensagens para o fornecedor JMS (neste caso, Azure Service Bus) em vez de assumir essa responsabilidade por si própria.
Pode usar seletores ao criar qualquer um dos seguintes consumidores:
- Subscrição duradoura partilhada
- Subscrição duradoura não partilhada
- Subscrição partilhada não durável
- Subscrição não partilhada não duradoura
- Consumidor da fila
- Navegador de filas
Observação
Service Bus seletores não suportam palavras-chave SQL LIKE e BETWEEN.
Mensagens agendadas (atraso na entrega)
O JMS 2.0 suporta o agendamento de uma mensagem para entrega futura usando o setDeliveryDelay método num MessageProducer ou JMSProducer. Quando define esta função, o Service Bus aceita a mensagem mas só a torna visível para os consumidores após o período de atraso terminar.
MessageProducer producer = session.createProducer(queue);
// Schedule a message for delivery 30 seconds from now
producer.setDeliveryDelay(30000);
producer.send(session.createTextMessage("Scheduled message"));
Para uma amostra funcional completa, veja QueueScheduledSend.java no repositório azure-servicebus-jms-samples.
Seleção e resiliência da fábrica de ligações
Quando utiliza ServiceBusJmsConnectionFactory no Spring Boot ou noutros frameworks que gerem as ligações JMS, escolha o invólucro da fábrica de ligações adequado para emissores e escutas, para assegurar um funcionamento fiável.
Configuração recomendada
| Role | Fábrica de conexões | Porquê |
|---|---|---|
Remetentes (JmsTemplate) |
CachingConnectionFactory Envolvimento ServiceBusJmsConnectionFactory |
JmsTemplate estabelece e fecha uma ligação para cada envio por defeito.
CachingConnectionFactory mantém uma única conexão AMQP e coloca em cache as sessões, evitando a criação e o encerramento frequentes de conexões, que podem esgotar os recursos do corretor de mensagens sob carga. |
Ouvintes (@JmsListener, DefaultMessageListenerContainer) |
Em bruto ServiceBusJmsConnectionFactory (sem encapsulamento) |
Cada contentor de escuta tem a sua própria ligação AMQP com um ciclo de vida independente. Se uma ligação falhar (expiração do token, atualização do gateway, blip de rede), apenas esse ouvinte é afetado, e o Spring recria a ligação automaticamente. |
O que evitar para os ouvintes
Advertência
Nunca uses SingleConnectionFactory com contentores de escuta. Obriga todos os ouvintes a partilhar uma única ligação JMS. Se essa ligação for interrompida por qualquer motivo, todos os ouvintes perdem a ligação simultaneamente e não conseguem recuperar de forma independente. Usa o raw ServiceBusJmsConnectionFactory para que cada contentor de ouvinte gere a sua própria ligação.
CachingConnectionFactory os contentores de escuta também podem causar problemas, porque as sessões em cache podem apontar para uma ligação subjacente desatualizada. Para os ouvintes, a fábrica de crus garante que cada recipiente pode criar uma nova ligação de forma independente.
Valores predefinidos do Spring Cloud Azure
Se utilizar spring-cloud-azure-starter-servicebus-jms (versão 6.2.0+), o modelo inicial aplica esta separação das fábricas por predefinição:
spring.jms.servicebus.pool.enabled |
spring.jms.cache.enabled |
Fábrica de emissores | Fábrica de ouvintes |
|---|---|---|---|
| (não definido) | (não definido) | CachingConnectionFactory |
ServiceBusJmsConnectionFactory |
| (não definido) | true |
CachingConnectionFactory |
CachingConnectionFactory |
| (não definido) | false |
ServiceBusJmsConnectionFactory |
ServiceBusJmsConnectionFactory |
true |
(não definido) | JmsPoolConnectionFactory |
JmsPoolConnectionFactory |
Em versões mais antigas (anteriores à 6.2.0), tanto os remetentes como os ouvintes usam ServiceBusJmsConnectionFactory por defeito, o que faz com que os remetentes criem uma nova ligação por envio.
Adicionar um ouvinte de exceção
Sem um processador de exceções, as quedas de ligação passam completamente despercebidas. Adicione um jakarta.jms.ExceptionListener tanto às fábricas de emissores como de recetores para observabilidade:
connection.setExceptionListener(exception -> {
log.error("JMS connection error: {}", exception.getMessage(), exception);
});
No Spring Boot, defina o ouvinte de exceção em ( CachingConnectionFactory para emissores) e ( DefaultJmsListenerContainerFactory para ouvintes).
Para uma amostra funcional completa que mostre todos estes padrões, consulte a amostra Spring Boot JMS Resiliency no repositório azure-servicebus-jms-samples.
Filas de mensagens não entregues
Cada fila e subscrição de tópico no Azure Service Bus tem associada uma fila de mensagens mortas (DLQ). O sistema move automaticamente mensagens que não consegue entregar ou processar para o DLQ. Por exemplo, o sistema move uma mensagem para o DLQ quando a mensagem ultrapassa o número máximo de entregas ou quando o seu tempo de vida (TTL) expira.
Importante
Para mover mensagens expiradas TTL para o DLQ, ative a dead-letter no momento do término da mensagem para a fila ou subscrição. Sem esta configuração, o sistema descarta silenciosamente mensagens expiradas. Para os passos de configuração, consulte Ativar letramento morto para fila ou subscrição.
No JMS, acedes ao DLQ como destino separado construindo o caminho completo e criando um JmsQueue com ele. Não é necessária nenhuma API especial.
Formato do caminho DLQ da fila:
<queue-name>/$deadletterqueue
Subscrição do tópico Formato do caminho DLQ:
<topic-name>/Subscriptions/<subscription-name>/$deadletterqueue
Exemplo - consumir a partir da fila de letras mortas de uma fila:
import org.apache.qpid.jms.JmsQueue;
// Construct the DLQ path for a queue named "orders"
String dlqPath = "orders/$deadletterqueue";
JmsQueue dlqDestination = new JmsQueue(dlqPath);
// Create a consumer on the DLQ and receive messages
MessageConsumer dlqConsumer = session.createConsumer(dlqDestination);
Message message = dlqConsumer.receive(5000);
As mensagens colocadas na fila de mensagens mortas incluem propriedades de metadados que descrevem por que motivo a mensagem foi colocada na fila de mensagens mortas:
| Property | Description |
|---|---|
DeadLetterReason |
A razão pela qual a mensagem estava com letra morta (por exemplo, TTLExpiredException ou MaxDeliveryCountExceeded). |
DeadLetterErrorDescription |
Uma descrição legível para humanos da razão da letra morta. |
Leia estas propriedades usando message.getStringProperty():
String reason = message.getStringProperty("DeadLetterReason");
String description = message.getStringProperty("DeadLetterErrorDescription");
Para uma amostra funcional completa, veja QueueDeadLetterReceive.java no repositório azure-servicebus-jms-samples.
Disposição AMQP e mapeamento da operação do Service Bus
Veja como uma disposição AMQP se traduz em uma operação do Service Bus:
ACCEPTED = 1; -> Complete()
REJECTED = 2; -> DeadLetter()
RELEASED = 3; (just unlock the message in service bus, will then get redelivered)
MODIFIED_FAILED = 4; -> Abandon() which increases delivery count
MODIFIED_FAILED_UNDELIVERABLE = 5; -> Defer()
Resumo
Este guia para programadores mostra como aplicações cliente Java que utilizam Java Message Service (JMS) podem ligar-se ao Azure Service Bus.
Próximos passos
Para mais informações sobre o Azure Service Bus e detalhes sobre entidades do Java Message Service (JMS), consulte os seguintes artigos:
- Escolha entre o JMS e o SDK nativo para Azure Service Bus
- Barramento de Serviço - Filas, tópicos e assinaturas
- Service Bus - Entidades do Java Message Service
- Suporte a AMQP 1.0 no Azure Service Bus
- Guia do desenvolvedor do Service Bus AMQP 1.0
- Começar com as filas do Service Bus
- API do Java Message Service (doc Oracle externo)
- Saiba como migrar do ActiveMQ para o Service Bus