Configuration¶
Options for the proto-confluent Flink Table format. Prefix each with the role
namespace in CREATE TABLE — e.g. value.proto-confluent.url or
key.proto-confluent.url.
| Option | Default | Description |
|---|---|---|
url |
(required) | Confluent Schema Registry URL (fallback key: schema-registry.url). |
topic |
(required) | Kafka topic used to derive the schema subject (<topic>-key / <topic>-value). |
is_key |
false |
Whether this format instance encodes/decodes the Kafka key. Set true on a key.format. |
message-class |
(none) | Fully-qualified generated protobuf message class used for serialization and schema registration instead of a dynamic (Row-derived) schema. Applies to the key when is_key is true and to the value otherwise. |
auto-register-schemas |
false |
Register the schema with the registry on write. |
normalize-schemas |
true |
Normalize schemas before registration/lookup. |
use-schema-id |
-1 |
Fixed schema ID for serialization (-1 = auto). |
skip-known-types |
true |
Skip well-known types during schema handling. |
on-deserialize-error |
fail |
fail (throw and fail the task) or skip (log, count, drop the poison record). Matched case-insensitively; any other value (including a typo) is treated as skip. |
dead-letter-topic |
(none) | Topic that receives raw bytes of records that fail to deserialize. Requires dead-letter.properties.bootstrap.servers; without it no producer is created and failures are only logged and counted (a WARN is logged at open). |
SSL (ssl.keystore.*, ssl.truststore.*), auth (basic-auth.*,
bearer-auth.*), properties, and dead-letter.properties are also supported.
Option precedence and validation¶
- Typed options beat tunneled
properties. Anything set through the rawpropertiesmap is applied first, then the typed Flink options overwrite it. Setting bothproperties.basic.auth.user.infoandbasic-auth.user-infotherefore resolves to the typedbasic-auth.user-infovalue; the same holds forbasic-auth.credentials-source,bearer-auth.*,ssl.keystore.*,ssl.truststore.*, andmessage-class. A tunneled key survives untouched only when its typed counterpart is unset. on-deserialize-erroris not validated. Onlyfail(case-insensitive) is fatal; every other value, valid or not, takes theskippath — the error is logged,numDeserializeErrorsis incremented, the record is optionally routed to the dead-letter topic, andnullis returned. A typo therefore silently disables fail-fast behavior.urlandtopicare required. Omitting either makes format creation fail with a FlinkValidationExceptionfromFactoryUtil.validateFactoryOptions("Missing required options"), for both the decoding and the encoding format.- A dead-letter topic without
bootstrap.serversis a no-op.dead-letter-topicalone does not fail the job; the producer is skipped and a WARN is logged.
Explicit key and value message classes¶
By default a sink derives a dynamic protobuf schema from the Flink Row
type. To instead pin an explicit named entity (a generated protobuf message
class) for the key and/or the value, set message-class on the corresponding
format. The format registers and serializes with that message's descriptor, so
downstream consumers can read the topic with a specific (strongly typed)
protobuf type.
CREATE TABLE keyed_sink (
`k_id` STRING, -- key column (prefixed)
`payload` STRING, -- value columns
`event_ts` STRING
) WITH (
'connector' = 'kafka',
'topic' = 'orders',
'properties.bootstrap.servers' = 'kafka:9092',
-- Key: explicit named message class
'key.format' = 'proto-confluent',
'key.fields' = 'k_id',
'key.fields-prefix' = 'k_',
'key.proto-confluent.url' = 'http://schema-registry:8081',
'key.proto-confluent.topic' = 'orders',
'key.proto-confluent.is_key' = 'true',
'key.proto-confluent.auto-register-schemas' = 'true',
'key.proto-confluent.message-class' = 'com.example.OrderProto$OrderKey',
-- Value: explicit named message class
'value.format' = 'proto-confluent',
'value.fields-include' = 'EXCEPT_KEY',
'value.proto-confluent.url' = 'http://schema-registry:8081',
'value.proto-confluent.topic' = 'orders',
'value.proto-confluent.is_key' = 'false',
'value.proto-confluent.auto-register-schemas' = 'true',
'value.proto-confluent.message-class' = 'com.example.OrderProto$Order'
)
Notes:
message-classis role-scoped byis_key: on akey.format(is_key = true) it sets the key message class; on avalue.formatit sets the value message class.- Use
key.fields-prefixwhen the same protobuf message backs both the key and the value, so the prefixed key columns still map to the proto field names once the prefix is stripped. - When
message-classis unset the format keeps the previous dynamic-schema behavior. - The class name is the JVM binary name — nested/generated message classes use
$(e.g.com.example.OrderProto$Order).
Schema evolution and subject naming¶
A source decodes each record with the writer schema named by the schema ID in the record's Confluent wire header, so a topic holding records written under several schema versions is read without extra configuration.
- Columns added in a later version. A table column that does not exist in the writer's schema is read as
NULL(and logged once per converter atWARN), so a table declared against v2 still reads v1 records. The same warning is how a mistyped column name surfaces: it becomes an always-NULLcolumn. - Columns removed in a later version. Declare only the columns the table needs; columns the writer no longer has follow the rule above.
use-schema-id. Pins the schema ID stamped into the wire header on a sink. The schema must already be registered under the subject.auto-register-schemas. Withfalse(the default), writing to a subject that has no registered schema fails instead of silently registering one. Withtrue, a change the registry rejects under the subject's compatibility level fails the job with the registry's error.normalize-schemas. The format always registers schemas derived from a protobuf descriptor, and those are already in Confluent's normalized form, so this option does not change what a sink registers. It does not retroactively match a denormalized schema that is already stored in the registry — that registers as a new version.- Subject-naming strategy. There is no dedicated option; set it through the
propertiespassthrough, e.g.'value.proto-confluent.properties' = 'value.subject.name.strategy:io.confluent.kafka.serializers.subject.RecordNameStrategy'. Strategies that derive the subject from the record rather than the topic requiremessage-classor a Row-derived schema, since no subject can be named before a schema exists.