From f44c735daf3ebdc5f55ca66a4000e240fbe79d9a Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Wed, 1 Apr 2026 15:19:34 +0200 Subject: [PATCH] feat(samples): Add Kafka producer and consumer to Spring Boot 3 sample app Add spring-kafka dependency and a simple Kafka producer/consumer setup behind a 'kafka' Spring profile. Includes a REST endpoint to produce messages and a KafkaListener that consumes them. Kafka auto-configuration is excluded by default and only activated when the 'kafka' profile is enabled. Co-Authored-By: Claude --- gradle/libs.versions.toml | 1 + .../build.gradle.kts | 3 +++ .../spring/boot/jakarta/KafkaConsumer.java | 19 ++++++++++++++ .../spring/boot/jakarta/KafkaController.java | 26 +++++++++++++++++++ .../resources/application-kafka.properties | 9 +++++++ .../src/main/resources/application.properties | 4 +++ 6 files changed, 62 insertions(+) create mode 100644 sentry-samples/sentry-samples-spring-boot-jakarta/src/main/java/io/sentry/samples/spring/boot/jakarta/KafkaConsumer.java create mode 100644 sentry-samples/sentry-samples-spring-boot-jakarta/src/main/java/io/sentry/samples/spring/boot/jakarta/KafkaController.java create mode 100644 sentry-samples/sentry-samples-spring-boot-jakarta/src/main/resources/application-kafka.properties diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index eb7ab86e4b..bede68144b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -183,6 +183,7 @@ springboot3-starter-security = { module = "org.springframework.boot:spring-boot- springboot3-starter-jdbc = { module = "org.springframework.boot:spring-boot-starter-jdbc", version.ref = "springboot3" } springboot3-starter-actuator = { module = "org.springframework.boot:spring-boot-starter-actuator", version.ref = "springboot3" } springboot3-starter-cache = { module = "org.springframework.boot:spring-boot-starter-cache", version.ref = "springboot3" } +spring-kafka3 = { module = "org.springframework.kafka:spring-kafka", version = "3.3.5" } springboot4-otel = { module = "io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter", version.ref = "otelInstrumentation" } springboot4-resttestclient = { module = "org.springframework.boot:spring-boot-resttestclient", version.ref = "springboot4" } springboot4-starter = { module = "org.springframework.boot:spring-boot-starter", version.ref = "springboot4" } diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts index a945b87109..e100f6a5ad 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts @@ -59,6 +59,9 @@ dependencies { implementation(libs.springboot3.starter.cache) implementation(libs.caffeine) + // kafka + implementation(libs.spring.kafka3) + // OpenFeature SDK implementation(libs.openfeature) diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/java/io/sentry/samples/spring/boot/jakarta/KafkaConsumer.java b/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/java/io/sentry/samples/spring/boot/jakarta/KafkaConsumer.java new file mode 100644 index 0000000000..8287d9a05a --- /dev/null +++ b/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/java/io/sentry/samples/spring/boot/jakarta/KafkaConsumer.java @@ -0,0 +1,19 @@ +package io.sentry.samples.spring.boot.jakarta; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.stereotype.Component; + +@Component +@Profile("kafka") +public class KafkaConsumer { + + private static final Logger logger = LoggerFactory.getLogger(KafkaConsumer.class); + + @KafkaListener(topics = "sentry-topic", groupId = "sentry-sample-group") + public void listen(String message) { + logger.info("Received message: {}", message); + } +} diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/java/io/sentry/samples/spring/boot/jakarta/KafkaController.java b/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/java/io/sentry/samples/spring/boot/jakarta/KafkaController.java new file mode 100644 index 0000000000..b65236c919 --- /dev/null +++ b/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/java/io/sentry/samples/spring/boot/jakarta/KafkaController.java @@ -0,0 +1,26 @@ +package io.sentry.samples.spring.boot.jakarta; + +import org.springframework.context.annotation.Profile; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Profile("kafka") +@RequestMapping("/kafka") +public class KafkaController { + + private final KafkaTemplate kafkaTemplate; + + public KafkaController(KafkaTemplate kafkaTemplate) { + this.kafkaTemplate = kafkaTemplate; + } + + @GetMapping("/produce") + String produce(@RequestParam(defaultValue = "hello from sentry!") String message) { + kafkaTemplate.send("sentry-topic", message); + return "Message sent: " + message; + } +} diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/resources/application-kafka.properties b/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/resources/application-kafka.properties new file mode 100644 index 0000000000..a943f203c8 --- /dev/null +++ b/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/resources/application-kafka.properties @@ -0,0 +1,9 @@ +# Kafka — activate with: --spring.profiles.active=kafka +spring.autoconfigure.exclude= +spring.kafka.bootstrap-servers=localhost:9092 +spring.kafka.consumer.group-id=sentry-sample-group +spring.kafka.consumer.auto-offset-reset=earliest +spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer +spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer +spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer +spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/resources/application.properties b/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/resources/application.properties index 60b92d369d..6a3dfb063b 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/resources/application.properties +++ b/sentry-samples/sentry-samples-spring-boot-jakarta/src/main/resources/application.properties @@ -37,6 +37,10 @@ spring.quartz.job-store-type=memory # Cache tracing sentry.enable-cache-tracing=true + +# Kafka is only active with the 'kafka' profile (--spring.profiles.active=kafka) +spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration + spring.cache.cache-names=todos spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s