A lightweight Kafka Streams application that reads temperature events from Kafka, transforms them, and writes a normalized output event using Confluent JSON Schema SerDe.
- Consumes string-key/string-value records from topic
temp - Expects input values to be JSON containing a top-level
payloadobject - Extracts metadata and measurement fields from that payload
- Converts temperature from Fahrenheit to Celsius
- Adds a UTC processing timestamp
- Publishes typed
ProcessedTemprecords toprocessed_KafkaStreams_temp - Registers and uses JSON Schema via Schema Registry
- Java 17
- Apache Kafka Streams
3.6.0 - Jackson Databind
2.15.2 - Confluent JSON Schema SerDe
7.9.0 - Maven
src/main/java/org/example/
├── KafkaStreamsProcessors.java # Stream topology + app bootstrap
└── ProcessedTemp.java # Output event model for JSON Schema SerDe
- Read from input topic
tempas<String, String> - Parse JSON message body
- Read fields from
payload - Build
ProcessedTemp - Compute
UPDATED_TEMPERATURE_CELSIUS = (F - 32) * 5 / 9 - Filter out invalid messages (parse errors or malformed data)
- Write to
processed_KafkaStreams_tempas<String, ProcessedTemp>
If a record is invalid, it is skipped and logged to stderr.
These values are hardcoded in KafkaStreamsProcessors:
- Kafka bootstrap server:
kafka:9092 - Schema Registry URL:
http://schema-registry:8081 - Streams application id:
temperature_processor - Input topic:
temp - Output topic:
processed_KafkaStreams_temp
This setup is typically intended for a Docker network where service names are kafka and schema-registry.
Before running the app, make sure you have:
- Java 17 installed
- Maven installed
- A running Kafka broker reachable at
kafka:9092(or update code) - A running Schema Registry reachable at
http://schema-registry:8081(or update code) - Input and output topics created
mvn clean packageCopy the created JAR from target/ into the docker project KafkaStreams folder, then build the Docker image:
docker build -t kafkastreams .Run the application container:
docker run -it --rm --name KafkaStreamsProcessors --network kafka-docker_kafka_network kafkastreams java -cp app.jar org.example.KafkaStreamsProcessorsYou should see logs similar to:
Listening to topic: tempKafka Streams processor started.
The stream logic expects input values with this shape:
{
"payload": {
"message_id": "abc-123",
"timestamp": "2026-03-16T10:00:00.000000000",
"kafka_timestamp": "2026-03-16T10:00:00.000000000",
"temperature": 77.0,
"payload": "optional raw payload text"
}
}- Kafka record key ->
PRODUCER payload.message_id->MESSAGE_IDpayload.timestamp->PRODUCED_TIMESTAMPpayload.kafka_timestamp->KAFKA_TIMESTAMPpayload.temperature->TEMPERATURE_FAHRENHEIT- Derived ->
UPDATED_TEMPERATURE_CELSIUS - Processing time (UTC now) ->
PROCESSED_TIMESTAMP payload.payload->PAYLOAD
Output records are written with JSON Schema SerDe as ProcessedTemp:
PRODUCER(String)MESSAGE_ID(String)TEMPERATURE_FAHRENHEIT(Double)UPDATED_TEMPERATURE_CELSIUS(Double)PRODUCED_TIMESTAMP(String)KAFKA_TIMESTAMP(String)PROCESSED_TIMESTAMP(String)PAYLOAD(String)
- Start Kafka + Schema Registry
- Start this app
- Produce a test event into topic
temp - Consume from
processed_KafkaStreams_tempand verify transformed fields
If your broker tools are available, your producer input can use:
{"payload":{"message_id":"m-1","timestamp":"2026-03-16T10:00:00.000000000","kafka_timestamp":"2026-03-16T10:00:00.000000000","temperature":86.0,"payload":"sensor-a"}}Expected Celsius value:
86.0F->30.0C
- Invalid JSON or missing/incorrect structure leads to record skip
- Skipped records are logged with key and error message
- Uncaught stream exceptions trigger application shutdown
- Graceful shutdown hook closes streams with timeout
- Cannot connect to Kafka: verify
kafka:9092is resolvable from where the app runs - Cannot connect to Schema Registry: verify
http://schema-registry:8081is reachable - No output records: confirm input JSON has top-level
payloadobject - Records skipped: check stderr logs for parse/validation messages
- Make bootstrap servers, topic names, and registry URL configurable via environment variables