Skip to content

Commit ef7c269

Browse files
committed
Add apicurio registry v3 migration documentation
1 parent 73ca1ca commit ef7c269

File tree

1 file changed

+306
-0
lines changed

1 file changed

+306
-0
lines changed
Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
////
2+
This guide is maintained in the main Quarkus repository
3+
and pull requests should be submitted there:
4+
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
5+
////
6+
= Migrating to Apicurio Registry 3.x
7+
include::_attributes.adoc[]
8+
:categories: messaging
9+
:summary: Guide for migrating from Apicurio Registry 2.x to 3.x in Quarkus applications.
10+
:topics: messaging,kafka,apicurio,registry,migration
11+
:extensions: io.quarkus:quarkus-apicurio-registry-avro,io.quarkus:quarkus-messaging-kafka
12+
13+
This guide covers the migration path from Apicurio Registry 2.x to 3.x for Quarkus applications using Kafka with schema registry serialization.
14+
15+
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.
16+
17+
== Overview of Changes
18+
19+
Quarkus has upgraded to Apicurio Registry 3.1.2. This upgrade includes:
20+
21+
* **New API endpoints**: `/apis/registry/v3` (was `/v2`)
22+
* **New Confluent compatibility endpoint**: `/apis/ccompat/v7` (was `/v6`)
23+
* **Changed schema ID format**: 4-byte integer IDs by default (was 8-byte long)
24+
* **Package restructuring**: Some configuration classes have been renamed
25+
* **New Kiota-based client**: REST client uses Microsoft Kiota for code generation
26+
27+
== Breaking Changes
28+
29+
=== Schema ID Format (Critical)
30+
31+
The most significant breaking change is the schema ID format:
32+
33+
[cols="1,1,2"]
34+
|===
35+
|Version |ID Format |ID Handler Class
36+
37+
|v2.x
38+
|8-byte (long)
39+
|Default behavior (no handler needed)
40+
41+
|v3.x
42+
|4-byte (int)
43+
|`io.apicurio.registry.serde.Default4ByteIdHandler`
44+
|===
45+
46+
Messages produced with v2.x cannot be consumed by v3.x (and vice versa) without explicit configuration.
47+
48+
=== API Endpoint Changes
49+
50+
[cols="1,1,1"]
51+
|===
52+
|Endpoint |v2.x |v3.x
53+
54+
|Apicurio API
55+
|`/apis/registry/v2`
56+
|`/apis/registry/v3`
57+
58+
|Confluent Compat
59+
|`/apis/ccompat/v6`
60+
|`/apis/ccompat/v7`
61+
|===
62+
63+
The Quarkus Dev Services automatically configures the correct endpoints for v3.x.
64+
65+
== Migration Scenarios
66+
67+
=== Scenario 1: New Application (Greenfield)
68+
69+
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.
70+
71+
[source,properties]
72+
----
73+
# No special configuration required - v3 defaults are used
74+
# Dev Services will start Apicurio Registry 3.x automatically
75+
----
76+
77+
=== Scenario 2: Migrating from v2 (No Existing Messages)
78+
79+
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:
80+
81+
1. Upgrade Quarkus to the version with Apicurio Registry 3.x
82+
2. Clear or recreate your Kafka topics
83+
3. Restart your application - new messages will use 4-byte IDs
84+
85+
=== Scenario 3: Consuming Existing v2 Messages
86+
87+
If you need to consume messages that were produced with Apicurio Registry 2.x, configure the `Legacy8ByteIdHandler`:
88+
89+
[source,properties]
90+
----
91+
# Configure consumer to read v2 messages with 8-byte schema IDs
92+
mp.messaging.incoming.movies.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
93+
----
94+
95+
Or configure globally for all channels:
96+
97+
[source,properties]
98+
----
99+
# Configure all consumers to use Legacy8ByteIdHandler
100+
mp.messaging.connector.smallrye-kafka.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
101+
----
102+
103+
=== Scenario 4: Mixed v2/v3 Environment
104+
105+
During a gradual migration where some services use v2 and others use v3:
106+
107+
**v3 service consuming from v2 producers:**
108+
[source,properties]
109+
----
110+
# Consumer reads v2 messages
111+
mp.messaging.incoming.from-v2-service.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
112+
----
113+
114+
**v3 service producing for v2 consumers:**
115+
[source,properties]
116+
----
117+
# Producer writes v2-compatible messages
118+
mp.messaging.outgoing.to-v2-service.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
119+
----
120+
121+
== Configuration Reference
122+
123+
=== ID Handler Options
124+
125+
[cols="2,1,3"]
126+
|===
127+
|Handler Class |ID Size |Use Case
128+
129+
|`io.apicurio.registry.serde.Default4ByteIdHandler`
130+
|4 bytes
131+
|Default for v3.x, new applications
132+
133+
|`io.apicurio.registry.serde.Legacy8ByteIdHandler`
134+
|8 bytes
135+
|Backward compatibility with v2.x messages
136+
|===
137+
138+
=== Configuration Properties
139+
140+
[cols="2,3"]
141+
|===
142+
|Property |Description
143+
144+
|`apicurio.registry.id-handler`
145+
|Fully qualified class name of the ID handler to use
146+
147+
|`apicurio.registry.url`
148+
|URL of the Apicurio Registry (auto-configured by Dev Services)
149+
150+
|`quarkus.apicurio-registry.devservices.image-name`
151+
|Docker image for Dev Services (default: `quay.io/apicurio/apicurio-registry:3.1.2`)
152+
|===
153+
154+
=== Per-Channel vs Global Configuration
155+
156+
**Per-channel configuration:**
157+
[source,properties]
158+
----
159+
# Incoming channel
160+
mp.messaging.incoming.my-channel.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
161+
162+
# Outgoing channel
163+
mp.messaging.outgoing.my-channel.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
164+
----
165+
166+
**Global configuration (all channels):**
167+
[source,properties]
168+
----
169+
mp.messaging.connector.smallrye-kafka.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
170+
----
171+
172+
== Code Changes
173+
174+
If you use Apicurio Registry APIs directly in your code, the following changes are required:
175+
176+
=== Package Renames
177+
178+
[cols="1,1"]
179+
|===
180+
|v2 Import |v3 Import
181+
182+
|`io.apicurio.registry.serde.avro.AvroKafkaSerdeConfig`
183+
|`io.apicurio.registry.serde.avro.AvroSerdeConfig`
184+
|===
185+
186+
=== Vertx Setup (Internal/Advanced)
187+
188+
If you manually configure Vertx for the registry client:
189+
190+
**v2 code:**
191+
[source,java]
192+
----
193+
import io.apicurio.registry.resolver.AbstractSchemaResolver;
194+
195+
AbstractSchemaResolver.setVertx(vertx);
196+
----
197+
198+
**v3 code:**
199+
[source,java]
200+
----
201+
import io.apicurio.registry.resolver.client.RegistryClientFacadeFactory;
202+
203+
RegistryClientFacadeFactory.vertx = vertx;
204+
----
205+
206+
NOTE: Most applications don't need to make this change - Quarkus handles Vertx configuration automatically.
207+
208+
== Dev Services Configuration
209+
210+
Dev Services for Apicurio Registry automatically starts a 3.x registry in dev and test modes:
211+
212+
[source,properties]
213+
----
214+
# Override the default image if needed
215+
quarkus.apicurio-registry.devservices.image-name=quay.io/apicurio/apicurio-registry:3.1.2
216+
217+
# Disable Dev Services if using an external registry
218+
quarkus.apicurio-registry.devservices.enabled=false
219+
----
220+
221+
The registry URL is automatically configured:
222+
[source,properties]
223+
----
224+
# These are set automatically by Dev Services:
225+
mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v3
226+
mp.messaging.connector.smallrye-kafka.schema.registry.url=http://localhost:8081/apis/ccompat/v7
227+
----
228+
229+
== Testing Both Modes
230+
231+
To validate that your application works correctly with both v2 and v3 ID formats, you can create tests that explicitly configure each mode:
232+
233+
[source,java]
234+
----
235+
@QuarkusTest
236+
public class SchemaRegistryCompatibilityTest {
237+
238+
@Test
239+
public void testV2CompatibilityMode() {
240+
// Configure Legacy8ByteIdHandler for this test
241+
Map<String, Object> config = new HashMap<>();
242+
config.put("apicurio.registry.id-handler",
243+
"io.apicurio.registry.serde.Legacy8ByteIdHandler");
244+
245+
// Test produce and consume with 8-byte IDs
246+
// ...
247+
}
248+
249+
@Test
250+
public void testV3NativeMode() {
251+
// Uses default Default4ByteIdHandler
252+
253+
// Test produce and consume with 4-byte IDs
254+
// ...
255+
}
256+
}
257+
----
258+
259+
== Migration Checklist
260+
261+
Use this checklist when migrating from Apicurio Registry 2.x to 3.x:
262+
263+
* [ ] Assess existing Kafka topics for v2 messages that need to be consumed
264+
* [ ] Configure `Legacy8ByteIdHandler` for channels consuming v2 messages
265+
* [ ] Update any direct API calls using `AvroKafkaSerdeConfig` to `AvroSerdeConfig`
266+
* [ ] Update any direct API calls using `AbstractSchemaResolver.setVertx()` to `RegistryClientFacadeFactory.vertx`
267+
* [ ] Test consumer compatibility with existing messages
268+
* [ ] Test producer compatibility with downstream consumers
269+
* [ ] Plan topic migration or dual-write strategy if needed
270+
271+
== Troubleshooting
272+
273+
=== "Unknown magic byte" Error
274+
275+
This error indicates a mismatch in schema ID format between producer and consumer:
276+
277+
[source]
278+
----
279+
io.apicurio.registry.serde.SerdeException: Unknown magic byte!
280+
----
281+
282+
**Solution:** Configure the consumer with the same ID handler used by the producer:
283+
[source,properties]
284+
----
285+
mp.messaging.incoming.my-channel.apicurio.registry.id-handler=io.apicurio.registry.serde.Legacy8ByteIdHandler
286+
----
287+
288+
=== Schema Not Found
289+
290+
If schemas aren't being found after migration:
291+
292+
1. Verify the registry URL is correct (`/apis/registry/v3` for v3)
293+
2. Check that the registry container is running (Dev Services should start it automatically)
294+
3. Verify schema compatibility settings in the registry
295+
296+
=== Verbose CDI Messages
297+
298+
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.
299+
300+
== Additional Resources
301+
302+
* https://www.apicur.io/registry/docs/apicurio-registry/3.0.x/index.html[Apicurio Registry 3.x Documentation]
303+
* https://www.apicur.io/blog/2025/03/30/migrate-registry-2-to-3[Official Apicurio Migration Guide]
304+
* https://www.apicur.io/blog/2025/04/03/evolving-serialization[Apicurio SerDes Evolution Blog Post]
305+
* xref:kafka-schema-registry-avro.adoc[Using Apache Kafka with Schema Registry and Avro]
306+
* xref:apicurio-registry-dev-services.adoc[Dev Services for Apicurio Registry]

0 commit comments

Comments
 (0)