diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index 7e2b4cc06ac85..4a4a60f8b5cd1 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -194,8 +194,7 @@
2.25.2
1.3.1.Final
1.12.0
- 2.6.13.Final
- 0.1.18.Final
+ 3.1.2
2.0.2
3.7.0
@@ -3928,24 +3927,19 @@
io.apicurio
- apicurio-registry-client
+ apicurio-registry-schema-resolver
${apicurio-registry.version}
io.apicurio
- apicurio-registry-serdes-avro-serde
+ apicurio-registry-avro-serde-kafka
${apicurio-registry.version}
io.apicurio
- apicurio-registry-serdes-jsonschema-serde
+ apicurio-registry-jsonschema-serde-kafka
${apicurio-registry.version}
-
- io.apicurio
- apicurio-common-rest-client-vertx
- ${apicurio-common-rest-client.version}
-
io.quarkus
quarkus-mutiny
diff --git a/build-parent/pom.xml b/build-parent/pom.xml
index a893c01246b2b..0fc3300b6297c 100644
--- a/build-parent/pom.xml
+++ b/build-parent/pom.xml
@@ -113,7 +113,7 @@
quay.io/artemiscloud/activemq-artemis-broker:1.0.25
- quay.io/apicurio/apicurio-registry-mem:2.6.13.Final
+ quay.io/apicurio/apicurio-registry:3.1.4
quay.io/jbosstm/lra-coordinator:latest
docker.io/library/rabbitmq:3.12-management
docker.io/apachepulsar/pulsar:3.2.4
diff --git a/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc b/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc
index 7a539a66901a4..6fa3be349052d 100644
--- a/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc
+++ b/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc
@@ -17,9 +17,9 @@ This automatic configuration only applies to serializers and deserializers from
[source,properties]
----
# for Apicurio Registry serde
-mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v2
+mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v3
# for Confluent Schema Registry serde
-mp.messaging.connector.smallrye-kafka.schema.registry.url=http://localhost:8081/apis/ccompat/v6
+mp.messaging.connector.smallrye-kafka.schema.registry.url=http://localhost:8081/apis/ccompat/v7
----
@@ -72,12 +72,12 @@ Note that the Kafka channels in SmallRye Reactive messaging are automatically co
== Configuring the image
-Dev Services for Apicurio Registry uses `apicurio/apicurio-registry-mem` images.
-You can select any 2.x version from https://hub.docker.com/r/apicurio/apicurio-registry-mem:
+Dev Services for Apicurio Registry uses `apicurio/apicurio-registry` images. These images use an in-memory h2 database by default.
+You can select any 3.x version from https://hub.docker.com/r/apicurio/apicurio-registry:
[source,properties,subs=attributes+]
----
-quarkus.apicurio-registry.devservices.image-name={apicurio-registry-image}
+quarkus.apicurio-registry.devservices.image-name=apicurio/apicurio-registry:latest-snapshot
----
[[Compose]]
diff --git a/docs/src/main/asciidoc/apicurio-registry-v3-migration.adoc b/docs/src/main/asciidoc/apicurio-registry-v3-migration.adoc
new file mode 100644
index 0000000000000..f58a550099b00
--- /dev/null
+++ b/docs/src/main/asciidoc/apicurio-registry-v3-migration.adoc
@@ -0,0 +1,306 @@
+////
+This guide is maintained in the main Quarkus repository
+and pull requests should be submitted there:
+https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
+////
+= Migrating to Apicurio Registry 3.x
+include::_attributes.adoc[]
+:categories: messaging
+:summary: Guide for migrating from Apicurio Registry 2.x to 3.x in Quarkus applications.
+:topics: messaging,kafka,apicurio,registry,migration
+:extensions: io.quarkus:quarkus-apicurio-registry-avro,io.quarkus:quarkus-messaging-kafka
+
+This guide covers the migration path from Apicurio Registry 2.x to 3.x for Quarkus applications using Kafka with schema registry serialization.
+
+IMPORTANT: Apicurio Registry 3.x introduces a **breaking change in schema ID format** from 8-byte (long) to 4-byte (int) identifiers. This affects message compatibility between v2 and v3 producers/consumers.
+
+== Overview of Changes
+
+Quarkus has upgraded to Apicurio Registry 3.1.2. This upgrade includes:
+
+* **New API endpoints**: `/apis/registry/v3` (was `/v2`)
+* **New Confluent compatibility endpoint**: `/apis/ccompat/v7` (was `/v6`)
+* **Changed schema ID format**: 4-byte integer IDs by default (was 8-byte long)
+* **Package restructuring**: Some configuration classes have been renamed
+* **New Kiota-based client**: REST client uses Microsoft Kiota for code generation
+
+== Breaking Changes
+
+=== Schema ID Format (Critical)
+
+The most significant breaking change is the schema ID format:
+
+[cols="1,1,2"]
+|===
+|Version |ID Format |ID Handler Class
+
+|v2.x
+|8-byte (long)
+|Default behavior (no handler needed)
+
+|v3.x
+|4-byte (int)
+|`io.apicurio.registry.serde.Default4ByteIdHandler`
+|===
+
+Messages produced with v2.x cannot be consumed by v3.x (and vice versa) without explicit configuration.
+
+=== API Endpoint Changes
+
+[cols="1,1,1"]
+|===
+|Endpoint |v2.x |v3.x
+
+|Apicurio API
+|`/apis/registry/v2`
+|`/apis/registry/v3`
+
+|Confluent Compat
+|`/apis/ccompat/v6`
+|`/apis/ccompat/v7`
+|===
+
+The Quarkus Dev Services automatically configures the correct endpoints for v3.x.
+
+== Migration Scenarios
+
+=== Scenario 1: New Application (Greenfield)
+
+For new applications starting fresh with Apicurio Registry 3.x, no special configuration is needed. The default 4-byte schema IDs will be used automatically.
+
+[source,properties]
+----
+# No special configuration required - v3 defaults are used
+# Dev Services will start Apicurio Registry 3.x automatically
+----
+
+=== Scenario 2: Migrating from v2 (No Existing Messages)
+
+If you are upgrading from v2 but don't have existing messages in Kafka topics that need to be consumed, you can migrate directly to v3 defaults:
+
+1. Upgrade Quarkus to the version with Apicurio Registry 3.x
+2. Clear or recreate your Kafka topics
+3. Restart your application - new messages will use 4-byte IDs
+
+=== Scenario 3: Consuming Existing v2 Messages
+
+If you need to consume messages that were produced with Apicurio Registry 2.x, configure the `Legacy8ByteIdHandler`:
+
+[source,properties]
+----
+# Configure consumer to read v2 messages with 8-byte schema IDs
+mp.messaging.incoming.movies.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
+----
+
+Or configure globally for all channels:
+
+[source,properties]
+----
+# Configure all consumers to use Legacy8ByteIdHandler
+mp.messaging.connector.smallrye-kafka.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
+----
+
+=== Scenario 4: Mixed v2/v3 Environment
+
+During a gradual migration where some services use v2 and others use v3:
+
+**v3 service consuming from v2 producers:**
+[source,properties]
+----
+# Consumer reads v2 messages
+mp.messaging.incoming.from-v2-service.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
+----
+
+**v3 service producing for v2 consumers:**
+[source,properties]
+----
+# Producer writes v2-compatible messages
+mp.messaging.outgoing.to-v2-service.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
+----
+
+== Configuration Reference
+
+=== ID Handler Options
+
+[cols="2,1,3"]
+|===
+|Handler Class |ID Size |Use Case
+
+|`io.apicurio.registry.serde.Default4ByteIdHandler`
+|4 bytes
+|Default for v3.x, new applications
+
+|`io.apicurio.registry.serde.Legacy8ByteIdHandler`
+|8 bytes
+|Backward compatibility with v2.x messages
+|===
+
+=== Configuration Properties
+
+[cols="2,3"]
+|===
+|Property |Description
+
+|`apicurio.registry.id-handler`
+|Fully qualified class name of the ID handler to use
+
+|`apicurio.registry.url`
+|URL of the Apicurio Registry (auto-configured by Dev Services)
+
+|`quarkus.apicurio-registry.devservices.image-name`
+|Docker image for Dev Services (default: `quay.io/apicurio/apicurio-registry:3.1.2`)
+|===
+
+=== Per-Channel vs Global Configuration
+
+**Per-channel configuration:**
+[source,properties]
+----
+# Incoming channel
+mp.messaging.incoming.my-channel.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
+
+# Outgoing channel
+mp.messaging.outgoing.my-channel.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
+----
+
+**Global configuration (all channels):**
+[source,properties]
+----
+mp.messaging.connector.smallrye-kafka.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
+----
+
+== Code Changes
+
+If you use Apicurio Registry APIs directly in your code, the following changes are required:
+
+=== Package Renames
+
+[cols="1,1"]
+|===
+|v2 Import |v3 Import
+
+|`io.apicurio.registry.serde.avro.AvroKafkaSerdeConfig`
+|`io.apicurio.registry.serde.avro.AvroSerdeConfig`
+|===
+
+=== Vertx Setup (Internal/Advanced)
+
+If you manually configure Vertx for the registry client:
+
+**v2 code:**
+[source,java]
+----
+import io.apicurio.registry.resolver.AbstractSchemaResolver;
+
+AbstractSchemaResolver.setVertx(vertx);
+----
+
+**v3 code:**
+[source,java]
+----
+import io.apicurio.registry.resolver.client.RegistryClientFacadeFactory;
+
+RegistryClientFacadeFactory.vertx = vertx;
+----
+
+NOTE: Most applications don't need to make this change - Quarkus handles Vertx configuration automatically.
+
+== Dev Services Configuration
+
+Dev Services for Apicurio Registry automatically starts a 3.x registry in dev and test modes:
+
+[source,properties]
+----
+# Override the default image if needed
+quarkus.apicurio-registry.devservices.image-name=quay.io/apicurio/apicurio-registry:3.1.2
+
+# Disable Dev Services if using an external registry
+quarkus.apicurio-registry.devservices.enabled=false
+----
+
+The registry URL is automatically configured:
+[source,properties]
+----
+# These are set automatically by Dev Services:
+mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v3
+mp.messaging.connector.smallrye-kafka.schema.registry.url=http://localhost:8081/apis/ccompat/v7
+----
+
+== Testing Both Modes
+
+To validate that your application works correctly with both v2 and v3 ID formats, you can create tests that explicitly configure each mode:
+
+[source,java]
+----
+@QuarkusTest
+public class SchemaRegistryCompatibilityTest {
+
+ @Test
+ public void testV2CompatibilityMode() {
+ // Configure Legacy8ByteIdHandler for this test
+ Map config = new HashMap<>();
+ config.put("apicurio.registry.id-handler",
+ "io.apicurio.registry.serde.Legacy8ByteIdHandler");
+
+ // Test produce and consume with 8-byte IDs
+ // ...
+ }
+
+ @Test
+ public void testV3NativeMode() {
+ // Uses default Default4ByteIdHandler
+
+ // Test produce and consume with 4-byte IDs
+ // ...
+ }
+}
+----
+
+== Migration Checklist
+
+Use this checklist when migrating from Apicurio Registry 2.x to 3.x:
+
+* [ ] Assess existing Kafka topics for v2 messages that need to be consumed
+* [ ] Configure `Legacy8ByteIdHandler` for channels consuming v2 messages
+* [ ] Update any direct API calls using `AvroKafkaSerdeConfig` to `AvroSerdeConfig`
+* [ ] Update any direct API calls using `AbstractSchemaResolver.setVertx()` to `RegistryClientFacadeFactory.vertx`
+* [ ] Test consumer compatibility with existing messages
+* [ ] Test producer compatibility with downstream consumers
+* [ ] Plan topic migration or dual-write strategy if needed
+
+== Troubleshooting
+
+=== "Unknown magic byte" Error
+
+This error indicates a mismatch in schema ID format between producer and consumer:
+
+[source]
+----
+io.apicurio.registry.serde.SerdeException: Unknown magic byte!
+----
+
+**Solution:** Configure the consumer with the same ID handler used by the producer:
+[source,properties]
+----
+mp.messaging.incoming.my-channel.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
+----
+
+=== Schema Not Found
+
+If schemas aren't being found after migration:
+
+1. Verify the registry URL is correct (`/apis/registry/v3` for v3)
+2. Check that the registry container is running (Dev Services should start it automatically)
+3. Verify schema compatibility settings in the registry
+
+=== Verbose CDI Messages
+
+If you see `Successfully retrieved a Vertx instance from CDI` INFO messages, these are normal but suppressed by default in Quarkus. If they appear, verify your Quarkus version includes the log suppression fix.
+
+== Additional Resources
+
+* https://www.apicur.io/registry/docs/apicurio-registry/3.0.x/index.html[Apicurio Registry 3.x Documentation]
+* https://www.apicur.io/blog/2025/03/30/migrate-registry-2-to-3[Official Apicurio Migration Guide]
+* https://www.apicur.io/blog/2025/04/03/evolving-serialization[Apicurio SerDes Evolution Blog Post]
+* xref:kafka-schema-registry-avro.adoc[Using Apache Kafka with Schema Registry and Avro]
+* xref:apicurio-registry-dev-services.adoc[Dev Services for Apicurio Registry]
diff --git a/docs/src/main/asciidoc/kafka-schema-registry-avro.adoc b/docs/src/main/asciidoc/kafka-schema-registry-avro.adoc
index 3bd1e50b4dc34..72272ad0abbb0 100644
--- a/docs/src/main/asciidoc/kafka-schema-registry-avro.adoc
+++ b/docs/src/main/asciidoc/kafka-schema-registry-avro.adoc
@@ -360,7 +360,7 @@ And run it in JVM mode with:
[source, bash]
----
-java -Dmp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v2 -jar target/quarkus-app/quarkus-run.jar
+java -Dmp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v3 -jar target/quarkus-app/quarkus-run.jar
----
NOTE: By default, the application tries to connect to a Kafka broker listening at `localhost:9092`.
@@ -370,7 +370,7 @@ Specifying the registry URL on the command line is not very convenient, so you c
[source,properties]
----
-%prod.mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v2
+%prod.mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v3
----
You can build a native executable with:
@@ -567,13 +567,13 @@ public class KafkaAndSchemaRegistryTestResource implements QuarkusTestResourceLi
@Override
public Map start() {
kafka.start();
- registry = new GenericContainer<>("apicurio/apicurio-registry-mem:2.4.2.Final")
+ registry = new GenericContainer<>("apicurio/apicurio-registry:3.0.6")
.withExposedPorts(8080)
.withEnv("QUARKUS_PROFILE", "prod");
registry.start();
Map properties = new HashMap<>();
properties.put("mp.messaging.connector.smallrye-kafka.apicurio.registry.url",
- "http://" + registry.getHost() + ":" + registry.getMappedPort(8080) + "/apis/registry/v2");
+ "http://" + registry.getHost() + ":" + registry.getMappedPort(8080) + "/apis/registry/v3");
properties.put("kafka.bootstrap.servers", kafka.getBootstrapServers());
return properties;
}
@@ -595,116 +595,6 @@ public class MovieResourceTest {
}
----
-[[apicurio-versions-compatibility]]
-== Using compatible versions of the Apicurio Registry
-
-The `quarkus-apicurio-registry-avro` extension depends on recent versions of Apicurio Registry client,
-and most versions of Apicurio Registry server and client are backwards compatible.
-For some you need to make sure that the client used by Serdes is compatible with the server.
-
-For example, with Apicurio Dev Service if you set the image name to use version `2.1.5.Final`:
-
-[source,properties]
-----
-quarkus.apicurio-registry.devservices.image-name=quay.io/apicurio/apicurio-registry-mem:2.1.5.Final
-----
-
-You need to make sure that `apicurio-registry-serdes-avro-serde` dependency
-and the REST client `apicurio-common-rest-client-vertx` dependency are set to compatible versions:
-
-[source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"]
-.pom.xml
-----
-
- io.quarkus
- quarkus-apicurio-registry-avro
-
-
- io.apicurio
- apicurio-common-rest-client-vertx
-
-
- io.apicurio
- apicurio-registry-serdes-avro-serde
-
-
-
-
- io.apicurio
- apicurio-registry-client
- 2.1.5.Final
-
-
- io.apicurio
- apicurio-registry-common
- 2.1.5.Final
-
-
- io.apicurio
- apicurio-registry-serdes-avro-serde
- 2.1.5.Final
-
-
- io.apicurio
- apicurio-common-rest-client-jdk
-
-
- io.apicurio
- apicurio-registry-client
-
-
- io.apicurio
- apicurio-registry-common
-
-
-
-
- io.apicurio
- apicurio-common-rest-client-vertx
- 0.1.5.Final
-
-----
-
-[source,gradle,role="secondary asciidoc-tabs-target-sync-gradle",subs=attributes+]
-.build.gradle
-----
-dependencies {
- implementation(platform("{quarkus-platform-groupid}:quarkus-bom:2.12.3.Final"))
-
- ...
-
- implementation("io.quarkus:quarkus-apicurio-registry-avro")
- implementation("io.apicurio:apicurio-registry-serdes-avro-serde") {
- exclude group: "io.apicurio", module: "apicurio-common-rest-client-jdk"
- exclude group: "io.apicurio", module: "apicurio-registry-client"
- exclude group: "io.apicurio", module: "apicurio-registry-common"
- version {
- strictly "2.1.5.Final"
- }
- }
- implementation("io.apicurio:apicurio-registry-client") {
- version {
- strictly "2.1.5.Final"
- }
- }
- implementation("io.apicurio:apicurio-registry-common") {
- version {
- strictly "2.1.5.Final"
- }
- }
- implementation("io.apicurio:apicurio-common-rest-client-vertx") {
- version {
- strictly "0.1.5.Final"
- }
- }
-}
-----
-
-Known previous compatible versions for `apicurio-registry-client` and `apicurio-common-rest-client-vertx` are the following
-
-- `apicurio-registry-client` 2.1.5.Final with `apicurio-common-rest-client-vertx` 0.1.5.Final
-- `apicurio-registry-client` 2.3.1.Final with `apicurio-common-rest-client-vertx` 0.1.13.Final
-
[[confluent]]
== Using the Confluent Schema Registry
diff --git a/docs/src/main/asciidoc/kafka-schema-registry-json-schema.adoc b/docs/src/main/asciidoc/kafka-schema-registry-json-schema.adoc
index b37e194345c11..fb25aef4096ab 100644
--- a/docs/src/main/asciidoc/kafka-schema-registry-json-schema.adoc
+++ b/docs/src/main/asciidoc/kafka-schema-registry-json-schema.adoc
@@ -388,7 +388,7 @@ And run it in JVM mode with:
[source, bash]
----
-java -Dmp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v2 -jar target/quarkus-app/quarkus-run.jar
+java -Dmp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v3 -jar target/quarkus-app/quarkus-run.jar
----
NOTE: By default, the application tries to connect to a Kafka broker listening at `localhost:9092`.
@@ -398,7 +398,7 @@ Specifying the registry URL on the command line is not very convenient, so you c
[source,properties]
----
-%prod.mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v2
+%prod.mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v3
----
You can build a native executable with:
@@ -595,13 +595,13 @@ public class KafkaAndSchemaRegistryTestResource implements QuarkusTestResourceLi
@Override
public Map start() {
kafka.start();
- registry = new GenericContainer<>("apicurio/apicurio-registry-mem:2.4.2.Final")
+ registry = new GenericContainer<>("apicurio/apicurio-registry:3.0.6")
.withExposedPorts(8080)
.withEnv("QUARKUS_PROFILE", "prod");
registry.start();
Map properties = new HashMap<>();
properties.put("mp.messaging.connector.smallrye-kafka.apicurio.registry.url",
- "http://" + registry.getHost() + ":" + registry.getMappedPort(8080) + "/apis/registry/v2");
+ "http://" + registry.getHost() + ":" + registry.getMappedPort(8080) + "/apis/registry/v3");
properties.put("kafka.bootstrap.servers", kafka.getBootstrapServers());
return properties;
}
@@ -623,116 +623,6 @@ public class MovieResourceTest {
}
----
-[[apicurio-versions-compatibility]]
-== Using compatible versions of the Apicurio Registry
-
-The `quarkus-apicurio-registry-json-schema` extension depends on recent versions of Apicurio Registry client,
-and most versions of Apicurio Registry server and client are backwards compatible.
-For some you need to make sure that the client used by Serdes is compatible with the server.
-
-For example, with Apicurio Dev Service if you set the image name to use version `2.1.5.Final`:
-
-[source,properties]
-----
-quarkus.apicurio-registry.devservices.image-name=quay.io/apicurio/apicurio-registry-mem:2.1.5.Final
-----
-
-You need to make sure that `apicurio-registry-serdes-json-schema-serde` dependency
-and the REST client `apicurio-common-rest-client-vertx` dependency are set to compatible versions:
-
-[source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"]
-.pom.xml
-----
-
- io.quarkus
- quarkus-apicurio-registry-json-schema
-
-
- io.apicurio
- apicurio-common-rest-client-vertx
-
-
- io.apicurio
- apicurio-registry-serdes-json-schema-serde
-
-
-
-
- io.apicurio
- apicurio-registry-client
- 2.1.5.Final
-
-
- io.apicurio
- apicurio-registry-common
- 2.1.5.Final
-
-
- io.apicurio
- apicurio-registry-serdes-json-schema-serde
- 2.1.5.Final
-
-
- io.apicurio
- apicurio-common-rest-client-jdk
-
-
- io.apicurio
- apicurio-registry-client
-
-
- io.apicurio
- apicurio-registry-common
-
-
-
-
- io.apicurio
- apicurio-common-rest-client-vertx
- 0.1.5.Final
-
-----
-
-[source,gradle,role="secondary asciidoc-tabs-target-sync-gradle",subs=attributes+]
-.build.gradle
-----
-dependencies {
- implementation(platform("{quarkus-platform-groupid}:quarkus-bom:2.12.3.Final"))
-
- ...
-
- implementation("io.quarkus:quarkus-apicurio-registry-json-schema")
- implementation("io.apicurio:apicurio-registry-serdes-json-schema-serde") {
- exclude group: "io.apicurio", module: "apicurio-common-rest-client-jdk"
- exclude group: "io.apicurio", module: "apicurio-registry-client"
- exclude group: "io.apicurio", module: "apicurio-registry-common"
- version {
- strictly "2.1.5.Final"
- }
- }
- implementation("io.apicurio:apicurio-registry-client") {
- version {
- strictly "2.1.5.Final"
- }
- }
- implementation("io.apicurio:apicurio-registry-common") {
- version {
- strictly "2.1.5.Final"
- }
- }
- implementation("io.apicurio:apicurio-common-rest-client-vertx") {
- version {
- strictly "0.1.5.Final"
- }
- }
-}
-----
-
-Known previous compatible versions for `apicurio-registry-client` and `apicurio-common-rest-client-vertx` are the following
-
-- `apicurio-registry-client` 2.1.5.Final with `apicurio-common-rest-client-vertx` 0.1.5.Final
-- `apicurio-registry-client` 2.3.1.Final with `apicurio-common-rest-client-vertx` 0.1.13.Final
-
[[confluent]]
== Using the Confluent Schema Registry
diff --git a/docs/src/main/asciidoc/kafka.adoc b/docs/src/main/asciidoc/kafka.adoc
index c95e632558728..b49db919c3e82 100644
--- a/docs/src/main/asciidoc/kafka.adoc
+++ b/docs/src/main/asciidoc/kafka.adoc
@@ -3437,11 +3437,11 @@ Then, you can configure the Quarkus application to connect to the schema registr
[source, properties]
----
mp.messaging.connector.smallrye-kafka.apicurio.registry.url=${RHOAS_SERVICE_REGISTRY_URL} <1>
-mp.messaging.connector.smallrye-kafka.apicurio.auth.service.token.endpoint=${RHOAS_OAUTH_TOKEN_ENDPOINT} <2>
-mp.messaging.connector.smallrye-kafka.apicurio.auth.client.id=${RHOAS_CLIENT_ID} <3>
-mp.messaging.connector.smallrye-kafka.apicurio.auth.client.secret=${RHOAS_CLIENT_ID} <4>
+mp.messaging.connector.smallrye-kafka.apicurio.registry.auth.service.token.endpoint=${RHOAS_OAUTH_TOKEN_ENDPOINT} <2>
+mp.messaging.connector.smallrye-kafka.apicurio.registry.auth.client.id=${RHOAS_CLIENT_ID} <3>
+mp.messaging.connector.smallrye-kafka.apicurio.registry.auth.client.secret=${RHOAS_CLIENT_ID} <4>
----
-<1> The service registry URL, given on the admin console, such as `https://bu98.serviceregistry.rhcloud.com/t/0e95af2c-6e11-475e-82ee-f13bd782df24/apis/registry/v2`
+<1> The service registry URL, given on the admin console, such as `https://bu98.serviceregistry.rhcloud.com/t/0e95af2c-6e11-475e-82ee-f13bd782df24/apis/registry/v3`
<2> The OAuth token endpoint URL, such as `https://identity.api.openshift.com/auth/realms/rhoas/protocol/openid-connect/token`
<3> The client id (from the service account)
<4> The client secret (from the service account)
diff --git a/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java b/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java
index d641c09a531f2..295ec7ba33aa4 100644
--- a/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java
+++ b/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java
@@ -385,14 +385,14 @@ private void handleAvro(BuildProducer reflectiveClass,
if (QuarkusClassLoader.isClassPresentAtRuntime("io.apicurio.registry.serde.avro.AvroKafkaDeserializer")
&& !capabilities.isPresent(Capability.APICURIO_REGISTRY_AVRO)) {
throw new RuntimeException(
- "Apicurio Registry 2.x Avro classes detected, please use the quarkus-apicurio-registry-avro extension");
+ "Apicurio Registry 3.x Avro classes detected, please use the quarkus-apicurio-registry-avro extension");
}
// --- Apicurio Registry 2.x Json Schema ---
if (QuarkusClassLoader.isClassPresentAtRuntime("io.apicurio.registry.serde.avro.JsonKafkaDeserializer")
&& !capabilities.isPresent(Capability.APICURIO_REGISTRY_JSON_SCHEMA)) {
throw new RuntimeException(
- "Apicurio Registry 2.x Json classes detected, please use the quarkus-apicurio-registry-json extension");
+ "Apicurio Registry 3.x Json classes detected, please use the quarkus-apicurio-registry-json extension");
}
}
diff --git a/extensions/schema-registry/apicurio/avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java b/extensions/schema-registry/apicurio/avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java
index 1a5bb9aba25a7..c638dd79c94c7 100644
--- a/extensions/schema-registry/apicurio/avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java
+++ b/extensions/schema-registry/apicurio/avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java
@@ -1,6 +1,5 @@
package io.quarkus.apicurio.registry.avro;
-import io.quarkus.bootstrap.classloading.QuarkusClassLoader;
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
@@ -29,18 +28,11 @@ public void apicurioRegistryAvro(BuildProducer reflect
"io.apicurio.registry.serde.avro.strategy.TopicRecordIdStrategy").methods().fields()
.build());
- reflectiveClass.produce(ReflectiveClassBuildItem.builder("io.apicurio.registry.serde.DefaultIdHandler",
- "io.apicurio.registry.serde.Legacy4ByteIdHandler",
+ reflectiveClass.produce(ReflectiveClassBuildItem.builder("io.apicurio.registry.serde.Default4ByteIdHandler",
+ "io.apicurio.registry.serde.Legacy8ByteIdHandler",
"io.apicurio.registry.serde.fallback.DefaultFallbackArtifactProvider",
"io.apicurio.registry.serde.headers.DefaultHeadersHandler").methods().fields()
.build());
-
- String defaultSchemaResolver = "io.apicurio.registry.serde.DefaultSchemaResolver";
- if (QuarkusClassLoader.isClassPresentAtRuntime(defaultSchemaResolver)) {
- // Class not present after 2.2.0.Final
- reflectiveClass.produce(ReflectiveClassBuildItem.builder(defaultSchemaResolver).methods()
- .fields().build());
- }
}
@BuildStep
diff --git a/extensions/schema-registry/apicurio/avro/runtime/pom.xml b/extensions/schema-registry/apicurio/avro/runtime/pom.xml
index f3d8fa5e3438c..e02d3a2d8d197 100644
--- a/extensions/schema-registry/apicurio/avro/runtime/pom.xml
+++ b/extensions/schema-registry/apicurio/avro/runtime/pom.xml
@@ -17,13 +17,7 @@
io.apicurio
- apicurio-registry-serdes-avro-serde
-
-
- io.apicurio
- apicurio-common-rest-client-jdk
-
-
+ apicurio-registry-avro-serde-kafka
diff --git a/extensions/schema-registry/apicurio/common/deployment/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClientProcessor.java b/extensions/schema-registry/apicurio/common/deployment/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClientProcessor.java
index bb74ef643ac1c..546fa4c296415 100644
--- a/extensions/schema-registry/apicurio/common/deployment/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClientProcessor.java
+++ b/extensions/schema-registry/apicurio/common/deployment/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClientProcessor.java
@@ -1,45 +1,18 @@
package io.quarkus.apicurio.registry.common;
-import java.io.IOException;
+import java.util.logging.Level;
-import io.apicurio.rest.client.spi.ApicurioHttpClientProvider;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
-import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
-import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
-import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
+import io.quarkus.deployment.builditem.LogCategoryBuildItem;
import io.quarkus.smallrye.openapi.deployment.spi.IgnoreStaticDocumentBuildItem;
import io.quarkus.vertx.deployment.VertxBuildItem;
public class ApicurioRegistryClientProcessor {
- @BuildStep
- public void apicurioRegistryClient(BuildProducer reflectiveClass,
- BuildProducer sslNativeSupport) {
- reflectiveClass
- .produce(ReflectiveClassBuildItem.builder("io.apicurio.rest.client.auth.exception.NotAuthorizedException",
- "io.apicurio.rest.client.auth.exception.ForbiddenException",
- "io.apicurio.rest.client.auth.exception.AuthException",
- "io.apicurio.rest.client.auth.exception.AuthErrorHandler",
- "io.apicurio.rest.client.auth.request.TokenRequestsProvider",
- "io.apicurio.rest.client.request.Request",
- "io.apicurio.rest.client.auth.AccessTokenResponse",
- "io.apicurio.rest.client.auth.Auth",
- "io.apicurio.rest.client.auth.BasicAuth",
- "io.apicurio.rest.client.auth.OidcAuth").methods().fields().build());
- }
-
- @BuildStep
- void registerSPIClient(BuildProducer services) throws IOException {
-
- services.produce(
- new ServiceProviderBuildItem(ApicurioHttpClientProvider.class.getName(),
- "io.apicurio.rest.client.VertxHttpClientProvider"));
- }
-
@BuildStep
void ignoreIncludedOpenAPIDocument(BuildProducer ignoreStaticDocumentProducer) {
// This will ignore the OpenAPI Document in META-INF/openapi.yaml in the apicurio-registry-common dependency
@@ -47,6 +20,13 @@ void ignoreIncludedOpenAPIDocument(BuildProducer
".*/io/apicurio/apicurio-registry-common/.*/apicurio-registry-common-.*.jar.*"));
}
+ @BuildStep
+ void logging(BuildProducer log) {
+ // Reduce the log level of Apicurio Registry client to avoid verbose INFO messages
+ // See https://github.com/quarkusio/quarkus/issues/51008
+ log.produce(new LogCategoryBuildItem("io.apicurio.registry.client", Level.WARNING));
+ }
+
@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
public void apicurioRegistryClient(VertxBuildItem vertx, ApicurioRegistryClient client, LaunchModeBuildItem launchMode) {
diff --git a/extensions/schema-registry/apicurio/common/deployment/src/test/java/io/quarkus/apicurio/registry/common/ApicurioRegistryInternalsExpectationTest.java b/extensions/schema-registry/apicurio/common/deployment/src/test/java/io/quarkus/apicurio/registry/common/ApicurioRegistryInternalsExpectationTest.java
index ab2da367a32d8..9d3e2f37ccd86 100644
--- a/extensions/schema-registry/apicurio/common/deployment/src/test/java/io/quarkus/apicurio/registry/common/ApicurioRegistryInternalsExpectationTest.java
+++ b/extensions/schema-registry/apicurio/common/deployment/src/test/java/io/quarkus/apicurio/registry/common/ApicurioRegistryInternalsExpectationTest.java
@@ -2,12 +2,9 @@
import org.junit.jupiter.api.Test;
-import io.apicurio.rest.client.spi.ApicurioHttpClientFactory;
-
public class ApicurioRegistryInternalsExpectationTest {
@Test
public void test() throws NoSuchFieldException {
// we need this to reset the client in continuous testing
- ApicurioHttpClientFactory.class.getDeclaredField("providerReference");
}
}
diff --git a/extensions/schema-registry/apicurio/common/runtime/pom.xml b/extensions/schema-registry/apicurio/common/runtime/pom.xml
index 5e04248f4f574..edbc13675e238 100644
--- a/extensions/schema-registry/apicurio/common/runtime/pom.xml
+++ b/extensions/schema-registry/apicurio/common/runtime/pom.xml
@@ -17,17 +17,7 @@
io.apicurio
- apicurio-registry-client
-
-
- io.apicurio
- apicurio-common-rest-client-jdk
-
-
-
-
- io.apicurio
- apicurio-common-rest-client-vertx
+ apicurio-registry-schema-resolver
org.apache.commons
diff --git a/extensions/schema-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java b/extensions/schema-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java
index 13914a24db994..14dffd02b9e6e 100644
--- a/extensions/schema-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java
+++ b/extensions/schema-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java
@@ -53,7 +53,7 @@ public Optional convert(List service
oauthTokenUrl = binding.getProperties().get("oauthtokenurl");
}
if (oauthTokenUrl != null) {
- properties.put(prefix + "apicurio.auth.service.token.endpoint", oauthTokenUrl);
+ properties.put(prefix + "apicurio.registry.auth.service.token.endpoint", oauthTokenUrl);
}
String clientId = binding.getProperties().get("clientId");
@@ -61,7 +61,7 @@ public Optional convert(List service
clientId = binding.getProperties().get("clientid");
}
if (clientId != null) {
- properties.put(prefix + "apicurio.auth.client.id", clientId);
+ properties.put(prefix + "apicurio.registry.auth.client.id", clientId);
}
String clientSecret = binding.getProperties().get("clientSecret");
@@ -69,7 +69,7 @@ public Optional convert(List service
clientSecret = binding.getProperties().get("clientsecret");
}
if (clientSecret != null) {
- properties.put(prefix + "apicurio.auth.client.secret", clientSecret);
+ properties.put(prefix + "apicurio.registry.auth.client.secret", clientSecret);
}
if (registryUrl != null) {
properties.put(prefix + "apicurio.registry.url", registryUrl);
diff --git a/extensions/schema-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClient.java b/extensions/schema-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClient.java
index 80a544a63979c..9ec4e10b8951f 100644
--- a/extensions/schema-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClient.java
+++ b/extensions/schema-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClient.java
@@ -1,13 +1,8 @@
package io.quarkus.apicurio.registry.common;
-import java.lang.reflect.Field;
-import java.util.concurrent.atomic.AtomicReference;
-
import org.jboss.logging.Logger;
-import io.apicurio.registry.rest.client.RegistryClientFactory;
-import io.apicurio.rest.client.VertxHttpClientProvider;
-import io.apicurio.rest.client.spi.ApicurioHttpClientFactory;
+import io.apicurio.registry.resolver.client.RegistryClientFacadeFactory;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.annotations.Recorder;
import io.vertx.core.Vertx;
@@ -18,17 +13,14 @@ public class ApicurioRegistryClient {
private static final Logger log = Logger.getLogger(ApicurioRegistryClient.class);
public void setup(RuntimeValue vertx) {
- RegistryClientFactory.setProvider(new VertxHttpClientProvider(vertx.getValue()));
+ RegistryClientFacadeFactory.vertx = vertx.getValue();
}
public void clearHttpClient() {
try {
- Field providerReference = ApicurioHttpClientFactory.class.getDeclaredField("providerReference");
- providerReference.setAccessible(true);
- AtomicReference ref = (AtomicReference) providerReference.get(null);
- ref.set(null);
- } catch (NoSuchFieldException | IllegalAccessException t) {
- log.error("Failed to clear Apicurio Http Client provider", t);
+ RegistryClientFacadeFactory.vertx = null;
+ } catch (Exception t) {
+ log.error("Failed to clear Apicurio Http Client", t);
}
}
-}
\ No newline at end of file
+}
diff --git a/extensions/schema-registry/apicurio/json-schema/deployment/src/main/java/io/quarkus/apicurio/registry/jsonschema/ApicurioRegistryJsonSchemaProcessor.java b/extensions/schema-registry/apicurio/json-schema/deployment/src/main/java/io/quarkus/apicurio/registry/jsonschema/ApicurioRegistryJsonSchemaProcessor.java
index 83c6f0886bba9..6b51932a8ca5e 100644
--- a/extensions/schema-registry/apicurio/json-schema/deployment/src/main/java/io/quarkus/apicurio/registry/jsonschema/ApicurioRegistryJsonSchemaProcessor.java
+++ b/extensions/schema-registry/apicurio/json-schema/deployment/src/main/java/io/quarkus/apicurio/registry/jsonschema/ApicurioRegistryJsonSchemaProcessor.java
@@ -1,6 +1,5 @@
package io.quarkus.apicurio.registry.jsonschema;
-import io.quarkus.bootstrap.classloading.QuarkusClassLoader;
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
@@ -23,24 +22,14 @@ public void apicurioRegistryJsonSchema(BuildProducer r
"io.apicurio.registry.serde.jsonschema.JsonSchemaKafkaSerializer").methods().build());
reflectiveClass.produce(ReflectiveClassBuildItem.builder("io.apicurio.registry.serde.strategy.SimpleTopicIdStrategy",
- "io.apicurio.registry.serde.strategy.TopicIdStrategy",
- "io.apicurio.registry.serde.strategy.QualifiedRecordIdStrategy",
- "io.apicurio.registry.serde.strategy.RecordIdStrategy",
- "io.apicurio.registry.serde.jsonschema.strategy.TopicRecordIdStrategy").methods().fields()
+ "io.apicurio.registry.serde.strategy.TopicIdStrategy").methods().fields()
.build());
- reflectiveClass.produce(ReflectiveClassBuildItem.builder("io.apicurio.registry.serde.DefaultIdHandler",
- "io.apicurio.registry.serde.Legacy4ByteIdHandler",
+ reflectiveClass.produce(ReflectiveClassBuildItem.builder("io.apicurio.registry.serde.Default4ByteIdHandler",
+ "io.apicurio.registry.serde.Legacy8ByteIdHandler",
"io.apicurio.registry.serde.fallback.DefaultFallbackArtifactProvider",
"io.apicurio.registry.serde.headers.DefaultHeadersHandler").methods().fields()
.build());
-
- String defaultSchemaResolver = "io.apicurio.registry.serde.DefaultSchemaResolver";
- if (QuarkusClassLoader.isClassPresentAtRuntime(defaultSchemaResolver)) {
- // Class not present after 2.2.0.Final
- reflectiveClass.produce(ReflectiveClassBuildItem.builder(defaultSchemaResolver).methods()
- .fields().build());
- }
}
@BuildStep
diff --git a/extensions/schema-registry/apicurio/json-schema/runtime/pom.xml b/extensions/schema-registry/apicurio/json-schema/runtime/pom.xml
index 94c82a3356400..a5a3bc453a127 100644
--- a/extensions/schema-registry/apicurio/json-schema/runtime/pom.xml
+++ b/extensions/schema-registry/apicurio/json-schema/runtime/pom.xml
@@ -17,13 +17,7 @@
io.apicurio
- apicurio-registry-serdes-jsonschema-serde
-
-
- io.apicurio
- apicurio-common-rest-client-jdk
-
-
+ apicurio-registry-jsonschema-serde-kafka
diff --git a/extensions/schema-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/ApicurioRegistryBuildTimeConfig.java b/extensions/schema-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/ApicurioRegistryBuildTimeConfig.java
index 98507fde7821a..d6532ca739ae7 100644
--- a/extensions/schema-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/ApicurioRegistryBuildTimeConfig.java
+++ b/extensions/schema-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/ApicurioRegistryBuildTimeConfig.java
@@ -40,8 +40,8 @@ interface ApicurioRegistryDevServicesBuildTimeConfig {
/**
* The Apicurio Registry image to use.
- * Note that only Apicurio Registry 2.x images are supported.
- * Specifically, the image repository must end with {@code apicurio/apicurio-registry-mem}.
+ * Note that only Apicurio Registry 3.x images are supported.
+ * Specifically, the image repository must end with {@code apicurio/apicurio-registry}.
*/
@ConfigDocDefault(value = "`{apicurio-registry-image}`", escape = false)
Optional imageName();
diff --git a/extensions/schema-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/DevServicesApicurioRegistryProcessor.java b/extensions/schema-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/DevServicesApicurioRegistryProcessor.java
index 2b83d2a270ea5..2261e3e9029e5 100644
--- a/extensions/schema-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/DevServicesApicurioRegistryProcessor.java
+++ b/extensions/schema-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/DevServicesApicurioRegistryProcessor.java
@@ -129,8 +129,8 @@ public void run() {
private Map getRegistryUrlConfigs(String baseUrl) {
return Map.of(
- APICURIO_REGISTRY_URL_CONFIG, baseUrl + "/apis/registry/v2",
- CONFLUENT_SCHEMA_REGISTRY_URL_CONFIG, baseUrl + "/apis/ccompat/v6");
+ APICURIO_REGISTRY_URL_CONFIG, baseUrl + "/apis/registry/v3",
+ CONFLUENT_SCHEMA_REGISTRY_URL_CONFIG, baseUrl + "/apis/ccompat/v7");
}
private void shutdownApicurioRegistry() {
@@ -187,7 +187,7 @@ private RunningDevService startApicurioRegistry(DockerStatusBuildItem dockerStat
getRegistryUrlConfigs("http://" + address.getUrl())))
.orElseGet(() -> {
ApicurioRegistryContainer container = new ApicurioRegistryContainer(
- DockerImageName.parse(config.imageName).asCompatibleSubstituteFor("apicurio/apicurio-registry-mem"),
+ DockerImageName.parse(config.imageName).asCompatibleSubstituteFor("apicurio/apicurio-registry"),
config.fixedExposedPort,
launchMode.getLaunchMode() == LaunchMode.DEVELOPMENT ? config.serviceName : null,
composeProjectBuildItem.getDefaultNetworkId(),
@@ -282,8 +282,8 @@ private ApicurioRegistryContainer(DockerImageName dockerImageName, int fixedExpo
withLabel(QUARKUS_DEV_SERVICE, serviceName);
}
withEnv("QUARKUS_PROFILE", "prod");
- if (!dockerImageName.getRepository().endsWith("apicurio/apicurio-registry-mem")) {
- throw new IllegalArgumentException("Only apicurio/apicurio-registry-mem images are supported");
+ if (!dockerImageName.getRepository().endsWith("apicurio/apicurio-registry")) {
+ throw new IllegalArgumentException("Only apicurio/apicurio-registry images are supported");
}
this.hostName = ConfigureUtil.configureNetwork(this, defaultNetworkId, useSharedNetwork, "apicurio-registry");
}
diff --git a/extensions/smallrye-reactive-messaging-kafka/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/DefaultSerdeDiscoveryState.java b/extensions/smallrye-reactive-messaging-kafka/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/DefaultSerdeDiscoveryState.java
index 1441859a31ce3..2a15336da4dbd 100644
--- a/extensions/smallrye-reactive-messaging-kafka/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/DefaultSerdeDiscoveryState.java
+++ b/extensions/smallrye-reactive-messaging-kafka/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/DefaultSerdeDiscoveryState.java
@@ -36,9 +36,9 @@ class DefaultSerdeDiscoveryState {
private Boolean connectorHasValueDeserializer;
private Boolean hasConfluent;
- private Boolean hasApicurio1;
- private Boolean hasApicurio2Avro;
+ private Boolean hasApicurioAvro;
private Boolean hasJsonb;
+ private boolean apicurioVersionWarningLogged;
DefaultSerdeDiscoveryState(IndexView index) {
this.index = index;
@@ -142,32 +142,30 @@ boolean hasConfluent() {
return hasConfluent;
}
- boolean hasApicurio1() {
- if (hasApicurio1 == null) {
+ boolean hasApicurioAvro() {
+ if (hasApicurioAvro == null) {
try {
- Class.forName("io.apicurio.registry.utils.serde.AvroKafkaDeserializer", false,
+ Class.forName("io.apicurio.registry.serde.avro.AvroKafkaDeserializer", false,
Thread.currentThread().getContextClassLoader());
- hasApicurio1 = true;
+ hasApicurioAvro = true;
} catch (ClassNotFoundException e) {
- hasApicurio1 = false;
+ hasApicurioAvro = false;
}
}
- return hasApicurio1;
+ return hasApicurioAvro;
}
- boolean hasApicurio2Avro() {
- if (hasApicurio2Avro == null) {
- try {
- Class.forName("io.apicurio.registry.serde.avro.AvroKafkaDeserializer", false,
- Thread.currentThread().getContextClassLoader());
- hasApicurio2Avro = true;
- } catch (ClassNotFoundException e) {
- hasApicurio2Avro = false;
- }
+ /**
+ * Returns true if the Apicurio version warning should be logged (first call only).
+ * Subsequent calls return false to avoid duplicate warnings.
+ */
+ boolean shouldLogApicurioVersionWarning() {
+ if (!apicurioVersionWarningLogged && hasApicurioAvro()) {
+ apicurioVersionWarningLogged = true;
+ return true;
}
-
- return hasApicurio2Avro;
+ return false;
}
boolean hasJsonb() {
diff --git a/extensions/smallrye-reactive-messaging-kafka/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/SmallRyeReactiveMessagingKafkaProcessor.java b/extensions/smallrye-reactive-messaging-kafka/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/SmallRyeReactiveMessagingKafkaProcessor.java
index d7a95eeee2456..b0b28d367cdf9 100644
--- a/extensions/smallrye-reactive-messaging-kafka/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/SmallRyeReactiveMessagingKafkaProcessor.java
+++ b/extensions/smallrye-reactive-messaging-kafka/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/SmallRyeReactiveMessagingKafkaProcessor.java
@@ -963,8 +963,7 @@ private Result serializerDeserializerFor(DefaultSerdeDiscoveryState discovery, T
if (isAvroGenerated || DotNames.AVRO_GENERIC_RECORD.equals(typeName)) {
int avroLibraries = 0;
avroLibraries += discovery.hasConfluent() ? 1 : 0;
- avroLibraries += discovery.hasApicurio1() ? 1 : 0;
- avroLibraries += discovery.hasApicurio2Avro() ? 1 : 0;
+ avroLibraries += discovery.hasApicurioAvro() ? 1 : 0;
if (avroLibraries > 1) {
LOGGER.debugf("Skipping Avro serde autodetection for %s, because multiple Avro serde libraries are present",
typeName);
@@ -976,12 +975,13 @@ private Result serializerDeserializerFor(DefaultSerdeDiscoveryState discovery, T
? Result.of("io.confluent.kafka.serializers.KafkaAvroSerializer")
: Result.of("io.confluent.kafka.serializers.KafkaAvroDeserializer")
.with(isAvroGenerated, "specific.avro.reader", "true");
- } else if (discovery.hasApicurio1()) {
- return serializer
- ? Result.of("io.apicurio.registry.utils.serde.AvroKafkaSerializer")
- : Result.of("io.apicurio.registry.utils.serde.AvroKafkaDeserializer")
- .with(isAvroGenerated, "apicurio.registry.use-specific-avro-reader", "true");
- } else if (discovery.hasApicurio2Avro()) {
+ } else if (discovery.hasApicurioAvro()) {
+ if (discovery.shouldLogApicurioVersionWarning()) {
+ LOGGER.info("Apicurio Registry Avro serde detected. Note: Apicurio Registry 3.x uses 4-byte schema IDs " +
+ "by default, while 2.x used 8-byte IDs. If consuming messages produced by Apicurio Registry 2.x, " +
+ "configure 'apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler' " +
+ "on your consumer channels for compatibility.");
+ }
return serializer
? Result.of("io.apicurio.registry.serde.avro.AvroKafkaSerializer")
: Result.of("io.apicurio.registry.serde.avro.AvroKafkaDeserializer")
diff --git a/integration-tests/kafka-avro-apicurio2/pom.xml b/integration-tests/kafka-avro-apicurio2/pom.xml
index 19398b353f8ba..0ddf52194c642 100644
--- a/integration-tests/kafka-avro-apicurio2/pom.xml
+++ b/integration-tests/kafka-avro-apicurio2/pom.xml
@@ -10,11 +10,16 @@
4.0.0
quarkus-integration-test-kafka-avro-apicurio2
- Quarkus - Integration Tests - Kafka Avro with Apicurio 2.x
- The Apache Kafka Avro with Apicurio Registry 2.x integration tests module
+ Quarkus - Integration Tests - Kafka Avro with Apicurio Registry
+ Apache Kafka Avro with Apicurio Registry 3.x integration tests - tests both v2 compatibility mode (Legacy8ByteIdHandler) and v3 native mode (Default4ByteIdHandler)
diff --git a/integration-tests/kafka-json-schema-apicurio2/src/main/java/io/quarkus/it/kafka/jsonschema/JsonSchemaKafkaCreator.java b/integration-tests/kafka-json-schema-apicurio2/src/main/java/io/quarkus/it/kafka/jsonschema/JsonSchemaKafkaCreator.java
index 119beaf837785..1744bd7a70717 100644
--- a/integration-tests/kafka-json-schema-apicurio2/src/main/java/io/quarkus/it/kafka/jsonschema/JsonSchemaKafkaCreator.java
+++ b/integration-tests/kafka-json-schema-apicurio2/src/main/java/io/quarkus/it/kafka/jsonschema/JsonSchemaKafkaCreator.java
@@ -14,7 +14,7 @@
import org.apache.kafka.common.serialization.IntegerSerializer;
import org.eclipse.microprofile.config.inject.ConfigProperty;
-import io.apicurio.registry.serde.SerdeConfig;
+import io.apicurio.registry.serde.config.SerdeConfig;
import io.apicurio.registry.serde.jsonschema.JsonSchemaKafkaDeserializer;
import io.apicurio.registry.serde.jsonschema.JsonSchemaKafkaSerializer;
import io.confluent.kafka.serializers.AbstractKafkaSchemaSerDeConfig;
diff --git a/integration-tests/kafka-json-schema-apicurio2/src/main/resources/application.properties b/integration-tests/kafka-json-schema-apicurio2/src/main/resources/application.properties
index e1de76ce2307d..1ea90c4f24f95 100644
--- a/integration-tests/kafka-json-schema-apicurio2/src/main/resources/application.properties
+++ b/integration-tests/kafka-json-schema-apicurio2/src/main/resources/application.properties
@@ -8,3 +8,7 @@ quarkus.native.resources.includes=json-schema.json
quarkus.kafka.health.enabled=true
quarkus.apicurio-registry.devservices.image-name=${apicurio-registry.image}
+
+# Default configuration uses Legacy8ByteIdHandler for v2 compatibility mode
+# This allows Apicurio v3 libraries to work with 8-byte schema IDs (v2 format)
+mp.messaging.connector.smallrye-kafka.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
\ No newline at end of file
diff --git a/integration-tests/kafka-json-schema-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaJsonSchemaIT.java b/integration-tests/kafka-json-schema-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaJsonSchemaIT.java
index 31ddb23296938..dd04b93ef7136 100644
--- a/integration-tests/kafka-json-schema-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaJsonSchemaIT.java
+++ b/integration-tests/kafka-json-schema-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaJsonSchemaIT.java
@@ -2,8 +2,7 @@
import org.junit.jupiter.api.BeforeAll;
-import io.apicurio.registry.rest.client.RegistryClientFactory;
-import io.apicurio.rest.client.VertxHttpClientProvider;
+import io.apicurio.registry.resolver.client.RegistryClientFacadeFactory;
import io.quarkus.it.kafka.jsonschema.JsonSchemaKafkaCreator;
import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusIntegrationTest;
@@ -23,7 +22,7 @@ JsonSchemaKafkaCreator creator() {
@BeforeAll
public static void setUp() {
// this is for the test JVM, which also uses Kafka client, which in turn also interacts with the registry
- RegistryClientFactory.setProvider(new VertxHttpClientProvider(Vertx.vertx()));
+ RegistryClientFacadeFactory.vertx = Vertx.vertx();
}
}
diff --git a/integration-tests/kafka-json-schema-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaJsonSchemaTestBase.java b/integration-tests/kafka-json-schema-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaJsonSchemaTestBase.java
index 729b8956fd47e..d8217c52190bb 100644
--- a/integration-tests/kafka-json-schema-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaJsonSchemaTestBase.java
+++ b/integration-tests/kafka-json-schema-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaJsonSchemaTestBase.java
@@ -23,7 +23,7 @@ public abstract class KafkaJsonSchemaTestBase {
@Test
public void testUrls() {
- Assertions.assertTrue(creator().getApicurioRegistryUrl().endsWith("/apis/registry/v2"));
+ Assertions.assertTrue(creator().getApicurioRegistryUrl().endsWith("/apis/registry/v3"));
}
@Test