Ontwikkelaarshandleiding voor Azure Service Bus JMS 2.0

Deze handleiding bevat gedetailleerde informatie waarmee u kunt communiceren met Azure Service Bus met behulp van de API Java Message Service (JMS) 2.0.

Als java-ontwikkelaar kunt u de volgende artikelen lezen als u nog geen gebruik hebt gemaakt van Azure Service Bus.

Aan de slag Concepten

programmeermodel voor Java Message Service (JMS)

Het programmeermodel Java Message Service-API wordt beschreven in de volgende secties:

Opmerking

De Azure Service Bus Premium-laag ondersteunt JMS 1.1 en JMS 2.0.

Azure Service Bus - Standard-laag biedt ondersteuning voor beperkte JMS 1.1-functionaliteit. Zie deze documentatie voor meer informatie.

JMS - Bouwstenen

Gebruik de volgende bouwstenen om te communiceren met de JMS-toepassing.

Opmerking

Deze handleiding is aangepast aan de Oracle Java EE 6 Tutorial for Java Message Service (JMS).

Raadpleeg deze zelfstudie voor een beter begrip van de Java Message Service (JMS).

Verbindingsfabriek

Opmerking

De azure-servicebus-jms bibliotheek is beschikbaar in twee varianten: com.azure:azure-servicebus-jms (versie 2.0.0+) voor Jakarta EE (jakarta.jms.*) en com.microsoft.azure:azure-servicebus-jms (versie 1.0.x) voor Java EE (javax.jms.*). Zie Jakarta EE en javax-ondersteuning voor hulp bij het kiezen van het juiste artefact.

De client gebruikt het verbindingsfactory-object om verbinding te maken met de JMS-provider. De connection factory omvat een reeks configuratieparameters voor verbindingen die de beheerder definieert.

Elke verbindingsfactory is een exemplaar van de ConnectionFactory, QueueConnectionFactoryof TopicConnectionFactory interface.

Om de verbinding met Azure Service Bus te vereenvoudigen, worden deze interfaces geïmplementeerd via respectievelijk ServiceBusJmsConnectionFactory, ServiceBusJmsQueueConnectionFactory of ServiceBusJmsTopicConnectionFactory.

Belangrijk

Java toepassingen die gebruikmaken van de JMS 2.0-API, kunnen verbinding maken met Azure Service Bus met behulp van de verbindingsreeks of met behulp van een TokenCredential om gebruik te maken van Microsoft Entra ondersteunde verificatie. Wanneer u Microsoft Entra ondersteunde verificatie gebruikt, moet u zo nodig rollen en machtigingen toewijzen aan de identiteit.

Maak een door het systeem toegewezen beheerde identiteit in Azure en gebruik deze identiteit om een TokenCredential.

TokenCredential tokenCredential = new DefaultAzureCredentialBuilder().build();

U kunt de verbindingsfactory instantiëren met de volgende parameters:

  • Tokenreferentie: vertegenwoordigt een referentie die een OAuth-token kan leveren.
  • Host: de hostnaam van de Azure Service Bus Premium-laagnaamruimte.
  • Kenmerkenbundel ServiceBusJmsConnectionFactorySettings, die het volgende bevat:
    • connectionIdleTimeoutMS - Time-out voor inactieve verbinding in milliseconden.
    • traceFrames - Booleaanse vlag voor het verzamelen van AMQP-traceringsframes voor foutopsporing.
    • Andere configuratieparameters.

Maak de factory, zoals wordt weergegeven in het volgende voorbeeld. De tokenreferenties en host zijn vereiste parameters, maar de andere eigenschappen zijn optioneel.

String host = "<YourNamespaceName>.servicebus.windows.net";
ConnectionFactory factory = new ServiceBusJmsConnectionFactory(tokenCredential, host, null); 

JMS-bestemming

Een bestemming is het object dat een client gebruikt om het doel op te geven van de berichten die de client produceert en de bron van de berichten die deze verbruikt.

Bestemmingen komen overeen met entiteiten in Azure Service Bus, zoals wachtrijen (in punt-naar-puntscenario's) en topics (in pub-subscenario's).

Verbindingen

Een verbinding omvat een virtuele verbinding met een JMS-provider. Met Azure Service Bus is er sprake van een stateful verbinding tussen de toepassing en Azure Service Bus via AMQP.

Maak een verbinding vanuit de verbindingsfabriek, zoals wordt weergegeven in het volgende voorbeeld:

Connection connection = factory.createConnection();

Sessies

Een sessie is een context met één thread voor het produceren en gebruiken van berichten. Gebruik deze om berichten, berichtproducenten en consumenten te maken. Het biedt ook een transactionele context om verzenden en ontvangen te groeperen in een atomische werkeenheid.

Maak een sessie op basis van het verbindingsobject, zoals wordt weergegeven in het volgende voorbeeld:

Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);

Opmerking

JMS-API biedt geen ondersteuning voor het ontvangen van berichten van service bus-wachtrijen of onderwerpen waarvoor berichtensessies zijn ingeschakeld.

Sessiemodi

Maak een sessie met een van de volgende modi.

Sessiemodi Gedrag
Session.AUTO_ACKNOWLEDGE De sessie bevestigt automatisch de ontvangst van een bericht van een client wanneer de sessie succesvol terugkeert van een oproep naar ontvangen, of wanneer de berichtlistener die de sessie aanroept om het bericht te verwerken succesvol terugkeert.
Session.KLANT_ERKENNING De client erkent een verbruikt bericht door de erkenningsmethode van het bericht aan te roepen.
Session.DUPS_OK_ACKNOWLEDGE Deze bevestigingsmodus instrueert de sessie om de bezorging van berichten op een luie manier te bevestigen.
Session.SESSION_TRANSACTED Geef deze waarde door als het argument aan de methode createSession(int sessionMode) in het verbindingsobject om op te geven dat de sessie een lokale transactie moet gebruiken.

Als u de sessiemodus niet opgeeft, wordt de standaardwaarde Session.AUTO_ACKNOWLEDGE.

JMSContext

Opmerking

JMSContext wordt gedefinieerd als onderdeel van de JMS 2.0-specificatie.

JMSContext combineert de functionaliteit die wordt geboden door het verbindings- en sessieobject. U maakt het op basis van het verbindingsfactoryobject.

JMSContext context = connectionFactory.createContext();

JMSContext-modi

Net als het sessieobject kunt u de JMSContext maken met dezelfde bevestigingsmodi als vermeld in sessiemodi.

JMSContext context = connectionFactory.createContext(JMSContext.AUTO_ACKNOWLEDGE);

Als u geen modus opgeeft, wordt de standaardwaarde JMSContext.AUTO_ACKNOWLEDGE.

JMS-berichtproducenten

Een berichtproducent is een object dat u maakt met behulp van een JMSContext of een sessie. Gebruik deze om berichten naar een bestemming te verzenden.

U kunt het maken als een zelfstandig object, zoals wordt weergegeven in het volgende voorbeeld:

JMSProducer producer = context.createProducer();

U kunt het ook tijdens runtime maken wanneer u een bericht wilt verzenden.

context.createProducer().send(destination, message);

JMS-berichtgebruikers

Een berichtconsumer is een object dat door een JMSContext of een sessie wordt gemaakt. Hiermee kunt u berichten ontvangen die naar een bestemming zijn verzonden. Maak deze, zoals wordt weergegeven in het volgende voorbeeld:

JMSConsumer consumer = context.createConsumer(dest);

Synchrone ontvangst via receive()-methode

De gebruiker van het bericht biedt een synchrone manier om berichten van de bestemming te ontvangen via de receive() methode.

Als u geen argumenten of time-out opgeeft of als u een time-out van 0 opgeeft, blokkeert de consument voor onbepaalde tijd, tenzij het bericht binnenkomt of de verbinding is verbroken (afhankelijk van wat eerder is).

Message m = consumer.receive();
Message m = consumer.receive(0);

Wanneer u een niet-nul-positief argument opgeeft, blokkeert de consument totdat die timer verloopt.

Message m = consumer.receive(1000); // time out after one second.

Asynchrone ontvangst met JMS-berichtlisteners

Een berichtenlistener is een object dat u gebruikt voor asynchrone verwerking van berichten op een bestemming. Hiermee wordt de MessageListener interface geïmplementeerd, die de onMessage methode bevat waarin de specifieke bedrijfslogica moet leven.

U moet een berichtlistenerobject instantiëren en registreren bij een specifieke berichtgebruiker met behulp van de setMessageListener methode.

Listener myListener = new Listener();
consumer.setMessageListener(myListener);

Gebruiken vanuit onderwerpen

U maakt JMS-berichtconsumenten op basis van een bestemming, wat een wachtrij of een onderwerp kan zijn.

Consumenten in wachtrijen zijn simpelweg objecten aan de clientzijde die zich in de context van de sessie (en verbinding) bevinden tussen de clienttoepassing en Azure Service Bus.

Onderwerpen voor consumenten hebben echter twee delen.

  • Een object aan de clientzijde dat zich in de context van de sessie (of JMSContext) bevindt en
  • Een abonnement dat een entiteit is in Azure Service Bus.

De abonnementen worden hier beschreven en kunnen een van de volgende typen zijn:

  • Gedeelde duurzame abonnementen
  • Gedeelde niet-duurzame abonnementen
  • Niet-gedeelde duurzame abonnementen
  • Niet-gedeelde niet-duurzame abonnementen

JMS-wachtrijbrowsers

De JMS-API biedt een QueueBrowser object dat de toepassing kan gebruiken om door de berichten in de wachtrij te bladeren en de headerwaarden voor elk bericht weer te geven.

U kunt een wachtrijbrowser maken met behulp van de JMSContext, zoals wordt weergegeven in het volgende voorbeeld:

QueueBrowser browser = context.createBrowser(queue);

Opmerking

JMS-API biedt geen API om door een onderwerp te bladeren.

Deze beperking bestaat omdat het onderwerp zelf de berichten niet opslaat. Zodra het bericht naar het onderwerp wordt verzonden, wordt het doorgestuurd naar de juiste abonnementen.

JMS-berichtselectoren

Ontvangende toepassingen kunnen berichtkiezers gebruiken om de berichten te filteren die ze ontvangen. Met behulp van berichtkiezers offload de ontvangende toepassing het werk van het filteren van berichten naar de JMS-provider (in dit geval Azure Service Bus) in plaats van die verantwoordelijkheid zelf te nemen.

U kunt selectors gebruiken bij het maken van een van de volgende consumenten:

  • Gedeeld duurzaam abonnement
  • Niet-gedeeld duurzaam abonnement
  • Gedeeld niet-duurzaam abonnement
  • Niet-gedeeld niet-duurzaam abonnement
  • Wachtrijconsumer
  • Wachtrijbrowser

Opmerking

Service Bus selectors bieden geen ondersteuning voor LIKE en BETWEEN SQL-trefwoorden.

Geplande berichten (verzendvertraging)

JMS 2.0 ondersteunt het plannen van een bericht voor toekomstige bezorging met behulp van de setDeliveryDelay methode op een MessageProducer of JMSProducer. Wanneer u deze eigenschap instelt, accepteert Service Bus het bericht, maar wordt het alleen zichtbaar voor consumenten nadat de vertragingsperiode is verstreken.

MessageProducer producer = session.createProducer(queue);

// Schedule a message for delivery 30 seconds from now
producer.setDeliveryDelay(30000);
producer.send(session.createTextMessage("Scheduled message"));

Zie QueueScheduledSend.java in de opslagplaats azure-servicebus-jms-samples voor een volledig werkend voorbeeld.

Selectie en veerkracht van verbindingsfabrieken

Wanneer u ServiceBusJmsConnectionFactory gebruikt in Spring Boot of andere frameworks die JMS-verbindingen beheren, kies dan de juiste verbindingsfactory-wrapper voor afzenders en listeners om een betrouwbare werking te garanderen.

Role Verbindingsfabriek Waarom
Afzenders (JmsTemplate) CachingConnectionFactory Verpakking ServiceBusJmsConnectionFactory JmsTemplate maakt en sluit standaard een verbinding per verzenden. CachingConnectionFactory onderhoudt één enkele AMQP-verbinding en slaat sessies op in de cache, waardoor verbindingsverloop wordt voorkomen dat de broker-resources onder belasting kan uitputten.
Listeners (@JmsListener, DefaultMessageListenerContainer) Onbewerkt ServiceBusJmsConnectionFactory (onverpakt) Elke listenercontainer krijgt een eigen AMQP-verbinding met een onafhankelijke levenscyclus. Als een verbinding mislukt (verloop van token, gateway-upgrade, netwerkstoring), wordt alleen die listener beïnvloed en wordt de verbinding automatisch opnieuw tot stand gebracht.

Wat te vermijden voor luisteraars

Warning

Gebruik nooit SingleConnectionFactory met listenercontainers. Het dwingt alle listeners om één JMS-verbinding te delen. Als deze verbinding om welke reden dan ook wordt onderbroken, verliezen alle listeners tegelijkertijd de verbinding en kunnen ze niet onafhankelijk herstellen. Gebruik de onbewerkte ServiceBusJmsConnectionFactory gegevens zodat elke listenercontainer een eigen verbinding beheert.

CachingConnectionFactory in listenercontainers kunnen ook problemen optreden omdat sessies in de cache mogelijk verwijzen naar een verouderde onderliggende verbinding. Voor listeners zorgt de raw factory ervoor dat elke container onafhankelijk een nieuwe verbinding kan maken.

Spring Cloud Azure standaardinstellingen

Als u (versie 6.2.0+) gebruikt spring-cloud-azure-starter-servicebus-jms , past de starter deze fabrieksscheiding standaard toe:

spring.jms.servicebus.pool.enabled spring.jms.cache.enabled Fabriek van afzender Listenerfabriek
(niet ingesteld) (niet ingesteld) CachingConnectionFactory ServiceBusJmsConnectionFactory
(niet ingesteld) true CachingConnectionFactory CachingConnectionFactory
(niet ingesteld) false ServiceBusJmsConnectionFactory ServiceBusJmsConnectionFactory
true (niet ingesteld) JmsPoolConnectionFactory JmsPoolConnectionFactory

In oudere versies (pre-6.2.0) gebruiken zowel afzenders als listeners ServiceBusJmsConnectionFactory standaard, waardoor afzenders per verzending een nieuwe verbinding aanmaken.

Een uitzonderingslistener toevoegen

Zonder uitzonderingslistener zijn verbindingsdruppels volledig stil. Voeg een jakarta.jms.ExceptionListener toe aan zowel de afzender- als de luisteraarfactories voor waarneembaarheid.

connection.setExceptionListener(exception -> {
    log.error("JMS connection error: {}", exception.getMessage(), exception);
});

Stel in Spring Boot de uitzonderingslistener in op de CachingConnectionFactory (voor afzenders) en de DefaultJmsListenerContainerFactory (voor listeners).

Zie het voorbeeld Spring Boot JMS Resilience sample in de opslagplaats azure-servicebus-jms-samples voor een volledig werkend voorbeeld met al deze patronen.

Wachtrijen voor ongeleverde berichten

Elk wachtrij- en onderwerpabonnement in Azure Service Bus heeft een gekoppelde adletterwachtrij (DLQ). Het systeem verplaatst automatisch berichten die het niet kan leveren of verwerken naar de DLQ. Het systeem verplaatst bijvoorbeeld een bericht naar de DLQ wanneer het bericht het maximale aantal bezorging overschrijdt of de time-to-live (TTL) verloopt.

Belangrijk

Als u verlopen TTL-berichten naar de DLQ wilt verplaatsen, schakelt u dead-lettering bij het verlopen van berichten in voor de wachtrij of het abonnement. Zonder deze instelling worden verlopen berichten stilletjes verwijderd. Zie voor configuratiestappen Dead Lettering inschakelen voor een wachtrij of abonnement.

In JMS benadert u de DLQ als een afzonderlijke bestemming door het volledige pad te construeren en er een JmsQueue mee te maken. Er is geen speciale API vereist.

DLQ-padopmaak voor wachtrij:

<queue-name>/$deadletterqueue

Indeling van het DLQ-pad voor onderwerpabonnement:

<topic-name>/Subscriptions/<subscription-name>/$deadletterqueue

Voorbeeld: verbruiken vanuit de wachtrij voor dode brieven van een wachtrij:

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);

Niet-geschreven berichten bevatten metagegevenseigenschappen die beschrijven waarom het bericht niet is geschreven:

Vastgoed Beschrijving
DeadLetterReason De reden waarom het bericht niet is geschreven (bijvoorbeeld TTLExpiredException of MaxDeliveryCountExceeded).
DeadLetterErrorDescription Een door mensen leesbare beschrijving van de reden van de dode letter.

Lees deze eigenschappen met behulp van message.getStringProperty():

String reason = message.getStringProperty("DeadLetterReason");
String description = message.getStringProperty("DeadLetterErrorDescription");

Zie QueueDeadLetterReceive.java in de opslagplaats azure-servicebus-jms-samples voor een volledig werkend voorbeeld.

AMQP-verwijdering en Service Bus-bewerkingstoewijzing

Hier ziet u hoe een AMQP-dispositie vertaalt naar een Service Bus-operatie:

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()

Samenvatting

Deze ontwikkelaarshandleiding laat zien hoe Java clienttoepassingen die gebruikmaken van Java Message Service (JMS) verbinding kunnen maken met Azure Service Bus.

Volgende stappen

Zie de volgende artikelen voor meer informatie over Azure Service Bus en details over Java Message Service -entiteiten (JMS):