diff --git a/bom/application/pom.xml b/bom/application/pom.xml index 6eb0efd7ad979a..0f39e0ed8af171 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -1208,6 +1208,26 @@ quarkus-avro-deployment ${project.version} + + io.quarkus + quarkus-apicurio-registry-devservice + ${project.version} + + + io.quarkus + quarkus-apicurio-registry-devservice-deployment + ${project.version} + + + io.quarkus + quarkus-apicurio-registry-common + ${project.version} + + + io.quarkus + quarkus-apicurio-registry-common-deployment + ${project.version} + io.quarkus quarkus-apicurio-registry-avro @@ -1218,6 +1238,26 @@ quarkus-apicurio-registry-avro-deployment ${project.version} + + io.quarkus + quarkus-apicurio-registry-confluent-common + ${project.version} + + + io.quarkus + quarkus-apicurio-registry-confluent-common-deployment + ${project.version} + + + io.quarkus + quarkus-apicurio-registry-confluent-avro + ${project.version} + + + io.quarkus + quarkus-apicurio-registry-confluent-avro-deployment + ${project.version} + io.quarkus quarkus-smallrye-health @@ -3071,6 +3111,11 @@ agroal-pool ${agroal.version} + + io.apicurio + apicurio-registry-client + ${apicurio-registry.version} + io.apicurio apicurio-registry-serdes-avro-serde diff --git a/core/deployment/src/main/java/io/quarkus/deployment/Capability.java b/core/deployment/src/main/java/io/quarkus/deployment/Capability.java index 90602ffba6ad11..68b8c93110e524 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/Capability.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/Capability.java @@ -121,4 +121,5 @@ public interface Capability { String APICURIO_REGISTRY = QUARKUS_PREFIX + "apicurio.registry"; String APICURIO_REGISTRY_AVRO = APICURIO_REGISTRY + ".avro"; + String CONFLUENT_REGISTRY_AVRO = APICURIO_REGISTRY + ".confluent.avro"; } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/Feature.java b/core/deployment/src/main/java/io/quarkus/deployment/Feature.java index 7010488ea423ca..72cf96d7d6cbf7 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/Feature.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/Feature.java @@ -12,6 +12,7 @@ public enum Feature { AGROAL, AMAZON_LAMBDA, APICURIO_REGISTRY_AVRO, + CONFLUENT_REGISTRY_AVRO, AWT, CACHE, CDI, diff --git a/devtools/bom-descriptor-json/pom.xml b/devtools/bom-descriptor-json/pom.xml index 5440493aa03080..c592340b635993 100644 --- a/devtools/bom-descriptor-json/pom.xml +++ b/devtools/bom-descriptor-json/pom.xml @@ -201,6 +201,19 @@ + + io.quarkus + quarkus-apicurio-registry-confluent-avro + ${project.version} + pom + test + + + * + * + + + io.quarkus quarkus-arc diff --git a/docs/pom.xml b/docs/pom.xml index e9c1aaf4ef8cc9..e69199e773fac7 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -161,6 +161,19 @@ + + io.quarkus + quarkus-apicurio-registry-confluent-avro-deployment + ${project.version} + pom + test + + + * + * + + + io.quarkus quarkus-arc-deployment diff --git a/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc b/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc index beb991b3fc9ac4..3e69f614927760 100644 --- a/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc +++ b/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc @@ -28,6 +28,14 @@ You can configure the registry URL for all Kafka channels in SmallRye Reactive M mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v2 ---- +NOTE: if `Confluent` Serde classes are present on the app's classpath, +Apicuiro Registry's Confluent-compatible registry url is used / set by Dev Services for Apicurio Registry by default: + +[source,properties] +---- +mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/ccompat/v6 +---- + == Shared registry Most of the time you need to share the registry between applications. diff --git a/docs/src/main/asciidoc/kafka-schema-registry-avro.adoc b/docs/src/main/asciidoc/kafka-schema-registry-avro.adoc index d6d85dfe84dfa0..996b2453d8281e 100644 --- a/docs/src/main/asciidoc/kafka-schema-registry-avro.adoc +++ b/docs/src/main/asciidoc/kafka-schema-registry-avro.adoc @@ -8,7 +8,7 @@ https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc include::./attributes.adoc[] This guide shows how your Quarkus application can use Apache Kafka, http://avro.apache.org/docs/current/[Avro] serialized -records, and connect to a schema registry (such as the https://docs.confluent.io/platform/current/schema-registry/index.html[Confluent Schema Registry] or https://www.apicur.io/registry/[Apicurio Registry]. +records, and connect to a schema registry (such as the https://docs.confluent.io/platform/current/schema-registry/index.html[Confluent Schema Registry] or https://www.apicur.io/registry/[Apicurio Registry]). If you are not familiar with Kafka and Kafka in Quarkus in particular, consider first going through the xref:kafka.adoc[Using Apache Kafka with Reactive Messaging] guide. @@ -311,6 +311,8 @@ See xref:kafka-dev-services.adoc[Dev Services for Kafka] and xref:apicurio-regis ==== You might have noticed that we didn't configure the schema registry URL anywhere. This is because Dev Services for Apicurio Registry configures all Kafka channels in SmallRye Reactive Messaging to use the automatically started registry instance. +If there are Confluent serde classes present on the classpath, +the url used with Dev Services for Apicurio Registry is the Confluent-compatible one. There's no Dev Services support for Confluent Schema Registry. If you want to use a running instance of Confluent Schema Registry, configure its URL, together with the URL of a Kafka broker: diff --git a/extensions/apicurio-registry-avro/deployment/pom.xml b/extensions/apicurio-registry/apicurio/avro/deployment/pom.xml similarity index 91% rename from extensions/apicurio-registry-avro/deployment/pom.xml rename to extensions/apicurio-registry/apicurio/avro/deployment/pom.xml index b07b8f192566ba..6ce0a0f7ea7b3f 100644 --- a/extensions/apicurio-registry-avro/deployment/pom.xml +++ b/extensions/apicurio-registry/apicurio/avro/deployment/pom.xml @@ -14,6 +14,14 @@ Quarkus - Apicurio Registry - Avro - Deployment + + io.quarkus + quarkus-apicurio-registry-devservice-deployment + + + io.quarkus + quarkus-apicurio-registry-common-deployment + io.quarkus quarkus-apicurio-registry-avro @@ -28,10 +36,6 @@ io.quarkus quarkus-avro-deployment - - io.quarkus - quarkus-vertx-deployment - io.quarkus quarkus-smallrye-openapi-spi diff --git a/extensions/apicurio-registry/apicurio/avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java b/extensions/apicurio-registry/apicurio/avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java new file mode 100644 index 00000000000000..1e029ff53218ed --- /dev/null +++ b/extensions/apicurio-registry/apicurio/avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java @@ -0,0 +1,45 @@ +package io.quarkus.apicurio.registry.avro; + +import io.quarkus.deployment.Feature; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; + +public class ApicurioRegistryAvroProcessor { + @BuildStep + FeatureBuildItem feature() { + return new FeatureBuildItem(Feature.APICURIO_REGISTRY_AVRO); + } + + @BuildStep + public void apicurioRegistryAvro(BuildProducer reflectiveClass, + BuildProducer sslNativeSupport) { + + reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, false, + "io.apicurio.registry.serde.avro.AvroKafkaDeserializer", + "io.apicurio.registry.serde.avro.AvroKafkaSerializer")); + + reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, + "io.apicurio.registry.serde.strategy.SimpleTopicIdStrategy", + "io.apicurio.registry.serde.strategy.TopicIdStrategy", + "io.apicurio.registry.serde.avro.DefaultAvroDatumProvider", + "io.apicurio.registry.serde.avro.ReflectAvroDatumProvider", + "io.apicurio.registry.serde.avro.strategy.RecordIdStrategy", + "io.apicurio.registry.serde.avro.strategy.TopicRecordIdStrategy")); + + reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, + "io.apicurio.registry.serde.DefaultSchemaResolver", + "io.apicurio.registry.serde.DefaultIdHandler", + "io.apicurio.registry.serde.Legacy4ByteIdHandler", + "io.apicurio.registry.serde.fallback.DefaultFallbackArtifactProvider", + "io.apicurio.registry.serde.headers.DefaultHeadersHandler")); + } + + @BuildStep + ExtensionSslNativeSupportBuildItem enableSslInNative() { + return new ExtensionSslNativeSupportBuildItem(Feature.APICURIO_REGISTRY_AVRO); + } + +} diff --git a/extensions/apicurio-registry-avro/pom.xml b/extensions/apicurio-registry/apicurio/avro/pom.xml similarity index 90% rename from extensions/apicurio-registry-avro/pom.xml rename to extensions/apicurio-registry/apicurio/avro/pom.xml index 3689c6ada15f2b..d3df1d5ac79cac 100644 --- a/extensions/apicurio-registry-avro/pom.xml +++ b/extensions/apicurio-registry/apicurio/avro/pom.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> - quarkus-extensions-parent + quarkus-apicurio-registry-apicurio-parent io.quarkus 999-SNAPSHOT ../pom.xml diff --git a/extensions/apicurio-registry-avro/runtime/pom.xml b/extensions/apicurio-registry/apicurio/avro/runtime/pom.xml similarity index 73% rename from extensions/apicurio-registry-avro/runtime/pom.xml rename to extensions/apicurio-registry/apicurio/avro/runtime/pom.xml index 7f4be7fd6dbc68..3908c5e89ff704 100644 --- a/extensions/apicurio-registry-avro/runtime/pom.xml +++ b/extensions/apicurio-registry/apicurio/avro/runtime/pom.xml @@ -12,7 +12,7 @@ quarkus-apicurio-registry-avro Quarkus - Apicurio Registry - Avro - Runtime - Provide support for the Apicurio Registry Avro library + io.apicurio @@ -24,31 +24,13 @@ - - io.apicurio - apicurio-common-rest-client-vertx - - - io.quarkus - quarkus-kubernetes-service-binding - true - - - - io.quarkus - quarkus-core - io.quarkus - quarkus-avro + quarkus-apicurio-registry-devservice io.quarkus - quarkus-vertx - - - org.apache.commons - commons-lang3 + quarkus-apicurio-registry-common diff --git a/extensions/apicurio-registry-avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/apicurio-registry/apicurio/avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml similarity index 100% rename from extensions/apicurio-registry-avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml rename to extensions/apicurio-registry/apicurio/avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml diff --git a/extensions/apicurio-registry/apicurio/common/deployment/pom.xml b/extensions/apicurio-registry/apicurio/common/deployment/pom.xml new file mode 100644 index 00000000000000..3663d61611bd69 --- /dev/null +++ b/extensions/apicurio-registry/apicurio/common/deployment/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + + quarkus-apicurio-registry-common-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-apicurio-registry-common-deployment + Quarkus - Apicurio Registry - Common Deployment + + + + io.quarkus + quarkus-apicurio-registry-common + + + + io.quarkus + quarkus-core-deployment + + + + io.quarkus + quarkus-vertx-deployment + + + io.quarkus + quarkus-smallrye-openapi-spi + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java b/extensions/apicurio-registry/apicurio/common/deployment/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClientProcessor.java similarity index 58% rename from extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java rename to extensions/apicurio-registry/apicurio/common/deployment/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClientProcessor.java index 16cb347e8630d4..7bb230d95463db 100644 --- a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java +++ b/extensions/apicurio-registry/apicurio/common/deployment/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClientProcessor.java @@ -1,49 +1,23 @@ -package io.quarkus.apicurio.registry.avro; +package io.quarkus.apicurio.registry.common; import java.io.IOException; import io.apicurio.rest.client.spi.ApicurioHttpClientProvider; -import io.quarkus.deployment.Feature; 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.FeatureBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem; import io.quarkus.smallrye.openapi.deployment.spi.IgnoreStaticDocumentBuildItem; import io.quarkus.vertx.deployment.VertxBuildItem; -public class ApicurioRegistryAvroProcessor { - @BuildStep - FeatureBuildItem feature() { - return new FeatureBuildItem(Feature.APICURIO_REGISTRY_AVRO); - } +public class ApicurioRegistryClientProcessor { @BuildStep - public void apicurioRegistryAvro(BuildProducer reflectiveClass, + public void apicurioRegistryClient(BuildProducer reflectiveClass, BuildProducer sslNativeSupport) { - - reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, false, - "io.apicurio.registry.serde.avro.AvroKafkaDeserializer", - "io.apicurio.registry.serde.avro.AvroKafkaSerializer")); - - reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, - "io.apicurio.registry.serde.strategy.SimpleTopicIdStrategy", - "io.apicurio.registry.serde.strategy.TopicIdStrategy", - "io.apicurio.registry.serde.avro.DefaultAvroDatumProvider", - "io.apicurio.registry.serde.avro.ReflectAvroDatumProvider", - "io.apicurio.registry.serde.avro.strategy.RecordIdStrategy", - "io.apicurio.registry.serde.avro.strategy.TopicRecordIdStrategy")); - - reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, - "io.apicurio.registry.serde.DefaultSchemaResolver", - "io.apicurio.registry.serde.DefaultIdHandler", - "io.apicurio.registry.serde.Legacy4ByteIdHandler", - "io.apicurio.registry.serde.fallback.DefaultFallbackArtifactProvider", - "io.apicurio.registry.serde.headers.DefaultHeadersHandler")); - reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, "io.apicurio.rest.client.auth.exception.NotAuthorizedException", "io.apicurio.rest.client.auth.exception.ForbiddenException", @@ -78,9 +52,4 @@ public void apicurioRegistryClient(VertxBuildItem vertx, ApicurioRegistryClient client.setup(vertx.getVertx()); } - @BuildStep - ExtensionSslNativeSupportBuildItem enableSslInNative() { - return new ExtensionSslNativeSupportBuildItem(Feature.APICURIO_REGISTRY_AVRO); - } - } diff --git a/extensions/apicurio-registry/apicurio/common/pom.xml b/extensions/apicurio-registry/apicurio/common/pom.xml new file mode 100644 index 00000000000000..7668040b1c0ef0 --- /dev/null +++ b/extensions/apicurio-registry/apicurio/common/pom.xml @@ -0,0 +1,22 @@ + + + + quarkus-apicurio-registry-apicurio-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + 4.0.0 + quarkus-apicurio-registry-common-parent + Quarkus - Apicurio Registry - Common + pom + + + deployment + runtime + + + diff --git a/extensions/apicurio-registry/apicurio/common/runtime/pom.xml b/extensions/apicurio-registry/apicurio/common/runtime/pom.xml new file mode 100644 index 00000000000000..49b384e4a30b33 --- /dev/null +++ b/extensions/apicurio-registry/apicurio/common/runtime/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + + quarkus-apicurio-registry-common-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-apicurio-registry-common + Quarkus - Apicurio Registry - Common Runtime + + + + io.apicurio + apicurio-registry-client + + + io.apicurio + apicurio-common-rest-client-vertx + + + io.quarkus + quarkus-kubernetes-service-binding + true + + + + io.quarkus + quarkus-core + + + io.quarkus + quarkus-avro + + + io.quarkus + quarkus-vertx + + + org.apache.commons + commons-lang3 + + + + diff --git a/extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryClient.java b/extensions/apicurio-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClient.java similarity index 90% rename from extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryClient.java rename to extensions/apicurio-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClient.java index ceae6a11f3a5c0..1a072229c2fcd0 100644 --- a/extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryClient.java +++ b/extensions/apicurio-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClient.java @@ -1,4 +1,4 @@ -package io.quarkus.apicurio.registry.avro; +package io.quarkus.apicurio.registry.common; import io.apicurio.registry.rest.client.RegistryClientFactory; import io.apicurio.rest.client.VertxHttpClientProvider; diff --git a/extensions/apicurio-registry/apicurio/pom.xml b/extensions/apicurio-registry/apicurio/pom.xml new file mode 100644 index 00000000000000..f514193c11a450 --- /dev/null +++ b/extensions/apicurio-registry/apicurio/pom.xml @@ -0,0 +1,21 @@ + + + + quarkus-apicurio-registry + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + 4.0.0 + quarkus-apicurio-registry-apicurio-parent + Quarkus - Apicurio Registry - Apicurio + pom + + + common + avro + + diff --git a/extensions/apicurio-registry/confluent/avro/deployment/pom.xml b/extensions/apicurio-registry/confluent/avro/deployment/pom.xml new file mode 100644 index 00000000000000..a58c6f28466ffa --- /dev/null +++ b/extensions/apicurio-registry/confluent/avro/deployment/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + + io.quarkus + quarkus-apicurio-registry-confluent-avro-parent + 999-SNAPSHOT + + + quarkus-apicurio-registry-confluent-avro-deployment + Quarkus - Apicurio Registry - Confluent Avro Deployment + + + + io.quarkus + quarkus-apicurio-registry-devservice-deployment + + + io.quarkus + quarkus-apicurio-registry-confluent-common-deployment + + + io.quarkus + quarkus-apicurio-registry-confluent-avro + + + + io.quarkus + quarkus-core-deployment + + + + io.quarkus + quarkus-avro-deployment + + + io.quarkus + quarkus-smallrye-openapi-spi + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/extensions/apicurio-registry/confluent/avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ConfluentRegistryAvroProcessor.java b/extensions/apicurio-registry/confluent/avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ConfluentRegistryAvroProcessor.java new file mode 100644 index 00000000000000..1dd9741989d41e --- /dev/null +++ b/extensions/apicurio-registry/confluent/avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ConfluentRegistryAvroProcessor.java @@ -0,0 +1,30 @@ +package io.quarkus.apicurio.registry.avro; + +import io.quarkus.deployment.Feature; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; + +public class ConfluentRegistryAvroProcessor { + @BuildStep + FeatureBuildItem feature() { + return new FeatureBuildItem(Feature.CONFLUENT_REGISTRY_AVRO); + } + + @BuildStep + public void confluentRegistryAvro(BuildProducer reflectiveClass, + BuildProducer sslNativeSupport) { + reflectiveClass + .produce(new ReflectiveClassBuildItem(true, false, + "io.confluent.kafka.serializers.KafkaAvroDeserializer", + "io.confluent.kafka.serializers.KafkaAvroSerializer")); + } + + @BuildStep + ExtensionSslNativeSupportBuildItem enableSslInNative() { + return new ExtensionSslNativeSupportBuildItem(Feature.CONFLUENT_REGISTRY_AVRO); + } + +} diff --git a/extensions/apicurio-registry/confluent/avro/pom.xml b/extensions/apicurio-registry/confluent/avro/pom.xml new file mode 100644 index 00000000000000..526f396c12ab52 --- /dev/null +++ b/extensions/apicurio-registry/confluent/avro/pom.xml @@ -0,0 +1,21 @@ + + + + quarkus-apicurio-registry-confluent-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + 4.0.0 + quarkus-apicurio-registry-confluent-avro-parent + Quarkus - Apicurio Registry - Confluent Avro + pom + + + deployment + runtime + + diff --git a/extensions/apicurio-registry/confluent/avro/runtime/pom.xml b/extensions/apicurio-registry/confluent/avro/runtime/pom.xml new file mode 100644 index 00000000000000..5dca6e094d9c3c --- /dev/null +++ b/extensions/apicurio-registry/confluent/avro/runtime/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + + io.quarkus + quarkus-apicurio-registry-confluent-avro-parent + 999-SNAPSHOT + + + quarkus-apicurio-registry-confluent-avro + Quarkus - Apicurio Registry - Confluent Avro Runtime + + + + io.quarkus + quarkus-apicurio-registry-devservice + + + io.quarkus + quarkus-apicurio-registry-confluent-common + + + + + + + + io.quarkus + quarkus-bootstrap-maven-plugin + + + io.quarkus.apicurio.registry.confluent.avro + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/extensions/apicurio-registry/confluent/avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/apicurio-registry/confluent/avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 00000000000000..3fc0f6d148be2c --- /dev/null +++ b/extensions/apicurio-registry/confluent/avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -0,0 +1,13 @@ +--- +artifact: ${project.groupId}:${project.artifactId}:${project.version} +name: "Apicurio Registry - Confluent Avro" +metadata: + keywords: + - "confluent" + - "avro" + guide: "https://quarkus.io/guides/kafka-schema-registry-avro" + categories: + - "serialization" + status: "experimental" + config: + - "avro.codegen." diff --git a/extensions/apicurio-registry/confluent/common/deployment/pom.xml b/extensions/apicurio-registry/confluent/common/deployment/pom.xml new file mode 100644 index 00000000000000..58e92ff0cf3ba6 --- /dev/null +++ b/extensions/apicurio-registry/confluent/common/deployment/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + + quarkus-apicurio-registry-confluent-common-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-apicurio-registry-confluent-common-deployment + Quarkus - Apicurio Registry - Confluent Common Deployment + + + + io.quarkus + quarkus-apicurio-registry-confluent-common + + + + io.quarkus + quarkus-core-deployment + + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/extensions/apicurio-registry/confluent/common/deployment/src/main/java/io/quarkus/apicurio/registry/common/ConfluentRegistryClientProcessor.java b/extensions/apicurio-registry/confluent/common/deployment/src/main/java/io/quarkus/apicurio/registry/common/ConfluentRegistryClientProcessor.java new file mode 100644 index 00000000000000..fd21daec5112c7 --- /dev/null +++ b/extensions/apicurio-registry/confluent/common/deployment/src/main/java/io/quarkus/apicurio/registry/common/ConfluentRegistryClientProcessor.java @@ -0,0 +1,54 @@ +package io.quarkus.apicurio.registry.common; + +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem; + +public class ConfluentRegistryClientProcessor { + + @BuildStep + public void confluentRegistryClient( + BuildProducer reflectiveClass, + BuildProducer serviceProviders, + BuildProducer sslNativeSupport) { + + reflectiveClass + .produce(new ReflectiveClassBuildItem(true, false, false, + "io.confluent.kafka.serializers.context.NullContextNameStrategy")); + + reflectiveClass + .produce(new ReflectiveClassBuildItem(true, true, false, + "io.confluent.kafka.serializers.subject.TopicNameStrategy", + "io.confluent.kafka.serializers.subject.TopicRecordNameStrategy", + "io.confluent.kafka.serializers.subject.RecordNameStrategy")); + + reflectiveClass + .produce(new ReflectiveClassBuildItem(true, true, false, + "io.confluent.kafka.schemaregistry.client.rest.entities.ErrorMessage", + "io.confluent.kafka.schemaregistry.client.rest.entities.Schema", + "io.confluent.kafka.schemaregistry.client.rest.entities.Config", + "io.confluent.kafka.schemaregistry.client.rest.entities.SchemaReference", + "io.confluent.kafka.schemaregistry.client.rest.entities.SchemaString", + "io.confluent.kafka.schemaregistry.client.rest.entities.SchemaTypeConverter", + "io.confluent.kafka.schemaregistry.client.rest.entities.ServerClusterId", + "io.confluent.kafka.schemaregistry.client.rest.entities.SujectVersion")); + + reflectiveClass + .produce(new ReflectiveClassBuildItem(true, true, false, + "io.confluent.kafka.schemaregistry.client.rest.entities.requests.CompatibilityCheckResponse", + "io.confluent.kafka.schemaregistry.client.rest.entities.requests.ConfigUpdateRequest", + "io.confluent.kafka.schemaregistry.client.rest.entities.requests.ModeGetResponse", + "io.confluent.kafka.schemaregistry.client.rest.entities.requests.ModeUpdateRequest", + "io.confluent.kafka.schemaregistry.client.rest.entities.requests.RegisterSchemaRequest", + "io.confluent.kafka.schemaregistry.client.rest.entities.requests.RegisterSchemaResponse")); + + serviceProviders + .produce(new ServiceProviderBuildItem( + "io.confluent.kafka.schemaregistry.client.security.basicauth.BasicAuthCredentialProvider", + "io.confluent.kafka.schemaregistry.client.security.basicauth.SaslBasicAuthCredentialProvider", + "io.confluent.kafka.schemaregistry.client.security.basicauth.UrlBasicAuthCredentialProvider", + "io.confluent.kafka.schemaregistry.client.security.basicauth.UserInfoCredentialProvider")); + } +} diff --git a/extensions/apicurio-registry/confluent/common/pom.xml b/extensions/apicurio-registry/confluent/common/pom.xml new file mode 100644 index 00000000000000..b416047f8ed50f --- /dev/null +++ b/extensions/apicurio-registry/confluent/common/pom.xml @@ -0,0 +1,22 @@ + + + + quarkus-apicurio-registry-confluent-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + 4.0.0 + quarkus-apicurio-registry-confluent-common-parent + Quarkus - Apicurio Registry - Confluent Common + pom + + + deployment + runtime + + + diff --git a/extensions/apicurio-registry/confluent/common/runtime/pom.xml b/extensions/apicurio-registry/confluent/common/runtime/pom.xml new file mode 100644 index 00000000000000..05fdc10b695026 --- /dev/null +++ b/extensions/apicurio-registry/confluent/common/runtime/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + + quarkus-apicurio-registry-confluent-common-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-apicurio-registry-confluent-common + Quarkus - Apicurio Registry - Confluent Common Runtime + + + + + io.quarkus + quarkus-core + + + io.quarkus + quarkus-avro + + + io.quarkus + quarkus-vertx + + + org.apache.commons + commons-lang3 + + + + diff --git a/extensions/apicurio-registry/confluent/common/runtime/src/main/java/io/quarkus/apicurio/registry/common/Empty.java b/extensions/apicurio-registry/confluent/common/runtime/src/main/java/io/quarkus/apicurio/registry/common/Empty.java new file mode 100644 index 00000000000000..19f32a1c96e2b9 --- /dev/null +++ b/extensions/apicurio-registry/confluent/common/runtime/src/main/java/io/quarkus/apicurio/registry/common/Empty.java @@ -0,0 +1,4 @@ +package io.quarkus.apicurio.registry.common; + +public class Empty { +} diff --git a/extensions/apicurio-registry/confluent/pom.xml b/extensions/apicurio-registry/confluent/pom.xml new file mode 100644 index 00000000000000..58bf35d87e1b36 --- /dev/null +++ b/extensions/apicurio-registry/confluent/pom.xml @@ -0,0 +1,21 @@ + + + + quarkus-apicurio-registry + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + 4.0.0 + quarkus-apicurio-registry-confluent-parent + Quarkus - Apicurio Registry - Confluent + pom + + + common + avro + + diff --git a/extensions/apicurio-registry/devservice/deployment/pom.xml b/extensions/apicurio-registry/devservice/deployment/pom.xml new file mode 100644 index 00000000000000..09f364c82588f3 --- /dev/null +++ b/extensions/apicurio-registry/devservice/deployment/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + + quarkus-apicurio-registry-devservice-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-apicurio-registry-devservice-deployment + Quarkus - Apicurio Registry - DevService Deployment + + + + io.quarkus + quarkus-apicurio-registry-devservice + + + + io.quarkus + quarkus-core-deployment + + + + io.quarkus + quarkus-vertx-deployment + + + io.quarkus + quarkus-smallrye-openapi-spi + + + + org.testcontainers + testcontainers + + + junit + junit + + + + + io.quarkus + quarkus-junit4-mock + + + io.quarkus + quarkus-devservices-deployment + + + + io.quarkus + quarkus-junit5-internal + test + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java b/extensions/apicurio-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java similarity index 100% rename from extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java rename to extensions/apicurio-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java diff --git a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryDevServicesBuildTimeConfig.java b/extensions/apicurio-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/ApicurioRegistryDevServicesBuildTimeConfig.java similarity index 94% rename from extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryDevServicesBuildTimeConfig.java rename to extensions/apicurio-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/ApicurioRegistryDevServicesBuildTimeConfig.java index 15f810d58363e1..cdb5705db2476d 100644 --- a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryDevServicesBuildTimeConfig.java +++ b/extensions/apicurio-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/ApicurioRegistryDevServicesBuildTimeConfig.java @@ -1,4 +1,4 @@ -package io.quarkus.apicurio.registry.avro; +package io.quarkus.apicurio.registry.devservice; import java.util.Optional; @@ -12,7 +12,8 @@ public class ApicurioRegistryDevServicesBuildTimeConfig { /** * If Dev Services for Apicurio Registry has been explicitly enabled or disabled. Dev Services are generally enabled * by default, unless there is an existing configuration present. For Apicurio Registry, Dev Services starts a registry - * unless {@code mp.messaging.connector.smallrye-kafka.apicurio.registry.url} is set. + * unless {@code mp.messaging.connector.smallrye-kafka.apicurio.registry.url} or + * {@code mp.messaging.connector.smallrye-kafka.schema.registry.url} is set. */ @ConfigItem public Optional enabled = Optional.empty(); diff --git a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/DevServicesApicurioRegistryProcessor.java b/extensions/apicurio-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/DevServicesApicurioRegistryProcessor.java similarity index 88% rename from extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/DevServicesApicurioRegistryProcessor.java rename to extensions/apicurio-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/DevServicesApicurioRegistryProcessor.java index 7456b684a2eb7f..ea81adf57b8678 100644 --- a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/DevServicesApicurioRegistryProcessor.java +++ b/extensions/apicurio-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/DevServicesApicurioRegistryProcessor.java @@ -1,7 +1,8 @@ -package io.quarkus.apicurio.registry.avro; +package io.quarkus.apicurio.registry.devservice; import java.time.Duration; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -33,14 +34,15 @@ * Starts Apicurio Registry as dev service if needed. *

* In the future, when we have multiple Apicurio Registry extensions (Avro, Protobuf, ...), - * this dev service support should probably be moved into an extra extension (quarkus-apicurio-registry-internal). + * this dev service support should probably be moved into an extra extension (quarkus-apicurio-registry-base). */ public class DevServicesApicurioRegistryProcessor { private static final Logger log = Logger.getLogger(DevServicesApicurioRegistryProcessor.class); private static final int APICURIO_REGISTRY_PORT = 8080; // inside the container - private static final String REGISTRY_URL_CONFIG = "mp.messaging.connector.smallrye-kafka.apicurio.registry.url"; + private static final String APLICURIO_REGISTRY_URL_CONFIG = "mp.messaging.connector.smallrye-kafka.apicurio.registry.url"; + private static final String SCHEMA_REGISTRY_URL_CONFIG = "mp.messaging.connector.smallrye-kafka.schema.registry.url"; /** * Label to add to shared Dev Service for Apicurio Registry running in containers. @@ -95,7 +97,7 @@ public DevServicesResultBuildItem startApicurioRegistryDevService(LaunchModeBuil if (devService.isOwner()) { log.infof("Dev Services for Apicurio Registry started. The registry is available at %s", - devService.getConfig().get(REGISTRY_URL_CONFIG)); + devService.getConfig().get(APLICURIO_REGISTRY_URL_CONFIG)); } // Configure the watch dog @@ -117,8 +119,10 @@ public void run() { return devService.toBuildItem(); } - private String getRegistryUrlConfig(String baseUrl) { - return baseUrl + "/apis/registry/v2"; + private Map getRegistryUrlConfigs(String baseUrl) { + return Map.of( + APLICURIO_REGISTRY_URL_CONFIG, baseUrl + "/apis/registry/v2", + SCHEMA_REGISTRY_URL_CONFIG, baseUrl + "/apis/ccompat/v6"); } private void shutdownApicurioRegistry() { @@ -141,8 +145,13 @@ private RunningDevService startApicurioRegistry(ApicurioRegistryDevServiceCfg co return null; } - if (ConfigUtils.isPropertyPresent(REGISTRY_URL_CONFIG)) { - log.debug("Not starting dev services for Apicurio Registry, " + REGISTRY_URL_CONFIG + " is configured."); + if (ConfigUtils.isPropertyPresent(APLICURIO_REGISTRY_URL_CONFIG)) { + log.debug("Not starting dev services for Apicurio Registry, " + APLICURIO_REGISTRY_URL_CONFIG + " is configured."); + return null; + } + + if (ConfigUtils.isPropertyPresent(SCHEMA_REGISTRY_URL_CONFIG)) { + log.debug("Not starting dev services for Apicurio Registry, " + SCHEMA_REGISTRY_URL_CONFIG + " is configured."); return null; } @@ -159,9 +168,9 @@ private RunningDevService startApicurioRegistry(ApicurioRegistryDevServiceCfg co // Starting the broker return apicurioRegistryContainerLocator.locateContainer(config.serviceName, config.shared, launchMode.getLaunchMode()) .map(address -> new RunningDevService(Feature.APICURIO_REGISTRY_AVRO.getName(), - address.getId(), null, REGISTRY_URL_CONFIG, + address.getId(), null, // address does not have the URL Scheme - just the host:port, so prepend http:// - getRegistryUrlConfig("http://" + address.getUrl()))) + getRegistryUrlConfigs("http://" + address.getUrl()))) .orElseGet(() -> { ApicurioRegistryContainer container = new ApicurioRegistryContainer( DockerImageName.parse(config.imageName), config.fixedExposedPort, @@ -171,7 +180,7 @@ private RunningDevService startApicurioRegistry(ApicurioRegistryDevServiceCfg co container.start(); return new RunningDevService(Feature.APICURIO_REGISTRY_AVRO.getName(), container.getContainerId(), - container::close, REGISTRY_URL_CONFIG, getRegistryUrlConfig(container.getUrl())); + container::close, getRegistryUrlConfigs(container.getUrl())); }); } @@ -185,7 +194,8 @@ private boolean hasKafkaChannelWithoutApicurioRegistry() { && "smallrye-kafka".equals(config.getOptionalValue(name, String.class).orElse("ignored")); boolean isConfigured = false; if ((isIncoming || isOutgoing) && isKafka) { - isConfigured = ConfigUtils.isPropertyPresent(name.replace(".connector", ".apicurio.registry.url")); + isConfigured = ConfigUtils.isPropertyPresent(name.replace(".connector", ".apicurio.registry.url")) || + ConfigUtils.isPropertyPresent(name.replace(".connector", ".schema.registry.url")); } if (!isConfigured) { return true; diff --git a/extensions/apicurio-registry/devservice/pom.xml b/extensions/apicurio-registry/devservice/pom.xml new file mode 100644 index 00000000000000..8f0f06834334ba --- /dev/null +++ b/extensions/apicurio-registry/devservice/pom.xml @@ -0,0 +1,22 @@ + + + + quarkus-apicurio-registry + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + 4.0.0 + quarkus-apicurio-registry-devservice-parent + Quarkus - Apicurio Registry - DevService + pom + + + deployment + runtime + + + diff --git a/extensions/apicurio-registry/devservice/runtime/pom.xml b/extensions/apicurio-registry/devservice/runtime/pom.xml new file mode 100644 index 00000000000000..fca635dd041da6 --- /dev/null +++ b/extensions/apicurio-registry/devservice/runtime/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + + quarkus-apicurio-registry-devservice-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-apicurio-registry-devservice + Quarkus - Apicurio Registry - DevService Runtime + + + + io.quarkus + quarkus-kubernetes-service-binding + true + + + + io.quarkus + quarkus-core + + + io.quarkus + quarkus-avro + + + io.quarkus + quarkus-vertx + + + org.apache.commons + commons-lang3 + + + + diff --git a/extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java b/extensions/apicurio-registry/devservice/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java similarity index 100% rename from extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java rename to extensions/apicurio-registry/devservice/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java diff --git a/extensions/apicurio-registry-avro/runtime/src/main/resources/META-INF/services/io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter b/extensions/apicurio-registry/devservice/runtime/src/main/resources/META-INF/services/io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter similarity index 100% rename from extensions/apicurio-registry-avro/runtime/src/main/resources/META-INF/services/io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter rename to extensions/apicurio-registry/devservice/runtime/src/main/resources/META-INF/services/io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter diff --git a/extensions/apicurio-registry/pom.xml b/extensions/apicurio-registry/pom.xml new file mode 100644 index 00000000000000..2a83a6efd0e647 --- /dev/null +++ b/extensions/apicurio-registry/pom.xml @@ -0,0 +1,22 @@ + + + + quarkus-extensions-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + 4.0.0 + quarkus-apicurio-registry + Quarkus - Apicurio Registry + pom + + + devservice + apicurio + confluent + + 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 6f508df693bc26..ac222e13e0d6ec 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 @@ -347,55 +347,13 @@ private void handleAvro(BuildProducer reflectiveClass, try { Class.forName("io.confluent.kafka.serializers.KafkaAvroDeserializer", false, Thread.currentThread().getContextClassLoader()); - reflectiveClass - .produce(new ReflectiveClassBuildItem(true, false, - "io.confluent.kafka.serializers.KafkaAvroDeserializer", - "io.confluent.kafka.serializers.KafkaAvroSerializer")); - - reflectiveClass - .produce(new ReflectiveClassBuildItem(true, false, false, - "io.confluent.kafka.serializers.context.NullContextNameStrategy")); - - reflectiveClass - .produce(new ReflectiveClassBuildItem(true, true, false, - "io.confluent.kafka.serializers.subject.TopicNameStrategy", - "io.confluent.kafka.serializers.subject.TopicRecordNameStrategy", - "io.confluent.kafka.serializers.subject.RecordNameStrategy")); - - reflectiveClass - .produce(new ReflectiveClassBuildItem(true, true, false, - "io.confluent.kafka.schemaregistry.client.rest.entities.ErrorMessage", - "io.confluent.kafka.schemaregistry.client.rest.entities.Schema", - "io.confluent.kafka.schemaregistry.client.rest.entities.Config", - "io.confluent.kafka.schemaregistry.client.rest.entities.SchemaReference", - "io.confluent.kafka.schemaregistry.client.rest.entities.SchemaString", - "io.confluent.kafka.schemaregistry.client.rest.entities.SchemaTypeConverter", - "io.confluent.kafka.schemaregistry.client.rest.entities.ServerClusterId", - "io.confluent.kafka.schemaregistry.client.rest.entities.SujectVersion")); - - reflectiveClass - .produce(new ReflectiveClassBuildItem(true, true, false, - "io.confluent.kafka.schemaregistry.client.rest.entities.requests.CompatibilityCheckResponse", - "io.confluent.kafka.schemaregistry.client.rest.entities.requests.ConfigUpdateRequest", - "io.confluent.kafka.schemaregistry.client.rest.entities.requests.ModeGetResponse", - "io.confluent.kafka.schemaregistry.client.rest.entities.requests.ModeUpdateRequest", - "io.confluent.kafka.schemaregistry.client.rest.entities.requests.RegisterSchemaRequest", - "io.confluent.kafka.schemaregistry.client.rest.entities.requests.RegisterSchemaResponse")); - } catch (ClassNotFoundException e) { - //ignore, Confluent Avro is not in the classpath - } - try { - Class.forName("io.confluent.kafka.schemaregistry.client.security.basicauth.BasicAuthCredentialProvider", false, - Thread.currentThread().getContextClassLoader()); - serviceProviders - .produce(new ServiceProviderBuildItem( - "io.confluent.kafka.schemaregistry.client.security.basicauth.BasicAuthCredentialProvider", - "io.confluent.kafka.schemaregistry.client.security.basicauth.SaslBasicAuthCredentialProvider", - "io.confluent.kafka.schemaregistry.client.security.basicauth.UrlBasicAuthCredentialProvider", - "io.confluent.kafka.schemaregistry.client.security.basicauth.UserInfoCredentialProvider")); + if (!capabilities.isPresent(Capability.CONFLUENT_REGISTRY_AVRO)) { + throw new RuntimeException( + "Confluent Avro classes detected, please use the quarkus-apicurio-registry-confluent-avro extension"); + } } catch (ClassNotFoundException e) { - // ignore, Confluent schema registry client not in the classpath + // ignore, Confluent Avro is not in the classpath } // --- Apicurio Registry 1.x --- diff --git a/extensions/pom.xml b/extensions/pom.xml index dfa6b6d3793cf0..3ec965df18da03 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -99,7 +99,7 @@ kafka-streams mongodb-client avro - apicurio-registry-avro + apicurio-registry devservices diff --git a/extensions/smallrye-reactive-messaging-kafka/deployment/pom.xml b/extensions/smallrye-reactive-messaging-kafka/deployment/pom.xml index 2b4f1d74e145aa..ac96a3608736a9 100644 --- a/extensions/smallrye-reactive-messaging-kafka/deployment/pom.xml +++ b/extensions/smallrye-reactive-messaging-kafka/deployment/pom.xml @@ -73,6 +73,11 @@ quarkus-apicurio-registry-avro-deployment test + + io.quarkus + quarkus-apicurio-registry-confluent-avro-deployment + test + io.rest-assured rest-assured diff --git a/integration-tests/kafka-avro-apicurio2/pom.xml b/integration-tests/kafka-avro-apicurio2/pom.xml index c52d919cd098cd..7fdee76810271f 100644 --- a/integration-tests/kafka-avro-apicurio2/pom.xml +++ b/integration-tests/kafka-avro-apicurio2/pom.xml @@ -22,7 +22,7 @@ --> - 2.1.5.Final + 2.2.0.Final @@ -77,11 +77,15 @@ - + io.quarkus quarkus-apicurio-registry-avro + + io.quarkus + quarkus-apicurio-registry-confluent-avro + @@ -209,6 +213,19 @@ + + io.quarkus + quarkus-apicurio-registry-confluent-avro-deployment + ${project.version} + pom + test + + + * + * + + + @@ -279,4 +296,4 @@ - + \ No newline at end of file diff --git a/integration-tests/kafka-avro-apicurio2/src/main/java/io/quarkus/it/kafka/avro/AvroKafkaCreator.java b/integration-tests/kafka-avro-apicurio2/src/main/java/io/quarkus/it/kafka/avro/AvroKafkaCreator.java index 065092035cb61d..8b7fc9bc2300b8 100644 --- a/integration-tests/kafka-avro-apicurio2/src/main/java/io/quarkus/it/kafka/avro/AvroKafkaCreator.java +++ b/integration-tests/kafka-avro-apicurio2/src/main/java/io/quarkus/it/kafka/avro/AvroKafkaCreator.java @@ -31,25 +31,44 @@ public class AvroKafkaCreator { @ConfigProperty(name = "kafka.bootstrap.servers") String bootstrap; - @ConfigProperty(name = "schema.url.confluent") - String confluent; - @ConfigProperty(name = "schema.url.apicurio") - String apicurio; + + @ConfigProperty(name = "mp.messaging.connector.smallrye-kafka.apicurio.registry.url") + String apicurioRegistryUrl; + + @ConfigProperty(name = "mp.messaging.connector.smallrye-kafka.schema.registry.url") + String confluentRegistryUrl; + + public AvroKafkaCreator() { + } + + public AvroKafkaCreator(String bootstrap, String apicurioRegistryUrl, String confluentRegistryUrl) { + this.bootstrap = bootstrap; + this.apicurioRegistryUrl = apicurioRegistryUrl; + this.confluentRegistryUrl = confluentRegistryUrl; + } + + public String getApicurioRegistryUrl() { + return apicurioRegistryUrl; + } + + public String getConfluentRegistryUrl() { + return confluentRegistryUrl; + } public KafkaConsumer createConfluentConsumer(String groupdIdConfig, String subscribtionName) { - return createConfluentConsumer(bootstrap, confluent, groupdIdConfig, subscribtionName); + return createConfluentConsumer(bootstrap, getConfluentRegistryUrl(), groupdIdConfig, subscribtionName); } public KafkaProducer createConfluentProducer(String clientId) { - return createConfluentProducer(bootstrap, confluent, clientId); + return createConfluentProducer(bootstrap, getConfluentRegistryUrl(), clientId); } public KafkaConsumer createApicurioConsumer(String groupdIdConfig, String subscribtionName) { - return createApicurioConsumer(bootstrap, apicurio, groupdIdConfig, subscribtionName); + return createApicurioConsumer(bootstrap, getApicurioRegistryUrl(), groupdIdConfig, subscribtionName); } public KafkaProducer createApicurioProducer(String clientId) { - return createApicurioProducer(bootstrap, apicurio, clientId); + return createApicurioProducer(bootstrap, getApicurioRegistryUrl(), clientId); } public static KafkaConsumer createConfluentConsumer(String bootstrap, String confluent, diff --git a/integration-tests/kafka-avro-apicurio2/src/main/resources/application.properties b/integration-tests/kafka-avro-apicurio2/src/main/resources/application.properties index eda85eda32cf3d..d4907bbe9f11b9 100644 --- a/integration-tests/kafka-avro-apicurio2/src/main/resources/application.properties +++ b/integration-tests/kafka-avro-apicurio2/src/main/resources/application.properties @@ -4,8 +4,3 @@ quarkus.log.category.\"org.apache.zookeeper\".level=WARN # enable health check quarkus.kafka.health.enabled=true - -# using QuarkusTestResourceLifecycleManager in this test -# Dev Services are tested by the means of kafka-avro-schema-quickstart -quarkus.kafka.devservices.enabled=false -quarkus.apicurio-registry.devservices.enabled=false diff --git a/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAndSchemaRegistryTestResource.java b/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAndSchemaRegistryTestResource.java deleted file mode 100644 index 696167560eddb1..00000000000000 --- a/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAndSchemaRegistryTestResource.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.quarkus.it.kafka; - -import java.util.HashMap; -import java.util.Map; - -import org.testcontainers.containers.GenericContainer; - -import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; -import io.strimzi.test.container.StrimziKafkaContainer; - -public class KafkaAndSchemaRegistryTestResource implements QuarkusTestResourceLifecycleManager { - - private static final StrimziKafkaContainer kafka = new StrimziKafkaContainer().withBrokerId(1); - - private static GenericContainer registry; - - public static String getBootstrapServers() { - return kafka.getBootstrapServers(); - } - - public static String getConfluentSchemaRegistryUrl() { - return "http://" + registry.getContainerIpAddress() + ":" + registry.getMappedPort(8080) + "/apis/ccompat/v6"; - } - - public static String getApicurioSchemaRegistryUrl() { - return "http://" + registry.getContainerIpAddress() + ":" + registry.getMappedPort(8080) + "/apis/registry/v2"; - } - - @Override - public Map start() { - kafka.start(); - registry = new GenericContainer<>("apicurio/apicurio-registry-mem:2.1.5.Final") - .withExposedPorts(8080) - .withEnv("QUARKUS_PROFILE", "prod"); - registry.start(); - Map properties = new HashMap<>(); - properties.put("schema.url.confluent", - "http://" + registry.getContainerIpAddress() + ":" + registry.getMappedPort(8080) + "/apis/ccompat/v6"); - properties.put("schema.url.apicurio", - "http://" + registry.getContainerIpAddress() + ":" + registry.getMappedPort(8080) + "/apis/registry/v2"); - properties.put("kafka.bootstrap.servers", kafka.getBootstrapServers()); - return properties; - } - - @Override - public void stop() { - registry.stop(); - kafka.close(); - } -} diff --git a/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAvroIT.java b/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAvroIT.java index 5030447a2e022b..cde33e53f4a2c1 100644 --- a/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAvroIT.java +++ b/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAvroIT.java @@ -4,13 +4,22 @@ import io.apicurio.registry.rest.client.RegistryClientFactory; import io.apicurio.rest.client.VertxHttpClientProvider; +import io.quarkus.it.kafka.avro.AvroKafkaCreator; import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.vertx.core.Vertx; @QuarkusIntegrationTest -@QuarkusTestResource(KafkaAndSchemaRegistryTestResource.class) -public class KafkaAvroIT extends KafkaAvroTest { +@QuarkusTestResource(value = KafkaResource.class, restrictToAnnotatedClass = true) +public class KafkaAvroIT extends KafkaAvroTestBase { + + AvroKafkaCreator creator; + + @Override + AvroKafkaCreator creator() { + return 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 diff --git a/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAvroTest.java b/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAvroTest.java index 418243f5d778d9..7aaeea67e39aa2 100644 --- a/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAvroTest.java +++ b/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAvroTest.java @@ -1,90 +1,18 @@ package io.quarkus.it.kafka; -import java.time.Duration; - -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.apache.kafka.clients.consumer.KafkaConsumer; -import org.apache.kafka.clients.producer.KafkaProducer; -import org.apache.kafka.clients.producer.ProducerRecord; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; +import javax.inject.Inject; import io.quarkus.it.kafka.avro.AvroKafkaCreator; -import io.quarkus.it.kafka.avro.Pet; -import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; @QuarkusTest -@QuarkusTestResource(KafkaAndSchemaRegistryTestResource.class) -public class KafkaAvroTest { - - private static final String CONFLUENT_PATH = "/avro/confluent"; - private static final String APICURIO_PATH = "/avro/apicurio"; - - @Test - public void testConfluentAvroProducer() { - KafkaConsumer consumer = AvroKafkaCreator.createConfluentConsumer( - KafkaAndSchemaRegistryTestResource.getBootstrapServers(), - KafkaAndSchemaRegistryTestResource.getConfluentSchemaRegistryUrl(), - "test-avro-confluent", - "test-avro-confluent-producer"); - testAvroProducer(consumer, CONFLUENT_PATH); - } +public class KafkaAvroTest extends KafkaAvroTestBase { - @Test - public void testConfluentAvroConsumer() { - KafkaProducer producer = AvroKafkaCreator.createConfluentProducer( - KafkaAndSchemaRegistryTestResource.getBootstrapServers(), - KafkaAndSchemaRegistryTestResource.getConfluentSchemaRegistryUrl(), - "test-avro-confluent-test"); - testAvroConsumer(producer, CONFLUENT_PATH, "test-avro-confluent-consumer"); - } - - @Test - public void testApicurioAvroProducer() { - KafkaConsumer consumer = AvroKafkaCreator.createApicurioConsumer( - KafkaAndSchemaRegistryTestResource.getBootstrapServers(), - KafkaAndSchemaRegistryTestResource.getApicurioSchemaRegistryUrl(), - "test-avro-apicurio", - "test-avro-apicurio-producer"); - testAvroProducer(consumer, APICURIO_PATH); - } - - @Test - public void testApicurioAvroConsumer() { - KafkaProducer producer = AvroKafkaCreator.createApicurioProducer( - KafkaAndSchemaRegistryTestResource.getBootstrapServers(), - KafkaAndSchemaRegistryTestResource.getApicurioSchemaRegistryUrl(), - "test-avro-apicurio-test"); - testAvroConsumer(producer, APICURIO_PATH, "test-avro-apicurio-consumer"); - } - - private void testAvroProducer(KafkaConsumer consumer, String path) { - RestAssured.given() - .header("content-type", "application/json") - .body("{\"name\":\"neo\", \"color\":\"tricolor\"}") - .post(path); - ConsumerRecord records = consumer.poll(Duration.ofMillis(20000)).iterator().next(); - Assertions.assertEquals(records.key(), (Integer) 0); - Pet pet = records.value(); - Assertions.assertEquals("neo", pet.getName()); - Assertions.assertEquals("tricolor", pet.getColor()); - consumer.close(); - } - - private void testAvroConsumer(KafkaProducer producer, String path, String topic) { - producer.send(new ProducerRecord<>(topic, 1, createPet())); - Pet retrieved = RestAssured.when().get(path).as(Pet.class); - Assertions.assertEquals("neo", retrieved.getName()); - Assertions.assertEquals("white", retrieved.getColor()); - producer.close(); - } + @Inject + AvroKafkaCreator creator; - private Pet createPet() { - Pet pet = new Pet(); - pet.setName("neo"); - pet.setColor("white"); - return pet; + @Override + AvroKafkaCreator creator() { + return creator; } } diff --git a/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAvroTestBase.java b/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAvroTestBase.java new file mode 100644 index 00000000000000..74e17f9f88d26e --- /dev/null +++ b/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaAvroTestBase.java @@ -0,0 +1,84 @@ +package io.quarkus.it.kafka; + +import java.time.Duration; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.producer.KafkaProducer; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import io.quarkus.it.kafka.avro.AvroKafkaCreator; +import io.quarkus.it.kafka.avro.Pet; +import io.restassured.RestAssured; + +public abstract class KafkaAvroTestBase { + + static final String CONFLUENT_PATH = "/avro/confluent"; + static final String APICURIO_PATH = "/avro/apicurio"; + + abstract AvroKafkaCreator creator(); + + @Test + public void testUrls() { + Assertions.assertTrue(creator().getApicurioRegistryUrl().endsWith("/apis/registry/v2")); + Assertions.assertTrue(creator().getConfluentRegistryUrl().endsWith("/apis/ccompat/v6")); + } + + @Test + public void testConfluentAvroProducer() { + KafkaConsumer consumer = creator().createConfluentConsumer( + "test-avro-confluent", + "test-avro-confluent-producer"); + testAvroProducer(consumer, CONFLUENT_PATH); + } + + @Test + public void testConfluentAvroConsumer() { + KafkaProducer producer = creator().createConfluentProducer("test-avro-confluent-test"); + testAvroConsumer(producer, CONFLUENT_PATH, "test-avro-confluent-consumer"); + } + + @Test + public void testApicurioAvroProducer() { + KafkaConsumer consumer = creator().createApicurioConsumer( + "test-avro-apicurio", + "test-avro-apicurio-producer"); + testAvroProducer(consumer, APICURIO_PATH); + } + + @Test + public void testApicurioAvroConsumer() { + KafkaProducer producer = creator().createApicurioProducer("test-avro-apicurio-test"); + testAvroConsumer(producer, APICURIO_PATH, "test-avro-apicurio-consumer"); + } + + protected void testAvroProducer(KafkaConsumer consumer, String path) { + RestAssured.given() + .header("content-type", "application/json") + .body("{\"name\":\"neo\", \"color\":\"tricolor\"}") + .post(path); + ConsumerRecord records = consumer.poll(Duration.ofMillis(20000)).iterator().next(); + Assertions.assertEquals(records.key(), (Integer) 0); + Pet pet = records.value(); + Assertions.assertEquals("neo", pet.getName()); + Assertions.assertEquals("tricolor", pet.getColor()); + consumer.close(); + } + + protected void testAvroConsumer(KafkaProducer producer, String path, String topic) { + producer.send(new ProducerRecord<>(topic, 1, createPet())); + Pet retrieved = RestAssured.when().get(path).as(Pet.class); + Assertions.assertEquals("neo", retrieved.getName()); + Assertions.assertEquals("white", retrieved.getColor()); + producer.close(); + } + + private Pet createPet() { + Pet pet = new Pet(); + pet.setName("neo"); + pet.setColor("white"); + return pet; + } +} diff --git a/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaResource.java b/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaResource.java new file mode 100644 index 00000000000000..024b9b7dc31e53 --- /dev/null +++ b/integration-tests/kafka-avro-apicurio2/src/test/java/io/quarkus/it/kafka/KafkaResource.java @@ -0,0 +1,40 @@ +package io.quarkus.it.kafka; + +import java.util.Collections; +import java.util.Map; + +import io.quarkus.it.kafka.avro.AvroKafkaCreator; +import io.quarkus.test.common.DevServicesContext; +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; + +public class KafkaResource implements QuarkusTestResourceLifecycleManager, DevServicesContext.ContextAware { + + AvroKafkaCreator creator; + + @Override + public void setIntegrationTestContext(DevServicesContext context) { + Map devServicesProperties = context.devServicesProperties(); + String bootstrapServers = devServicesProperties.get("kafka.bootstrap.servers"); + if (bootstrapServers != null) { + String apicurioUrl = devServicesProperties.get("mp.messaging.connector.smallrye-kafka.apicurio.registry.url"); + String confluentUrl = devServicesProperties.get("mp.messaging.connector.smallrye-kafka.schema.registry.url"); + creator = new AvroKafkaCreator(bootstrapServers, apicurioUrl, confluentUrl); + } + } + + @Override + public Map start() { + return Collections.emptyMap(); + } + + @Override + public void stop() { + } + + @Override + public void inject(TestInjector testInjector) { + testInjector.injectIntoFields( + creator, + new TestInjector.MatchesType(AvroKafkaCreator.class)); + } +} diff --git a/integration-tests/kafka-avro/pom.xml b/integration-tests/kafka-avro/pom.xml index 9d7c69589620c4..891efbf948568c 100644 --- a/integration-tests/kafka-avro/pom.xml +++ b/integration-tests/kafka-avro/pom.xml @@ -81,6 +81,10 @@ apicurio-registry-utils-serde ${apicurio.version} + + io.apicurio + apicurio-registry-client + org.jboss.spec.javax.interceptor jboss-interceptors-api_1.2_spec @@ -95,6 +99,30 @@ + + io.apicurio + apicurio-registry-client + ${apicurio.version} + + + org.jboss.spec.javax.interceptor + jboss-interceptors-api_1.2_spec + + + jakarta.activation + jakarta.activation-api + + + com.worldturner.medeia + medeia-validator-jackson + + + + + + io.quarkus + quarkus-apicurio-registry-confluent-avro + com.google.guava @@ -182,6 +210,19 @@ + + io.quarkus + quarkus-apicurio-registry-confluent-avro-deployment + ${project.version} + pom + test + + + * + * + + + io.quarkus quarkus-rest-client-deployment diff --git a/integration-tests/kafka-avro/src/main/resources/application.properties b/integration-tests/kafka-avro/src/main/resources/application.properties index c0f22a629a9992..c1b0831aa2f290 100644 --- a/integration-tests/kafka-avro/src/main/resources/application.properties +++ b/integration-tests/kafka-avro/src/main/resources/application.properties @@ -7,3 +7,4 @@ quarkus.kafka.health.enabled=true # using QuarkusTestResourceLifecycleManager in this test quarkus.kafka.devservices.enabled=false +quarkus.apicurio-registry.devservices.enabled=false diff --git a/test-framework/common/src/main/java/io/quarkus/test/common/QuarkusTestResourceLifecycleManager.java b/test-framework/common/src/main/java/io/quarkus/test/common/QuarkusTestResourceLifecycleManager.java index c25a9e5a039229..9e0e521caa2981 100644 --- a/test-framework/common/src/main/java/io/quarkus/test/common/QuarkusTestResourceLifecycleManager.java +++ b/test-framework/common/src/main/java/io/quarkus/test/common/QuarkusTestResourceLifecycleManager.java @@ -127,6 +127,23 @@ public boolean test(Field field) { } } + /** + * Returns {@code true} if the field can be assigned to the supplied type. + */ + class MatchesType implements Predicate { + + private final Class expectedFieldType; + + public MatchesType(Class expectedFieldType) { + this.expectedFieldType = expectedFieldType; + } + + @Override + public boolean test(Field field) { + return field.getType().isAssignableFrom(expectedFieldType); + } + } + /** * Returns {@code true} if the field is annotated with the supplied annotation and can also be assigned * to the supplied type.