Enhance your career, get your certificate as a Data Streaming Engineer | Get your Certificate
It's sometimes advantageous to produce distinct but related event types to the same topic, e.g., to guarantee the exact order of different events for the same key. For example, consider pageview and purchase records associated with the same customer ID. In order to properly attribute purchases to preceding pageviews, these distinct events must be sent to the same topic so that the order is preserved in one Kafka topic partition. But, let's say we also need to maintain the topic-name subject constraints with Schema Registry.
To accomplish this with Avro-formatted events, we can use a top-level union schema whose branches are the distinct record types.
The example in this tutorial uses a top-level Avro schema specifying that a record is either a purchase or a pageview:
[
{
"type":"record",
"namespace": "io.confluent.developer.avro",
"name":"Purchase",
"fields": [
{"name": "item", "type":"string"},
{"name": "amount", "type": "double"},
{"name": "customer_id", "type": "string"}
]
},
{
"type":"record",
"namespace": "io.confluent.developer.avro",
"name":"Pageview",
"fields": [
{"name": "url", "type":"string"},
{"name": "is_special", "type": "boolean"},
{"name": "customer_id", "type": "string"}
]
}
]Now, if you use the top-level schema for a topic, then you can produce either io.confluent.developer.avro.Purchase or io.confluent.developer.avro.Pageview records to the topic. Only this top-level union schema is registered in Schema Registry (as the avro-events-value subject); the individual Purchase and Pageview types are not registered as separate subjects.
In order to run this example, first clone the confluentinc/tutorials GitHub repository (if you haven't already) and navigate to the tutorials directory:
git clone git@github.com:confluentinc/tutorials.git
cd tutorialsNow you can either execute the unit test included with the example, or run the example in Docker or in Confluent Cloud.
To run the unit tests, use the provided Gradle Wrapper:
./gradlew clean :multiple-event-types-avro:kafka:test --info Start Kafka by running:
docker compose -f ./docker/docker-compose-kafka-sr.yml up -dCreate the avro-events topic:
docker exec -t broker kafka-topics --create --topic avro-events --bootstrap-server broker:9092Run the following task to register the schemas in Schema Registry:
./gradlew :multiple-event-types-avro:kafka:registerSchemasTaskBuild the application uberjar:
./gradlew :multiple-event-types-avro:kafka:shadowJarRun the application, which produces and consumes pageview and purchase events, with the following command:
java -jar multiple-event-types-avro/kafka/build/libs/multiple-event-types-avro-standalone-0.0.1.jar \
multiple-event-types-avro/kafka/local.propertiesStop Kafka and Schema Registry:
docker compose -f ./docker/docker-compose-kafka-sr.yml downgit clone git@github.com:confluentinc/tutorials.git
cd tutorialsLog in to your Confluent Cloud account:
confluent login --prompt --saveInstall a CLI plugin that will streamline the creation of resources in Confluent Cloud:
confluent plugin install confluent-quickstartRun the plugin from the top-level directory of the tutorials repository to create the Confluent Cloud resources needed for this tutorial.
Note: You may specify a different cloud provider (gcp or azure) or region. You can find supported regions in a given cloud provider by running confluent kafka region list --cloud <CLOUD>.
confluent quickstart \
--environment-name kafka-multiple-event-types-env \
--kafka-cluster-name kafka-multiple-event-types-cluster \
--create-kafka-key \
--create-sr-key \
--kafka-java-properties-file multiple-event-types-avro/kafka/cloud.propertiesThe plugin should complete in under a minute.
Create the topic for the application:
confluent kafka topic create avro-eventsBefore registering the schemas, update the schemaRegistry block in multiple-event-types-avro/kafka/build.gradle to point at your Confluent Cloud Schema Registry cluster and authenticate with a clientConfig. Populate the placeholders below with the corresponding schema.registry.url and basic.auth.user.info values from multiple-event-types-avro/kafka/cloud.properties:
schemaRegistry {
url = '<SCHEMA_REGISTRY_URL>'
clientConfig = [
'basic.auth.credentials.source': 'USER_INFO',
'basic.auth.user.info' : '<SCHEMA_REGISTRY_API_KEY>:<SCHEMA_REGISTRY_API_SECRET>'
]
register {
subject('avro-events-value', 'multiple-event-types-avro/kafka/src/main/avro/all-events.avsc', "AVRO")
}
}Then, run the following task to register the schemas in Schema Registry:
./gradlew :multiple-event-types-avro:kafka:registerSchemasTaskIn the Confluent Cloud Console, navigate to Topics in the left-hand navigation, select the avro-events topic, and click Data contract. Validate that a Value schema has been set.
Build the application uberjar:
./gradlew :multiple-event-types-avro:kafka:shadowJarRun the application, which produces and consumes pageview and purchase events, with the following command. Note that we are passing the client configuration as an argument:
java -jar multiple-event-types-avro/kafka/build/libs/multiple-event-types-avro-standalone-0.0.1.jar \
multiple-event-types-avro/kafka/cloud.propertiesIn the Confluent Cloud Console, select the Messages tab for the avro-events topic and view the messages that are produced.
When you are finished, delete the kafka-multiple-event-types-env environment by first getting the environment ID of the form env-123456 corresponding to it:
confluent environment listDelete the environment, including all resources created for this tutorial:
confluent environment delete <ENVIRONMENT ID>