### Full EasyKafka Configuration Example Source: https://github.com/studeyang/easykafka/blob/master/README.md A comprehensive example demonstrating the integration of EasyKafka configurations within a Spring Boot application. This includes Kafka cluster definitions, producer and consumer specific settings, and runtime configurations. ```yaml spring: application: name: order-service easykafka: init: kafkaCluster: - cluster: order brokers: order-kafka.example.com:9092 tag: BASE - cluster: order brokers: order-kafka-gray.example.com:9092 tag: GRAY - cluster: payment brokers: pay-kafka.example.com:9092 producer: - beanName: orderProducer config: retries: 3 batch.size: 32768 linger.ms: 5 acks: all consumer: - beanName: paymentConsumer cluster: payment config: session.timeout.ms: 30000 runtime: producer: partitionSize: 1000 async: corePoolSize: 5 maxPoolSize: 10 keepAliveSeconds: 120 queueCapacity: 500 consumer: groupIdPrefix: "order-service-" ``` -------------------------------- ### Configure Kafka Cluster Source: https://github.com/studeyang/easykafka/blob/master/README.md Configure your Kafka cluster connection details in the application's YAML file. This example sets up a cluster named 'send'. ```yaml easykafka: init: kafkaCluster: - cluster: send brokers: kafka.example.com:9092 ``` -------------------------------- ### EasyKafka Module Structure Source: https://github.com/studeyang/easykafka/blob/master/README.md Outlines the directory structure of the EasyKafka project, detailing the core client module, Spring Boot starter, and example applications for producers and consumers. ```text easykafka/ ├── easykafka-client/ # 核心模块:生产者/消费者逻辑与注解 ├── easykafka-spring-boot-starter/ # Spring Boot 自动配置入口 ├── example-sdk/ # 消息定义包(模拟真实 SDK jar) ├── example-producer/ # 生产者示例应用 └── example-consumer/ # 消费者示例应用 ``` -------------------------------- ### Automatic Retry Mechanism Example Source: https://context7.com/studeyang/easykafka/llms.txt Demonstrates the automatic retry mechanism for message sending failures. The framework retries up to 3 times with exponential backoff. The `onFail` callback is invoked only after all retries are exhausted. ```java // 重试参数(RetryableSender 硬编码): // - 最大重试次数:3 次 // - 初始等待时间:100ms // - 退避倍数:2x(100ms → 200ms → 400ms,上限 5000ms) // 验证重试行为的示例(消费端故意使处理抛异常,触发生产端重试观测) OrderCreatedEvent event = new OrderCreatedEvent(); event.setOrderId("ORD-RETRY-TEST"); EventPublisher.publish(event, new MessageCallback() { @Override public void onSuccess() { // 重试成功后仅调用一次 log.info("消息最终发送成功(可能经历重试)"); } @Override public void onFail(Exception e) { // 3 次重试全部失败后调用 log.error("消息发送最终失败,需人工介入", e); // 写入补偿表 / 触发告警 compensationService.save(event, e); } }); ``` -------------------------------- ### Maven Build and Test Commands Source: https://github.com/studeyang/easykafka/blob/master/README.md Common Maven commands for building, testing, and packaging EasyKafka modules. Includes instructions for running all tests, specific module tests, and tests for individual classes or methods. ```bash # 构建所有模块 mvn clean install # 运行所有测试 mvn clean test # 运行指定模块的测试 mvn clean test -f easykafka-client/pom.xml # 运行指定测试类 mvn test -Dtest=JsonUtilsTest # 运行指定测试方法 mvn test -Dtest=JsonUtilsTest#someMethod # 打包(CI 环境使用) mvn -B package --file pom.xml ``` -------------------------------- ### Maven Build and Test Commands Source: https://context7.com/studeyang/easykafka/llms.txt Common Maven commands for building, testing, and packaging the EasyKafka project. Includes commands for running all tests, specific modules, test classes, or test methods, and for CI builds. ```bash # 构建所有模块 mvn clean install # 运行所有测试 mvn clean test # 运行指定模块的测试 mvn clean test -f easykafka-client/pom.xml # 运行指定测试类 mvn test -Dtest=JsonUtilsTest # 运行指定测试方法 mvn test -Dtest=JsonUtilsTest#someMethod # CI 打包 mvn -B package --file pom.xml ``` -------------------------------- ### Add Consumer Dependencies Source: https://github.com/studeyang/easykafka/blob/master/README.md Include the EasyKafka starter and the shared message definition package for consumers. ```xml io.github.studeyang easykafka-spring-boot-starter ${easykafka.version} io.github.studeyang example-sdk ${sdk.version} ``` -------------------------------- ### Include EasyKafka Starter Dependency Source: https://context7.com/studeyang/easykafka/llms.txt Add the EasyKafka Spring Boot Starter to your project's pom.xml to enable automatic configuration and bean registration. Consumer applications also need to include the shared message definition package. ```xml io.github.studeyang easykafka-spring-boot-starter ${easykafka.version} io.github.studeyang example-sdk ${sdk.version} ``` -------------------------------- ### Add EasyKafka Dependency Source: https://github.com/studeyang/easykafka/blob/master/README.md Include the EasyKafka Spring Boot starter dependency in your project to use its features. ```xml io.github.studeyang easykafka-spring-boot-starter ${easykafka.version} ``` -------------------------------- ### Producer Runtime Configuration Source: https://github.com/studeyang/easykafka/blob/master/README.md Configure producer runtime settings like partition size and asynchronous thread pool parameters. Ensure thread pool settings are appropriate for your application's load. ```yaml easykafka: runtime: producer: partitionSize: 500 # 批量发送时的分区大小 async: corePoolSize: 3 # 核心线程数 maxPoolSize: 5 # 最大线程数 keepAliveSeconds: 60 # 空闲线程存活时间(秒) queueCapacity: 100 # 队列容量 rejectedHandler: java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy threadNamePrefix: kafka-async-producer- ``` -------------------------------- ### Publishing Messages with Callbacks Source: https://github.com/studeyang/easykafka/blob/master/README.md Illustrates how to use EventPublisher to send messages and handle success or failure asynchronously using callbacks. ```APIDOC ## Sending Messages with Callbacks `EventPublisher.publish` supports callbacks for asynchronous execution upon successful or failed message sending. ### Full Callback (MessageCallback) ```java EventPublisher.publish(event, new MessageCallback() { @Override public void onSuccess() { log.info("Message sent successfully"); } @Override public void onFail(Exception e) { log.error("Message sending failed", e); // Compensating operations can be performed here } }); ``` ### Success Only Callback (SuccessCallback) ```java EventPublisher.publish(event, new SuccessCallback() { @Override public void onSuccess() { log.info("Message sent successfully"); } }); ``` ### Failure Only Callback (FailCallback) ```java EventPublisher.publish(event, new FailCallback() { @Override public void onFail(Exception e) { log.error("Message sending failed, performing alert", e); } }); ``` ### Batch Sending ```java List events = buildEvents(); EventPublisher.publish(events); ``` ``` -------------------------------- ### Generic Publishing with ObjectPublisher Source: https://github.com/studeyang/easykafka/blob/master/README.md Explains how to use ObjectPublisher for sending messages that do not inherit from Event or when a dynamic Topic needs to be specified. ```APIDOC ## Generic Publishing (ObjectPublisher) Use `ObjectPublisher` when the message object does not inherit from `Event` or when you need to dynamically specify the Topic. ### Sending to a Specific Topic ```java ObjectPublisher.publish(myObject, new TopicMetadata("send", "custom-topic")); ``` ### Sending with Full Metadata ```java MessageMetadata metadata = new MessageMetadataBuilder() .topicMetadata("send", "custom-topic") .messageKey("key-123") .messageHeader("requestId", "req-456") .messageTag(Tag.GRAY) .build(); ObjectPublisher.publish(myObject, metadata); ``` ### Sending with Callbacks ```java ObjectPublisher.publish(myObject, metadata, new MessageCallback() { public void onSuccess() { ... } public void onFail(Exception e) { ... } }); ``` ``` -------------------------------- ### Send Message using EventPublisher Source: https://github.com/studeyang/easykafka/blob/master/README.md Send a message by creating an instance of your event class, setting its properties, and calling `EventPublisher.publish()`. ```java import io.github.open.easykafka.client.EventPublisher; OrderCreatedEvent event = new OrderCreatedEvent(); event.setOrderId("ORD-123"); event.setUserId("USER-456"); EventPublisher.publish(event); ``` -------------------------------- ### Configure Kafka Clusters in application.yml Source: https://context7.com/studeyang/easykafka/llms.txt Define Kafka cluster information in application.yml under `easykafka.init.kafkaCluster`. This configuration automatically registers Producer Beans and Listener Container Factories. Each cluster entry requires a logical identifier (`cluster`), broker addresses (`brokers`), and an optional environment tag (`tag`). ```yaml # application.yml spring: application: name: order-service easykafka: init: kafkaCluster: - cluster: order # 逻辑集群标识,与 @Topic / @EventHandler 中的 cluster 对应 brokers: order-kafka.example.com:9092 tag: BASE # BASE(默认)= 基线环境 - cluster: order brokers: order-kafka-gray.example.com:9092 tag: GRAY # GRAY = 灰度环境;未配置时框架自动复制 BASE 配置 - cluster: payment brokers: pay-kafka.example.com:9092 runtime: producer: partitionSize: 1000 async: corePoolSize: 5 maxPoolSize: 10 keepAliveSeconds: 120 queueCapacity: 500 threadNamePrefix: kafka-async-producer- consumer: groupIdPrefix: "order-service-" # 最终 groupId = groupIdPrefix + topicName ``` -------------------------------- ### Multi-Cluster Configuration for EasyKafka Source: https://github.com/studeyang/easykafka/blob/master/README.md Configure EasyKafka to connect to multiple Kafka clusters simultaneously by defining them in the application's YAML configuration. ```yaml easykafka: init: kafkaCluster: - cluster: order # 订单集群 brokers: order-kafka.example.com:9092 - cluster: payment # 支付集群 brokers: pay-kafka.example.com:9092 ``` -------------------------------- ### Cluster Configuration Reference Source: https://github.com/studeyang/easykafka/blob/master/README.md Provides a reference for configuring Kafka clusters, including logical cluster names, broker addresses, and environment tags. ```APIDOC ## Cluster Configuration Reference ### Cluster Configuration ```yaml easykafka: init: kafkaCluster: - cluster: send # Logical cluster name (corresponds to @Topic/@EventHandler) brokers: 127.0.0.1:9092 # Broker addresses, comma-separated tag: BASE # Tag: BASE (default) or GRAY ``` | Property | Type | Required | Default Value | Description | |---|---|---|---|---| | `cluster` | String | Yes | - | Logical cluster identifier. | | `brokers` | String | Yes | - | List of Broker addresses in `host:port` format. | | `tag` | Tag | No | BASE | Environment tag (BASE / GRAY). | ``` -------------------------------- ### Multi-Cluster and Gray Routing Source: https://github.com/studeyang/easykafka/blob/master/README.md Details EasyKafka's support for multiple Kafka clusters within a single application and its built-in gray routing capabilities. ```APIDOC ## Multi-Cluster and Gray Routing EasyKafka supports integrating multiple Kafka clusters in the same application and provides built-in gray routing capabilities. ### Multi-Cluster Configuration ```yaml easykafka: init: kafkaCluster: - cluster: order # Order cluster brokers: order-kafka.example.com:9092 - cluster: payment # Payment cluster brokers: pay-kafka.example.com:9092 ``` ### Gray Routing Configuration Configure gray nodes with `tag: gray` for a cluster. The framework automatically routes based on the current environment. ```yaml easykafka: init: kafkaCluster: - cluster: send brokers: kafka-prod.example.com:9092 # Baseline environment - cluster: send brokers: kafka-gray.example.com:9092 tag: gray # Gray environment ``` > **Note**: If no gray nodes are configured, the framework duplicates the baseline configuration for gray, which does not affect normal startup. ### Manually Specifying Routing Tag ```java // Force routing to the gray cluster MessageMetadata metadata = new MessageMetadataBuilder() .topicMetadata("send", "order-topic") .messageTag(Tag.GRAY) .build(); ObjectPublisher.publish(event, metadata); ``` ``` -------------------------------- ### Implement Full Send Callback with MessageCallback Source: https://github.com/studeyang/easykafka/blob/master/README.md Provide a complete callback implementation using MessageCallback to handle both successful and failed message sends asynchronously. ```java EventPublisher.publish(event, new MessageCallback() { @Override public void onSuccess() { log.info("消息发送成功"); } @Override public void onFail(Exception e) { log.error("消息发送失败", e); // 可在此处做补偿操作 } }); ``` -------------------------------- ### Multi-Cluster and Gray Routing Configuration Source: https://context7.com/studeyang/easykafka/llms.txt Configure multiple Kafka clusters for an application, using 'tag: GRAY' for gray nodes. The framework automatically selects the target cluster based on the current environment. If no gray nodes are configured, it defaults to the baseline configuration. ```yaml # application.yml — 多集群 + 灰度路由示例 easykafka: init: kafkaCluster: # 订单集群 - 基线 - cluster: order brokers: order-kafka.example.com:9092 tag: BASE # 订单集群 - 灰度 - cluster: order brokers: order-kafka-gray.example.com:9092 tag: GRAY # 支付集群(仅基线,框架自动补充灰度配置) - cluster: payment brokers: pay-kafka.example.com:9092 ``` -------------------------------- ### Generic Sending with ObjectPublisher using Full Metadata Source: https://github.com/studeyang/easykafka/blob/master/README.md Send objects with detailed metadata, including topic, message key, headers, and tags, using ObjectPublisher and MessageMetadataBuilder. ```java MessageMetadata metadata = new MessageMetadataBuilder() .topicMetadata("send", "custom-topic") .messageKey("key-123") .messageHeader("requestId", "req-456") .messageTag(Tag.GRAY) .build(); ObjectPublisher.publish(myObject, metadata); ``` -------------------------------- ### Send Single Domain Event using EventPublisher Source: https://context7.com/studeyang/easykafka/llms.txt The `EventPublisher.publish(Event)` method provides a static facade for asynchronously sending `Event` messages. The framework automatically populates essential metadata such as `messageId`, `messageKey`, `messageTag`, `messageTopic`, and `messageCreateTime` based on annotations and current context. ```java import io.github.open.easykafka.client.EventPublisher; // 构造消息对象 OrderCreatedEvent event = new OrderCreatedEvent(); event.setOrderId("ORD-20250601-001"); event.setUserId("USER-888"); event.setAmount(299.99); event.setRequestId("REQ-abc123"); event.setRetryCount(0); // 发送(异步,无回调) EventPublisher.publish(event); // 框架自动: // messageId = UUID // messageKey = event.getOrderId()(@MessageKey 字段) // messageHeader = {requestId: "REQ-abc123", retryCount: 0}(@MessageHeader 字段) // messageTopic = {cluster: "order", name: "order-created-topic"} // messageTag = 当前环境(BASE / GRAY)自动选择 // messageCreateTime = 发送时间 ``` -------------------------------- ### EasyKafka Producer Send Flow Source: https://github.com/studeyang/easykafka/blob/master/README.md Illustrates the sequence of operations when publishing an event using EasyKafka's producer. Highlights the use of an asynchronous thread pool, message conversion, and a sender chain with retry and reporting capabilities. ```text EventPublisher.publish(event) │ ▼ DefaultMessagePublisher(异步线程池) │ ▼ SendMessageConverter(Event → SendMessage) │ ▼ Sender 责任链(装饰器模式) ├── ReportableSender(记录发送结果日志) ├── RetryableSender(失败重试,最多 3 次,指数退避) └── ProducerSender(构建 ProducerRecord,调用 Kafka) │ ▼ ProducerContainer.getProducer(cluster, tag) │ ▼ StringKafkaProducer → Kafka Broker │ ▼ MessageCallback.onSuccess() / onFail() ``` -------------------------------- ### Cluster Configuration Reference Source: https://github.com/studeyang/easykafka/blob/master/README.md Defines the configuration parameters for connecting to Kafka clusters, including cluster name, broker addresses, and environment tags. ```yaml easykafka: init: kafkaCluster: - cluster: send # 逻辑集群名称(与 @Topic/@EventHandler 对应) brokers: 127.0.0.1:9092 # Broker 地址,多个用逗号分隔 tag: BASE # 标签:BASE(默认)或 GRAY ``` -------------------------------- ### Gray Routing Configuration for Kafka Clusters Source: https://github.com/studeyang/easykafka/blob/master/README.md Set up gray routing by configuring gray nodes within your Kafka cluster definitions. The framework automatically routes based on the current environment. ```yaml easykafka: init: kafkaCluster: - cluster: send brokers: kafka-prod.example.com:9092 # 基线环境 - cluster: send brokers: kafka-gray.example.com:9092 tag: gray # 灰度环境 ``` -------------------------------- ### Publish Event with Callbacks Source: https://context7.com/studeyang/easykafka/llms.txt Publish a single event with asynchronous callbacks for success and failure. Supports MessageCallback, SuccessCallback, and FailCallback interfaces. ```java import io.github.open.easykafka.client.EventPublisher; import io.github.open.easykafka.client.producer.callback.MessageCallback; import io.github.open.easykafka.client.producer.callback.SuccessCallback; import io.github.open.easykafka.client.producer.callback.FailCallback; OrderCreatedEvent event = new OrderCreatedEvent(); event.setOrderId("ORD-20250601-002"); // 完整回调(成功 + 失败) EventPublisher.publish(event, new MessageCallback() { @Override public void onSuccess() { log.info("[OrderCreatedEvent] 消息发送成功,orderId={}", event.getOrderId()); } @Override public void onFail(Exception e) { log.error("[OrderCreatedEvent] 消息发送失败,orderId={}", event.getOrderId(), e); // 可触发告警、写入补偿表等操作 } }); // 仅关注成功 EventPublisher.publish(event, (SuccessCallback) () -> log.info("发送成功")); // 仅关注失败 EventPublisher.publish(event, (FailCallback) e -> log.error("发送失败,进行告警", e)); ``` -------------------------------- ### Publish Generic Object with Topic Metadata Source: https://context7.com/studeyang/easykafka/llms.txt Publish generic objects (not extending Event) or when dynamic topic specification is needed. Non-String objects are JSON serialized. Use this for simple object publishing. ```java import io.github.open.easykafka.client.ObjectPublisher; import io.github.open.easykafka.client.model.TopicMetadata; import java.util.Arrays; import java.util.List; // 发送 List 类型消息(EventPublisher 不支持) List payload = Arrays.asList("item-1", "item-2", "item-3"); ObjectPublisher.publish(payload, new TopicMetadata("order", "order-sync-topic")); // 实际发送的 Kafka value: ["item-1","item-2","item-3"] ``` -------------------------------- ### Implement Success-Only Send Callback with SuccessCallback Source: https://github.com/studeyang/easykafka/blob/master/README.md Use SuccessCallback when you only need to be notified upon successful message delivery. ```java EventPublisher.publish(event, new SuccessCallback() { @Override public void onSuccess() { log.info("消息发送成功"); } }); ``` -------------------------------- ### Publish Generic Object with Full Message Metadata Source: https://context7.com/studeyang/easykafka/llms.txt Publish generic objects with detailed message metadata, including Key, Headers, and routing tags (BASE/GRAY), using MessageMetadataBuilder for precise control. Includes an asynchronous callback. ```java import io.github.open.easykafka.client.ObjectPublisher; import io.github.open.easykafka.client.model.MessageMetadata; import io.github.open.easykafka.client.model.MessageMetadataBuilder; import io.github.open.easykafka.client.model.Tag; String message = "{\"source\":\"legacy-system\",\"data\":\"...\" }"; MessageMetadata metadata = new MessageMetadataBuilder() .topicMetadata("order", "order-sync-topic") // 指定集群和 Topic .messageKey("ORD-20250601-099") // Kafka Record Key .messageHeader("requestId", "REQ-xyz") // Header(String 类型) .messageHeader("retryCount", 0) // Header(Integer 类型) .messageTag(Tag.BASE) // 强制路由到基线集群 .build(); ObjectPublisher.publish(message, metadata, new MessageCallback() { @Override public void onSuccess() { log.info("legacy 消息同步成功"); } @Override public void onFail(Exception e) { log.error("legacy 消息同步失败", e); } }); ``` -------------------------------- ### Message Headers with @MessageHeader and @Header Source: https://github.com/studeyang/easykafka/blob/master/README.md Demonstrates how to use @MessageHeader to add fields to Kafka message headers and @Header to retrieve them in the consumer. ```APIDOC ## Message Headers ### Producer Side Annotate fields in your message class with `@MessageHeader` to have their values written to Kafka Record Headers. ```java @Topic(cluster = "send", name = "order-topic") public class OrderCreatedEvent extends Event { @MessageHeader private String requestId; @MessageHeader private String traceId; } ``` ### Consumer Side Use the `@Header` annotation in your Kafka handler method to retrieve values from message headers. ```java @KafkaHandler public void handle(OrderCreatedEvent event, @Header(value = "requestId", required = false) String requestId, @Header(value = "traceId", required = false) String traceId) { log.info("requestId={}, traceId={}", requestId, traceId); } ``` ``` -------------------------------- ### EasyKafka Consumer Flow Source: https://github.com/studeyang/easykafka/blob/master/README.md Describes the process of consuming messages with EasyKafka. Covers annotation discovery, listener container factory creation, and message routing to specific handler methods based on message type. ```text Kafka Broker │ ▼ @EventHandler(标注在消费者类上) │ ▼ EventHandlerAnnotationBeanPostProcessor (发现 Handler,注册元数据到 ListenerContainer) │ ▼ KafkaListenerContainerFactoryRegistrar (为每个集群创建 ConcurrentKafkaListenerContainerFactory 命名规则:{cluster}KafkaListenerContainerFactory AckMode:RECORD,自定义反序列化器) │ ▼ @KafkaHandler 方法(根据消息类型自动路由到对应方法) ``` -------------------------------- ### Force Routing to Gray Cluster Source: https://context7.com/studeyang/easykafka/llms.txt Use ObjectPublisher with MessageMetadataBuilder to explicitly send messages to a gray cluster. This is useful for validating gray releases. Ensure MessageMetadata is built correctly with the desired topic and message tag. ```java // 强制路由到灰度集群(适用于灰度发布验证) import io.github.open.easykafka.client.ObjectPublisher; import io.github.open.easykafka.client.model.MessageMetadataBuilder; import io.github.open.easykafka.client.model.Tag; MessageMetadata grayMetadata = new MessageMetadataBuilder() .topicMetadata("order", "order-created-topic") .messageTag(Tag.GRAY) // 强制发往灰度集群 .build(); ObjectPublisher.publish(orderCreatedEvent, grayMetadata); ``` -------------------------------- ### Generic Sending with ObjectPublisher and Callback Source: https://github.com/studeyang/easykafka/blob/master/README.md Combine generic sending with callbacks for asynchronous handling of send results when using ObjectPublisher. ```java ObjectPublisher.publish(myObject, metadata, new MessageCallback() { public void onSuccess() { ... } public void onFail(Exception e) { ... } }); ``` -------------------------------- ### Batch Sending of Events Source: https://github.com/studeyang/easykafka/blob/master/README.md Efficiently send multiple events in a single batch operation using EventPublisher.publish with a list of events. ```java List events = buildEvents(); EventPublisher.publish(events); ``` -------------------------------- ### Consumer Runtime Configuration Source: https://github.com/studeyang/easykafka/blob/master/README.md Set a prefix for consumer group IDs to help organize and identify consumers within your application. The final group ID is formed by concatenating this prefix with the topic name. ```yaml easykafka: runtime: consumer: groupIdPrefix: "my-service-" # 消费者组 ID 前缀 ``` -------------------------------- ### Kafka Event Handler with @EventHandler Source: https://github.com/studeyang/easykafka/blob/master/README.md Shows how to declare a class as a Kafka message processor using the @EventHandler annotation, which is a wrapper around @KafkaListener. ```APIDOC ## Kafka Event Handler Annotate a consumer class with `@EventHandler` to declare it as a Kafka message processor. This annotation wraps the underlying `@KafkaListener`. ```java @Service @EventHandler( cluster = "send", topics = "order-topic", concurrency = "3" ) public class OrderEventHandler { @KafkaHandler public void handleCreated(OrderCreatedEvent event) { ... } @KafkaHandler public void handleCancelled(OrderCancelledEvent event) { ... } } ``` ### @EventHandler Properties | Property | Type | Required | Default Value | Description | |---|---|---|---|---| | `cluster` | String | Yes | - | The Kafka cluster name to consume from. | | `topics` | String | Yes | - | The Topic name to subscribe to. | | `groupId` | String | No | Auto-generated | The consumer group ID. Defaults to `{groupIdPrefix}{topics}`. | | `concurrency` | String | No | "1" | The number of concurrent consumer threads. | | `id` | String | No | Auto-generated | The Listener container ID. | ``` -------------------------------- ### Implement Failure-Only Send Callback with FailCallback Source: https://github.com/studeyang/easykafka/blob/master/README.md Implement FailCallback to handle only message sending failures, allowing for error logging or compensation logic. ```java EventPublisher.publish(event, new FailCallback() { @Override public void onFail(Exception e) { log.error("消息发送失败,进行告警", e); } }); ``` -------------------------------- ### EventPublisher.publish(Event, MessageCallback) Source: https://context7.com/studeyang/easykafka/llms.txt Sends an event and triggers a callback asynchronously upon completion. Supports MessageCallback (success+failure), SuccessCallback (success only), and FailCallback (failure only). ```APIDOC ## `EventPublisher.publish(Event, MessageCallback)` — Send with Callback Sends a message and triggers a callback in an asynchronous thread after sending. Supports three types of interfaces: `MessageCallback` (success+failure), `SuccessCallback` (success only), and `FailCallback` (failure only). ### Method ```java EventPublisher.publish(event, callback); ``` ### Parameters - **event** (Event) - The event object to publish. - **callback** (MessageCallback | SuccessCallback | FailCallback) - The callback to execute upon message sending. ### Request Example ```java // Full callback (success + failure) EventPublisher.publish(event, new MessageCallback() { @Override public void onSuccess() { log.info("[OrderCreatedEvent] Message sent successfully, orderId={}", event.getOrderId()); } @Override public void onFail(Exception e) { log.error("[OrderCreatedEvent] Message sending failed, orderId={}", event.getOrderId(), e); // Trigger alerts, write compensation tables, etc. } }); // Focus only on success EventPublisher.publish(event, (SuccessCallback) () -> log.info("Sent successfully")); // Focus only on failure EventPublisher.publish(event, (FailCallback) e -> log.error("Sending failed, triggering alert", e)); ``` ``` -------------------------------- ### ObjectPublisher.publish(Object, TopicMetadata) Source: https://context7.com/studeyang/easykafka/llms.txt Publishes generic objects that do not inherit from Event, or when a dynamic Topic needs to be specified. Non-String objects are JSON serialized. ```APIDOC ## `ObjectPublisher.publish(Object, TopicMetadata)` — Generic Object Send (Simple Mode) Use `ObjectPublisher` when the message object does not inherit from `Event` (e.g., `List`, plain POJO, `String`) or when the target Topic needs to be dynamically specified. Non-String type messages will be JSON serialized first. ### Method ```java ObjectPublisher.publish(object, topicMetadata); ``` ### Parameters - **object** (Object) - The object to publish. - **topicMetadata** (TopicMetadata) - Metadata specifying the target topic. ### Request Example ```java // Send List type message (not supported by EventPublisher) List payload = Arrays.asList("item-1", "item-2", "item-3"); ObjectPublisher.publish(payload, new TopicMetadata("order", "order-sync-topic")); // Actual Kafka value sent: ["item-1","item-2","item-3"] ``` ``` -------------------------------- ### Implement Message Handler Source: https://github.com/studeyang/easykafka/blob/master/README.md Implement a message handler by creating a Spring service annotated with `@EventHandler`, specifying the cluster and topics to subscribe to. Use `@KafkaHandler` to define methods for specific message types. ```java import io.github.open.easykafka.client.annotation.EventHandler; import org.springframework.kafka.annotation.KafkaHandler; import org.springframework.stereotype.Service; @Service @EventHandler(cluster = "send", topics = "order-topic") public class OrderEventHandler { @KafkaHandler public void handle(OrderCreatedEvent event) { System.out.println("收到订单创建事件: " + event.getOrderId()); } } ``` -------------------------------- ### ObjectPublisher.publish(Object, MessageMetadata) Source: https://context7.com/studeyang/easykafka/llms.txt Publishes generic objects with full metadata control using MessageMetadataBuilder for Key, Header, and routing tags. ```APIDOC ## `ObjectPublisher.publish(Object, MessageMetadata)` — Generic Object Send (Full Metadata) Control the Key, Header, and routing tags (BASE / GRAY) precisely by chaining metadata using `MessageMetadataBuilder`. ### Method ```java ObjectPublisher.publish(object, metadata, callback); ``` ### Parameters - **object** (Object) - The object to publish. - **metadata** (MessageMetadata) - The metadata for the message. - **callback** (MessageCallback) - Optional callback for success/failure. ### Request Example ```java String message = "{\"source\":\"legacy-system\",\"data\":\"...\" }"; MessageMetadata metadata = new MessageMetadataBuilder() .topicMetadata("order", "order-sync-topic") // Specify cluster and Topic .messageKey("ORD-20250601-099") // Kafka Record Key .messageHeader("requestId", "REQ-xyz") // Header (String type) .messageHeader("retryCount", 0) // Header (Integer type) .messageTag(Tag.BASE) // Force route to baseline cluster .build(); ObjectPublisher.publish(message, metadata, new MessageCallback() { @Override public void onSuccess() { log.info("Legacy message sync successful"); } @Override public void onFail(Exception e) { log.error("Legacy message sync failed", e); } }); ``` ``` -------------------------------- ### Batch Publish Events Source: https://context7.com/studeyang/easykafka/llms.txt Publish multiple events in a single call, suitable for scenarios where events are batched before notifying downstream systems. Each message is retried independently. ```java import io.github.open.easykafka.client.EventPublisher; import java.util.ArrayList; import java.util.List; List events = new ArrayList<>(); for (int i = 1; i <= 5; i++) { OrderCreatedEvent e = new OrderCreatedEvent(); e.setOrderId("ORD-" + i); e.setUserId("USER-" + i); events.add(e); } // 批量异步发送,每条消息独立重试 EventPublisher.publish(events); ``` -------------------------------- ### Manually Specify Routing Tag for Messages Source: https://github.com/studeyang/easykafka/blob/master/README.md Force message routing to a specific cluster environment, such as the gray cluster, by setting the message tag using MessageMetadataBuilder. ```java // 强制路由到灰度集群 MessageMetadata metadata = new MessageMetadataBuilder() .topicMetadata("send", "order-topic") .messageTag(Tag.GRAY) .build(); ObjectPublisher.publish(event, metadata); ``` -------------------------------- ### Generic Sending with ObjectPublisher to a Specific Topic Source: https://github.com/studeyang/easykafka/blob/master/README.md Utilize ObjectPublisher to send objects that do not extend Event or when a dynamic Topic needs to be specified. ```java ObjectPublisher.publish(myObject, new TopicMetadata("send", "custom-topic")); ``` -------------------------------- ### Define Message Class with @Topic Source: https://github.com/studeyang/easykafka/blob/master/README.md Define your message class by extending `Event` and annotating it with `@Topic` to specify the Kafka cluster and topic name. ```java import io.github.open.easykafka.client.annotation.Topic; import io.github.open.easykafka.client.message.Event; @Topic(cluster = "send", name = "order-topic") public class OrderCreatedEvent extends Event { private String orderId; private String userId; // getter/setter ... } ``` -------------------------------- ### Define Message Key with @MessageKey Source: https://github.com/studeyang/easykafka/blob/master/README.md Annotate a field in your message class with `@MessageKey` to designate it as the Kafka Record Key. This ensures messages with the same key are routed to the same partition. ```java @Topic(cluster = "send", name = "order-topic") public class OrderCreatedEvent extends Event { @MessageKey private String orderId; // 同一 orderId 的消息路由到同一分区 } ``` -------------------------------- ### EventPublisher.publish(Collection) Source: https://context7.com/studeyang/easykafka/llms.txt Publishes multiple events of the same or different types in a single call. Suitable for scenarios where events are batched and then notified to downstream systems. ```APIDOC ## `EventPublisher.publish(Collection)` — Batch Send Sends multiple `Event` messages of the same or different types in one call, suitable for scenarios where events are batched before notifying downstream systems. ### Method ```java EventPublisher.publish(events); ``` ### Parameters - **events** (Collection) - A collection of event objects to publish. ### Request Example ```java List events = new ArrayList<>(); for (int i = 1; i <= 5; i++) { OrderCreatedEvent e = new OrderCreatedEvent(); e.setOrderId("ORD-" + i); e.setUserId("USER-" + i); events.add(e); } // Batch asynchronous send, each message retried independently EventPublisher.publish(events); ``` ``` -------------------------------- ### Specify Message Key with @MessageKey Annotation Source: https://context7.com/studeyang/easykafka/llms.txt Annotate a field with `@MessageKey` to designate its value as the Kafka Record Key. This ensures that messages with the same key are consistently routed to the same partition, preserving order for related messages. ```java import io.github.open.easykafka.client.annotation.Topic; import io.github.open.easykafka.client.annotation.MessageKey; import io.github.open.easykafka.client.message.Event; @Topic(cluster = "payment", name = "payment-topic") public class PaymentCompletedEvent extends Event { @MessageKey private String paymentId; // 相同 paymentId 的消息始终路由到同一 Kafka 分区 private String orderId; private Double amount; private String status; } ``` -------------------------------- ### @EventHandler Annotation Source: https://context7.com/studeyang/easykafka/llms.txt Registers a consumer for specific Kafka topics within a cluster. This annotation wraps `@KafkaListener` and automatically configures the necessary Kafka listener container factory and consumer group. ```APIDOC ## `@EventHandler` Annotation — Register Consumer Annotate a Spring Bean class to declare it as a message handler for a specified cluster and topic. This internally wraps `@KafkaListener`, and the framework automatically creates a `ConcurrentKafkaListenerContainerFactory` and registers the consumer group. ### Usage ```java @Service @EventHandler(cluster = "clusterName", topics = "topicName") public class MyEventHandler implements IEventHandler { // ... handler methods ... } ``` ### Parameters - **cluster** (string) - The Kafka cluster name. - **topics** (string[]) - An array of topic names to subscribe to. - **concurrency** (string, optional) - The number of concurrent consumer threads. Defaults to 1. - **groupId** (string, optional) - The consumer group ID. If not provided, it's auto-generated as `groupIdPrefix + topicName`. ### Handler Method Annotate methods within the handler class with `@KafkaHandler` to process specific message types. You can also inject headers using `@Header`. ### Example ```java import io.github.open.easykafka.client.annotation.EventHandler; import io.github.open.easykafka.client.message.IEventHandler; import org.springframework.kafka.annotation.KafkaHandler; import org.springframework.messaging.handler.annotation.Header; import org.springframework.stereotype.Service; import java.nio.ByteBuffer; import java.util.Optional; @Slf4j @Service @EventHandler( cluster = "order", topics = "order-created-topic", concurrency = "3" // Concurrent consumer threads, defaults to 1 // groupId = "my-group" // If not provided, auto-generated: groupIdPrefix + topicName ) public class OrderCreatedEventHandler implements IEventHandler { // Handle OrderCreatedEvent type messages @KafkaHandler public void handleOrderCreated(OrderCreatedEvent event, @Header(value = "requestId", required = false) String requestId, @Header(value = "retryCount", required = false) ByteBuffer retryCount) { int retry = Optional.ofNullable(retryCount).map(ByteBuffer::getInt).orElse(0); log.info("Received order creation event orderId={}, requestId={}, retryCount={}", event.getOrderId(), requestId, retry); // Business logic... } // Handle another message type for the same Topic within the same Handler class @KafkaHandler public void handleOrderCancelled(OrderCancelledEvent event) { log.info("Received order cancellation event orderId={}", event.getOrderId()); } } ``` ``` -------------------------------- ### Define Message Topic with @Topic Annotation Source: https://context7.com/studeyang/easykafka/llms.txt Use the `@Topic` annotation on message classes to specify the Kafka cluster and topic name. This metadata is automatically used by the framework to construct `ProducerRecord` instances during message sending. ```java import io.github.open.easykafka.client.annotation.Topic; import io.github.open.easykafka.client.annotation.MessageKey; import io.github.open.easykafka.client.annotation.MessageHeader; import io.github.open.easykafka.client.message.Event; // 定义一条领域事件消息 @Topic(cluster = "order", name = "order-created-topic") public class OrderCreatedEvent extends Event { @MessageKey // 该字段值作为 Kafka Record Key,相同 key 路由到同一分区 private String orderId; @MessageHeader // 该字段值写入 Kafka Record Header,消费端可通过 @Header 读取 private String requestId; @MessageHeader private String traceId; private String userId; private Double amount; // getter / setter ... } ``` -------------------------------- ### Declare Kafka Message Handler with @EventHandler Source: https://github.com/studeyang/easykafka/blob/master/README.md Use the @EventHandler annotation on a consumer class to declare it as a Kafka message processor. This annotation is a wrapper around @KafkaListener. ```java @Service @EventHandler( cluster = "send", topics = "order-topic", concurrency = "3" ) public class OrderEventHandler { @KafkaHandler public void handleCreated(OrderCreatedEvent event) { ... } @KafkaHandler public void handleCancelled(OrderCancelledEvent event) { ... } } ``` -------------------------------- ### Automatic Retries on Send Failure Source: https://github.com/studeyang/easykafka/blob/master/README.md Describes the automatic retry mechanism for message sending failures, managed by the framework without requiring business code intervention. ```APIDOC ## Automatic Retries The framework automatically retries on send failures without intervention from business code: | Parameter | Value | |---|---| | Maximum Retries | 3 times | | Initial Wait Time | 100ms | | Backoff Multiplier | 2x | | Maximum Wait Time | 5000ms | | Retry Strategy | Exponential Backoff | ``` -------------------------------- ### Define Message Headers with @MessageHeader Source: https://github.com/studeyang/easykafka/blob/master/README.md Annotate fields in your event class with @MessageHeader to have their values written to Kafka Record Headers. Consumers can retrieve these values using the @Header annotation. ```java @Topic(cluster = "send", name = "order-topic") public class OrderCreatedEvent extends Event { @MessageHeader private String requestId; @MessageHeader private String traceId; } ``` ```java @KafkaHandler public void handle(OrderCreatedEvent event, @Header(value = "requestId", required = false) String requestId, @Header(value = "traceId", required = false) String traceId) { log.info("requestId={}, traceId={}", requestId, traceId); } ``` -------------------------------- ### Register Event Handler with @EventHandler Source: https://context7.com/studeyang/easykafka/llms.txt Annotate a Spring Bean class to declare it as a message handler for specific clusters and topics. This annotation wraps @KafkaListener and automatically configures the consumer factory and group ID. ```java import io.github.open.easykafka.client.annotation.EventHandler; import io.github.open.easykafka.client.message.IEventHandler; import org.springframework.kafka.annotation.KafkaHandler; import org.springframework.messaging.handler.annotation.Header; import org.springframework.stereotype.Service; import java.nio.ByteBuffer; import java.util.Optional; @Slf4j @Service @EventHandler( cluster = "order", topics = "order-created-topic", concurrency = "3" // 并发消费线程数,默认 1 // groupId = "my-group" // 不填则自动生成:groupIdPrefix + topicName ) public class OrderCreatedEventHandler implements IEventHandler { // 处理 OrderCreatedEvent 类型消息 @KafkaHandler public void handleOrderCreated(OrderCreatedEvent event, @Header(value = "requestId", required = false) String requestId, @Header(value = "retryCount", required = false) ByteBuffer retryCount) { int retry = Optional.ofNullable(retryCount).map(ByteBuffer::getInt).orElse(0); log.info("收到订单创建事件 orderId={}, requestId={}, retryCount={}", event.getOrderId(), requestId, retry); // 业务处理逻辑... } // 同一 Handler 类处理同 Topic 下的另一种消息类型 @KafkaHandler public void handleOrderCancelled(OrderCancelledEvent event) { log.info("收到订单取消事件 orderId={}", event.getOrderId()); } } ``` -------------------------------- ### Add Message Headers with @MessageHeader Annotation Source: https://context7.com/studeyang/easykafka/llms.txt Use the `@MessageHeader` annotation on message fields to include their values in the Kafka Record Headers. Supported types include `String` and `Integer`. Consumers can access these header values using the `@Header` parameter in their handler methods. ```java import io.github.open.easykafka.client.annotation.Topic; import io.github.open.easykafka.client.annotation.MessageHeader; import io.github.open.easykafka.client.message.Event; @Topic(cluster = "order", name = "order-created-topic") public class OrderCreatedEvent extends Event { @MessageHeader private String requestId; // 写入 Header "requestId" @MessageHeader private Integer retryCount; // 写入 Header "retryCount" private String orderId; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.