├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── dco.yml ├── dependabot.yml └── workflows │ ├── announce-milestone-planning.yml │ ├── auto-cherry-pick.yml │ ├── backport-issue.yml │ ├── ci-snapshot.yml │ ├── deploy-docs.yml │ ├── merge-dependabot-pr.yml │ ├── pr-build.yml │ ├── release.yml │ └── verify-staged-artifacts.yml ├── .gitignore ├── CODE_OF_CONDUCT.adoc ├── CONTRIBUTING.adoc ├── LICENCE.txt ├── README.md ├── build.gradle ├── gradle.properties ├── gradle ├── docs.gradle ├── publish-maven.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── samples ├── README.adoc ├── sample-01 │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── README.adoc │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ ├── common │ │ │ │ ├── Foo1.java │ │ │ │ └── Foo2.java │ │ │ │ └── example │ │ │ │ ├── Application.java │ │ │ │ └── Controller.java │ │ └── resources │ │ │ └── application.yml │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── ApplicationTests.java ├── sample-02 │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── README.adoc │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ ├── common │ │ │ │ ├── Bar1.java │ │ │ │ ├── Bar2.java │ │ │ │ ├── Foo1.java │ │ │ │ └── Foo2.java │ │ │ │ └── example │ │ │ │ ├── Application.java │ │ │ │ ├── Controller.java │ │ │ │ └── MultiMethods.java │ │ └── resources │ │ │ └── application.yml │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── ApplicationTests.java ├── sample-03 │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── README.adoc │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ ├── common │ │ │ │ ├── Foo1.java │ │ │ │ └── Foo2.java │ │ │ │ └── example │ │ │ │ ├── Application.java │ │ │ │ └── Controller.java │ │ └── resources │ │ │ └── application.yml │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── ApplicationTests.java ├── sample-04 │ ├── README.adoc │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── Application.java │ │ │ │ └── Controller.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── ApplicationTests.java ├── sample-05 │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── README.adoc │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── Sample05Application.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── Sample05Application1Tests.java │ │ │ └── Sample05Application2Tests.java │ │ └── resources │ │ ├── junit-platform.properties │ │ ├── kafka-broker.properties │ │ └── logback-test.xml ├── sample-06 │ ├── README.adoc │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── Application.java │ │ │ │ └── Topology.java │ │ └── resources │ │ │ ├── application-test.properties │ │ │ ├── application.properties │ │ │ └── application.yml │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── ApplicationTests.java ├── sample-07 │ ├── .gitignore │ ├── README.adoc │ ├── build.gradle │ ├── compose.yaml │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── sample07 │ │ │ ├── Sample07Application.java │ │ │ └── Sample07KafkaListener.java │ │ └── resources │ │ └── application.yaml └── sample-08 │ ├── .gitattributes │ ├── .gitignore │ ├── README.adoc │ ├── build.gradle │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── sample08 │ │ │ └── Sample08Application.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── sample08 │ └── Sample08ApplicationTests.java ├── settings.gradle ├── spring-kafka-bom └── spring-kafka-bom.txt ├── spring-kafka-docs ├── build.gradle └── src │ └── main │ ├── antora │ ├── antora-playbook.yml │ ├── antora.yml │ └── modules │ │ └── ROOT │ │ ├── examples │ │ ├── java-examples │ │ └── kotlin-examples │ │ ├── nav.adoc │ │ └── pages │ │ ├── appendix.adoc │ │ ├── appendix │ │ ├── change-history.adoc │ │ ├── micrometer.adoc │ │ ├── native-images.adoc │ │ └── override-boot-dependencies.adoc │ │ ├── index.adoc │ │ ├── introduction.adoc │ │ ├── kafka.adoc │ │ ├── kafka │ │ ├── annotation-error-handling.adoc │ │ ├── configuring-topics.adoc │ │ ├── connecting.adoc │ │ ├── container-factory.adoc │ │ ├── container-props.adoc │ │ ├── dynamic-containers.adoc │ │ ├── events.adoc │ │ ├── exactly-once.adoc │ │ ├── headers.adoc │ │ ├── interceptors.adoc │ │ ├── kerberos.adoc │ │ ├── micrometer.adoc │ │ ├── pause-resume-partitions.adoc │ │ ├── pause-resume.adoc │ │ ├── producer-interceptor-managed-in-spring.adoc │ │ ├── receiving-messages.adoc │ │ ├── receiving-messages │ │ │ ├── annotation-send-to.adoc │ │ │ ├── async-returns.adoc │ │ │ ├── class-level-kafkalistener.adoc │ │ │ ├── container-thread-naming.adoc │ │ │ ├── enforced-rebalance.adoc │ │ │ ├── filtering.adoc │ │ │ ├── kafkalistener-attrs.adoc │ │ │ ├── kafkalistener-lifecycle.adoc │ │ │ ├── listener-annotation.adoc │ │ │ ├── listener-group-id.adoc │ │ │ ├── listener-meta.adoc │ │ │ ├── message-listener-container.adoc │ │ │ ├── message-listeners.adoc │ │ │ ├── ooo-commits.adoc │ │ │ ├── rebalance-listeners.adoc │ │ │ ├── retrying-deliveries.adoc │ │ │ ├── sequencing.adoc │ │ │ ├── template-receive.adoc │ │ │ └── validation.adoc │ │ ├── seek.adoc │ │ ├── sending-messages.adoc │ │ ├── serdes.adoc │ │ ├── thread-safety.adoc │ │ ├── tombstones.adoc │ │ ├── topic │ │ │ └── partition-initial-offset.adoc │ │ └── transactions.adoc │ │ ├── other-resources.adoc │ │ ├── quick-tour.adoc │ │ ├── reference.adoc │ │ ├── retrytopic.adoc │ │ ├── retrytopic │ │ ├── access-topic-info-runtime.adoc │ │ ├── accessing-delivery-attempts.adoc │ │ ├── back-off-delay-precision.adoc │ │ ├── change-kboe-logging-level.adoc │ │ ├── dlt-strategies.adoc │ │ ├── features.adoc │ │ ├── how-the-pattern-works.adoc │ │ ├── multi-retry.adoc │ │ ├── programmatic-construction.adoc │ │ ├── retry-config.adoc │ │ ├── retry-topic-combine-blocking.adoc │ │ ├── retry-topic-lcf.adoc │ │ └── topic-naming.adoc │ │ ├── streams.adoc │ │ ├── testing.adoc │ │ ├── tips.adoc │ │ └── whats-new.adoc │ ├── java │ └── org │ │ └── springframework │ │ └── kafka │ │ └── jdocs │ │ ├── dynamic │ │ ├── Application.java │ │ ├── MyListener.java │ │ └── MyPojo.java │ │ ├── requestreply │ │ └── Application.java │ │ ├── started │ │ ├── consumer │ │ │ └── Application.java │ │ ├── noboot │ │ │ ├── Config.java │ │ │ ├── Listener.java │ │ │ └── Sender.java │ │ └── producer │ │ │ └── Application.java │ │ └── topics │ │ └── Config.java │ ├── kotlin │ └── org │ │ └── springframework │ │ └── kafka │ │ └── kdocs │ │ ├── dynamic │ │ └── Application.kt │ │ ├── requestreply │ │ └── Application.kt │ │ ├── started │ │ ├── consumer │ │ │ └── Application.kt │ │ ├── noboot │ │ │ ├── Config.kt │ │ │ ├── Listener.kt │ │ │ └── Sender.kt │ │ └── producer │ │ │ └── Application.kt │ │ └── topics │ │ └── Config.kt │ └── resources │ └── logback.xml ├── spring-kafka-test └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── springframework │ │ │ └── kafka │ │ │ └── test │ │ │ ├── EmbeddedKafkaBroker.java │ │ │ ├── EmbeddedKafkaBrokerFactory.java │ │ │ ├── EmbeddedKafkaKraftBroker.java │ │ │ ├── assertj │ │ │ ├── KafkaConditions.java │ │ │ └── package-info.java │ │ │ ├── condition │ │ │ ├── EmbeddedKafkaCondition.java │ │ │ ├── LogLevels.java │ │ │ ├── LogLevelsCondition.java │ │ │ └── package-info.java │ │ │ ├── context │ │ │ ├── EmbeddedKafka.java │ │ │ ├── EmbeddedKafkaContextCustomizer.java │ │ │ ├── EmbeddedKafkaContextCustomizerFactory.java │ │ │ └── package-info.java │ │ │ ├── core │ │ │ ├── BrokerAddress.java │ │ │ └── package-info.java │ │ │ ├── hamcrest │ │ │ ├── KafkaMatchers.java │ │ │ └── package-info.java │ │ │ ├── junit │ │ │ ├── GlobalEmbeddedKafkaTestExecutionListener.java │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ ├── rule │ │ │ ├── Log4j2LevelAdjuster.java │ │ │ └── package-info.java │ │ │ └── utils │ │ │ ├── ContainerTestUtils.java │ │ │ ├── JUnitUtils.java │ │ │ ├── KafkaTestUtils.java │ │ │ └── package-info.java │ └── resources │ │ └── META-INF │ │ ├── services │ │ └── org.junit.platform.launcher.TestExecutionListener │ │ └── spring.factories │ └── test │ ├── java │ └── org │ │ └── springframework │ │ └── kafka │ │ └── test │ │ ├── AddressableEmbeddedBrokerTests.java │ │ ├── EmbeddedKafkaKraftBrokerTests.java │ │ ├── assertj │ │ └── KafkaConditionsTests.java │ │ ├── condition │ │ ├── EmbeddedKafkaConditionTests.java │ │ ├── WithNestedClassContextTests.java │ │ └── WithSpringTestContextTests.java │ │ ├── context │ │ └── EmbeddedKafkaContextCustomizerTests.java │ │ ├── hamcrest │ │ └── KafkaMatchersTests.java │ │ ├── junit │ │ └── GlobalEmbeddedKafkaTestExecutionListenerTests.java │ │ └── utils │ │ └── KafkaTestUtilsTests.java │ └── resources │ ├── junit-platform.properties │ └── log4j2-test.xml ├── spring-kafka └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── springframework │ │ │ └── kafka │ │ │ ├── KafkaException.java │ │ │ ├── annotation │ │ │ ├── DltHandler.java │ │ │ ├── EnableKafka.java │ │ │ ├── EnableKafkaRetryTopic.java │ │ │ ├── EnableKafkaStreams.java │ │ │ ├── KafkaBootstrapConfiguration.java │ │ │ ├── KafkaHandler.java │ │ │ ├── KafkaListener.java │ │ │ ├── KafkaListenerAnnotationBeanPostProcessor.java │ │ │ ├── KafkaListenerConfigurationSelector.java │ │ │ ├── KafkaListenerConfigurer.java │ │ │ ├── KafkaListeners.java │ │ │ ├── KafkaStreamsDefaultConfiguration.java │ │ │ ├── PartitionOffset.java │ │ │ ├── RetryTopicConfigurationProvider.java │ │ │ ├── RetryableTopic.java │ │ │ ├── RetryableTopicAnnotationProcessor.java │ │ │ ├── TopicPartition.java │ │ │ └── package-info.java │ │ │ ├── aot │ │ │ ├── KafkaAvroBeanRegistrationAotProcessor.java │ │ │ ├── KafkaRuntimeHints.java │ │ │ └── package-info.java │ │ │ ├── config │ │ │ ├── AbstractKafkaListenerContainerFactory.java │ │ │ ├── AbstractKafkaListenerEndpoint.java │ │ │ ├── CompositeKafkaStreamsCustomizer.java │ │ │ ├── CompositeKafkaStreamsInfrastructureCustomizer.java │ │ │ ├── ConcurrentKafkaListenerContainerFactory.java │ │ │ ├── ContainerCustomizer.java │ │ │ ├── ContainerPostProcessor.java │ │ │ ├── KafkaListenerConfigUtils.java │ │ │ ├── KafkaListenerContainerFactory.java │ │ │ ├── KafkaListenerEndpoint.java │ │ │ ├── KafkaListenerEndpointAdapter.java │ │ │ ├── KafkaListenerEndpointRegistrar.java │ │ │ ├── KafkaListenerEndpointRegistry.java │ │ │ ├── KafkaStreamsConfiguration.java │ │ │ ├── KafkaStreamsCustomizer.java │ │ │ ├── KafkaStreamsInfrastructureCustomizer.java │ │ │ ├── MethodKafkaListenerEndpoint.java │ │ │ ├── MultiMethodKafkaListenerEndpoint.java │ │ │ ├── StreamsBuilderFactoryBean.java │ │ │ ├── StreamsBuilderFactoryBeanConfigurer.java │ │ │ ├── TopicBuilder.java │ │ │ └── package-info.java │ │ │ ├── core │ │ │ ├── ABSwitchCluster.java │ │ │ ├── CleanupConfig.java │ │ │ ├── ConsumerFactory.java │ │ │ ├── ConsumerPostProcessor.java │ │ │ ├── DefaultKafkaConsumerFactory.java │ │ │ ├── DefaultKafkaProducerFactory.java │ │ │ ├── DefaultShareConsumerFactory.java │ │ │ ├── DefaultTransactionIdSuffixStrategy.java │ │ │ ├── KafkaAdmin.java │ │ │ ├── KafkaAdminOperations.java │ │ │ ├── KafkaMetricsSupport.java │ │ │ ├── KafkaOperations.java │ │ │ ├── KafkaProducerException.java │ │ │ ├── KafkaResourceFactory.java │ │ │ ├── KafkaResourceHolder.java │ │ │ ├── KafkaTemplate.java │ │ │ ├── MicrometerConsumerListener.java │ │ │ ├── MicrometerProducerListener.java │ │ │ ├── NoProducerAvailableException.java │ │ │ ├── ProducerFactory.java │ │ │ ├── ProducerFactoryUtils.java │ │ │ ├── ProducerPostProcessor.java │ │ │ ├── RoutingKafkaTemplate.java │ │ │ ├── ShareConsumerFactory.java │ │ │ ├── TransactionIdSuffixStrategy.java │ │ │ ├── package-info.java │ │ │ └── reactive │ │ │ │ ├── ReactiveKafkaConsumerTemplate.java │ │ │ │ ├── ReactiveKafkaProducerTemplate.java │ │ │ │ └── package-info.java │ │ │ ├── event │ │ │ ├── ConcurrentContainerStoppedEvent.java │ │ │ ├── ConsumerFailedToStartEvent.java │ │ │ ├── ConsumerPartitionPausedEvent.java │ │ │ ├── ConsumerPartitionResumedEvent.java │ │ │ ├── ConsumerPausedEvent.java │ │ │ ├── ConsumerResumedEvent.java │ │ │ ├── ConsumerRetryAuthEvent.java │ │ │ ├── ConsumerRetryAuthSuccessfulEvent.java │ │ │ ├── ConsumerStartedEvent.java │ │ │ ├── ConsumerStartingEvent.java │ │ │ ├── ConsumerStoppedEvent.java │ │ │ ├── ConsumerStoppingEvent.java │ │ │ ├── ContainerStoppedEvent.java │ │ │ ├── KafkaEvent.java │ │ │ ├── ListenerContainerIdleEvent.java │ │ │ ├── ListenerContainerNoLongerIdleEvent.java │ │ │ ├── ListenerContainerPartitionIdleEvent.java │ │ │ ├── ListenerContainerPartitionNoLongerIdleEvent.java │ │ │ ├── NonResponsiveConsumerEvent.java │ │ │ └── package-info.java │ │ │ ├── listener │ │ │ ├── AbstractConsumerSeekAware.java │ │ │ ├── AbstractKafkaBackOffManagerFactory.java │ │ │ ├── AbstractMessageListenerContainer.java │ │ │ ├── AcknowledgingConsumerAwareMessageListener.java │ │ │ ├── AcknowledgingMessageListener.java │ │ │ ├── AfterRollbackProcessor.java │ │ │ ├── BackOffHandler.java │ │ │ ├── BatchAcknowledgingConsumerAwareMessageListener.java │ │ │ ├── BatchAcknowledgingMessageListener.java │ │ │ ├── BatchConsumerAwareMessageListener.java │ │ │ ├── BatchInterceptor.java │ │ │ ├── BatchListenerFailedException.java │ │ │ ├── BatchMessageListener.java │ │ │ ├── CommonContainerStoppingErrorHandler.java │ │ │ ├── CommonDelegatingErrorHandler.java │ │ │ ├── CommonErrorHandler.java │ │ │ ├── CommonLoggingErrorHandler.java │ │ │ ├── CommonMixedErrorHandler.java │ │ │ ├── CompositeBatchInterceptor.java │ │ │ ├── CompositeRecordInterceptor.java │ │ │ ├── ConcurrentMessageListenerContainer.java │ │ │ ├── ConsumerAwareListenerErrorHandler.java │ │ │ ├── ConsumerAwareMessageListener.java │ │ │ ├── ConsumerAwareRebalanceListener.java │ │ │ ├── ConsumerAwareRecordRecoverer.java │ │ │ ├── ConsumerPauseResumeEventPublisher.java │ │ │ ├── ConsumerProperties.java │ │ │ ├── ConsumerRecordRecoverer.java │ │ │ ├── ConsumerSeekAware.java │ │ │ ├── ContainerGroup.java │ │ │ ├── ContainerGroupSequencer.java │ │ │ ├── ContainerPartitionPausingBackOffManager.java │ │ │ ├── ContainerPartitionPausingBackOffManagerFactory.java │ │ │ ├── ContainerPausingBackOffHandler.java │ │ │ ├── ContainerProperties.java │ │ │ ├── DeadLetterPublishingRecoverer.java │ │ │ ├── DefaultAfterRollbackProcessor.java │ │ │ ├── DefaultBackOffHandler.java │ │ │ ├── DefaultErrorHandler.java │ │ │ ├── DefaultListenerMetadata.java │ │ │ ├── DelegatingMessageListener.java │ │ │ ├── DeliveryAttemptAware.java │ │ │ ├── DeliveryAttemptAwareRetryListener.java │ │ │ ├── ErrorHandlingUtils.java │ │ │ ├── ExceptionClassifier.java │ │ │ ├── FailedBatchProcessor.java │ │ │ ├── FailedRecordProcessor.java │ │ │ ├── FailedRecordTracker.java │ │ │ ├── FallbackBatchErrorHandler.java │ │ │ ├── GenericMessageListener.java │ │ │ ├── GenericMessageListenerContainer.java │ │ │ ├── KafkaBackOffManagerFactory.java │ │ │ ├── KafkaBackoffException.java │ │ │ ├── KafkaConsumerBackoffManager.java │ │ │ ├── KafkaExceptionLogLevelAware.java │ │ │ ├── KafkaListenerErrorHandler.java │ │ │ ├── KafkaMessageListenerContainer.java │ │ │ ├── ListenerContainerPauseService.java │ │ │ ├── ListenerContainerRegistry.java │ │ │ ├── ListenerExecutionFailedException.java │ │ │ ├── ListenerMetadata.java │ │ │ ├── ListenerType.java │ │ │ ├── ListenerUtils.java │ │ │ ├── LoggingCommitCallback.java │ │ │ ├── ManualAckListenerErrorHandler.java │ │ │ ├── MessageListener.java │ │ │ ├── MessageListenerContainer.java │ │ │ ├── OffsetAndMetadataProvider.java │ │ │ ├── RecordInRetryException.java │ │ │ ├── RecordInterceptor.java │ │ │ ├── RecoveryStrategy.java │ │ │ ├── RetryListener.java │ │ │ ├── SeekUtils.java │ │ │ ├── ThreadStateProcessor.java │ │ │ ├── TimestampedException.java │ │ │ ├── adapter │ │ │ │ ├── AbstractDelegatingMessageListenerAdapter.java │ │ │ │ ├── AbstractFilteringMessageListener.java │ │ │ │ ├── AbstractRetryingMessageListenerAdapter.java │ │ │ │ ├── AdapterUtils.java │ │ │ │ ├── AsyncRepliesAware.java │ │ │ │ ├── BatchMessagingMessageListenerAdapter.java │ │ │ │ ├── BatchToRecordAdapter.java │ │ │ │ ├── ConsumerRecordMetadata.java │ │ │ │ ├── ContinuationHandlerMethodArgumentResolver.java │ │ │ │ ├── ConvertingMessageListener.java │ │ │ │ ├── DefaultBatchToRecordAdapter.java │ │ │ │ ├── DelegatingInvocableHandler.java │ │ │ │ ├── FilteringBatchMessageListenerAdapter.java │ │ │ │ ├── FilteringMessageListenerAdapter.java │ │ │ │ ├── HandlerAdapter.java │ │ │ │ ├── InvocationResult.java │ │ │ │ ├── KafkaBackoffAwareMessageListenerAdapter.java │ │ │ │ ├── KafkaMessageHandlerMethodFactory.java │ │ │ │ ├── KafkaNullAwarePayloadArgumentResolver.java │ │ │ │ ├── KotlinAwareInvocableHandlerMethod.java │ │ │ │ ├── MessagingMessageListenerAdapter.java │ │ │ │ ├── RecordFilterStrategy.java │ │ │ │ ├── RecordMessagingMessageListenerAdapter.java │ │ │ │ ├── ReplyHeadersConfigurer.java │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ │ ├── mock │ │ │ ├── MockConsumerFactory.java │ │ │ ├── MockProducerFactory.java │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ ├── requestreply │ │ │ ├── AggregatingReplyingKafkaTemplate.java │ │ │ ├── CorrelationKey.java │ │ │ ├── KafkaReplyTimeoutException.java │ │ │ ├── ReplyingKafkaOperations.java │ │ │ ├── ReplyingKafkaTemplate.java │ │ │ ├── RequestReplyFuture.java │ │ │ ├── RequestReplyMessageFuture.java │ │ │ ├── RequestReplyTypedMessageFuture.java │ │ │ └── package-info.java │ │ │ ├── retrytopic │ │ │ ├── BackOffValuesGenerator.java │ │ │ ├── DeadLetterPublishingRecovererFactory.java │ │ │ ├── DefaultDestinationTopicProcessor.java │ │ │ ├── DefaultDestinationTopicResolver.java │ │ │ ├── DestinationTopic.java │ │ │ ├── DestinationTopicContainer.java │ │ │ ├── DestinationTopicProcessor.java │ │ │ ├── DestinationTopicPropertiesFactory.java │ │ │ ├── DestinationTopicResolver.java │ │ │ ├── DltStrategy.java │ │ │ ├── EndpointCustomizer.java │ │ │ ├── EndpointCustomizerFactory.java │ │ │ ├── ExceptionBasedDltDestination.java │ │ │ ├── ListenerContainerFactoryConfigurer.java │ │ │ ├── ListenerContainerFactoryResolver.java │ │ │ ├── RetryTopicBeanNames.java │ │ │ ├── RetryTopicComponentFactory.java │ │ │ ├── RetryTopicConfiguration.java │ │ │ ├── RetryTopicConfigurationBuilder.java │ │ │ ├── RetryTopicConfigurationSupport.java │ │ │ ├── RetryTopicConfigurer.java │ │ │ ├── RetryTopicConstants.java │ │ │ ├── RetryTopicHeaders.java │ │ │ ├── RetryTopicNamesProviderFactory.java │ │ │ ├── RetryTopicSchedulerWrapper.java │ │ │ ├── SameIntervalTopicReuseStrategy.java │ │ │ ├── SuffixingRetryTopicNamesProviderFactory.java │ │ │ ├── TopicSuffixingStrategy.java │ │ │ └── package-info.java │ │ │ ├── security │ │ │ └── jaas │ │ │ │ ├── KafkaJaasLoginModuleInitializer.java │ │ │ │ └── package-info.java │ │ │ ├── streams │ │ │ ├── HeaderEnricherProcessor.java │ │ │ ├── KafkaStreamsInteractiveQueryService.java │ │ │ ├── KafkaStreamsMicrometerListener.java │ │ │ ├── RecoveringDeserializationExceptionHandler.java │ │ │ ├── messaging │ │ │ │ ├── MessagingFunction.java │ │ │ │ ├── MessagingProcessor.java │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ │ ├── support │ │ │ ├── AbstractKafkaHeaderMapper.java │ │ │ ├── Acknowledgment.java │ │ │ ├── AllowDenyCollectionManager.java │ │ │ ├── CompositeProducerInterceptor.java │ │ │ ├── CompositeProducerListener.java │ │ │ ├── DefaultKafkaHeaderMapper.java │ │ │ ├── EndpointHandlerMethod.java │ │ │ ├── EndpointHandlerMultiMethod.java │ │ │ ├── ExponentialBackOffWithMaxRetries.java │ │ │ ├── JacksonMimeTypeModule.java │ │ │ ├── JacksonPresent.java │ │ │ ├── JacksonUtils.java │ │ │ ├── JavaUtils.java │ │ │ ├── KafkaHeaderMapper.java │ │ │ ├── KafkaHeaders.java │ │ │ ├── KafkaMessageHeaderAccessor.java │ │ │ ├── KafkaNull.java │ │ │ ├── KafkaStreamBrancher.java │ │ │ ├── KafkaUtils.java │ │ │ ├── LogIfLevelEnabled.java │ │ │ ├── LoggingProducerListener.java │ │ │ ├── ProducerListener.java │ │ │ ├── SendResult.java │ │ │ ├── SimpleKafkaHeaderMapper.java │ │ │ ├── Suffixer.java │ │ │ ├── TopicForRetryable.java │ │ │ ├── TopicPartitionOffset.java │ │ │ ├── converter │ │ │ │ ├── BatchMessageConverter.java │ │ │ │ ├── BatchMessagingMessageConverter.java │ │ │ │ ├── ByteArrayJsonMessageConverter.java │ │ │ │ ├── BytesJsonMessageConverter.java │ │ │ │ ├── ConversionException.java │ │ │ │ ├── JsonMessageConverter.java │ │ │ │ ├── KafkaMessageHeaders.java │ │ │ │ ├── MappingJacksonParameterizedConverter.java │ │ │ │ ├── MessageConverter.java │ │ │ │ ├── MessagingMessageConverter.java │ │ │ │ ├── ProjectingMessageConverter.java │ │ │ │ ├── RecordMessageConverter.java │ │ │ │ ├── StringJsonMessageConverter.java │ │ │ │ └── package-info.java │ │ │ ├── mapping │ │ │ │ ├── AbstractJavaTypeMapper.java │ │ │ │ ├── ClassMapper.java │ │ │ │ ├── DefaultJackson2JavaTypeMapper.java │ │ │ │ ├── Jackson2JavaTypeMapper.java │ │ │ │ └── package-info.java │ │ │ ├── micrometer │ │ │ │ ├── KafkaListenerObservation.java │ │ │ │ ├── KafkaListenerObservationConvention.java │ │ │ │ ├── KafkaRecordReceiverContext.java │ │ │ │ ├── KafkaRecordSenderContext.java │ │ │ │ ├── KafkaTemplateObservation.java │ │ │ │ ├── KafkaTemplateObservationConvention.java │ │ │ │ ├── MicrometerHolder.java │ │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ └── serializer │ │ │ │ ├── DelegatingByTopicDeserializer.java │ │ │ │ ├── DelegatingByTopicSerialization.java │ │ │ │ ├── DelegatingByTopicSerializer.java │ │ │ │ ├── DelegatingByTypeSerializer.java │ │ │ │ ├── DelegatingDeserializer.java │ │ │ │ ├── DelegatingSerializer.java │ │ │ │ ├── DeserializationException.java │ │ │ │ ├── DeserializationExceptionHeader.java │ │ │ │ ├── ErrorHandlingDeserializer.java │ │ │ │ ├── FailedDeserializationInfo.java │ │ │ │ ├── JsonDeserializer.java │ │ │ │ ├── JsonSerde.java │ │ │ │ ├── JsonSerializer.java │ │ │ │ ├── JsonTypeResolver.java │ │ │ │ ├── ParseStringDeserializer.java │ │ │ │ ├── RetryingDeserializer.java │ │ │ │ ├── SerializationUtils.java │ │ │ │ ├── StringOrBytesSerializer.java │ │ │ │ ├── ToFromStringSerde.java │ │ │ │ ├── ToStringSerializer.java │ │ │ │ └── package-info.java │ │ │ └── transaction │ │ │ ├── ChainedKafkaTransactionManager.java │ │ │ ├── KafkaAwareTransactionManager.java │ │ │ ├── KafkaTransactionManager.java │ │ │ └── package-info.java │ └── resources │ │ └── META-INF │ │ └── spring │ │ └── aot.factories │ └── test │ ├── java │ └── org │ │ └── springframework │ │ └── kafka │ │ ├── annotation │ │ ├── AliasPropertiesTests.java │ │ ├── AsyncListenerTests.java │ │ ├── BatchListenerConversion2Tests.java │ │ ├── BatchListenerConversionTests.java │ │ ├── ContainerFactoryTests.java │ │ ├── EnableKafkaIntegrationTests.java │ │ └── KafkaListenerAnnotationBeanPostProcessorTests.java │ │ ├── config │ │ ├── KafkaListenerEndpointRegistryTests.java │ │ ├── KafkaStreamsCustomizerTests.java │ │ ├── RecordMessagingMessageListenerAdapterTests.java │ │ ├── StreamsBuilderFactoryBeanInMemoryStateStoreTests.java │ │ ├── StreamsBuilderFactoryBeanTests.java │ │ └── StreamsBuilderFactoryLateConfigTests.java │ │ ├── core │ │ ├── DefaultKafkaConsumerFactoryTests.java │ │ ├── DefaultKafkaProducerFactoryTests.java │ │ ├── DefaultShareConsumerFactoryTests.java │ │ ├── DefaultTransactionIdSuffixStrategyTests.java │ │ ├── KafkaAdminBadContextTests.java │ │ ├── KafkaAdminTests.java │ │ ├── KafkaTemplateTests.java │ │ ├── KafkaTemplateTransactionTests.java │ │ ├── RoutingKafkaTemplateTests.java │ │ ├── TransactionSynchronizationTests.java │ │ └── reactive │ │ │ ├── ReactiveKafkaProducerTemplateIntegrationTests.java │ │ │ └── ReactiveKafkaProducerTemplateTransactionIntegrationTests.java │ │ ├── listener │ │ ├── ABSwitchClusterTests.java │ │ ├── AbstractConsumerSeekAwareTests.java │ │ ├── AsyncAckAfterHandleTests.java │ │ ├── CommitOnAssignmentTests.java │ │ ├── CommonContainerStoppingErrorHandler1Tests.java │ │ ├── CommonContainerStoppingErrorHandler2Tests.java │ │ ├── CommonContainerStoppingErrorHandler3Tests.java │ │ ├── CommonDelegatingErrorHandlerTests.java │ │ ├── CommonMixedErrorHandlerTests.java │ │ ├── ConcurrentMessageListenerContainerMockTests.java │ │ ├── ConcurrentMessageListenerContainerTests.java │ │ ├── ConsumerAwareRebalanceListenerTests.java │ │ ├── ConsumerSeekAwareTests.java │ │ ├── ContainerCustomizationTests.java │ │ ├── ContainerEnforceRebalanceTests.java │ │ ├── ContainerGroupSequencerTests.java │ │ ├── ContainerPauseImmediateTests.java │ │ ├── DeadLetterPublishingRecovererTests.java │ │ ├── DefaultAfterRollbackProcessorTests.java │ │ ├── DefaultErrorHandlerBatchIntegrationTests.java │ │ ├── DefaultErrorHandlerBatchTests.java │ │ ├── DefaultErrorHandlerNoSeeksBatchAckTests.java │ │ ├── DefaultErrorHandlerNoSeeksBatchListenerTests.java │ │ ├── DefaultErrorHandlerNoSeeksRecordAckNoResumeContainerPausedTests.java │ │ ├── DefaultErrorHandlerNoSeeksRecordAckNoResumePartitionTests.java │ │ ├── DefaultErrorHandlerNoSeeksRecordAckTests.java │ │ ├── DefaultErrorHandlerRecordTests.java │ │ ├── DefaultErrorHandlerSeekAfterCommitExceptionBatchAckTests.java │ │ ├── DefaultErrorHandlerSeekAfterCommitExceptionBatchListenerTests.java │ │ ├── DefaultErrorHandlerSeekAfterCommitExceptionTests.java │ │ ├── DeliveryAttemptAwareRetryListenerIntegrationTests.java │ │ ├── DeliveryAttemptAwareRetryListenerTests.java │ │ ├── ErrorHandlingCoverageTests.java │ │ ├── ErrorHandlingDeserializerTests.java │ │ ├── ErrorHandlingUtilsTest.java │ │ ├── ExceptionClassifierTests.java │ │ ├── FailedBatchProcessorTests.java │ │ ├── FailedRecordProcessorTests.java │ │ ├── FailedRecordTrackerTests.java │ │ ├── FallbackBatchErrorHandlerIntegrationTests.java │ │ ├── FallbackBatchErrorHandlerTests.java │ │ ├── HeaderMethodArgumentResolverTests.java │ │ ├── KafkaListenerEndpointRegistryLifecycleTests.java │ │ ├── KafkaMessageListenerContainerTests.java │ │ ├── ListenerContainerPauseServiceTests.java │ │ ├── ListenerErrorHandlerTests.java │ │ ├── ListenerUtilsTests.java │ │ ├── LoggingErrorHandlerTests.java │ │ ├── ManualAckPartialBatchTests.java │ │ ├── ManualAssignmentInitialSeekTests.java │ │ ├── ManualImmediateNackBatchTests.java │ │ ├── ManualNackBatchTests.java │ │ ├── ManualNackBatchTxTests.java │ │ ├── ManualNackPauseResumeTests.java │ │ ├── ManualNackRecordTests.java │ │ ├── ManualNackRecordZeroSleepTests.java │ │ ├── MissingGroupIdTests.java │ │ ├── MissingTopicCheckOverrideAdminConfigTests.java │ │ ├── MissingTopicsTests.java │ │ ├── MockConsumerTests.java │ │ ├── PauseContainerManualAssignmentTests.java │ │ ├── PauseContainerWhileErrorHandlerIsRetryingTests.java │ │ ├── RemainingRecordsErrorHandlerTests.java │ │ ├── SeekToCurrentOnErrorBatchModeTXTests.java │ │ ├── SeekToCurrentOnErrorBatchModeTests.java │ │ ├── SeekToCurrentOnErrorRecordModeTXTests.java │ │ ├── SeekToCurrentOnErrorRecordModeTests.java │ │ ├── SeekToCurrentRecovererTests.java │ │ ├── SubBatchPerPartitionTests.java │ │ ├── SubBatchPerPartitionTxRollbackTests.java │ │ ├── SubBatchPerPartitionTxTests.java │ │ ├── TestOOMError.java │ │ ├── TransactionalContainerTests.java │ │ └── adapter │ │ │ ├── BatchAdapterConversionErrorsTests.java │ │ │ ├── BatchListenerWithRecordAdapterTests.java │ │ │ ├── BatchMessagingMessageListenerAdapterTests.java │ │ │ ├── ConvertingMessageListenerTests.java │ │ │ ├── FilteringAdapterTests.java │ │ │ ├── KafkaBackoffAwareMessageListenerAdapterTests.java │ │ │ └── MessagingMessageListenerAdapterTests.java │ │ ├── requestreply │ │ ├── CorrelationKeyTests.java │ │ └── ReplyingKafkaTemplateTests.java │ │ ├── retrytopic │ │ ├── AsyncCompletableFutureRetryTopicClassLevelIntegrationTests.java │ │ ├── AsyncCompletableFutureRetryTopicScenarioTests.java │ │ ├── AsyncMonoFutureRetryTopicClassLevelIntegrationTests.java │ │ ├── AsyncMonoRetryTopicScenarioTests.java │ │ ├── BackOffValuesGeneratorTests.java │ │ ├── CircularDltHandlerTests.java │ │ ├── DeadLetterPublishingRecovererFactoryTests.java │ │ ├── DefaultDestinationTopicProcessorTests.java │ │ ├── DefaultDestinationTopicResolverTests.java │ │ ├── DeliveryHeaderTests.java │ │ ├── DestinationTopicPropertiesFactoryTests.java │ │ ├── DestinationTopicTests.java │ │ ├── DltStartupTests.java │ │ ├── EndpointCustomizerFactoryTests.java │ │ ├── ExistingRetryTopicClassLevelIntegrationTests.java │ │ ├── ExistingRetryTopicIntegrationTests.java │ │ ├── ListenerContainerFactoryConfigurerTests.java │ │ ├── ListenerContainerFactoryResolverTests.java │ │ ├── PartitionResolverTests.java │ │ ├── RetryTopicClassLevelExceptionRoutingIntegrationTests.java │ │ ├── RetryTopicClassLevelIntegrationTests.java │ │ ├── RetryTopicConfigurationBuilderTests.java │ │ ├── RetryTopicConfigurationIntegrationTests.java │ │ ├── RetryTopicConfigurationManualAssignmentIntegrationTests.java │ │ ├── RetryTopicConfigurationProviderTests.java │ │ ├── RetryTopicConfigurationSupportTests.java │ │ ├── RetryTopicConfigurerTests.java │ │ ├── RetryTopicConstantsTests.java │ │ ├── RetryTopicExceptionRoutingIntegrationTests.java │ │ ├── RetryTopicHeadersTests.java │ │ ├── RetryTopicIntegrationTests.java │ │ ├── RetryTopicSameContainerFactoryIntegrationTests.java │ │ ├── RetryableTopicAnnotationProcessorTests.java │ │ └── TestClockUtils.java │ │ ├── security │ │ └── jaas │ │ │ └── KafkaJaasLoginModuleInitializerTests.java │ │ ├── streams │ │ ├── Configurer1Tests.java │ │ ├── Configurer2Tests.java │ │ ├── HeaderEnricherProcessorTests.java │ │ ├── KafkaStreamsBranchTests.java │ │ ├── KafkaStreamsInteractiveQueryServiceTests.java │ │ ├── KafkaStreamsJsonSerializationTests.java │ │ ├── KafkaStreamsTests.java │ │ ├── RecoveringDeserializationExceptionHandlerTests.java │ │ └── messaging │ │ │ └── MessagingProcessorTests.java │ │ └── support │ │ ├── DefaultKafkaHeaderMapperTests.java │ │ ├── ExponentialBackOffWithMaxRetriesTests.java │ │ ├── KafkaStreamBrancherTests.java │ │ ├── LogIfLevelEnabledTests.java │ │ ├── LoggingProducerListenerTests.java │ │ ├── SimpleKafkaHeaderMapperTests.java │ │ ├── TopicPartitionOffsetTests.java │ │ ├── converter │ │ ├── BatchMessageConverterTests.java │ │ ├── MessagingMessageConverterTests.java │ │ └── ProjectingMessageConverterTests.java │ │ ├── micrometer │ │ ├── KafkaListenerObservationTests.java │ │ ├── MicrometerHolderTests.java │ │ ├── MicrometerMetricsTests.java │ │ ├── ObservationIntegrationTests.java │ │ └── ObservationTests.java │ │ ├── serializer │ │ ├── DelegatingByTopicSerializationTests.java │ │ ├── DelegatingSerializationTests.java │ │ ├── JsonSerdeTests.java │ │ ├── JsonSerializationTests.java │ │ ├── RetryingDeserializerTests.java │ │ ├── SerializationIntegrationTests.java │ │ ├── SerializationTestUtils.java │ │ ├── SerializationUtilsTests.java │ │ ├── StringOrBytesSerializerTests.java │ │ ├── ToStringSerializationTests.java │ │ └── testentities │ │ │ └── DummyEntity.java │ │ └── transaction │ │ └── ResourcelessTransactionManager.java │ ├── kotlin │ └── org │ │ └── springframework │ │ └── kafka │ │ ├── core │ │ └── KotlinProducerFactoryTests.kt │ │ └── listener │ │ ├── EnableKafkaKotlinCoroutinesTests.kt │ │ └── EnableKafkaKotlinTests.kt │ └── resources │ ├── broker.properties │ ├── jaas-sample-kafka-only.conf │ └── log4j2-test.xml └── src ├── api └── overview.html ├── checkstyle ├── checkstyle-header.txt ├── checkstyle-suppressions.xml └── checkstyle.xml ├── dist └── notice.txt └── idea └── spring-framework.xml /.editorconfig: -------------------------------------------------------------------------------- 1 | root=true 2 | 3 | [*.java] 4 | indent_style = tab 5 | indent_size = 4 6 | continuation_indent_size = 8 7 | 8 | [*.xml] 9 | indent_style = tab 10 | indent_size = 4 11 | continuation_indent_size = 8 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'type: bug, status: waiting-for-triage' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **In what version(s) of Spring for Apache Kafka are you seeing this issue?** 11 | 12 | For example: 13 | 14 | 2.8.2 15 | 16 | Between 2.7.0 and 2.8.2 17 | 18 | **Describe the bug** 19 | 20 | A clear and concise description of what the bug is. 21 | Do not create an issue to ask a question; see below. 22 | 23 | **To Reproduce** 24 | 25 | Steps to reproduce the behavior. 26 | 27 | **Expected behavior** 28 | 29 | A clear and concise description of what you expected to happen. 30 | 31 | **Sample** 32 | 33 | A link to a GitHub repository with a [minimal, reproducible, sample](https://stackoverflow.com/help/minimal-reproducible-example). 34 | 35 | Reports that include a sample will take priority over reports that do not. 36 | At times, we may require a sample, so it is good to try and include a sample up front. 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Community Support 4 | url: https://stackoverflow.com/questions/tagged/spring-kafka 5 | about: Please ask and answer questions on StackOverflow with the tag spring-kafka, or use the Discussions tab above 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 'status: waiting-for-triage, type: enhancement' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Expected Behavior** 11 | 12 | 13 | 14 | **Current Behavior** 15 | 16 | 17 | 18 | **Context** 19 | 20 | 26 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /.github/dco.yml: -------------------------------------------------------------------------------- 1 | require: 2 | members: false 3 | -------------------------------------------------------------------------------- /.github/workflows/announce-milestone-planning.yml: -------------------------------------------------------------------------------- 1 | name: Announce Milestone Planning in Chat 2 | 3 | on: 4 | milestone: 5 | types: [ created, edited ] 6 | 7 | jobs: 8 | announce-milestone-planning: 9 | uses: spring-io/spring-github-workflows/.github/workflows/spring-announce-milestone-planning.yml@v5 10 | secrets: 11 | SPRING_RELEASE_CHAT_WEBHOOK_URL: ${{ secrets.SPRING_RELEASE_GCHAT_WEBHOOK_URL }} 12 | -------------------------------------------------------------------------------- /.github/workflows/auto-cherry-pick.yml: -------------------------------------------------------------------------------- 1 | name: Auto Cherry-Pick 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - '*.x' 8 | 9 | jobs: 10 | cherry-pick-commit: 11 | uses: spring-io/spring-github-workflows/.github/workflows/spring-cherry-pick.yml@v5 12 | secrets: 13 | GH_ACTIONS_REPO_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/backport-issue.yml: -------------------------------------------------------------------------------- 1 | name: Backport Issue 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*.x' 7 | 8 | jobs: 9 | backport-issue: 10 | uses: spring-io/spring-github-workflows/.github/workflows/spring-backport-issue.yml@v5 11 | secrets: 12 | GH_ACTIONS_REPO_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/ci-snapshot.yml: -------------------------------------------------------------------------------- 1 | name: CI SNAPSHOT 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | push: 7 | branches: 8 | - main 9 | - '*.x' 10 | 11 | schedule: 12 | - cron: '0 5 * * *' 13 | 14 | concurrency: 15 | group: group-snapshot-for-${{ github.ref }} 16 | cancel-in-progress: true 17 | 18 | jobs: 19 | build-snapshot: 20 | uses: spring-io/spring-github-workflows/.github/workflows/spring-artifactory-gradle-snapshot.yml@main 21 | with: 22 | gradleTasks: ${{ github.event_name == 'schedule' && '--rerun-tasks' || '' }} 23 | secrets: 24 | DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} 25 | ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} 26 | ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} 27 | -------------------------------------------------------------------------------- /.github/workflows/deploy-docs.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*.x' 7 | - main 8 | tags: 9 | - '**' 10 | 11 | workflow_dispatch: 12 | 13 | permissions: 14 | actions: write 15 | 16 | jobs: 17 | dispatch-docs-build: 18 | if: github.repository_owner == 'spring-projects' 19 | uses: spring-io/spring-github-workflows/.github/workflows/spring-dispatch-docs-build.yml@v5 20 | -------------------------------------------------------------------------------- /.github/workflows/merge-dependabot-pr.yml: -------------------------------------------------------------------------------- 1 | name: Merge Dependabot PR 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | - '*.x' 8 | 9 | run-name: Merge Dependabot PR ${{ github.ref_name }} 10 | 11 | jobs: 12 | merge-dependabot-pr: 13 | permissions: write-all 14 | 15 | uses: spring-io/spring-github-workflows/.github/workflows/spring-merge-dependabot-pr.yml@main 16 | with: 17 | mergeArguments: --auto --squash 18 | autoMergeSnapshots: true 19 | -------------------------------------------------------------------------------- /.github/workflows/pr-build.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request Build 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | - '*.x' 8 | 9 | jobs: 10 | build-pull-request: 11 | uses: spring-io/spring-github-workflows/.github/workflows/spring-gradle-pull-request-build.yml@main 12 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | run-name: Release current version for branch ${{ github.ref_name }} 7 | 8 | jobs: 9 | release: 10 | permissions: 11 | actions: write 12 | contents: write 13 | issues: write 14 | 15 | uses: spring-io/spring-github-workflows/.github/workflows/spring-artifactory-gradle-release.yml@main 16 | with: 17 | deployMilestoneToCentral: true 18 | secrets: 19 | GH_ACTIONS_REPO_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }} 20 | DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} 21 | JF_ARTIFACTORY_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }} 22 | ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} 23 | ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} 24 | OSSRH_S01_TOKEN_USERNAME: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }} 25 | OSSRH_S01_TOKEN_PASSWORD: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }} 26 | OSSRH_STAGING_PROFILE_NAME: ${{ secrets.OSSRH_STAGING_PROFILE_NAME }} 27 | GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} 28 | GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} 29 | SPRING_RELEASE_CHAT_WEBHOOK_URL: ${{ secrets.SPRING_RELEASE_GCHAT_WEBHOOK_URL }} 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.ipr 3 | *.iws 4 | .classpath 5 | .gradle 6 | .idea 7 | .project 8 | .settings 9 | .sts4-cache 10 | .checkstyle 11 | bin 12 | build 13 | out 14 | target 15 | .DS_Store 16 | .vscode 17 | 18 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version=4.0.0-SNAPSHOT 2 | org.gradle.jvmargs=-Xmx1536M -Dfile.encoding=UTF-8 3 | org.gradle.caching=true 4 | org.gradle.parallel=true 5 | kotlin.stdlib.default.dependency=false 6 | #kotlin.jvm.target.validation.mode = IGNORE 7 | -------------------------------------------------------------------------------- /gradle/publish-maven.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'maven-publish' 2 | 3 | publishing { 4 | publications { 5 | mavenJava(MavenPublication) { 6 | pom { 7 | afterEvaluate { 8 | name = project.description 9 | description = project.description 10 | } 11 | url = linkScmUrl 12 | organization { 13 | name = 'Spring IO' 14 | url = 'https://spring.io/projects/spring-kafka' 15 | } 16 | licenses { 17 | license { 18 | name = 'Apache License, Version 2.0' 19 | url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' 20 | distribution = 'repo' 21 | } 22 | } 23 | scm { 24 | url = linkScmUrl 25 | connection = linkScmConnection 26 | developerConnection = linkScmDevConnection 27 | } 28 | developers { 29 | developer { 30 | id = 'sobychacko' 31 | name = 'Soby Chacko' 32 | email = 'soby.chacko@broadcom.com' 33 | roles = ['project lead'] 34 | } 35 | developer { 36 | id = 'garyrussell' 37 | name = 'Gary Russell' 38 | email = 'github@gprussell.net' 39 | roles = ['project founder and project lead emeritus'] 40 | } 41 | developer { 42 | id = 'artembilan' 43 | name = 'Artem Bilan' 44 | email = 'artem.bilan@broadcom.com' 45 | roles = ['contributor'] 46 | } 47 | } 48 | issueManagement { 49 | system = 'GitHub' 50 | url = linkIssue 51 | } 52 | } 53 | versionMapping { 54 | usage('java-api') { 55 | fromResolutionResult() 56 | } 57 | usage('java-runtime') { 58 | fromResolutionResult() 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-projects/spring-kafka/fd0b0db0fe75ab4b0c4a9ac3fc8d7ad2a76703fc/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionSha256Sum=8d97a97984f6cbd2b85fe4c60a743440a347544bf18818048e611f5288d46c94 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /samples/README.adoc: -------------------------------------------------------------------------------- 1 | == Samples 2 | 3 | * sample-01 - Simple producer/consumer with dead-letter topic 4 | * sample-02 - Multi-method listener 5 | * sample-03 - Transactions 6 | * sample-04 - Topic based (non-blocking) retry 7 | * sample-05 - Global embedded Kafka testing 8 | * sample-06 - Kafka Streams tests with TopologyTestDriver 9 | * sample-07 - The New consumer rebalance protocol in spring-kafka 10 | * sample-08 - The Micrometer observation propagation from `KafkaTemplate` to `@KafkaListener` 11 | -------------------------------------------------------------------------------- /samples/sample-01/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /samples/sample-01/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-projects/spring-kafka/fd0b0db0fe75ab4b0c4a9ac3fc8d7ad2a76703fc/samples/sample-01/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /samples/sample-01/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /samples/sample-01/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | kafka-sample-01 8 | 3.2.0-SNAPSHOT 9 | jar 10 | 11 | kafka-sample-01 12 | Kafka Sample 1 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 3.2.5 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 17 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.kafka 31 | spring-kafka 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-web 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-maven-plugin 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /samples/sample-01/src/main/java/com/common/Foo1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common; 18 | 19 | /** 20 | * @author Gary Russell 21 | * @since 2.2.1 22 | * 23 | */ 24 | public class Foo1 { 25 | 26 | private String foo; 27 | 28 | public Foo1() { 29 | } 30 | 31 | public Foo1(String foo) { 32 | this.foo = foo; 33 | } 34 | 35 | public String getFoo() { 36 | return this.foo; 37 | } 38 | 39 | public void setFoo(String foo) { 40 | this.foo = foo; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "Foo1 [foo=" + this.foo + "]"; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /samples/sample-01/src/main/java/com/common/Foo2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common; 18 | 19 | /** 20 | * @author Gary Russell 21 | * @since 2.2.1 22 | * 23 | */ 24 | public class Foo2 { 25 | 26 | private String foo; 27 | 28 | public Foo2() { 29 | } 30 | 31 | public Foo2(String foo) { 32 | this.foo = foo; 33 | } 34 | 35 | public String getFoo() { 36 | return this.foo; 37 | } 38 | 39 | public void setFoo(String foo) { 40 | this.foo = foo; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "Foo2 [foo=" + this.foo + "]"; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /samples/sample-01/src/main/java/com/example/Controller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example; 18 | 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.kafka.core.KafkaTemplate; 21 | import org.springframework.web.bind.annotation.PathVariable; 22 | import org.springframework.web.bind.annotation.PostMapping; 23 | import org.springframework.web.bind.annotation.RestController; 24 | 25 | import com.common.Foo1; 26 | 27 | /** 28 | * @author Gary Russell 29 | * @since 2.2.1 30 | */ 31 | @RestController 32 | public class Controller { 33 | 34 | @Autowired 35 | private KafkaTemplate template; 36 | 37 | @PostMapping(path = "/send/foo/{what}") 38 | public void sendFoo(@PathVariable String what) { 39 | this.template.send("topic1", new Foo1(what)); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /samples/sample-01/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | kafka: 3 | producer: 4 | value-serializer: org.springframework.kafka.support.serializer.JsonSerializer 5 | consumer: 6 | value-deserializer: org.apache.kafka.common.serialization.ByteArrayDeserializer 7 | -------------------------------------------------------------------------------- /samples/sample-01/src/test/java/com/example/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example; 18 | 19 | import org.junit.jupiter.api.Test; 20 | 21 | import org.springframework.boot.test.context.SpringBootTest; 22 | import org.springframework.test.context.TestPropertySource; 23 | 24 | @SpringBootTest 25 | @TestPropertySource(properties = "spring.profiles.active=test") 26 | public class ApplicationTests { 27 | 28 | @Test 29 | public void contextLoads() { 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /samples/sample-02/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /samples/sample-02/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-projects/spring-kafka/fd0b0db0fe75ab4b0c4a9ac3fc8d7ad2a76703fc/samples/sample-02/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /samples/sample-02/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /samples/sample-02/README.adoc: -------------------------------------------------------------------------------- 1 | == Sample 2 2 | 3 | This sample demonstrates a simple producer and a multi-method consumer; the producer sends objects of types `Foo1` and `Bar1` and the consumer receives objects of type `Foo2` and `Bar2` (the objects have the same field, `foo`). 4 | 5 | The producer uses a `JsonSerializer`; the consumer uses a `ByteArrayDeserializer`, together with a `ByteArrayJsonMessageConverter` which converts to the required type of the listener method argument. 6 | We can't infer the type in this case (because the type is used to choose the method to call). 7 | We therefore configure type mapping on the producer and consumer side. 8 | See the `application.yml` for the producer side and the `converter` bean on the consumer side. 9 | 10 | The `MultiMethods` `@KafkaListener` has 3 methods; one for each of the known objects and a fallback default method for others. 11 | 12 | Run the application and use curl to send some data: 13 | 14 | `$ curl -X POST http://localhost:8080/send/foo/bar` 15 | 16 | `$ curl -X POST http://localhost:8080/send/bar/baz` 17 | 18 | `$ curl -X POST http://localhost:8080/send/unknown/xxx` 19 | 20 | Console: 21 | 22 | `Received: Foo2 [foo=bar]` 23 | `Received: Bar2 [bar=baz]` 24 | `Received unknown: xxx` 25 | 26 | 27 | -------------------------------------------------------------------------------- /samples/sample-02/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | kafka-sample-02 8 | 3.2.0-SNAPSHOT 9 | jar 10 | 11 | kafka-sample-02 12 | Kafka Sample 2 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 3.2.5 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 17 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.kafka 31 | spring-kafka 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-web 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-maven-plugin 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /samples/sample-02/src/main/java/com/common/Bar1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common; 18 | 19 | /** 20 | * @author Gary Russell 21 | * @since 2.2.1 22 | * 23 | */ 24 | public class Bar1 { 25 | 26 | public String bar; 27 | 28 | public Bar1() { 29 | } 30 | 31 | public Bar1(String bar) { 32 | this.bar = bar; 33 | } 34 | 35 | public String getBar() { 36 | return this.bar; 37 | } 38 | 39 | public void setBar(String bar) { 40 | this.bar = bar; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "Bar1 [bar=" + this.bar + "]"; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /samples/sample-02/src/main/java/com/common/Bar2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common; 18 | 19 | /** 20 | * @author Gary Russell 21 | * @since 2.2.1 22 | * 23 | */ 24 | public class Bar2 { 25 | 26 | public String bar; 27 | 28 | public Bar2() { 29 | } 30 | 31 | public Bar2(String bar) { 32 | this.bar = bar; 33 | } 34 | 35 | public String getBar() { 36 | return this.bar; 37 | } 38 | 39 | public void setBar(String bar) { 40 | this.bar = bar; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "Bar2 [bar=" + this.bar + "]"; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /samples/sample-02/src/main/java/com/common/Foo1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common; 18 | 19 | /** 20 | * @author Gary Russell 21 | * @since 5.1 22 | * 23 | */ 24 | public class Foo1 { 25 | 26 | private String foo; 27 | 28 | public Foo1() { 29 | } 30 | 31 | public Foo1(String foo) { 32 | this.foo = foo; 33 | } 34 | 35 | public String getFoo() { 36 | return this.foo; 37 | } 38 | 39 | public void setFoo(String foo) { 40 | this.foo = foo; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "Foo1 [foo=" + this.foo + "]"; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /samples/sample-02/src/main/java/com/common/Foo2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common; 18 | 19 | /** 20 | * @author Gary Russell 21 | * @since 5.1 22 | * 23 | */ 24 | public class Foo2 { 25 | 26 | private String foo; 27 | 28 | public Foo2() { 29 | } 30 | 31 | public Foo2(String foo) { 32 | this.foo = foo; 33 | } 34 | 35 | public String getFoo() { 36 | return this.foo; 37 | } 38 | 39 | public void setFoo(String foo) { 40 | this.foo = foo; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "Foo2 [foo=" + this.foo + "]"; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /samples/sample-02/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | kafka: 3 | producer: 4 | value-serializer: org.springframework.kafka.support.serializer.JsonSerializer 5 | properties: 6 | "[spring.json.type.mapping]": foo:com.common.Foo1,bar:com.common.Bar1 7 | consumer: 8 | value-deserializer: org.apache.kafka.common.serialization.ByteArrayDeserializer 9 | -------------------------------------------------------------------------------- /samples/sample-02/src/test/java/com/example/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example; 18 | 19 | import org.junit.jupiter.api.Test; 20 | 21 | import org.springframework.boot.test.context.SpringBootTest; 22 | import org.springframework.test.context.TestPropertySource; 23 | 24 | @SpringBootTest 25 | @TestPropertySource(properties = "spring.profiles.active=test") 26 | public class ApplicationTests { 27 | 28 | @Test 29 | public void contextLoads() { 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /samples/sample-03/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /samples/sample-03/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-projects/spring-kafka/fd0b0db0fe75ab4b0c4a9ac3fc8d7ad2a76703fc/samples/sample-03/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /samples/sample-03/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /samples/sample-03/README.adoc: -------------------------------------------------------------------------------- 1 | == Sample 3 2 | 3 | This sample demonstrates the use of transactions, including container-managed transactions on the consumer side. 4 | The listener receives a batch of messages and sends them to another topic, all within one transaction. 5 | 6 | Run the application and use curl to send some data: 7 | 8 | `$ curl -X POST http://localhost:8080/send/foos/a,b,c,d,e` 9 | 10 | Console: 11 | 12 | [source, bash] 13 | ---- 14 | 2018-11-05 11:50:29.244 INFO 60437 --- [fooGroup2-0-C-1] com.example.Application : Received: [Foo2 [foo=a], Foo2 [foo=b], Foo2 [foo=c], Foo2 [foo=d], Foo2 [foo=e]] 15 | 16 | 2018-11-05 11:50:29.247 INFO 60437 --- [fooGroup2-0-C-1] com.example.Application : Messages sent, hit enter to commit tx 17 | 18 | 2018-11-05 11:50:33.045 INFO 60437 --- [fooGroup3-0-C-1] com.example.Application : Received: [A, B, C, D, E] 19 | ---- 20 | 21 | 22 | -------------------------------------------------------------------------------- /samples/sample-03/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | kafka-sample-03 8 | 3.2.0-SNAPSHOT 9 | jar 10 | 11 | kafka-sample-03 12 | Kafka Sample 3 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 3.2.5 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 17 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.kafka 31 | spring-kafka 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-web 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-maven-plugin 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /samples/sample-03/src/main/java/com/common/Foo1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common; 18 | 19 | /** 20 | * @author Gary Russell 21 | * @since 2.2.1 22 | * 23 | */ 24 | public class Foo1 { 25 | 26 | private String foo; 27 | 28 | public Foo1() { 29 | } 30 | 31 | public Foo1(String foo) { 32 | this.foo = foo; 33 | } 34 | 35 | public String getFoo() { 36 | return this.foo; 37 | } 38 | 39 | public void setFoo(String foo) { 40 | this.foo = foo; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "Foo1 [foo=" + this.foo + "]"; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /samples/sample-03/src/main/java/com/common/Foo2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common; 18 | 19 | /** 20 | * @author Gary Russell 21 | * @since 2.2.1 22 | * 23 | */ 24 | public class Foo2 { 25 | 26 | private String foo; 27 | 28 | public Foo2() { 29 | } 30 | 31 | public Foo2(String foo) { 32 | this.foo = foo; 33 | } 34 | 35 | public String getFoo() { 36 | return this.foo; 37 | } 38 | 39 | public void setFoo(String foo) { 40 | this.foo = foo; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "Foo2 [foo=" + this.foo + "]"; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /samples/sample-03/src/main/java/com/example/Controller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example; 18 | 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.kafka.core.KafkaTemplate; 21 | import org.springframework.util.StringUtils; 22 | import org.springframework.web.bind.annotation.PathVariable; 23 | import org.springframework.web.bind.annotation.PostMapping; 24 | import org.springframework.web.bind.annotation.RestController; 25 | 26 | import com.common.Foo1; 27 | 28 | /** 29 | * @author Gary Russell 30 | * @since 2.2.1 31 | */ 32 | @RestController 33 | public class Controller { 34 | 35 | @Autowired 36 | private KafkaTemplate template; 37 | 38 | @PostMapping(path = "/send/foos/{what}") 39 | public void sendFoo(@PathVariable String what) { 40 | this.template.executeInTransaction(kafkaTemplate -> { 41 | StringUtils.commaDelimitedListToSet(what).stream() 42 | .map(s -> new Foo1(s)) 43 | .forEach(foo -> kafkaTemplate.send("topic2", foo)); 44 | return null; 45 | }); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /samples/sample-03/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | kafka: 3 | producer: 4 | value-serializer: org.springframework.kafka.support.serializer.JsonSerializer 5 | transaction-id-prefix: tx. 6 | consumer: 7 | value-deserializer: org.apache.kafka.common.serialization.ByteArrayDeserializer 8 | properties: 9 | isolation.level: read_committed 10 | listener: 11 | type: batch 12 | -------------------------------------------------------------------------------- /samples/sample-03/src/test/java/com/example/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example; 18 | 19 | import org.junit.jupiter.api.Test; 20 | 21 | import org.springframework.boot.test.context.SpringBootTest; 22 | 23 | @SpringBootTest 24 | public class ApplicationTests { 25 | 26 | @Test 27 | public void contextLoads() { 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /samples/sample-04/README.adoc: -------------------------------------------------------------------------------- 1 | == Sample 4 2 | 3 | This sample demonstrates non-blocking retry (`@RetryableTopic`) with a simple producer and consumer; the producer sends Strings posted to the rest controller. 4 | 5 | Strings starting with `fail` are rejected and retried. 6 | 7 | Run the application and use curl to send some data: 8 | 9 | `$ curl -X POST http://localhost:8080/send/fail; curl -X POST http://localhost:8080/send/good` 10 | 11 | Console: 12 | 13 | [source, bash] 14 | ---- 15 | 16 | 2021-05-11 16:17:55.372 INFO 75520 --- [ fooGroup-0-C-1] com.example.Application : Received: fail from topic4 @ xx 17 | 18 | 2021-05-11 16:17:55.399 INFO 75520 --- [ fooGroup-0-C-1] com.example.Application : Received: good from topic4 @ xx 19 | 20 | 2021-05-11 16:17:57.384 INFO 75520 --- [etry-2000-0-C-1] com.example.Application : Received: fail from topic4-retry-2000 @ xx 21 | 22 | 2021-05-11 16:18:01.390 INFO 75520 --- [etry-4000-0-C-1] com.example.Application : Received: fail from topic4-retry-4000 @ xx 23 | 24 | 2021-05-11 16:18:09.399 INFO 75520 --- [etry-8000-0-C-1] com.example.Application : Received: fail from topic4-retry-8000 @ xx 25 | 26 | 2021-05-11 16:18:19.407 INFO 75520 --- [try-10000-0-C-1] com.example.Application : Received: fail from topic4-retry-10000 @ xx 27 | 28 | 2021-05-11 16:18:19.918 INFO 75520 --- [Group-dlt-0-C-1] com.example.Application : DLT Received: fail from topic4-dlt @ xx 29 | ---- 30 | 31 | As you can see the "good" record is processed while the failed record is retried by the series of retry topics. 32 | -------------------------------------------------------------------------------- /samples/sample-04/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | kafka-sample-04 8 | 3.2.0-SNAPSHOT 9 | jar 10 | 11 | kafka-sample-04 12 | Kafka Sample 4 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 3.2.5 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 17 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.kafka 31 | spring-kafka 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-web 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-maven-plugin 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /samples/sample-04/src/main/java/com/example/Controller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example; 18 | 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.kafka.core.KafkaTemplate; 21 | import org.springframework.web.bind.annotation.PathVariable; 22 | import org.springframework.web.bind.annotation.PostMapping; 23 | import org.springframework.web.bind.annotation.RestController; 24 | 25 | /** 26 | * @author Gary Russell 27 | * @since 2.2.1 28 | */ 29 | @RestController 30 | public class Controller { 31 | 32 | @Autowired 33 | private KafkaTemplate template; 34 | 35 | @PostMapping(path = "/send/{what}") 36 | public void sendFoo(@PathVariable String what) { 37 | this.template.send("topic4", what); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /samples/sample-04/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.root=off 2 | logging.level.com.example=info 3 | #logging.level.org.springframework.kafka=error 4 | -------------------------------------------------------------------------------- /samples/sample-04/src/test/java/com/example/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example; 18 | 19 | import org.junit.jupiter.api.Test; 20 | 21 | import org.springframework.boot.test.context.SpringBootTest; 22 | import org.springframework.test.context.TestPropertySource; 23 | 24 | @SpringBootTest 25 | @TestPropertySource(properties = "spring.profiles.active=test") 26 | public class ApplicationTests { 27 | 28 | @Test 29 | public void contextLoads() { 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /samples/sample-05/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /samples/sample-05/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-projects/spring-kafka/fd0b0db0fe75ab4b0c4a9ac3fc8d7ad2a76703fc/samples/sample-05/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /samples/sample-05/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar 3 | -------------------------------------------------------------------------------- /samples/sample-05/src/main/java/com/example/Sample05Application.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example; 18 | 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.SpringBootApplication; 21 | import org.springframework.kafka.annotation.KafkaListener; 22 | 23 | /** 24 | * Plain Kafka listener sample which purpose is only to be used in the tests assertions. 25 | * See unit tests for this project for more information. 26 | * 27 | * @author Artem Bilan 28 | * 29 | * @since 3.0 30 | * 31 | */ 32 | @SpringBootApplication 33 | public class Sample05Application { 34 | 35 | public static void main(String[] args) { 36 | SpringApplication.run(Sample05Application.class, args); 37 | } 38 | 39 | @KafkaListener(id ="sampleListener", topics = "topic1") 40 | void listenForTopic(String payload) { 41 | System.out.println("Received: " + payload); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /samples/sample-05/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.kafka.producer.properties[max.block.ms]=1000 2 | spring.kafka.consumer.auto-offset-reset=earliest 3 | logging.level.root=error 4 | -------------------------------------------------------------------------------- /samples/sample-05/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | spring.kafka.embedded.topics=topic1,topic2 2 | -------------------------------------------------------------------------------- /samples/sample-05/src/test/resources/kafka-broker.properties: -------------------------------------------------------------------------------- 1 | auto.create.topics.enable=false 2 | -------------------------------------------------------------------------------- /samples/sample-05/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /samples/sample-06/src/main/java/com/example/Application.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example; 18 | 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | 22 | import org.springframework.boot.SpringApplication; 23 | import org.springframework.boot.autoconfigure.SpringBootApplication; 24 | import org.springframework.kafka.annotation.EnableKafkaStreams; 25 | 26 | /** 27 | * 28 | * @author Nacho Munoz 29 | * @since 3.2.0 30 | */ 31 | @EnableKafkaStreams 32 | @SpringBootApplication 33 | public class Application { 34 | 35 | private final Logger logger = LoggerFactory.getLogger(Application.class); 36 | 37 | public static void main(String[] args) { 38 | SpringApplication.run(Application.class, args); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /samples/sample-06/src/main/resources/application-test.properties: -------------------------------------------------------------------------------- 1 | logging.level.root=off 2 | logging.level.com.example=info 3 | 4 | bootstrap.servers= 5 | spring.kafka.properties.bootstrap.servers=${bootstrap.servers} 6 | spring.kafka.streams.application-id=Sample-06-Service-Test 7 | -------------------------------------------------------------------------------- /samples/sample-06/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.root=off 2 | logging.level.com.example=info 3 | 4 | spring.kafka.streams.application-id=Sample-06-Service 5 | -------------------------------------------------------------------------------- /samples/sample-06/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level.root: info 3 | input-topic: 4 | name: input 5 | output-topic: 6 | name: output 7 | -------------------------------------------------------------------------------- /samples/sample-07/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | -------------------------------------------------------------------------------- /samples/sample-07/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.springframework.boot' version '3.3.0-SNAPSHOT' 4 | id 'io.spring.dependency-management' version '1.1.5' 5 | } 6 | 7 | group = 'com.example' 8 | version = '3.2.0-SNAPSHOT' 9 | 10 | java { 11 | sourceCompatibility = '17' 12 | } 13 | 14 | repositories { 15 | mavenCentral() 16 | maven { url 'https://repo.spring.io/milestone' } 17 | maven { url 'https://repo.spring.io/snapshot' } 18 | } 19 | 20 | dependencies { 21 | implementation 'org.springframework.boot:spring-boot-starter' 22 | implementation 'org.springframework.kafka:spring-kafka' 23 | developmentOnly 'org.springframework.boot:spring-boot-docker-compose' 24 | } 25 | 26 | tasks.named('test') { 27 | useJUnitPlatform() 28 | } 29 | -------------------------------------------------------------------------------- /samples/sample-07/compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | broker: 4 | image: bitnami/kafka:3.7.0 5 | hostname: broker 6 | container_name: broker 7 | ports: 8 | - "9092:9092" 9 | - "10000:9094" 10 | environment: 11 | # Kraft Settings 12 | KAFKA_CFG_NODE_ID: 0 13 | KAFKA_KRAFT_CLUSTER_ID: HsDBs9l6UUmQq7Y5E6bNlw 14 | KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 0@localhost:9093 15 | KAFKA_CFG_PROCESS_ROLES: controller,broker 16 | 17 | # Listeners 18 | KAFKA_CFG_LISTENERS: INTERNAL://broker:29092, PLAINTEXT://0.0.0.0:9092, EXTERNAL://:9094, CONTROLLER://:9093 19 | KAFKA_CFG_ADVERTISED_LISTENERS: INTERNAL://broker:29092, PLAINTEXT://broker:9092, EXTERNAL://127.0.0.1:10000 20 | KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT,INTERNAL:PLAINTEXT 21 | KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER 22 | KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE: "true" 23 | KAFKA_CFG_INTER_BROKER_LISTENER_NAME: INTERNAL 24 | KAFKA_CFG_GROUP_INITIAL_REBALANCE_DELAY_MS: 0 25 | 26 | # Clustering 27 | KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR: 1 28 | KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 29 | KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 30 | KAFKA_CFG_DEFAULT_REPLICATION_FACTOR: 1 31 | 32 | # KIP-848 33 | KAFKA_CFG_GROUP_COORDINATOR_REBALANCE_PROTOCOLS: "classic,consumer" 34 | KAFKA_CFG_TRANSACTION_PARTITION_VERIFICATION_ENABLE: "false" 35 | -------------------------------------------------------------------------------- /samples/sample-07/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-projects/spring-kafka/fd0b0db0fe75ab4b0c4a9ac3fc8d7ad2a76703fc/samples/sample-07/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /samples/sample-07/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /samples/sample-07/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { url 'https://repo.spring.io/milestone' } 4 | maven { url 'https://repo.spring.io/snapshot' } 5 | gradlePluginPortal() 6 | } 7 | } 8 | 9 | rootProject.name = 'sample-07' 10 | -------------------------------------------------------------------------------- /samples/sample-07/src/main/java/com/example/sample07/Sample07Application.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.sample07; 18 | 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.SpringBootApplication; 21 | 22 | /** 23 | * New consumer rebalance protocol sample which purpose is only to demonstrate the application 24 | * of the New Consumer Rebalance Protocol in Spring Kafka. 25 | * 26 | * @author Sanghyeok An. 27 | * 28 | * @since 3.2.0 29 | */ 30 | 31 | @SpringBootApplication 32 | public class Sample07Application { 33 | 34 | public static void main(String[] args) { 35 | SpringApplication.run(Sample07Application.class, args); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /samples/sample-07/src/main/java/com/example/sample07/Sample07KafkaListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.sample07; 18 | 19 | import org.springframework.kafka.annotation.KafkaListener; 20 | import org.springframework.stereotype.Component; 21 | 22 | /** 23 | * New consumer rebalance protocol sample which purpose is only to demonstrate the application 24 | * of the New Consumer Rebalance Protocol in Spring Kafka. 25 | * Each consumer will subscribe test-topic with different group id. 26 | * Then, new consumer rebalance protocol will be completed successfully. 27 | * 28 | * @author Sanghyeok An. 29 | * 30 | * @since 3.2.0 31 | */ 32 | 33 | @Component 34 | public class Sample07KafkaListener { 35 | 36 | @KafkaListener(topics = "test-topic", groupId = "sample07-1") 37 | public void listenWithGroup1(String message) { 38 | System.out.println("Received message at group sample07-1: " + message); 39 | } 40 | 41 | @KafkaListener(topics = "test-topic", groupId = "sample07-2") 42 | public void listenWithGroup2(String message) { 43 | System.out.println("Received message at group sample07-2: " + message); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /samples/sample-07/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | docker: 3 | compose: 4 | lifecycle-management: start_and_stop 5 | start: 6 | command: up 7 | stop: 8 | command: down 9 | timeout: 10s 10 | kafka: 11 | consumer: 12 | bootstrap-servers: localhost:10000 13 | key-deserializer: org.apache.kafka.common.serialization.StringDeserializer 14 | value-deserializer: org.apache.kafka.common.serialization.StringDeserializer 15 | properties: 16 | group.protocol: consumer 17 | -------------------------------------------------------------------------------- /samples/sample-08/.gitattributes: -------------------------------------------------------------------------------- 1 | /gradlew text eol=lf 2 | *.bat text eol=crlf 3 | *.jar binary 4 | -------------------------------------------------------------------------------- /samples/sample-08/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | -------------------------------------------------------------------------------- /samples/sample-08/README.adoc: -------------------------------------------------------------------------------- 1 | == Sample 8 2 | 3 | This sample demonstrates the application with a Micrometer observation propagation from the producer to consumer over Apache Kafka broker. 4 | 5 | The configuration mostly rely on the Spring Boot auto-configuration for observability and Spring for Apache Kafka. 6 | In the `application.properties` we enable observation for the `KafkaTemplate` and `@KafkaListener` to have them both in the same trace id. 7 | The `KafkaTemplate` is configured for the `observation-topic` as a default topic. 8 | And the same property is used by `@KafkaListener` for its `topics` property. 9 | Then we configure consumer for required `group-id` and `offset-reset` as `earliest` to be able to consume the produced a bit earlier than the Kafka listener container start. 10 | 11 | In the `Sample08Application` we have a simple `@KafkaListener` POJO method to just log a `CosnumerRecord`. 12 | The `ProducerListener` is there for logging what was produced by the `KafkaTemplate`. 13 | And `ApplicationRunner` is to emit a data via `KafkaTemplate` when application is ready. 14 | 15 | When we run this application we can see in logs one message from producer and one from consumer and both those messages are correlated with the same trace id. 16 | 17 | The `Sample08ApplicationTests` starts an embedded Kafka broker and provides a `TestSpanHandler` bean for trace and span verifications. 18 | The single test in this class verifies that we have only two mentioned spans: one from the producer and one from the consumer. 19 | And that both those spans belong to the same trace id. -------------------------------------------------------------------------------- /samples/sample-08/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.springframework.boot' version '3.4.1' 4 | id 'io.spring.dependency-management' version '1.1.7' 5 | } 6 | 7 | group = 'com.example' 8 | version = '0.0.1-SNAPSHOT' 9 | 10 | java { 11 | toolchain { 12 | languageVersion = JavaLanguageVersion.of(17) 13 | } 14 | } 15 | 16 | repositories { 17 | mavenCentral() 18 | } 19 | 20 | dependencies { 21 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 22 | implementation 'io.micrometer:micrometer-tracing-bridge-brave' 23 | implementation 'org.springframework.kafka:spring-kafka' 24 | 25 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 26 | testImplementation 'org.springframework.kafka:spring-kafka-test' 27 | testImplementation('io.micrometer:micrometer-tracing-integration-test') { 28 | exclude group: 'io.opentelemetry' 29 | exclude group: 'com.wavefront' 30 | exclude group: 'io.micrometer', module: 'micrometer-tracing-bridge-otel' 31 | } 32 | 33 | testRuntimeOnly 'org.junit.platform:junit-platform-launcher' 34 | } 35 | 36 | tasks.named('test') { 37 | useJUnitPlatform() 38 | } 39 | -------------------------------------------------------------------------------- /samples/sample-08/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-projects/spring-kafka/fd0b0db0fe75ab4b0c4a9ac3fc8d7ad2a76703fc/samples/sample-08/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /samples/sample-08/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /samples/sample-08/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'sample-08' 2 | -------------------------------------------------------------------------------- /samples/sample-08/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=sample-08 2 | 3 | spring.kafka.template.observation-enabled=true 4 | spring.kafka.template.default-topic=observation-topic 5 | spring.kafka.listener.observation-enabled=true 6 | spring.kafka.consumer.group-id=observation-group 7 | spring.kafka.consumer.auto-offset-reset=earliest 8 | 9 | logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}] 10 | logging.level.root=error 11 | logging.level.com.example.sample08=info 12 | 13 | management.tracing.sampling.probability=1 14 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | plugins { 9 | id 'io.spring.develocity.conventions' version '0.0.22' 10 | id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0' 11 | } 12 | 13 | rootProject.name = 'spring-kafka-dist' 14 | 15 | rootDir.eachDir { dir -> 16 | if (dir.name.startsWith('spring-')) { 17 | include ":${dir.name}" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /spring-kafka-bom/spring-kafka-bom.txt: -------------------------------------------------------------------------------- 1 | This meta-project is used to generate a bill-of-materials POM that contains the other projects in a dependencyManagement section. 2 | -------------------------------------------------------------------------------- /spring-kafka-docs/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.antora' version '1.0.0' 3 | id 'io.spring.antora.generate-antora-yml' version '0.0.1' 4 | } 5 | 6 | apply from: "${rootDir}/gradle/docs.gradle" 7 | apply plugin: 'java' 8 | apply plugin: 'eclipse' 9 | apply plugin: 'idea' 10 | apply plugin: 'kotlin' 11 | apply plugin: 'kotlin-spring' 12 | 13 | description = 'Spring Kafka Code Snippets For Docs' 14 | 15 | dependencies { 16 | implementation "org.springframework.boot:spring-boot-starter:$springBootVersion" 17 | implementation project (':spring-kafka') 18 | implementation 'org.jetbrains.kotlin:kotlin-stdlib' 19 | implementation 'com.fasterxml.jackson.core:jackson-core' 20 | implementation 'com.fasterxml.jackson.core:jackson-databind' 21 | } 22 | 23 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/antora.yml: -------------------------------------------------------------------------------- 1 | name: kafka 2 | version: true 3 | title: Spring for Apache Kafka 4 | nav: 5 | - modules/ROOT/nav.adoc 6 | ext: 7 | collector: 8 | run: 9 | # FIXME Change "command" to the command that generates your antora.yml and other antora resources 10 | # See https://gitlab.com/antora/antora-collector-extension/-/blob/main/docs/modules/ROOT/pages/configuration-keys.adoc?ref_type=heads#collector-reference 11 | # HINT: Maven is typically something like: 12 | # ./mvnw validate process-resources -am -Pantora-process-resources 13 | command: gradlew :spring-kafka-docs:generateAntoraResources 14 | local: true 15 | scan: 16 | # FIXME Change "dir" to the location that generated files are at 17 | # See https://gitlab.com/antora/antora-collector-extension/-/blob/main/docs/modules/ROOT/pages/configuration-keys.adoc?ref_type=heads#collector-reference 18 | # HINT: Maven is typically something like: 19 | # target/classes/antora-resources/ 20 | dir: spring-kafka-docs/build/generated-antora-resources 21 | 22 | asciidoc: 23 | attributes: 24 | attribute-missing: 'warn' 25 | chomp: 'all' 26 | java-examples: example$java-examples/org/springframework/kafka/jdocs 27 | kotlin-examples: example$kotlin-examples/org/springframework/kafka/kdocs -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/examples/java-examples: -------------------------------------------------------------------------------- 1 | ../../../../java/ -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/examples/kotlin-examples: -------------------------------------------------------------------------------- 1 | ../../../../kotlin/ -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/appendix.adoc: -------------------------------------------------------------------------------- 1 | = Appendix 2 | 3 | 4 | 5 | [appendix] 6 | 7 | [appendix] 8 | 9 | 10 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/appendix/micrometer.adoc: -------------------------------------------------------------------------------- 1 | [[observation-gen]] 2 | = Micrometer Observation Documentation 3 | 4 | include::partial$metrics.adoc[leveloffset=-1] 5 | 6 | include::partial$spans.adoc[leveloffset=-1] 7 | 8 | include::partial$conventions.adoc[leveloffset=-1] 9 | 10 | 11 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/appendix/native-images.adoc: -------------------------------------------------------------------------------- 1 | [[native-images]] 2 | = Native Images 3 | 4 | {spring-framework-reference-url}/core/aot.html[Spring AOT] native hints are provided to assist in developing native images for Spring applications that use Spring for Apache Kafka, including hints for AVRO generated classes used in `@KafkaListener`+++s+++. 5 | 6 | IMPORTANT: `spring-kafka-test` (and, specifically, its `EmbeddedKafkaBroker`) is not supported in native images. 7 | 8 | Some examples can be seen in the https://github.com/spring-projects/spring-aot-smoke-tests/tree/main/integration[`spring-aot-smoke-tests` GitHub repository]. 9 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/index.adoc: -------------------------------------------------------------------------------- 1 | [[spring-kafka-reference]] 2 | = Overview 3 | :numbered: 4 | :icons: font 5 | :hide-uri-scheme: 6 | Gary Russell; Artem Bilan; Biju Kunjummen; Jay Bryant; Soby Chacko; Tomaz Fernandes 7 | 8 | *{project-version}* 9 | 10 | The Spring for Apache Kafka project applies core Spring concepts to the development of Kafka-based messaging solutions. 11 | We provide a "`template`" as a high-level abstraction for sending messages. 12 | We also provide support for Message-driven POJOs. 13 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/introduction.adoc: -------------------------------------------------------------------------------- 1 | [[introduction]] 2 | = Introduction 3 | 4 | This first part of the reference documentation is a high-level overview of Spring for Apache Kafka and the underlying concepts and some code snippets that can help you get up and running as quickly as possible. -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka.adoc: -------------------------------------------------------------------------------- 1 | [[kafka]] 2 | = Using Spring for Apache Kafka 3 | :page-section-summary-toc: 1 4 | 5 | This section offers detailed explanations of the various concerns that impact using Spring for Apache Kafka. 6 | For a quick but less detailed introduction, see xref:quick-tour.adoc[Quick Tour]. 7 | 8 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/kerberos.adoc: -------------------------------------------------------------------------------- 1 | [[kerberos]] 2 | = JAAS and Kerberos 3 | :page-section-summary-toc: 1 4 | 5 | Starting with version 2.0, a `KafkaJaasLoginModuleInitializer` class has been added to assist with Kerberos configuration. 6 | You can add this bean, with the desired configuration, to your application context. 7 | The following example configures such a bean: 8 | 9 | [source, java] 10 | ---- 11 | @Bean 12 | public KafkaJaasLoginModuleInitializer jaasConfig() throws IOException { 13 | KafkaJaasLoginModuleInitializer jaasConfig = new KafkaJaasLoginModuleInitializer(); 14 | jaasConfig.setControlFlag("REQUIRED"); 15 | Map options = new HashMap<>(); 16 | options.put("useKeyTab", "true"); 17 | options.put("storeKey", "true"); 18 | options.put("keyTab", "/etc/security/keytabs/kafka_client.keytab"); 19 | options.put("principal", "kafka-client-1@EXAMPLE.COM"); 20 | jaasConfig.setOptions(options); 21 | return jaasConfig; 22 | } 23 | ---- 24 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/pause-resume-partitions.adoc: -------------------------------------------------------------------------------- 1 | [[pause-resume-partitions]] 2 | = Pausing and Resuming Partitions on Listener Containers 3 | :page-section-summary-toc: 1 4 | 5 | Since version 2.7 you can pause and resume the consumption of specific partitions assigned to that consumer by using the `pausePartition(TopicPartition topicPartition)` and `resumePartition(TopicPartition topicPartition)` methods in the listener containers. 6 | The pausing and resuming take place respectively before and after the `poll()` similar to the `pause()` and `resume()` methods. 7 | The `isPartitionPauseRequested()` method returns true if pause for that partition has been requested. 8 | The `isPartitionPaused()` method returns true if that partition has effectively been paused. 9 | 10 | Also since version 2.7 `ConsumerPartitionPausedEvent` and `ConsumerPartitionResumedEvent` instances are published with the container as the `source` property and the `TopicPartition` instance. 11 | 12 | 13 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/receiving-messages.adoc: -------------------------------------------------------------------------------- 1 | [[receiving-messages]] 2 | = Receiving Messages 3 | :page-section-summary-toc: 1 4 | 5 | You can receive messages by configuring a `MessageListenerContainer` and providing a message listener or by using the `@KafkaListener` annotation. 6 | 7 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/receiving-messages/container-thread-naming.adoc: -------------------------------------------------------------------------------- 1 | [[container-thread-naming]] 2 | = Container Thread Naming 3 | :page-section-summary-toc: 1 4 | 5 | A `TaskExecutor` is used to invoke the consumer and the listener. 6 | You can provide a custom executor by setting the `consumerExecutor` property of the container's `ContainerProperties`. 7 | When using pooled executors, be sure that enough threads are available to handle the concurrency across all the containers in which they are used. 8 | When using the `ConcurrentMessageListenerContainer`, a thread from the executor is used for each consumer (`concurrency`). 9 | 10 | If you do not provide a consumer executor, a `SimpleAsyncTaskExecutor` is used for each container. 11 | This executor creates threads with names similar to `-C-`. 12 | For the `ConcurrentMessageListenerContainer`, the `` part of the thread name becomes `-m`, where `m` represents the consumer instance. 13 | `n` increments each time the container is started. 14 | So, with a bean name of `container`, threads in this container will be named `container-0-C-1`, `container-1-C-1` etc., after the container is started the first time; `container-0-C-2`, `container-1-C-2` etc., after a stop and subsequent start. 15 | 16 | Starting with version `3.0.1`, you can now change the name of the thread, regardless of which executor is used. 17 | Set the `AbstractMessageListenerContainer.changeConsumerThreadName` property to `true` and the `AbstractMessageListenerContainer.threadNameSupplier` will be invoked to obtain the thread name. 18 | This is a `Function`, with the default implementation returning `container.getListenerId()`. 19 | 20 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/receiving-messages/kafkalistener-attrs.adoc: -------------------------------------------------------------------------------- 1 | [[kafkalistener-attrs]] 2 | = `@KafkaListener` Attribute Modification 3 | 4 | Starting with version 2.7.2, you can now programmatically modify annotation attributes before the container is created. 5 | To do so, add one or more `KafkaListenerAnnotationBeanPostProcessor.AnnotationEnhancer` to the application context. 6 | `AnnotationEnhancer` is a `BiFunction, AnnotatedElement, Map` and must return a map of attributes. 7 | The attribute values can contain SpEL and/or property placeholders; the enhancer is called before any resolution is performed. 8 | If more than one enhancer is present, and they implement `Ordered`, they will be invoked in order. 9 | 10 | IMPORTANT: `AnnotationEnhancer` bean definitions must be declared `static` because they are required very early in the application context's lifecycle. 11 | 12 | An example follows: 13 | 14 | [source, java] 15 | ---- 16 | @Bean 17 | public static AnnotationEnhancer groupIdEnhancer() { 18 | return (attrs, element) -> { 19 | attrs.put("groupId", attrs.get("id") + "." + (element instanceof Class 20 | ? ((Class) element).getSimpleName() 21 | : ((Method) element).getDeclaringClass().getSimpleName() 22 | + "." + ((Method) element).getName())); 23 | return attrs; 24 | }; 25 | } 26 | ---- 27 | 28 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/receiving-messages/listener-group-id.adoc: -------------------------------------------------------------------------------- 1 | [[listener-group-id]] 2 | = Obtaining the Consumer `group.id` 3 | :page-section-summary-toc: 1 4 | 5 | When running the same listener code in multiple containers, it may be useful to be able to determine which container (identified by its `group.id` consumer property) that a record came from. 6 | 7 | You can call `KafkaUtils.getConsumerGroupId()` on the listener thread to do this. 8 | Alternatively, you can access the group id in a method parameter. 9 | 10 | [source, java] 11 | ---- 12 | @KafkaListener(id = "id", topicPattern = "someTopic") 13 | public void listener(@Payload String payload, @Header(KafkaHeaders.GROUP_ID) String groupId) { 14 | ... 15 | } 16 | ---- 17 | 18 | IMPORTANT: This is available in record listeners and batch listeners that receive a `List` of records. 19 | It is **not** available in a batch listener that receives a `ConsumerRecords` argument. 20 | Use the `KafkaUtils` mechanism in that case. 21 | 22 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/receiving-messages/listener-meta.adoc: -------------------------------------------------------------------------------- 1 | [[kafka-listener-meta]] 2 | = `@KafkaListener` as a Meta Annotation 3 | 4 | Starting with version 2.2, you can now use `@KafkaListener` as a meta annotation. 5 | The following example shows how to do so: 6 | 7 | [source, java] 8 | ---- 9 | @Target(ElementType.METHOD) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @KafkaListener 12 | public @interface MyThreeConsumersListener { 13 | 14 | @AliasFor(annotation = KafkaListener.class, attribute = "id") 15 | String id(); 16 | 17 | @AliasFor(annotation = KafkaListener.class, attribute = "topics") 18 | String[] topics(); 19 | 20 | @AliasFor(annotation = KafkaListener.class, attribute = "concurrency") 21 | String concurrency() default "3"; 22 | 23 | } 24 | ---- 25 | 26 | You must alias at least one of `topics`, `topicPattern`, or `topicPartitions` (and, usually, `id` or `groupId` unless you have specified a `group.id` in the consumer factory configuration). 27 | The following example shows how to do so: 28 | 29 | [source, java] 30 | ---- 31 | @MyThreeConsumersListener(id = "my.group", topics = "my.topic") 32 | public void listen1(String in) { 33 | ... 34 | } 35 | ---- 36 | 37 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/receiving-messages/ooo-commits.adoc: -------------------------------------------------------------------------------- 1 | [[ooo-commits]] 2 | = Manually Committing Offsets 3 | :page-section-summary-toc: 1 4 | 5 | Normally, when using `AckMode.MANUAL` or `AckMode.MANUAL_IMMEDIATE`, the acknowledgments must be acknowledged in order, because Kafka does not maintain state for each record, only a committed offset for each group/partition. 6 | Starting with version 2.8, you can now set the container property `asyncAcks`, which allows the acknowledgments for records returned by the poll to be acknowledged in any order. 7 | The listener container will defer the out-of-order commits until the missing acknowledgments are received. 8 | The consumer will be paused (no new records delivered) until all the offsets for the previous poll have been committed. 9 | 10 | IMPORTANT: While this feature allows applications to process records asynchronously, it should be understood that it increases the possibility of duplicate deliveries after a failure. 11 | 12 | IMPORTANT: When `asyncAcks` is activated, it is not possible to use `nack()` (negative acknowledgments) when xref:kafka/receiving-messages/message-listener-container.adoc#committing-offsets[Committing Offsets]. 13 | 14 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/receiving-messages/retrying-deliveries.adoc: -------------------------------------------------------------------------------- 1 | [[retrying-deliveries]] 2 | = Retrying Deliveries 3 | :page-section-summary-toc: 1 4 | 5 | See the `DefaultErrorHandler` in xref:kafka/annotation-error-handling.adoc[Handling Exceptions]. 6 | 7 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/receiving-messages/template-receive.adoc: -------------------------------------------------------------------------------- 1 | [[kafka-template-receive]] 2 | = Using `KafkaTemplate` to Receive 3 | :page-section-summary-toc: 1 4 | 5 | This section covers how to use `KafkaTemplate` to receive messages. 6 | 7 | Starting with version 2.8, the template has four `receive()` methods: 8 | 9 | [source, java] 10 | ---- 11 | ConsumerRecord receive(String topic, int partition, long offset); 12 | 13 | ConsumerRecord receive(String topic, int partition, long offset, Duration pollTimeout); 14 | 15 | ConsumerRecords receive(Collection requested); 16 | 17 | ConsumerRecords receive(Collection requested, Duration pollTimeout); 18 | ---- 19 | 20 | As you can see, you need to know the partition and offset of the record(s) you need to retrieve; a new `Consumer` is created (and closed) for each operation. 21 | 22 | With the last two methods, each record is retrieved individually and the results assembled into a `ConsumerRecords` object. 23 | When creating the `TopicPartitionOffset`+++s+++ for the request, only positive, absolute offsets are supported. 24 | 25 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/topic/partition-initial-offset.adoc: -------------------------------------------------------------------------------- 1 | [[topicpartition-initial-offset]] 2 | = Topic/Partition Initial Offset 3 | :page-section-summary-toc: 1 4 | 5 | There are several ways to set the initial offset for a partition. 6 | 7 | When manually assigning partitions, you can set the initial offset (if desired) in the configured `TopicPartitionOffset` arguments (see xref:kafka/receiving-messages/message-listener-container.adoc[Message Listener Containers]). 8 | You can also seek to a specific offset at any time. 9 | 10 | When you use group management where the broker assigns partitions: 11 | 12 | * For a new `group.id`, the initial offset is determined by the `auto.offset.reset` consumer property (`earliest` or `latest`). 13 | * For an existing group ID, the initial offset is the current offset for that group ID. 14 | You can, however, seek to a specific offset during initialization (or at any time thereafter). 15 | 16 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/other-resources.adoc: -------------------------------------------------------------------------------- 1 | [[other-resources]] 2 | = Other Resources 3 | 4 | In addition to this reference documentation, we recommend a number of other resources that may help you learn about Spring and Apache Kafka. 5 | 6 | - {kafka-page}[Apache Kafka Project Home Page] 7 | - https://projects.spring.io/spring-kafka/[Spring for Apache Kafka Home Page] 8 | - https://github.com/spring-projects/spring-kafka[Spring for Apache Kafka GitHub Repository] 9 | - https://github.com/spring-projects/spring-integration[Spring Integration GitHub Repository (Apache Kafka Module)] 10 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/reference.adoc: -------------------------------------------------------------------------------- 1 | [[reference]] 2 | = Reference 3 | 4 | This part of the reference documentation details the various components that comprise Spring for Apache Kafka. 5 | The xref:kafka.adoc[main chapter] covers the core classes to develop a Kafka application with Spring. -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/retrytopic.adoc: -------------------------------------------------------------------------------- 1 | [[retry-topic]] 2 | = Non-Blocking Retries 3 | :page-section-summary-toc: 1 4 | 5 | Version 2.9 changed the mechanism to bootstrap infrastructure beans; see xref:retrytopic/retry-config.adoc[Configuration] for the two mechanisms that are now required to bootstrap the feature. 6 | 7 | Achieving non-blocking retry / dlt functionality with Kafka usually requires setting up extra topics and creating and configuring the corresponding listeners. 8 | Since 2.7 Spring for Apache Kafka offers support for that via the `@RetryableTopic` annotation and `RetryTopicConfiguration` class to simplify that bootstrapping. 9 | 10 | Since 3.2, Spring for Apache Kafka supports non-blocking retries with xref:kafka/receiving-messages/class-level-kafkalistener.adoc[@KafkaListener on a Class]. 11 | 12 | IMPORTANT: Non-blocking retries are not supported with xref:kafka/receiving-messages/listener-annotation.adoc#batch-listeners[Batch Listeners]. 13 | 14 | IMPORTANT: Non-Blocking Retries cannot combine with xref:kafka/transactions.adoc#container-transaction-manager[Container Transactions]. 15 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/retrytopic/access-topic-info-runtime.adoc: -------------------------------------------------------------------------------- 1 | [[access-topic-info-runtime]] 2 | = Accessing Topics' Information at Runtime 3 | :page-section-summary-toc: 1 4 | 5 | Since 2.9, you can access information regarding the topic chain at runtime by injecting the provided `DestinationTopicContainer` bean. 6 | This interface provides methods to look up the next topic in the chain or the DLT for a topic if configured, as well as useful properties such as the topic's name, delay and type. 7 | 8 | As a real-world use-case example, you can use such information so a console application can resend a record from the DLT to the first retry topic in the chain after the cause of the failed processing, e.g. bug / inconsistent state, has been resolved. 9 | 10 | IMPORTANT: The `DestinationTopic` provided by the `DestinationTopicContainer#getNextDestinationTopicFor()` method corresponds to the next topic registered in the chain for the input topic. 11 | The actual topic the message will be forwarded to may differ due to different factors such as exception classification, number of attempts or single-topic fixed-delay strategies. 12 | Use the `DestinationTopicResolver` interface if you need to weigh in these factors. 13 | 14 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/retrytopic/accessing-delivery-attempts.adoc: -------------------------------------------------------------------------------- 1 | [[accessing-delivery-attempts]] 2 | = Accessing Delivery Attempts 3 | 4 | To access blocking and non-blocking delivery attempts, add these headers to your `@KafkaListener` method signature: 5 | 6 | [source, java] 7 | ---- 8 | @Header(KafkaHeaders.DELIVERY_ATTEMPT) int blockingAttempts, 9 | @Header(name = RetryTopicHeaders.DEFAULT_HEADER_ATTEMPTS, required = false) Integer nonBlockingAttempts 10 | ---- 11 | 12 | Blocking delivery attempts are only provided if you set `ContainerProperties`+++'+++s xref:kafka/container-props.adoc#deliveryAttemptHeader[deliveryAttemptHeader] to `true`. 13 | 14 | Note that the non blocking attempts will be `null` for the initial delivery. 15 | 16 | Starting with version 3.0.10, a convenient `KafkaMessageHeaderAccessor` is provided to allow simpler access to these headers; the accessor can be provided as a parameter for the listener method: 17 | 18 | [souce, java] 19 | ---- 20 | @RetryableTopic(backoff = @Backoff(...)) 21 | @KafkaListener(id = "dh1", topics = "dh1") 22 | void listen(Thing thing, KafkaMessageHeaderAccessor accessor) { 23 | ... 24 | } 25 | ---- 26 | 27 | Use `accessor.getBlockingRetryDeliveryAttempt()` and `accessor.getNonBlockingRetryDeliveryAttempt()` to get the values. 28 | The accessor will throw an `IllegalStateException` if blocking retries are not enabled; for non-blocking retries, the accessor returns `1` for the initial delivery. 29 | 30 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/retrytopic/back-off-delay-precision.adoc: -------------------------------------------------------------------------------- 1 | [[back-off-delay-precision]] 2 | = Back Off Delay Precision 3 | :page-section-summary-toc: 1 4 | 5 | [[overview-and-guarantees]] 6 | == Overview and Guarantees 7 | 8 | All message processing and backing off is handled by the consumer thread, and, as such, delay precision is guaranteed on a best-effort basis. 9 | If one message's processing takes longer than the next message's back off period for that consumer, the next message's delay will be higher than expected. 10 | Also, for short delays (about 1s or less), the maintenance work the thread has to do, such as committing offsets, may delay the message processing execution. 11 | The precision can also be affected if the retry topic's consumer is handling more than one partition, because we rely on waking up the consumer from polling and having full pollTimeouts to make timing adjustments. 12 | 13 | That being said, for consumers handling a single partition the message's processing should occur approximately at its exact due time for most situations. 14 | 15 | IMPORTANT: It is guaranteed that a message will never be processed before its due time. 16 | 17 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/retrytopic/change-kboe-logging-level.adoc: -------------------------------------------------------------------------------- 1 | [[change-kboe-logging-level]] 2 | = Changing KafkaBackOffException Logging Level 3 | :page-section-summary-toc: 1 4 | 5 | When a message in the retry topic is not due for consumption, a `KafkaBackOffException` is thrown. 6 | Such exceptions are logged by default at `DEBUG` level, but you can change this behavior by setting an error handler customizer in the `ListenerContainerFactoryConfigurer` in a `@Configuration` class. 7 | 8 | For example, to change the logging level to WARN you might add: 9 | 10 | [source, java] 11 | ---- 12 | @Override 13 | protected void configureCustomizers(CustomizersConfigurer customizersConfigurer) { 14 | customizersConfigurer.customizeErrorHandler(defaultErrorHandler -> 15 | defaultErrorHandler.setLogLevel(KafkaException.Level.WARN)) 16 | } 17 | ---- 18 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/retrytopic/multi-retry.adoc: -------------------------------------------------------------------------------- 1 | [[multi-retry]] 2 | = Multiple Listeners, Same Topic(s) 3 | 4 | Starting with version 3.0, it is now possible to configure multiple listeners on the same topic(s). 5 | In order to do this, you must use custom topic naming to isolate the retry topics from each other. 6 | This is best shown with an example: 7 | 8 | [source, java] 9 | ---- 10 | @RetryableTopic(... 11 | retryTopicSuffix = "-listener1", dltTopicSuffix = "-listener1-dlt", 12 | topicSuffixingStrategy = TopicSuffixingStrategy.SUFFIX_WITH_INDEX_VALUE) 13 | @KafkaListener(id = "listener1", groupId = "group1", topics = TWO_LISTENERS_TOPIC, ...) 14 | void listen1(String message, @Header(KafkaHeaders.RECEIVED_TOPIC) String receivedTopic) { 15 | ... 16 | } 17 | 18 | @RetryableTopic(... 19 | retryTopicSuffix = "-listener2", dltTopicSuffix = "-listener2-dlt", 20 | topicSuffixingStrategy = TopicSuffixingStrategy.SUFFIX_WITH_INDEX_VALUE) 21 | @KafkaListener(id = "listener2", groupId = "group2", topics = TWO_LISTENERS_TOPIC, ...) 22 | void listen2(String message, @Header(KafkaHeaders.RECEIVED_TOPIC) String receivedTopic) { 23 | ... 24 | } 25 | ---- 26 | 27 | The `topicSuffixingStrategy` is optional. 28 | The framework will configure and use a separate set of retry topics for each listener. 29 | 30 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/antora/modules/ROOT/pages/retrytopic/retry-topic-lcf.adoc: -------------------------------------------------------------------------------- 1 | [[retry-topic-lcf]] 2 | = Specifying a ListenerContainerFactory 3 | 4 | By default the RetryTopic configuration will use the provided factory from the `@KafkaListener` annotation, but you can specify a different one to be used to create the retry topic and dlt listener containers. 5 | 6 | For the `@RetryableTopic` annotation you can provide the factory's bean name, and using the `RetryTopicConfiguration` bean you can either provide the bean name or the instance itself. 7 | 8 | [source, java] 9 | ---- 10 | @RetryableTopic(listenerContainerFactory = "my-retry-topic-factory") 11 | @KafkaListener(topics = "my-annotated-topic") 12 | public void processMessage(MyPojo message) { 13 | // ... message processing 14 | } 15 | ---- 16 | [source, java] 17 | ---- 18 | @Bean 19 | public RetryTopicConfiguration myRetryTopic(KafkaTemplate template, 20 | ConcurrentKafkaListenerContainerFactory factory) { 21 | return RetryTopicConfigurationBuilder 22 | .newInstance() 23 | .listenerFactory(factory) 24 | .create(template); 25 | } 26 | 27 | @Bean 28 | public RetryTopicConfiguration myOtherRetryTopic(KafkaTemplate template) { 29 | return RetryTopicConfigurationBuilder 30 | .newInstance() 31 | .listenerFactory("my-retry-topic-factory") 32 | .create(template); 33 | } 34 | ---- 35 | 36 | IMPORTANT: Since 2.8.3 you can use the same factory for retryable and non-retryable topics. 37 | 38 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/java/org/springframework/kafka/jdocs/dynamic/MyListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.jdocs.dynamic; 18 | 19 | import org.apache.kafka.clients.consumer.ConsumerRecord; 20 | 21 | import org.springframework.kafka.listener.MessageListener; 22 | 23 | /** 24 | * {@link MessageListener} for dynamic containers. 25 | * @author Gary Russell 26 | * @since 2.8.9 27 | * 28 | */ 29 | //tag::listener[] 30 | 31 | public class MyListener implements MessageListener { 32 | 33 | @Override 34 | public void onMessage(ConsumerRecord data) { 35 | // ... 36 | } 37 | 38 | } 39 | // end::listener[] 40 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/java/org/springframework/kafka/jdocs/dynamic/MyPojo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.jdocs.dynamic; 18 | 19 | import org.springframework.kafka.annotation.KafkaListener; 20 | 21 | /** 22 | * Pojo for dynamic listener creation. 23 | * @author Gary Russell 24 | * @since 2.8.9 25 | * 26 | */ 27 | //tag::pojo[] 28 | 29 | public class MyPojo { 30 | 31 | private final String id; 32 | 33 | private final String topic; 34 | 35 | public MyPojo(String id, String topic) { 36 | this.id = id; 37 | this.topic = topic; 38 | } 39 | 40 | public String getId() { 41 | return this.id; 42 | } 43 | 44 | public String getTopic() { 45 | return this.topic; 46 | } 47 | 48 | @KafkaListener(id = "#{__listener.id}", topics = "#{__listener.topic}") 49 | public void listen(String in) { 50 | System.out.println(in); 51 | } 52 | 53 | } 54 | // end::pojo[] 55 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/java/org/springframework/kafka/jdocs/started/noboot/Listener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.jdocs.started.noboot; 18 | 19 | import org.springframework.kafka.annotation.KafkaListener; 20 | 21 | /** 22 | * Code snippet for quick start. 23 | * 24 | * @author Gary Russell 25 | * @since 2.7 26 | * 27 | */ 28 | // tag::startedNoBootListener[] 29 | public class Listener { 30 | 31 | @KafkaListener(id = "listen1", topics = "topic1") 32 | public void listen1(String in) { 33 | System.out.println(in); 34 | } 35 | 36 | } 37 | // end::startedNoBootListener[] 38 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/java/org/springframework/kafka/jdocs/started/noboot/Sender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.jdocs.started.noboot; 18 | 19 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 20 | import org.springframework.kafka.core.KafkaTemplate; 21 | 22 | /** 23 | * Code snippet for quick start. 24 | * 25 | * @author Gary Russell 26 | * @since 2.7 27 | * 28 | */ 29 | // tag::startedNoBootSender[] 30 | public class Sender { 31 | 32 | public static void main(String[] args) { 33 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); 34 | context.getBean(Sender.class).send("test", 42); 35 | } 36 | 37 | private final KafkaTemplate template; 38 | 39 | public Sender(KafkaTemplate template) { 40 | this.template = template; 41 | } 42 | 43 | public void send(String toSend, int key) { 44 | this.template.send("topic1", key, toSend); 45 | } 46 | 47 | } 48 | // end::startedNoBootSender[] 49 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/kotlin/org/springframework/kafka/kdocs/started/consumer/Application.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.kafka.kdocs.started.consumer 17 | 18 | import org.apache.kafka.clients.admin.NewTopic 19 | import org.springframework.boot.autoconfigure.SpringBootApplication 20 | import org.springframework.boot.runApplication 21 | import org.springframework.context.annotation.Bean 22 | import org.springframework.kafka.annotation.KafkaListener 23 | import org.springframework.kafka.kdocs.started.producer.Application 24 | 25 | /** 26 | * Code snippet for quick start. 27 | * 28 | * @author Gary Russell 29 | * @author Artem Bilan 30 | * @since 2.7 31 | */ 32 | // tag::startedConsumer[] 33 | @SpringBootApplication 34 | class Application { 35 | 36 | @Bean 37 | fun topic() = NewTopic("topic1", 10, 1) 38 | 39 | @KafkaListener(id = "myId", topics = ["topic1"]) 40 | fun listen(value: String?) { 41 | println(value) 42 | } 43 | 44 | } 45 | 46 | fun main(args: Array) = runApplication(*args) 47 | 48 | // end::startedConsumer[] 49 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/kotlin/org/springframework/kafka/kdocs/started/noboot/Listener.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.kafka.kdocs.started.noboot 17 | 18 | import org.springframework.kafka.annotation.KafkaListener 19 | 20 | /** 21 | * Code snippet for quick start. 22 | * 23 | * @author Gary Russell 24 | * @since 2.7 25 | */ 26 | // tag::startedNoBootListener[] 27 | class Listener { 28 | 29 | @KafkaListener(id = "listen1", topics = ["topic1"]) 30 | fun listen1(`in`: String) { 31 | println(`in`) 32 | } 33 | 34 | } 35 | // end::startedNoBootListener[] 36 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/kotlin/org/springframework/kafka/kdocs/started/noboot/Sender.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.kafka.kdocs.started.noboot 17 | 18 | import org.springframework.kafka.core.KafkaTemplate 19 | 20 | /** 21 | * Code snippet for quick start. 22 | * 23 | * @author Gary Russell 24 | * @author Artem Bilan 25 | * @since 2.7 26 | */ 27 | // tag::startedNoBootSender[] 28 | class Sender(private val template: KafkaTemplate) { 29 | 30 | fun send(toSend: String, key: Int) { 31 | template.send("topic1", key, toSend) 32 | } 33 | 34 | } 35 | // end::startedNoBootSender[] 36 | -------------------------------------------------------------------------------- /spring-kafka-docs/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /spring-kafka-test/src/main/java/org/springframework/kafka/test/assertj/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides a class for assertj conditions. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.test.assertj; 6 | -------------------------------------------------------------------------------- /spring-kafka-test/src/main/java/org/springframework/kafka/test/condition/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes for JUnit5 conditions. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.test.condition; 6 | -------------------------------------------------------------------------------- /spring-kafka-test/src/main/java/org/springframework/kafka/test/context/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes for EmbeddedKafka context customization. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.test.context; 6 | -------------------------------------------------------------------------------- /spring-kafka-test/src/main/java/org/springframework/kafka/test/core/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * core package for spring-kafka-test module. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.test.core; 6 | -------------------------------------------------------------------------------- /spring-kafka-test/src/main/java/org/springframework/kafka/test/hamcrest/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides hamcrest matchers. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.test.hamcrest; 6 | -------------------------------------------------------------------------------- /spring-kafka-test/src/main/java/org/springframework/kafka/test/junit/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides JUnit specific extensions in spring-kafka-test. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.test.junit; 6 | -------------------------------------------------------------------------------- /spring-kafka-test/src/main/java/org/springframework/kafka/test/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides top-level API for EmbeddedKafka. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.test; 6 | -------------------------------------------------------------------------------- /spring-kafka-test/src/main/java/org/springframework/kafka/test/rule/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides JUnit rules. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.test.rule; 6 | -------------------------------------------------------------------------------- /spring-kafka-test/src/main/java/org/springframework/kafka/test/utils/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Utils package. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.test.utils; 6 | -------------------------------------------------------------------------------- /spring-kafka-test/src/main/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener: -------------------------------------------------------------------------------- 1 | org.springframework.kafka.test.junit.GlobalEmbeddedKafkaTestExecutionListener 2 | -------------------------------------------------------------------------------- /spring-kafka-test/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Spring Test ContextCustomizerFactories 2 | org.springframework.test.context.ContextCustomizerFactory=\ 3 | org.springframework.kafka.test.context.EmbeddedKafkaContextCustomizerFactory 4 | -------------------------------------------------------------------------------- /spring-kafka-test/src/test/java/org/springframework/kafka/test/condition/WithSpringTestContextTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.test.condition; 18 | 19 | import org.junit.jupiter.api.Test; 20 | 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.context.annotation.Configuration; 23 | import org.springframework.kafka.test.EmbeddedKafkaBroker; 24 | import org.springframework.kafka.test.context.EmbeddedKafka; 25 | import org.springframework.test.annotation.DirtiesContext; 26 | import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; 27 | 28 | import static org.assertj.core.api.Assertions.assertThat; 29 | 30 | /** 31 | * @author Gary Russell 32 | * @since 2.7.2 33 | * 34 | */ 35 | @SpringJUnitConfig 36 | @EmbeddedKafka 37 | @DirtiesContext 38 | public class WithSpringTestContextTests { 39 | 40 | @Test 41 | void canAutowireBrokerInMethod(@Autowired EmbeddedKafkaBroker broker) { 42 | assertThat(broker).isNotNull(); 43 | } 44 | 45 | @Configuration 46 | static class Config { 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /spring-kafka-test/src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | spring.kafka.embedded.count=1 2 | spring.kafka.embedded.topics=topic1,topic2 3 | -------------------------------------------------------------------------------- /spring-kafka-test/src/test/resources/log4j2-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/annotation/DltHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.annotation; 18 | 19 | 20 | import java.lang.annotation.Documented; 21 | import java.lang.annotation.ElementType; 22 | import java.lang.annotation.Retention; 23 | import java.lang.annotation.RetentionPolicy; 24 | import java.lang.annotation.Target; 25 | 26 | /** 27 | * Annotation to determine the method that should process the DLT topic message. 28 | * The method can have the same parameters as a {@link KafkaListener} method can have (Message, Acknowledgement, etc). 29 | * 30 | *

31 | * The annotated method must be in the same class as the corresponding {@link KafkaListener} annotation. 32 | * 33 | * @author Tomaz Fernandes 34 | * @since 2.7 35 | * 36 | */ 37 | @Target(ElementType.METHOD) 38 | @Retention(RetentionPolicy.RUNTIME) 39 | @Documented 40 | public @interface DltHandler { 41 | 42 | } 43 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/annotation/KafkaListenerConfigurationSelector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.annotation; 18 | 19 | import org.springframework.context.annotation.DeferredImportSelector; 20 | import org.springframework.core.annotation.Order; 21 | import org.springframework.core.type.AnnotationMetadata; 22 | 23 | /** 24 | * A {@link DeferredImportSelector} implementation with the lowest order to import a 25 | * {@link KafkaBootstrapConfiguration} as late as possible. 26 | * 27 | * @author Artem Bilan 28 | * 29 | * @since 2.3 30 | */ 31 | @Order 32 | public class KafkaListenerConfigurationSelector implements DeferredImportSelector { 33 | 34 | @Override 35 | public String[] selectImports(AnnotationMetadata importingClassMetadata) { 36 | return new String[] { KafkaBootstrapConfiguration.class.getName() }; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/annotation/KafkaListeners.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.annotation; 18 | 19 | import java.lang.annotation.Documented; 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.RetentionPolicy; 23 | import java.lang.annotation.Target; 24 | 25 | /** 26 | * Container annotation that aggregates several {@link KafkaListener} annotations. 27 | *

28 | * Can be used natively, declaring several nested {@link KafkaListener} annotations. 29 | * Can also be used in conjunction with Java 8's support for repeatable annotations, 30 | * where {@link KafkaListener} can simply be declared several times on the same method 31 | * (or class), implicitly generating this container annotation. 32 | * 33 | * @author Gary Russell 34 | * 35 | * @see KafkaListener 36 | */ 37 | @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE }) 38 | @Retention(RetentionPolicy.RUNTIME) 39 | @Documented 40 | public @interface KafkaListeners { 41 | 42 | KafkaListener[] value(); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/annotation/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Package for kafka annotations 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.annotation; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/aot/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes to support Spring AOT. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.aot; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/config/ContainerCustomizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.config; 18 | 19 | import org.springframework.kafka.listener.AbstractMessageListenerContainer; 20 | 21 | /** 22 | * Called by the container factory after the container is created and configured. 23 | * 24 | * @param the key type. 25 | * @param the value type. 26 | * @param the container type. 27 | * 28 | * @author Gary Russell 29 | * @since 2.3.4 30 | * 31 | */ 32 | @FunctionalInterface 33 | public interface ContainerCustomizer> { 34 | 35 | /** 36 | * Configure the container. 37 | * @param container the container. 38 | */ 39 | void configure(C container); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/config/KafkaStreamsInfrastructureCustomizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.config; 18 | 19 | import org.apache.kafka.streams.StreamsBuilder; 20 | import org.apache.kafka.streams.Topology; 21 | 22 | /** 23 | * A customizer for infrastructure components such as the {@code StreamsBuilder} and 24 | * {@code Topology}. It can be provided to the {@link StreamsBuilderFactoryBean} which 25 | * will apply the changes before creating the stream. 26 | * 27 | * @author Gary Russell 28 | * @since 2.4.1 29 | * 30 | */ 31 | public interface KafkaStreamsInfrastructureCustomizer { 32 | 33 | /** 34 | * Configure the builder. 35 | * @param builder the builder. 36 | */ 37 | default void configureBuilder(StreamsBuilder builder) { 38 | // no-op 39 | } 40 | 41 | /** 42 | * Configure the topology. 43 | * @param topology the topology 44 | */ 45 | default void configureTopology(Topology topology) { 46 | // no-op 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/config/StreamsBuilderFactoryBeanConfigurer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.config; 18 | 19 | import org.springframework.core.Ordered; 20 | 21 | /** 22 | * A configurer for {@link StreamsBuilderFactoryBean}. Applied, in order, to the single 23 | * {@link StreamsBuilderFactoryBean} configured by the framework. Invoked after the bean 24 | * is created and before it is started. Default order is 0. 25 | * 26 | * @author Gary Russell 27 | * @since 2.6.7 28 | * 29 | */ 30 | @FunctionalInterface 31 | public interface StreamsBuilderFactoryBeanConfigurer extends Ordered { 32 | 33 | /** 34 | * Configure the factory bean. 35 | * @param factoryBean the factory bean. 36 | */ 37 | void configure(StreamsBuilderFactoryBean factoryBean); 38 | 39 | @Override 40 | default int getOrder() { 41 | return 0; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/config/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Package for kafka configuration 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.config; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/core/CleanupConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.core; 18 | 19 | /** 20 | * Specifies time of {@link org.apache.kafka.streams.KafkaStreams#cleanUp()} execution. 21 | * 22 | * @author Pawel Szymczyk 23 | */ 24 | public class CleanupConfig { 25 | 26 | private final boolean onStart; 27 | 28 | private final boolean onStop; 29 | 30 | public CleanupConfig() { 31 | this(false, false); 32 | } 33 | 34 | public CleanupConfig(boolean onStart, boolean onStop) { 35 | this.onStart = onStart; 36 | this.onStop = onStop; 37 | } 38 | 39 | public boolean cleanupOnStart() { 40 | return this.onStart; 41 | } 42 | 43 | public boolean cleanupOnStop() { 44 | return this.onStop; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/core/ConsumerPostProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.core; 18 | 19 | import java.util.function.Function; 20 | 21 | import org.apache.kafka.clients.consumer.Consumer; 22 | 23 | /** 24 | * Called by consumer factories to perform post processing on newly created consumers. 25 | * 26 | * @param the key type. 27 | * @param the value type 28 | * 29 | * @author Gary Russell 30 | * @since 2.5.3 31 | * 32 | */ 33 | public interface ConsumerPostProcessor extends Function, Consumer> { 34 | 35 | } 36 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/core/ProducerPostProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.core; 18 | 19 | import java.util.function.Function; 20 | 21 | import org.apache.kafka.clients.producer.Producer; 22 | 23 | /** 24 | * Called by producer factories to perform post processing on newly created producers. 25 | * 26 | * @param the key type. 27 | * @param the value type 28 | * 29 | * @author Gary Russell 30 | * @since 2.5.3 31 | * 32 | */ 33 | public interface ProducerPostProcessor extends Function, Producer> { 34 | 35 | } 36 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/core/TransactionIdSuffixStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.core; 18 | 19 | import org.jspecify.annotations.Nullable; 20 | 21 | /** 22 | * The strategy for managing transactional producer suffixes. 23 | * 24 | * @author Ilya Starchenko 25 | * 26 | * @since 3.2 27 | */ 28 | public interface TransactionIdSuffixStrategy { 29 | 30 | /** 31 | * Acquire the suffix for the transactional producer. 32 | * @param txIdPrefix the transaction id prefix. 33 | * @return the suffix. 34 | */ 35 | String acquireSuffix(@Nullable String txIdPrefix); 36 | 37 | /** 38 | * Release the suffix for the transactional producer. 39 | * @param txIdPrefix the transaction id prefix. 40 | * @param suffix the suffix. 41 | */ 42 | void releaseSuffix(@Nullable String txIdPrefix, @Nullable String suffix); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/core/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Package for kafka core components 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.core; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/core/reactive/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Reactive component for consumer and producer. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.core.reactive; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/event/ConsumerFailedToStartEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.event; 18 | 19 | /** 20 | * An event published when a consumer fails to start. 21 | * 22 | * @author Gary Russell 23 | * @since 2.3 24 | * 25 | */ 26 | public class ConsumerFailedToStartEvent extends KafkaEvent { 27 | 28 | private static final long serialVersionUID = 1L; 29 | 30 | /** 31 | * Construct an instance with the provided source and container. 32 | * @param source the container instance that generated the event. 33 | * @param container the container or the parent container if the container is a child. 34 | */ 35 | public ConsumerFailedToStartEvent(Object source, Object container) { 36 | super(source, container); 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "ConsumerFailedToStartEvent [source=" + getSource() + "]"; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/event/ConsumerRetryAuthSuccessfulEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.event; 18 | 19 | /** 20 | * An event published when authentication or authorization has been retried successfully. 21 | * 22 | * @author Daniel Gentes 23 | * @since 3.0 24 | * 25 | */ 26 | public class ConsumerRetryAuthSuccessfulEvent extends KafkaEvent { 27 | 28 | private static final long serialVersionUID = 1L; 29 | 30 | /** 31 | * Construct an instance with the provided source and container. 32 | * @param source the container instance that generated the event. 33 | * @param container the container or the parent container 34 | * if the container is a child. 35 | */ 36 | public ConsumerRetryAuthSuccessfulEvent(Object source, Object container) { 37 | super(source, container); 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "ConsumerRetryAuthSuccessfulEvent [source=" + getSource() + "]"; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/event/ConsumerStartedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.event; 18 | 19 | /** 20 | * An event published when a consumer has started. 21 | * 22 | * @author Gary Russell 23 | * @since 2.3 24 | * 25 | */ 26 | public class ConsumerStartedEvent extends KafkaEvent { 27 | 28 | private static final long serialVersionUID = 1L; 29 | 30 | /** 31 | * Construct an instance with the provided source and container. 32 | * @param source the container instance that generated the event. 33 | * @param container the container or the parent container if the container is a child. 34 | */ 35 | public ConsumerStartedEvent(Object source, Object container) { 36 | super(source, container); 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "ConsumerStartedEvent [source=" + getSource() + "]"; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/event/ConsumerStartingEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.event; 18 | 19 | /** 20 | * An event published when a consumer is initializing. 21 | * 22 | * @author Gary Russell 23 | * @since 2.3 24 | * 25 | */ 26 | public class ConsumerStartingEvent extends KafkaEvent { 27 | 28 | private static final long serialVersionUID = 1L; 29 | 30 | /** 31 | * Construct an instance with the provided source and container. 32 | * @param source the container instance that generated the event. 33 | * @param container the container or the parent container if the container is a child. 34 | */ 35 | public ConsumerStartingEvent(Object source, Object container) { 36 | super(source, container); 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "ConsumerStartingEvent [source=" + getSource() + "]"; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/event/ContainerStoppedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.event; 18 | 19 | /** 20 | * An event published when a container is stopped. 21 | * 22 | * @author Gary Russell 23 | * @since 2.2 24 | * 25 | */ 26 | public class ContainerStoppedEvent extends KafkaEvent { 27 | 28 | private static final long serialVersionUID = 1L; 29 | 30 | /** 31 | * Construct an instance with the provided source and container. 32 | * @param source the container instance that generated the event. 33 | * @param container the container or the parent container if the container is a child. 34 | * @since 2.2.1 35 | */ 36 | public ContainerStoppedEvent(Object source, Object container) { 37 | super(source, container); 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "ContainerStoppedEvent [source=" + getSource() + "]"; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/event/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Application Events. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.event; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/ConsumerAwareRecordRecoverer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.apache.kafka.clients.consumer.Consumer; 20 | import org.apache.kafka.clients.consumer.ConsumerRecord; 21 | import org.jspecify.annotations.Nullable; 22 | 23 | /** 24 | * A {@link ConsumerRecordRecoverer} that supports getting a reference to the 25 | * {@link Consumer}. 26 | * 27 | * @author Gary Russell 28 | * @since 2.7 29 | * 30 | */ 31 | @FunctionalInterface 32 | public interface ConsumerAwareRecordRecoverer extends ConsumerRecordRecoverer { 33 | 34 | @Override 35 | default void accept(ConsumerRecord record, Exception exception) { 36 | accept(record, null, exception); 37 | } 38 | 39 | /** 40 | * Recover the record. 41 | * @param record the record. 42 | * @param consumer the consumer. 43 | * @param exception the exception. 44 | * @since 2.7 45 | */ 46 | void accept(ConsumerRecord record, @Nullable Consumer consumer, @Nullable Exception exception); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/ConsumerPauseResumeEventPublisher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import java.util.Collection; 20 | 21 | import org.apache.kafka.common.TopicPartition; 22 | 23 | /** 24 | * Objects that can publish consumer pause/resume events. 25 | * 26 | * @author Gary Russell 27 | * @since 2.8.10 28 | * 29 | */ 30 | public interface ConsumerPauseResumeEventPublisher { 31 | 32 | /** 33 | * Publish a consumer paused event. 34 | * @param partitions the paused partitions. 35 | * @param reason the reason. 36 | */ 37 | void publishConsumerPausedEvent(Collection partitions, String reason); 38 | 39 | /** 40 | * Publish a consumer resumed event. 41 | * @param partitions the resumed partitions. 42 | */ 43 | void publishConsumerResumedEvent(Collection partitions); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/ConsumerRecordRecoverer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import java.util.function.BiConsumer; 20 | 21 | import org.apache.kafka.clients.consumer.ConsumerRecord; 22 | 23 | /** 24 | * A {@link BiConsumer} extension for recovering consumer records. 25 | * 26 | * @author Gary Russell 27 | * @since 2.3 28 | * 29 | */ 30 | @FunctionalInterface 31 | public interface ConsumerRecordRecoverer extends BiConsumer, Exception> { 32 | 33 | } 34 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/DefaultBackOffHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.jspecify.annotations.Nullable; 20 | 21 | /** 22 | * Default {@link BackOffHandler}; suspends the thread for the back off. If a container is 23 | * provided, {@link ListenerUtils#stoppableSleep(MessageListenerContainer, long)} is used, 24 | * to terminate the suspension if the container is stopped. 25 | * 26 | * @author Jan Marincek 27 | * @author Gary Russell 28 | * @since 2.9 29 | */ 30 | public class DefaultBackOffHandler implements BackOffHandler { 31 | 32 | @Override 33 | public void onNextBackOff(@Nullable MessageListenerContainer container, @Nullable Exception exception, long nextBackOff) { 34 | try { 35 | if (container == null) { 36 | Thread.sleep(nextBackOff); 37 | } 38 | else { 39 | ListenerUtils.stoppableSleep(container, nextBackOff); 40 | } 41 | } 42 | catch (InterruptedException e) { 43 | Thread.currentThread().interrupt(); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/DefaultListenerMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.jspecify.annotations.Nullable; 20 | 21 | import org.springframework.util.Assert; 22 | 23 | /** 24 | * Default implementation for {@link ListenerMetadata}. 25 | * @author Francois Rosiere 26 | * @since 2.8.6 27 | */ 28 | class DefaultListenerMetadata implements ListenerMetadata { 29 | 30 | private final MessageListenerContainer container; 31 | 32 | DefaultListenerMetadata(MessageListenerContainer container) { 33 | Assert.notNull(container, "'container' must not be null"); 34 | this.container = container; 35 | } 36 | 37 | @Override 38 | @Nullable 39 | public String getListenerId() { 40 | return this.container.getListenerId(); 41 | } 42 | 43 | @Override 44 | @Nullable 45 | public String getGroupId() { 46 | return this.container.getGroupId(); 47 | } 48 | 49 | @Override 50 | @Nullable 51 | public byte[] getListenerInfo() { 52 | return this.container.getListenerInfo(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/DelegatingMessageListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | /** 20 | * Classes implementing this interface allow containers to determine the type of the 21 | * ultimate listener. 22 | * 23 | * @param the type received by the listener. 24 | * 25 | * @author Gary Russell 26 | * @since 2.0 27 | * 28 | */ 29 | public interface DelegatingMessageListener { 30 | 31 | /** 32 | * Return the delegate. 33 | * @return the delegate. 34 | */ 35 | T getDelegate(); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/DeliveryAttemptAware.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.springframework.kafka.support.TopicPartitionOffset; 20 | 21 | /** 22 | * A component implementing this interface can provide the next delivery attempt. 23 | * 24 | * @author Gary Russell 25 | * @since 2.5 26 | * 27 | */ 28 | @FunctionalInterface 29 | public interface DeliveryAttemptAware { 30 | 31 | /** 32 | * Return the next delivery attempt for the topic/partition/offset. 33 | * @param topicPartitionOffset the topic/partition/offset. 34 | * @return the next delivery attempt. 35 | */ 36 | int deliveryAttempt(TopicPartitionOffset topicPartitionOffset); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/GenericMessageListenerContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | /** 20 | * Generic message listener container; adds parameters. 21 | * 22 | * @param the key type. 23 | * @param the value type. 24 | * 25 | * @author Gary Russell 26 | * @since 2.1.3 27 | * 28 | */ 29 | public interface GenericMessageListenerContainer extends MessageListenerContainer { 30 | 31 | } 32 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/KafkaBackOffManagerFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | /** 20 | * 21 | * Creates a {@link KafkaBackOffManagerFactory} instance. 22 | * 23 | * @author Tomaz Fernandes 24 | * @since 2.7 25 | * @see KafkaConsumerBackoffManager 26 | */ 27 | public interface KafkaBackOffManagerFactory { 28 | 29 | KafkaConsumerBackoffManager create(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/ListenerMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.jspecify.annotations.Nullable; 20 | 21 | /** 22 | * Metadata associated to a {@link org.springframework.kafka.annotation.KafkaListener}. 23 | * 24 | * @author Francois Rosiere 25 | * @author Gary Russell 26 | * @since 2.8.5 27 | * @see org.springframework.kafka.annotation.KafkaListener 28 | */ 29 | public interface ListenerMetadata { 30 | 31 | /** 32 | * Return the listener id. 33 | * @return the listener id. 34 | */ 35 | @Nullable 36 | String getListenerId(); 37 | 38 | /** 39 | * Return the group id. 40 | * @return the group id. 41 | */ 42 | @Nullable 43 | String getGroupId(); 44 | 45 | /** 46 | * Return the listener info. 47 | * @return the listener info. 48 | */ 49 | @Nullable 50 | byte[] getListenerInfo(); 51 | 52 | } 53 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/ListenerType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | /** 20 | * Defines the listener type. 21 | * 22 | * @author Gary Russell 23 | * @since 2.0 24 | * 25 | */ 26 | public enum ListenerType { 27 | 28 | /** 29 | * Acknowledging and consumer aware. 30 | */ 31 | ACKNOWLEDGING_CONSUMER_AWARE, 32 | 33 | /** 34 | * Consumer aware. 35 | */ 36 | CONSUMER_AWARE, 37 | 38 | /** 39 | * Acknowledging. 40 | */ 41 | ACKNOWLEDGING, 42 | 43 | /** 44 | * Simple. 45 | */ 46 | SIMPLE 47 | 48 | } 49 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/ManualAckListenerErrorHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.apache.kafka.clients.consumer.Consumer; 20 | import org.jspecify.annotations.Nullable; 21 | 22 | import org.springframework.kafka.support.Acknowledgment; 23 | import org.springframework.messaging.Message; 24 | 25 | /** 26 | * A {@link KafkaListenerErrorHandler} that supports manual acks. 27 | * 28 | * @author Gary Russell 29 | * @since 2.9 30 | * 31 | */ 32 | @FunctionalInterface 33 | public interface ManualAckListenerErrorHandler extends KafkaListenerErrorHandler { 34 | 35 | @Override 36 | default Object handleError(Message message, ListenerExecutionFailedException exception) { 37 | throw new UnsupportedOperationException("Adapter should never call this"); 38 | } 39 | 40 | @Override 41 | Object handleError(Message message, ListenerExecutionFailedException exception, @Nullable Consumer consumer, 42 | @Nullable Acknowledgment ack); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/MessageListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.apache.kafka.clients.consumer.ConsumerRecord; 20 | 21 | /** 22 | * Listener for handling individual incoming Kafka messages. 23 | * 24 | * @param the key type. 25 | * @param the value type. 26 | * 27 | * @author Marius Bogoevici 28 | * @author Gary Russell 29 | */ 30 | @FunctionalInterface 31 | public interface MessageListener extends GenericMessageListener> { 32 | 33 | } 34 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/OffsetAndMetadataProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.apache.kafka.clients.consumer.OffsetAndMetadata; 20 | 21 | /** 22 | * Provider for {@link OffsetAndMetadata}. The provider can be used to have more granularity when creating an 23 | * {@link OffsetAndMetadata}. The provider is used for both sync and async commits of the offsets. 24 | * 25 | * @author Francois Rosiere 26 | * @since 2.8.5 27 | * @see org.apache.kafka.clients.consumer.OffsetCommitCallback 28 | */ 29 | public interface OffsetAndMetadataProvider { 30 | 31 | /** 32 | * Provide an offset and metadata object for the given listener metadata and offset. 33 | * 34 | * @param listenerMetadata metadata associated to a listener. 35 | * @param offset an offset. 36 | * @return an offset and metadata. 37 | */ 38 | OffsetAndMetadata provide(ListenerMetadata listenerMetadata, long offset); 39 | } 40 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/RecordInRetryException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.jspecify.annotations.Nullable; 20 | 21 | import org.springframework.core.NestedRuntimeException; 22 | 23 | /** 24 | * Internal {@link NestedRuntimeException} that is used as an exception thrown 25 | * when the record is in retry and not yet recovered during error handling. 26 | * This is to prevent the record from being prematurely committed in the middle of a retry. 27 | *

28 | * Intended only for framework use and thus the package-protected access. 29 | * 30 | * @author Soby Chacko 31 | * @since 3.3.0 32 | */ 33 | @SuppressWarnings("serial") 34 | class RecordInRetryException extends NestedRuntimeException { 35 | 36 | /** 37 | * Package protected constructor to create an instance with the provided properties. 38 | * 39 | * @param message logging message 40 | * @param cause {@link Throwable} 41 | */ 42 | RecordInRetryException(String message, @Nullable Throwable cause) { 43 | super(message, cause); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/RecoveryStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.apache.kafka.clients.consumer.Consumer; 20 | import org.apache.kafka.clients.consumer.ConsumerRecord; 21 | import org.jspecify.annotations.Nullable; 22 | 23 | /** 24 | * Called to determine whether a record should be skipped. 25 | * 26 | * @author Gary Russell 27 | * @since 2.7 28 | */ 29 | @FunctionalInterface 30 | public interface RecoveryStrategy { 31 | 32 | /** 33 | * Return true if the record should be skipped because it was successfully 34 | * recovered. 35 | * @param record the record. 36 | * @param ex the exception. 37 | * @param container the container (or parent if a child container). 38 | * @param consumer the consumer. 39 | * @return true to skip. 40 | * @throws InterruptedException if the thread is interrupted. 41 | */ 42 | boolean recovered(ConsumerRecord record, @Nullable Exception ex, @Nullable MessageListenerContainer container, 43 | @Nullable Consumer consumer) throws InterruptedException; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/ThreadStateProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.apache.kafka.clients.consumer.Consumer; 20 | 21 | /** 22 | * A general interface for managing thread-bound resources when a {@link Consumer} is 23 | * available. 24 | * 25 | * @author Karol Dowbecki 26 | * @author Gary Russell 27 | * @since 2.8 28 | * 29 | */ 30 | public interface ThreadStateProcessor { 31 | 32 | /** 33 | * Call to set up thread-bound resources which will be available for the 34 | * entire duration of enclosed operation involving a {@link Consumer}. 35 | * 36 | * @param consumer the consumer. 37 | */ 38 | default void setupThreadState(Consumer consumer) { 39 | } 40 | 41 | /** 42 | * Call to clear thread-bound resources which were set up in 43 | * {@link #setupThreadState(Consumer)}. 44 | * 45 | * @param consumer the consumer. 46 | */ 47 | default void clearThreadState(Consumer consumer) { 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/adapter/AsyncRepliesAware.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener.adapter; 18 | 19 | /** 20 | * Message handler adapter implementing this interface can detect {@link HandlerAdapter} async return types. 21 | * 22 | * @author Wang zhiyang 23 | * 24 | * @since 3.2 25 | */ 26 | public interface AsyncRepliesAware { 27 | 28 | /** 29 | * Return true if the {@link HandlerAdapter} return type is async. 30 | * @return true for async replies. 31 | * @since 3.2 32 | */ 33 | default boolean isAsyncReplies() { 34 | return false; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/adapter/InvocationResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener.adapter; 18 | 19 | import org.jspecify.annotations.Nullable; 20 | 21 | import org.springframework.expression.Expression; 22 | 23 | /** 24 | * The result of a method invocation. 25 | * @param result the result. 26 | * @param messageReturnType the message return type. 27 | * @param sendTo the expression about sends topic. 28 | * 29 | * @author Gary Russell 30 | * @since 2.2 31 | */ 32 | public record InvocationResult(@Nullable Object result, @Nullable Expression sendTo, boolean messageReturnType) { 33 | 34 | @Override 35 | public String toString() { 36 | return "InvocationResult [result=" + this.result 37 | + ", sendTo=" + (this.sendTo == null ? "null" : this.sendTo.getExpressionString()) 38 | + ", messageReturnType=" + this.messageReturnType + "]"; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/adapter/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes for adapting listeners. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.listener.adapter; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/listener/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Package for kafka listeners 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.listener; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/mock/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes to support the use of MockConsumer and MockProducer. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.mock; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Base package for kafka 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/requestreply/KafkaReplyTimeoutException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.requestreply; 18 | 19 | import org.springframework.kafka.KafkaException; 20 | 21 | /** 22 | * Exception when a reply is not received within a timeout. 23 | * 24 | * @author Gary Russell 25 | * @since 2.3 26 | * 27 | */ 28 | public class KafkaReplyTimeoutException extends KafkaException { 29 | 30 | private static final long serialVersionUID = 1L; 31 | 32 | public KafkaReplyTimeoutException(String message) { 33 | super(message); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/requestreply/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes for request/reply semantics. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.requestreply; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/retrytopic/DltStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.retrytopic; 18 | 19 | /** 20 | * 21 | * Strategies for handling DLT processing. 22 | * 23 | * @author Tomaz Fernandes 24 | * @since 2.7 25 | * 26 | */ 27 | public enum DltStrategy { 28 | 29 | /** 30 | * Don't create a DLT. 31 | */ 32 | NO_DLT, 33 | 34 | /** 35 | * Always send the message back to the DLT for reprocessing in case of failure in 36 | * DLT processing. 37 | */ 38 | ALWAYS_RETRY_ON_ERROR, 39 | 40 | /** 41 | * Fail if DLT processing throws an error. 42 | */ 43 | FAIL_ON_ERROR 44 | 45 | } 46 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/retrytopic/RetryTopicConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.retrytopic; 18 | 19 | /** 20 | * 21 | * Constants for the RetryTopic functionality. 22 | * 23 | * @author Tomaz Fernandes 24 | * @since 2.7 25 | * 26 | */ 27 | public abstract class RetryTopicConstants { 28 | 29 | /** 30 | * Default suffix for retry topics. 31 | */ 32 | public static final String DEFAULT_RETRY_SUFFIX = "-retry"; 33 | 34 | /** 35 | * Default suffix for dlt. 36 | */ 37 | public static final String DEFAULT_DLT_SUFFIX = "-dlt"; 38 | 39 | /** 40 | * Default number of times the message processing should be attempted, 41 | * including the first. 42 | */ 43 | public static final int DEFAULT_MAX_ATTEMPTS = 3; 44 | 45 | /** 46 | * Constant to represent that the integer property is not set. 47 | */ 48 | public static final int NOT_SET = -1; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/retrytopic/RetryTopicHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.retrytopic; 18 | 19 | /** 20 | * 21 | * Contains the headers that will be used in the forwarded messages. 22 | * 23 | * @author Tomaz Fernandes 24 | * @since 2.7 25 | * 26 | */ 27 | public abstract class RetryTopicHeaders { 28 | 29 | /** 30 | * The default header for the backoff due timestamp. 31 | */ 32 | public static final String DEFAULT_HEADER_BACKOFF_TIMESTAMP = "retry_topic-backoff-timestamp"; 33 | 34 | /** 35 | * The default header for the attempts. 36 | */ 37 | public static final String DEFAULT_HEADER_ATTEMPTS = "retry_topic-attempts"; 38 | 39 | /** 40 | * The default header for the original message's timestamp. 41 | */ 42 | public static final String DEFAULT_HEADER_ORIGINAL_TIMESTAMP = "retry_topic-original-timestamp"; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/retrytopic/SameIntervalTopicReuseStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2023 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.retrytopic; 18 | 19 | /** 20 | * 21 | * Strategy for topic reuse when multiple, sequential retries have the same backoff 22 | * interval. 23 | * 24 | *

25 | * It can be used only when the retries that have the same interval are located 26 | * in the end of the retry chain (it cannot be used for retries with the same 27 | * interval in the middle of the retry chain). 28 | * 29 | * @author João Lima 30 | * @since 3.0.4 31 | * 32 | */ 33 | public enum SameIntervalTopicReuseStrategy { 34 | 35 | /** 36 | * Uses a single retry topic for sequential attempts with the same interval. 37 | */ 38 | SINGLE_TOPIC, 39 | 40 | /** 41 | * Uses one separate topic per retry attempt. 42 | */ 43 | MULTIPLE_TOPICS 44 | 45 | } 46 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/retrytopic/TopicSuffixingStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.retrytopic; 18 | 19 | /** 20 | * 21 | * Constants for the RetryTopic functionality. 22 | * 23 | * @author Tomaz Fernandes 24 | * @since 2.7 25 | * 26 | */ 27 | public enum TopicSuffixingStrategy { 28 | 29 | /** 30 | * Suffixes the topics with their index in the retry topics. 31 | * E.g. my-retry-topic-0, my-retry-topic-1, my-retry-topic-2. 32 | */ 33 | SUFFIX_WITH_INDEX_VALUE, 34 | 35 | /** 36 | * Suffixes the topics the delay value for the topic. 37 | * E.g. my-retry-topic-1000, my-retry-topic-2000, my-retry-topic-4000. 38 | */ 39 | SUFFIX_WITH_DELAY_VALUE 40 | 41 | } 42 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/retrytopic/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Package for retryable topic handling. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.retrytopic; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/security/jaas/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes related to jaas. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.security.jaas; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/streams/messaging/MessagingFunction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.streams.messaging; 18 | 19 | import org.springframework.messaging.Message; 20 | 21 | /** 22 | * A function that receives a spring-messaging {@link Message} and returns 23 | * a {@link Message}. 24 | * 25 | * @author Gary Russell 26 | * @since 2.3 27 | * 28 | */ 29 | @FunctionalInterface 30 | public interface MessagingFunction { 31 | 32 | Message exchange(Message message); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/streams/messaging/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Package for classes related to spring-messaging with Kafka Streams. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.streams.messaging; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/streams/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Package for classes related to Kafka Streams. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.streams; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/JacksonPresent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support; 18 | 19 | import org.jspecify.annotations.Nullable; 20 | 21 | import org.springframework.util.ClassUtils; 22 | 23 | /** 24 | * The utility to check if Jackson JSON processor is present in the classpath. 25 | * 26 | * @author Artem Bilan 27 | * @author Gary Russell 28 | * 29 | * @since 1.3 30 | */ 31 | public final class JacksonPresent { 32 | 33 | private static final @Nullable ClassLoader classLoader = ClassUtils.getDefaultClassLoader(); // NOSONAR 34 | 35 | private static final boolean jackson2Present = // NOSONAR 36 | ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && 37 | ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader); 38 | 39 | public static boolean isJackson2Present() { 40 | return jackson2Present; 41 | } 42 | 43 | private JacksonPresent() { 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/KafkaHeaderMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support; 18 | 19 | import java.util.Map; 20 | 21 | import org.apache.kafka.common.header.Headers; 22 | 23 | import org.springframework.messaging.MessageHeaders; 24 | 25 | /** 26 | * Header mapper for Apache Kafka. 27 | * 28 | * @author Gary Russell 29 | * @since 1.3 30 | * 31 | */ 32 | public interface KafkaHeaderMapper { 33 | 34 | /** 35 | * Map from the given {@link MessageHeaders} to the specified target headers. 36 | * @param headers the abstracted MessageHeaders. 37 | * @param target the native target headers. 38 | */ 39 | void fromHeaders(MessageHeaders headers, Headers target); 40 | 41 | /** 42 | * Map from the given native headers to a map of headers for the eventual 43 | * {@link MessageHeaders}. 44 | * @param source the native headers. 45 | * @param target the target headers. 46 | */ 47 | void toHeaders(Headers source, Map target); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/KafkaNull.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support; 18 | 19 | /** 20 | * This class represents NULL Kafka payload. 21 | * 22 | * @author Dariusz Szablinski 23 | * @author Gary Russell 24 | * @since 1.0.3 25 | */ 26 | public final class KafkaNull { 27 | 28 | /** 29 | * Instance of KafkaNull. 30 | */ 31 | public static final KafkaNull INSTANCE = new KafkaNull(); 32 | 33 | private KafkaNull() { 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/TopicForRetryable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support; 18 | 19 | import org.apache.kafka.clients.admin.NewTopic; 20 | 21 | /** 22 | * Marker to indicate this {@link NewTopic} is for retryable topics; admin will ignore these if 23 | * a regular {@link NewTopic} exist. 24 | * 25 | * @author Gary Russell 26 | * @since 2.8.10 27 | * 28 | */ 29 | public class TopicForRetryable extends NewTopic { 30 | 31 | /** 32 | * Create an instance with the provided properties. 33 | * @param topic the topic. 34 | * @param numPartitions the partitions. 35 | * @param replicationFactor the replication factor. 36 | */ 37 | public TopicForRetryable(String topic, int numPartitions, short replicationFactor) { 38 | super(topic, numPartitions, replicationFactor); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/converter/KafkaMessageHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support.converter; 18 | 19 | import java.util.Map; 20 | 21 | import org.springframework.messaging.MessageHeaders; 22 | 23 | /** 24 | * Overload of message headers configurable for adding id and timestamp headers. 25 | * 26 | * @author Marius Bogoevici 27 | * @author Gary Russell 28 | * @since 1.1 29 | * 30 | */ 31 | @SuppressWarnings("serial") 32 | public class KafkaMessageHeaders extends MessageHeaders { 33 | 34 | /** 35 | * Construct headers with or without id and/or timestamp. 36 | * @param generateId true to add an ID header. 37 | * @param generateTimestamp true to add a timestamp header. 38 | */ 39 | KafkaMessageHeaders(boolean generateId, boolean generateTimestamp) { 40 | super(null, generateId ? null : ID_VALUE_NONE, generateTimestamp ? null : -1L); 41 | } 42 | 43 | @Override 44 | public Map getRawHeaders() { //NOSONAR - not useless, widening to public 45 | return super.getRawHeaders(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/converter/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Package for kafka converters 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.support.converter; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/mapping/ClassMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support.mapping; 18 | 19 | import org.apache.kafka.common.header.Headers; 20 | import org.jspecify.annotations.Nullable; 21 | 22 | /** 23 | * Strategy for setting metadata on messages such that one can create the class 24 | * that needs to be instantiated when receiving a message. 25 | * 26 | * @author Mark Pollack 27 | * @author James Carr 28 | * @author Gary Russell 29 | * 30 | * @since 2.1 31 | */ 32 | public interface ClassMapper { 33 | 34 | void fromClass(Class clazz, Headers headers); 35 | 36 | @Nullable 37 | Class toClass(Headers headers); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/mapping/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes related to type mapping. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.support.mapping; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/micrometer/KafkaListenerObservationConvention.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support.micrometer; 18 | 19 | import io.micrometer.observation.Observation.Context; 20 | import io.micrometer.observation.ObservationConvention; 21 | 22 | /** 23 | * {@link ObservationConvention} for Kafka listener key values. 24 | * 25 | * @author Gary Russell 26 | * @since 3.0 27 | * 28 | */ 29 | public interface KafkaListenerObservationConvention extends ObservationConvention { 30 | 31 | @Override 32 | default boolean supportsContext(Context context) { 33 | return context instanceof KafkaRecordReceiverContext; 34 | } 35 | 36 | @Override 37 | default String getName() { 38 | return "spring.kafka.listener"; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/micrometer/KafkaTemplateObservationConvention.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support.micrometer; 18 | 19 | import io.micrometer.observation.Observation.Context; 20 | import io.micrometer.observation.ObservationConvention; 21 | 22 | /** 23 | * {@link ObservationConvention} for Kafka template key values. 24 | * 25 | * @author Gary Russell 26 | * @since 3.0 27 | * 28 | */ 29 | public interface KafkaTemplateObservationConvention extends ObservationConvention { 30 | 31 | @Override 32 | default boolean supportsContext(Context context) { 33 | return context instanceof KafkaRecordSenderContext; 34 | } 35 | 36 | @Override 37 | default String getName() { 38 | return "spring.kafka.template"; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/micrometer/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes to support Micrometer. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.support.micrometer; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Package for kafka support 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.support; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/serializer/DeserializationExceptionHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support.serializer; 18 | 19 | import org.apache.kafka.common.header.internals.RecordHeader; 20 | 21 | /** 22 | * A package-protected header used to contain serialized 23 | * {@link DeserializationException}s. Only headers of this type will be examined for 24 | * deserialization. 25 | * 26 | * @author Gary Russell 27 | * @since 2.9.11 28 | */ 29 | class DeserializationExceptionHeader extends RecordHeader { 30 | 31 | /** 32 | * Construct an instance with the provided properties. 33 | * @param key the key. 34 | * @param value the value; 35 | */ 36 | DeserializationExceptionHeader(String key, byte[] value) { 37 | super(key, value); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/serializer/JsonTypeResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support.serializer; 18 | 19 | import com.fasterxml.jackson.databind.JavaType; 20 | import org.apache.kafka.common.header.Headers; 21 | import org.jspecify.annotations.Nullable; 22 | 23 | /** 24 | * Determine the {@link JavaType} from the topic/data/headers. 25 | * 26 | * @author Gary Russell 27 | * @since 2.5.3 28 | * 29 | */ 30 | @FunctionalInterface 31 | public interface JsonTypeResolver { 32 | 33 | /** 34 | * Determine the type. 35 | * @param topic the topic. 36 | * @param data the serialized data. 37 | * @param headers the headers. 38 | * @return the type. 39 | */ 40 | JavaType resolveType(String topic, byte[] data, @Nullable Headers headers); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/support/serializer/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes related to Kafka serialization. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.support.serializer; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/transaction/KafkaAwareTransactionManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.transaction; 18 | 19 | import org.springframework.kafka.core.ProducerFactory; 20 | import org.springframework.transaction.PlatformTransactionManager; 21 | 22 | /** 23 | * A transaction manager that can provide a {@link ProducerFactory}. 24 | * 25 | * @param the key type. 26 | * @param the value type. 27 | * 28 | * @author Gary Russell 29 | * @since 2.1.3 30 | * 31 | */ 32 | public interface KafkaAwareTransactionManager extends PlatformTransactionManager { 33 | 34 | /** 35 | * Get the producer factory. 36 | * @return the producerFactory 37 | */ 38 | ProducerFactory getProducerFactory(); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /spring-kafka/src/main/java/org/springframework/kafka/transaction/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides classes related to transactions. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.kafka.transaction; 6 | -------------------------------------------------------------------------------- /spring-kafka/src/main/resources/META-INF/spring/aot.factories: -------------------------------------------------------------------------------- 1 | org.springframework.aot.hint.RuntimeHintsRegistrar=org.springframework.kafka.aot.KafkaRuntimeHints 2 | org.springframework.beans.factory.aot.BeanRegistrationAotProcessor=org.springframework.kafka.aot.KafkaAvroBeanRegistrationAotProcessor 3 | -------------------------------------------------------------------------------- /spring-kafka/src/test/java/org/springframework/kafka/listener/ErrorHandlingCoverageTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import java.util.Map; 20 | 21 | import org.junit.jupiter.api.Test; 22 | 23 | import static org.assertj.core.api.Assertions.assertThat; 24 | 25 | /** 26 | * @author Gary Russell 27 | * @since 2.9.3 28 | * 29 | */ 30 | public class ErrorHandlingCoverageTests { 31 | 32 | @Test 33 | void coverageDefault() { 34 | DefaultErrorHandler eh = new DefaultErrorHandler(); 35 | eh.addNotRetryableExceptions(IllegalStateException.class); 36 | eh.setClassifications(Map.of(IllegalArgumentException.class, false), false); 37 | assertThat(eh.removeClassification(IllegalStateException.class)).isNull(); 38 | assertThat(eh.removeClassification(IllegalArgumentException.class)).isFalse(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /spring-kafka/src/test/java/org/springframework/kafka/listener/ManualImmediateNackBatchTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.listener; 18 | 19 | import org.springframework.kafka.listener.ContainerProperties.AckMode; 20 | 21 | /** 22 | * @author Gary Russell 23 | * @since 2.8 24 | * 25 | */ 26 | public class ManualImmediateNackBatchTests extends ManualNackBatchTests { 27 | 28 | static { 29 | ackMode = AckMode.MANUAL_IMMEDIATE; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /spring-kafka/src/test/java/org/springframework/kafka/requestreply/CorrelationKeyTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.requestreply; 18 | 19 | import org.junit.jupiter.api.Test; 20 | 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | 23 | /** 24 | * @author Gary Russell 25 | * @since 2.8.10 26 | * 27 | */ 28 | public class CorrelationKeyTests { 29 | 30 | @Test 31 | void asString() { 32 | CorrelationKey key = new CorrelationKey(new byte[16]); 33 | assertThat(key.toString()).isEqualTo("00000000-0000-0000-0000-000000000000"); 34 | key = new CorrelationKey(new byte[10]); 35 | assertThat(key.toString()).isEqualTo("00000000000000000000"); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /spring-kafka/src/test/java/org/springframework/kafka/retrytopic/RetryTopicConstantsTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.retrytopic; 18 | 19 | import org.junit.jupiter.api.Test; 20 | 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | 23 | /** 24 | * @author Tomaz Fernandes 25 | * @since 2.7 26 | */ 27 | class RetryTopicConstantsTests { 28 | 29 | private static final String DEFAULT_RETRY_SUFFIX = "-retry"; 30 | 31 | private static final String DEFAULT_DLT_SUFFIX = "-dlt"; 32 | 33 | private static final int DEFAULT_MAX_ATTEMPTS = 3; 34 | 35 | private static final int NOT_SET = -1; 36 | 37 | @Test 38 | public void assertRetryTopicConstants() { 39 | new RetryTopicConstants() { }; // for coverage 40 | assertThat(RetryTopicConstants.DEFAULT_DLT_SUFFIX).isEqualTo(DEFAULT_DLT_SUFFIX); 41 | assertThat(RetryTopicConstants.DEFAULT_RETRY_SUFFIX).isEqualTo(DEFAULT_RETRY_SUFFIX); 42 | assertThat(RetryTopicConstants.DEFAULT_MAX_ATTEMPTS).isEqualTo(DEFAULT_MAX_ATTEMPTS); 43 | assertThat(RetryTopicConstants.NOT_SET).isEqualTo(NOT_SET); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /spring-kafka/src/test/java/org/springframework/kafka/retrytopic/TestClockUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.retrytopic; 18 | 19 | import java.time.Clock; 20 | import java.time.Instant; 21 | import java.time.ZoneId; 22 | 23 | /** 24 | * @author tomazlemos 25 | * @since 14/02/21 26 | */ 27 | public abstract class TestClockUtils { 28 | 29 | public static Clock CLOCK = Clock.fixed(Instant.ofEpochMilli(325587600000L), ZoneId.systemDefault()); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /spring-kafka/src/test/java/org/springframework/kafka/support/TopicPartitionOffsetTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support; 18 | 19 | import java.util.Objects; 20 | 21 | import org.apache.kafka.common.TopicPartition; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import org.springframework.kafka.support.TopicPartitionOffset.SeekPosition; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * @author Gary Russell 30 | * @since 2.3.13 31 | * 32 | */ 33 | public class TopicPartitionOffsetTests { 34 | 35 | @Test 36 | void hashCodeTest() { 37 | assertThat(new TopicPartitionOffset("foo", 1, SeekPosition.BEGINNING).hashCode()) 38 | .isNotEqualTo(new TopicPartitionOffset("foo", 1, SeekPosition.END).hashCode()); 39 | } 40 | 41 | @Test 42 | void hashCodeNPE() { 43 | assertThat(new TopicPartitionOffset("foo", 0).hashCode()) 44 | .isEqualTo(Objects.hash(new TopicPartition("foo", 0), null)); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /spring-kafka/src/test/java/org/springframework/kafka/support/serializer/testentities/DummyEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.kafka.support.serializer.testentities; 18 | 19 | import java.util.List; 20 | import java.util.Map; 21 | import java.util.Objects; 22 | 23 | /** 24 | * @author Igor Stepanov 25 | */ 26 | public class DummyEntity { 27 | 28 | public int intValue; 29 | 30 | public Long longValue; 31 | 32 | public String stringValue; 33 | 34 | public Map> complexStruct; 35 | 36 | @Override 37 | public boolean equals(Object o) { 38 | if (this == o) { 39 | return true; 40 | } 41 | if (o == null || getClass() != o.getClass()) { 42 | return false; 43 | } 44 | DummyEntity that = (DummyEntity) o; 45 | return intValue == that.intValue && 46 | Objects.equals(longValue, that.longValue) && 47 | Objects.equals(stringValue, that.stringValue) && 48 | Objects.equals(complexStruct, that.complexStruct); 49 | } 50 | 51 | @Override 52 | public int hashCode() { 53 | return Objects.hash(intValue, longValue, stringValue, complexStruct); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /spring-kafka/src/test/resources/broker.properties: -------------------------------------------------------------------------------- 1 | delete.topic.enable = false 2 | -------------------------------------------------------------------------------- /spring-kafka/src/test/resources/jaas-sample-kafka-only.conf: -------------------------------------------------------------------------------- 1 | KafkaClient { 2 | com.sun.security.auth.module.Krb5LoginModule required 3 | useKeyTab=true 4 | storeKey=true 5 | keyTab="/etc/security/keytabs/kafka_client.keytab" 6 | principal="kafka-client-1@EXAMPLE.COM"; 7 | }; 8 | -------------------------------------------------------------------------------- /spring-kafka/src/test/resources/log4j2-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/api/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | This document is the API specification for Spring for Apache Kafka project 4 |


5 |
6 |

7 | For further API reference and developer documentation, see the 8 | Spring 9 | for Apache Kafka reference documentation. 10 | That documentation contains more detailed, developer-targeted 11 | descriptions, with conceptual overviews, definitions of terms, 12 | workarounds, and working code examples. 13 |

14 | 15 |

16 | If you are interested in commercial consultancy, and 17 | support for Spring for Apache Kafka, please visit 18 | https://spring.io/ 19 |

20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /src/checkstyle/checkstyle-header.txt: -------------------------------------------------------------------------------- 1 | ^\Q/*\E$ 2 | ^\Q * Copyright \E20\d\d(\-20\d\d)?\Q the original author or authors.\E$ 3 | ^\Q *\E$ 4 | ^\Q * Licensed under the Apache License, Version 2.0 (the "License");\E$ 5 | ^\Q * you may not use this file except in compliance with the License.\E$ 6 | ^\Q * You may obtain a copy of the License at\E$ 7 | ^\Q *\E$ 8 | ^\Q * https://www.apache.org/licenses/LICENSE-2.0\E$ 9 | ^\Q *\E$ 10 | ^\Q * Unless required by applicable law or agreed to in writing, software\E$ 11 | ^\Q * distributed under the License is distributed on an "AS IS" BASIS,\E$ 12 | ^\Q * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\E$ 13 | ^\Q * See the License for the specific language governing permissions and\E$ 14 | ^\Q * limitations under the License.\E$ 15 | ^\Q */\E$ 16 | ^$ 17 | ^.*$ 18 | -------------------------------------------------------------------------------- /src/checkstyle/checkstyle-suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/dist/notice.txt: -------------------------------------------------------------------------------- 1 | Spring for Apache Kafka Framework ${version} 2 | Copyright (c) 2016-${copyright} Pivotal, Inc. 3 | 4 | This product is licensed to you under the Apache License, Version 2.0 5 | (the "License"). You may not use this product except in compliance with 6 | the License. 7 | 8 | This product may include a number of subcomponents with separate 9 | copyright notices and license terms. Your use of the source code for 10 | these subcomponents is subject to the terms and conditions of the 11 | subcomponent's license, as noted in the license.txt file. 12 | --------------------------------------------------------------------------------