Publishing messages
A producer builds an Avro message with its generated builder and sends it through a
KafkaTemplate<AvroMessageKey, AvroMessage>. For the default cluster, inject the KafkaTemplate
directly; for a non-default cluster add @Qualifier("<clusterName>") on the injected template (see
Configuration reference).
A publisher component
@Component
@RequiredArgsConstructor
class DeclarationPublisher {
private final KafkaTemplate<AvroMessageKey, AvroMessage> kafkaTemplate;
void publish(String declarationId) {
JmeDeclarationCreatedEvent event = JmeDeclarationCreatedEventBuilder.create()
.idempotenceId(declarationId)
.declarationIdReference(declarationId)
.build();
kafkaTemplate.send("jme-messaging-declaration-created", event);
}
}
Each message type ships with a generated builder (e.g. JmeDeclarationCreatedEventBuilder). These
builders extend a jEAP base class — AvroDomainEventBuilder for events and AvroCommandBuilder for
commands (from jeap-messaging-avro) — which auto-fills the MessageType information (type name,
version, identity, timestamps; see Defining messages). Always build messages
through these builders rather than constructing the Avro objects by hand, and set a meaningful
idempotenceId, as consumers rely on it to deduplicate.
kafkaTemplate.send(topic, message) returns a future. To send synchronously, block on it with
.get(timeout).
Choosing the topic
A message type has a default topic taken from its registry descriptor; you can also send to an explicit topic name as shown above.
The MessagePublisher abstraction
jeap-messaging-api defines a MessagePublisher interface. Implement a publisher class that decides
where messages go, and inject it into your message generators. This is a system-layer concept that
keeps the routing decision out of the business code — see Architecture.
Producer contract required
A producer contract is REQUIRED for every produced type (see
Message contracts). The publishWithoutContractAllowed property must be
false in production (see Configuration reference).
Multi-cluster caveat with Lombok
When using a @Qualifier("<clusterName>") on a constructor-injected KafkaTemplate, note that
Lombok does NOT copy field annotations to generated constructors by default. Configure
lombok.copyableAnnotations so the qualifier reaches the generated constructor, otherwise the wrong
cluster's template may be injected. See
https://projectlombok.org/features/constructor.