← Zur Uebersicht

Topics, durable Subscriptions und Message-Selektoren

Beispiele: PolicyEventPublisherBean (Publisher), PolicyDocumentGenerationMDB + CustomerNotificationMDB (zwei unabhaengige Abonnenten), beide novaris-notification-jms.

Ein Publisher, mehrere unabhaengige Abonnenten

PolicyEventPublisherBean.publish(...) weiss nichts von seinen Abonnenten - es sendet einfach auf das Topic jms/novaris/policyEventsTopic. Wie viele Abonnenten es gibt und was sie mit der Nachricht tun, ist dem Publisher voellig gleichgueltig; genau diese Entkopplung ist der Sinn von Publish/Subscribe. In diesem Projekt gibt es aktuell zwei Abonnenten - PolicyDocumentGenerationMDB (Dokumentenerzeugung) und CustomerNotificationMDB (Kundenbenachrichtigung) - ein drittes System koennte jederzeit hinzukommen, ohne dass am Publisher irgendetwas geaendert werden muesste.

Durable Subscriptions: was passiert, wenn ein Abonnent gerade nicht laeuft?

Eine nicht-dauerhafte ("non-durable") Subscription existiert nur, solange die Consumer-Verbindung aktiv ist - ist der Abonnent gerade nicht erreichbar (Neustart, Deployment, Ausfall), gehen in dieser Zeit publizierte Nachrichten fuer ihn unwiederbringlich verloren. Eine dauerhafte ("durable") Subscription dagegen laesst den JMS-Provider Nachrichten fuer diesen Abonnenten zwischenspeichern, bis er wieder verfuegbar ist:

@ActivationConfigProperty(propertyName = "subscriptionDurability", propertyValue = "Durable"),
@ActivationConfigProperty(propertyName = "clientId", propertyValue = "novaris-notification-jms-docgen"),
@ActivationConfigProperty(propertyName = "subscriptionName", propertyValue = "policy-document-generation"),

Die Subscription wird durch die Kombination aus clientId und subscriptionName identifiziert - nicht durch die Bean-Klasse. Beide Werte muessen ueber Neustarts/Deployments hinweg stabil bleiben, sonst legt der Provider eine neue (leere) Subscription an, statt die bestehende (mit ihren aufgestauten Nachrichten) wiederzuverwenden. PolicyDocumentGenerationMDB und CustomerNotificationMDB verwenden bewusst unterschiedliche clientId-Werte, siehe deren Javadoc.

Message-Selektoren: serverseitiges Filtern vor der Zustellung

Ein Topic kann Nachrichten unterschiedlichster Art fuehren - hier: POLICY_ISSUED und CLAIM_REGISTERED (siehe PolicyEventTypes). Nicht jeder Abonnent interessiert sich fuer alles. Ein Message-Selektor ist ein SQL-92-aehnlicher Filterausdruck auf Message-Properties, den der JMS-Provider vor der Zustellung auswertet:

// PolicyDocumentGenerationMDB - nur Policenausstellungen
messageSelector = "eventType = 'POLICY_ISSUED'"

// CustomerNotificationMDB - Policenausstellungen UND Schadensmeldungen
messageSelector = "eventType = 'POLICY_ISSUED' OR eventType = 'CLAIM_REGISTERED'"

Beide Selektoren werten dieselbe Message-Property eventType aus, die PolicyEventPublisherBean explizit setzt:

message.setStringProperty("eventType", eventType);

Wichtig: der Selektor prueft eine Property, nicht den Java-Typ der deserialisierten Payload - genau deshalb spiegelt der Publisher eventType sowohl als Property als auch als Feld im PolicyEventMessage-Objekt selbst (siehe dessen Javadoc fuer die volle Begruendung). Ein Consumer mit nicht passendem Selektor bekommt die Nachricht gar nicht erst zugestellt - er muss sie nicht empfangen und wieder verwerfen, der Provider filtert vorher.

Fan-out konkret beobachtet

NotificationTopicFanoutTest (novaris-notification-jms) beweist das Zusammenspiel gegen einen echten eingebetteten Broker: dieselbe POLICY_ISSUED-Nachricht erreicht beide Abonnenten, eine CLAIM_REGISTERED-Nachricht dagegen nur den Customer-Notification-Abonnenten (dessen Selektor beide Typen zulaesst) - der Document-Generation-Abonnent bekommt sie gar nicht erst zugestellt. Das ist der Kern von selektivem Publish/Subscribe in einem einzigen, beobachtbaren Test.

⌂ Cockpit