Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En esta guía se proporciona información detallada que le ayudará a comunicarse correctamente con Azure Service Bus mediante la API de Java Message Service (JMS) 2.0.
Como desarrollador de Java, si no está familiarizado con Azure Service Bus, considere la posibilidad de leer los artículos siguientes.
| Cómo empezar | Conceptos |
|---|---|
Modelo de programación de Java Message Service (JMS)
El modelo de programación de la API de Message Service Java se describe en las secciones siguientes:
Nota:
El nivel Premium de Azure Service Bus admite JMS 1.1 y JMS 2.0.
Azure Service Bus: el nivel estándar admite una funcionalidad limitada de JMS 1.1. Para más información, consulte esta documentación.
JMS: bloques de construcción
Use los siguientes bloques de creación para comunicarse con la aplicación JMS.
Nota:
Esta guía se adapta del tutorial Oracle Java EE 6 para Java Message Service (JMS).
Para comprender mejor la Java Message Service (JMS), consulte este tutorial.
Fábrica de conexiones
Nota:
La azure-servicebus-jms biblioteca está disponible en dos variantes: com.azure:azure-servicebus-jms (versión 2.0.0+) para Jakarta EE () y jakarta.jms.* (com.microsoft.azure:azure-servicebus-jmsversión 1.0.x) para Java EE (javax.jms.*). Para obtener instrucciones sobre cómo elegir el artefacto correcto, consulte Compatibilidad con Jakarta EE y javax.
El cliente usa el objeto de generador de conexiones para conectarse al proveedor de JMS. El generador de conexiones encapsula un conjunto de parámetros de configuración de conexión que define el administrador.
Cada generador de conexiones es una instancia de la ConnectionFactoryinterfaz , QueueConnectionFactoryo TopicConnectionFactory .
Para simplificar la conexión a Azure Service Bus, estas interfaces se implementan a través de ServiceBusJmsConnectionFactory, ServiceBusJmsQueueConnectionFactory o ServiceBusJmsTopicConnectionFactory respectivamente.
Importante
Aplicaciones Java que usan la API de JMS 2.0 pueden conectarse a Azure Service Bus mediante la cadena de conexión o mediante un TokenCredential para aprovechar la autenticación respaldada por Microsoft Entra. Al usar autenticación respaldada por Microsoft Entra, asegúrese de asignar roles y permisos a la identidad según sea necesario.
- Identidad administrada asignada por el sistema
- Identidad administrada asignada por el usuario
- Entidad de servicio
Cree una identidad administrada asignada por el sistema en Azure y use esta identidad para crear un TokenCredential.
TokenCredential tokenCredential = new DefaultAzureCredentialBuilder().build();
Puede crear instancias del generador de conexiones con los parámetros siguientes:
- Credencial de token: representa una credencial capaz de proporcionar un token de OAuth.
- Host: el nombre de host del espacio de nombres de nivel Premium de Azure Service Bus.
- Bolsa de propiedades de ServiceBusJmsConnectionFactorySettings, que contiene:
-
connectionIdleTimeoutMS- tiempo de espera para conexión inactiva en milisegundos. -
traceFrames: marca booleana para recopilar marcos de seguimiento de AMQP para la depuración. - Otros parámetros de configuración.
-
Cree la fábrica como se muestra en el ejemplo siguiente. Las credenciales de token y el host son parámetros necesarios, pero las otras propiedades son opcionales.
String host = "<YourNamespaceName>.servicebus.windows.net";
ConnectionFactory factory = new ServiceBusJmsConnectionFactory(tokenCredential, host, null);
Destino de JMS
Un destino es el objeto que usa un cliente para especificar el destino de los mensajes que genera y el origen de los mensajes que consume.
Los destinos se asignan a entidades de Azure Service Bus: colas (en escenarios de punto a punto) y temas (en escenarios de publicación y suscripción).
Conexiones
Una conexión encapsula una conexión virtual con un proveedor de JMS. Con Azure Service Bus, esto representa una conexión con estado entre la aplicación y Azure Service Bus mediante AMQP.
Cree una conexión desde el generador de conexiones, como se muestra en el ejemplo siguiente:
Connection connection = factory.createConnection();
Sesiones
Una sesión es un contexto de un solo subproceso para generar y consumir mensajes. Úselo para crear mensajes, productores de mensajes y consumidores. También proporciona un contexto transaccional para agrupar los envíos y recibirlos en una unidad atómica de trabajo.
Cree una sesión a partir del objeto de conexión como se muestra en el ejemplo siguiente:
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Nota:
La API de JMS no admite la recepción de mensajes de colas o temas de Service Bus con sesiones de mensajería habilitadas.
Modos de sesión
Cree una sesión con cualquiera de los modos siguientes.
| Modos de sesión | Comportamiento |
|---|---|
| Session.AUTO_ACKNOWLEDGE | La sesión confirma automáticamente la recepción de un mensaje de un cliente cuando la sesión vuelve correctamente de una llamada para recibir o cuando el agente de escucha de mensajes llama a la sesión para procesar el mensaje correctamente. |
| Session.CLIENT_ACKNOWLEDGE | El cliente reconoce un mensaje consumido llamando al método de confirmación del mensaje. |
| Session.DUPS_OK_ACKNOWLEDGE | Este modo de confirmación indica a la sesión que confirme de forma diferida la entrega de mensajes. |
| Session.SESSION_TRANSACTED | Pase este valor como argumento al método createSession(int sessionMode) en el objeto Connection para especificar que la sesión debe usar una transacción local. |
Si no especifica el modo de sesión, el valor predeterminado es Session.AUTO_ACKNOWLEDGE.
JMSContext
Nota:
JMSContext se define como parte de la especificación JMS 2.0.
JMSContext combina la funcionalidad proporcionada por la conexión y el objeto de sesión. Se crea a partir del objeto de generador de conexiones.
JMSContext context = connectionFactory.createContext();
Modos de JMSContext
Al igual que el objeto Session , puede crear JMSContext con los mismos modos de confirmación que se mencionan en Modos de sesión.
JMSContext context = connectionFactory.createContext(JMSContext.AUTO_ACKNOWLEDGE);
Si no especifica un modo, el valor predeterminado es JMSContext.AUTO_ACKNOWLEDGE.
Productores de mensajes de JMS
Un productor de mensajes es un objeto que se crea mediante JMSContext o una sesión. Úselo para enviar mensajes a un destino.
Puede crearlo como un objeto independiente, como se muestra en el ejemplo siguiente:
JMSProducer producer = context.createProducer();
O bien, puede crearlo en tiempo de ejecución cuando necesite enviar un mensaje.
context.createProducer().send(destination, message);
Consumidores de mensajes de JMS
Un consumidor de mensajes es un objeto que un JMSContext o una sesión crea. Úselo para recibir mensajes enviados a un destino. Créela como se muestra en el ejemplo siguiente:
JMSConsumer consumer = context.createConsumer(dest);
Recepción sincrónica a través del método receive()
El consumidor de mensajes proporciona una manera sincrónica de recibir mensajes del destino a través del receive() método .
Si no especifica argumentos o tiempo de espera, o especifica un tiempo de espera de 0, el consumidor se bloquea indefinidamente a menos que llegue el mensaje o se interrumpe la conexión (lo que ocurra primero).
Message m = consumer.receive();
Message m = consumer.receive(0);
Cuando se proporciona un argumento positivo distinto de cero, el consumidor se bloquea hasta que expire el temporizador.
Message m = consumer.receive(1000); // time out after one second.
Recepciones asincrónicas con clientes de escucha de mensajes JMS
Un agente de escucha de mensajes es un objeto que se usa para el control asincrónico de mensajes en un destino. Implementa la interfaz MessageListener, que contiene el método onMessage en el que debe residir la lógica de negocios específica.
Debe instanciar un objeto listener de mensajes y registrarlo en un consumidor de mensajes específico mediante el método setMessageListener.
Listener myListener = new Listener();
consumer.setMessageListener(myListener);
Consumo desde temas
Se crean consumidores de mensajes JMS para un destino, que puede ser una cola o un tópico.
Los consumidores de colas son simplemente objetos del lado cliente que residen dentro del contexto de la sesión (y conexión) entre la aplicación cliente y Azure Service Bus.
Sin embargo, los consumidores de temas tienen dos partes:
- Objeto del lado cliente que reside en el contexto de la sesión (o JMSContext) y
- una suscripción que es una entidad en Azure Service Bus.
Las suscripciones se documentan aquí y pueden ser uno de los siguientes tipos:
- Suscripciones duraderas compartidas
- Suscripciones no duraderas compartidas
- Suscripciones duraderas no compartidas
- Suscripciones no duraderas no compartidas
Exploradores de colas de JMS
La API de JMS proporciona un QueueBrowser objeto que la aplicación puede usar para examinar los mensajes de la cola y mostrar los valores de encabezado de cada mensaje.
Puede crear un queue Browser mediante JMSContext, como se muestra en el ejemplo siguiente:
QueueBrowser browser = context.createBrowser(queue);
Nota:
La API de JMS no proporciona una API para examinar un tema.
Esta limitación existe porque el propio tema no almacena los mensajes. En cuanto se envía el mensaje al tema, se reenvía a las suscripciones adecuadas.
Selectores de mensajes de JMS
Las aplicaciones receptoras pueden usar selectores de mensajes para filtrar los mensajes que reciben. Mediante el uso de selectores de mensajes, la aplicación receptora descarga el trabajo de filtrar mensajes al proveedor de JMS (en este caso, Azure Service Bus) en lugar de asumir esa responsabilidad.
Puede usar selectores al crear cualquiera de los consumidores siguientes:
- Suscripción duradera compartida
- Suscripción duradera no compartida
- Suscripción compartida no duradera
- Suscripción no duradera no compartida
- Consumidor de cola
- Explorador de colas
Nota:
Service Bus selectores no admiten LIKE ni BETWEEN palabras clave SQL.
Mensajes programados (retraso de entrega)
JMS 2.0 admite la programación de un mensaje para su entrega futura utilizando el método setDeliveryDelay en un MessageProducer o JMSProducer. Al establecer esta propiedad, Service Bus acepta el mensaje, pero solo hace que sea visible para los consumidores una vez transcurrido el período de retraso.
MessageProducer producer = session.createProducer(queue);
// Schedule a message for delivery 30 seconds from now
producer.setDeliveryDelay(30000);
producer.send(session.createTextMessage("Scheduled message"));
Para obtener un ejemplo de trabajo completo, consulte QueueScheduledSend.java en el repositorio azure-servicebus-jms-samples.
Selección y resistencia de la factoría de conexión
Cuando utilice ServiceBusJmsConnectionFactory en Spring Boot u otros marcos que gestionan conexiones JMS, elija la envoltura adecuada de la fábrica de conexiones para remitentes y escuchas para asegurar un funcionamiento confiable.
Configuración recomendada
| Role | Fábrica de conexiones | Por qué |
|---|---|---|
Remitentes (JmsTemplate) |
CachingConnectionFactory envoltura ServiceBusJmsConnectionFactory |
JmsTemplate crea y cierra una conexión por envío de forma predeterminada.
CachingConnectionFactory mantiene una única conexión AMQP y almacena en caché las sesiones, lo que evita el cambio de conexión que puede agotar los recursos del broker bajo carga. |
Escuchadores (@JmsListener, DefaultMessageListenerContainer) |
Sin procesar ServiceBusJmsConnectionFactory (desencapsulado) |
Cada contenedor de escucha obtiene su propia conexión AMQP con un ciclo de vida independiente. Si se produce un error en una conexión (expiración del token, actualización de puerta de enlace, blip de red), solo ese agente de escucha se ve afectado y Spring vuelve a crear la conexión automáticamente. |
Qué evitar para los oyentes
Advertencia
Nunca use SingleConnectionFactory con contenedores de oyentes. Obliga a todos los agentes de escucha a compartir una única conexión JMS. Si esa conexión se interrumpe por cualquier motivo, todos los oyentes perderán la conectividad al mismo tiempo y no podrán recuperarse por sí mismos. Utiliza el ServiceBusJmsConnectionFactory sin procesar para que cada contenedor de oyente administre su propia conexión.
CachingConnectionFactory en los contenedores de escucha también puede causar problemas porque las sesiones almacenadas en caché pueden hacer referencia a una conexión subyacente obsoleta. En el caso de los escuchas, la fábrica sin procesar garantiza que cada contenedor pueda crear una conexión nueva de forma independiente.
Valores predeterminados de Spring Cloud Azure
Si usa spring-cloud-azure-starter-servicebus-jms (versión 6.2.0+), el iniciador aplica esta separación de fábrica de forma predeterminada:
spring.jms.servicebus.pool.enabled |
spring.jms.cache.enabled |
Fábrica de remitentes | Fábrica de listeners |
|---|---|---|---|
| (no establecido) | (no establecido) | CachingConnectionFactory |
ServiceBusJmsConnectionFactory |
| (no establecido) | true |
CachingConnectionFactory |
CachingConnectionFactory |
| (no establecido) | false |
ServiceBusJmsConnectionFactory |
ServiceBusJmsConnectionFactory |
true |
(no establecido) | JmsPoolConnectionFactory |
JmsPoolConnectionFactory |
En versiones anteriores (anteriores a la versión 6.2.0), los remitentes y los agentes de escucha usan ServiceBusJmsConnectionFactory de forma predeterminada, lo que hace que los remitentes creen una nueva conexión por envío.
Adición de un agente de escucha de excepciones
Sin un listener de excepciones, las interrupciones de conexión son completamente silenciosas. Agregue un elemento jakarta.jms.ExceptionListener a los generadores de remitentes y agentes de escucha para la observabilidad:
connection.setExceptionListener(exception -> {
log.error("JMS connection error: {}", exception.getMessage(), exception);
});
En Spring Boot, establezca el escuchador de excepciones en CachingConnectionFactory (para remitentes) y DefaultJmsListenerContainerFactory (para escuchadores).
Para ver un ejemplo de trabajo completo que muestra todos estos patrones, consulte el ejemplo de resiliencia de JMS de Spring Boot en el repositorio azure-servicebus-jms-samples.
Colas de mensajes no entregados
Cada cola y suscripción de tema en Azure Service Bus tiene asociada una cola de letras muertas (DLQ). El sistema mueve automáticamente los mensajes que no se pueden entregar ni procesar al DLQ. Por ejemplo, el sistema mueve un mensaje a la DLQ cuando el mensaje supera el número máximo de entregas o expira su período de vida (TTL).
Importante
Para mover los mensajes expirados de TTL al DLQ, habilite el marcado como fallido al expirar el mensaje para la cola o suscripción. Sin esta configuración, el sistema descarta silenciosamente los mensajes expirados. Para conocer los pasos de configuración, consulte Habilitar letras muertas para una cola o suscripción.
En JMS, se accede al DLQ como un destino independiente construyendo la ruta completa y creando un JmsQueue con ella. No se requiere ninguna API especial.
Formato de ruta de acceso DLQ de cola:
<queue-name>/$deadletterqueue
Formato de ruta de acceso a la DLQ de suscripción a un tema:
<topic-name>/Subscriptions/<subscription-name>/$deadletterqueue
Ejemplo: consumo desde la cola de mensajes fallidos de una cola:
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);
Los mensajes con mensajes fallidos incluyen propiedades de metadatos que describen por qué el mensaje estaba fallido:
| Propiedad | Description |
|---|---|
DeadLetterReason |
La razón por la que el mensaje no se pudo entregar (por ejemplo, TTLExpiredException o MaxDeliveryCountExceeded). |
DeadLetterErrorDescription |
Una descripción legible de la razón de los mensajes no entregados. |
Lea estas propiedades mediante message.getStringProperty():
String reason = message.getStringProperty("DeadLetterReason");
String description = message.getStringProperty("DeadLetterErrorDescription");
Para obtener un ejemplo de trabajo completo, consulte QueueDeadLetterReceive.java en el repositorio azure-servicebus-jms-samples.
Asignación de la operación de Service Bus y eliminación de AMQP
Este es el modo en que una disposición de AMQP se traduce en una operación de 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()
Resumen
En esta guía para desarrolladores se muestra cómo Java las aplicaciones cliente que usan Java Message Service (JMS) pueden conectarse a Azure Service Bus.
Pasos siguientes
Para obtener más información sobre Azure Service Bus y detalles sobre las entidades de Java Message Service (JMS), consulte los siguientes artículos:
- Choose entre JMS y el SDK nativo para Azure Service Bus
- Service Bus: colas, temas y suscripciones
- Service Bus - entidades de Servicio de Mensajería Java
- Compatibilidad con AMQP 1.0 en Azure Service Bus
- Guía del desarrollador de AMQP 1.0 de Service Bus
- Introducción a las colas de Service Bus
- API de Java Message Service (documento externo de Oracle)
- Aprenda a migrar de ActiveMQ a Service Bus