diff --git a/bom/application/pom.xml b/bom/application/pom.xml index 6eb0efd7ad979..a4f70e9d77cb2 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -1208,6 +1208,16 @@ quarkus-avro-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 +1228,36 @@ quarkus-apicurio-registry-avro-deployment ${project.version} + + io.quarkus + quarkus-confluent-registry-common + ${project.version} + + + io.quarkus + quarkus-confluent-registry-common-deployment + ${project.version} + + + io.quarkus + quarkus-confluent-registry-avro + ${project.version} + + + io.quarkus + quarkus-confluent-registry-avro-deployment + ${project.version} + + + io.quarkus + quarkus-schema-registry-devservice + ${project.version} + + + io.quarkus + quarkus-schema-registry-devservice-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 90602ffba6ad1..507116e713a24 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,7 @@ public interface Capability { String APICURIO_REGISTRY = QUARKUS_PREFIX + "apicurio.registry"; String APICURIO_REGISTRY_AVRO = APICURIO_REGISTRY + ".avro"; + + String CONFLUENT_REGISTRY = QUARKUS_PREFIX + "confluent.registry"; + String CONFLUENT_REGISTRY_AVRO = CONFLUENT_REGISTRY + ".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 7010488ea423c..01f7016e8832b 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/Feature.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/Feature.java @@ -16,6 +16,7 @@ public enum Feature { CACHE, CDI, CONFIG_YAML, + CONFLUENT_REGISTRY_AVRO, ELASTICSEARCH_REST_CLIENT_COMMON, ELASTICSEARCH_REST_CLIENT, ELASTICSEARCH_REST_HIGH_LEVEL_CLIENT, diff --git a/devtools/bom-descriptor-json/pom.xml b/devtools/bom-descriptor-json/pom.xml index 5440493aa0308..0a391d1d2d568 100644 --- a/devtools/bom-descriptor-json/pom.xml +++ b/devtools/bom-descriptor-json/pom.xml @@ -292,6 +292,19 @@ + + io.quarkus + quarkus-confluent-registry-avro + ${project.version} + pom + test + + + * + * + + + io.quarkus quarkus-container-image diff --git a/docs/pom.xml b/docs/pom.xml index e9c1aaf4ef8cc..835c8bab9fc95 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -252,6 +252,19 @@ + + io.quarkus + quarkus-confluent-registry-avro-deployment + ${project.version} + pom + test + + + * + * + + + io.quarkus quarkus-container-image-deployment diff --git a/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc b/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc index beb991b3fc9ac..630bf70254a9b 100644 --- a/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc +++ b/docs/src/main/asciidoc/apicurio-registry-dev-services.adoc @@ -7,9 +7,18 @@ https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc include::./attributes.adoc[] -If the `quarkus-apicurio-registry-avro` extension is present, Dev Services for Apicurio Registry automatically starts an Apicurio Registry instance in dev mode and when running tests. +If an extension for schema registry, such as `quarkus-apicurio-registry-avro` or `quarkus-confluent-registry-avro`, is present, Dev Services for Apicurio Registry automatically starts an Apicurio Registry instance in dev mode and when running tests. Also, all Kafka channels in SmallRye Reactive Messaging are automatically configured to use this registry. -(This automatic configuration of course only applies to serializers and deserializers from the Apicurio Registry Avro library.) +This automatic configuration only applies to serializers and deserializers from Apicurio Registry serde libraries and Confluent Schema Registry serde libraries, because there properties are set: + +[source,properties] +---- +# for Apicurio Registry serde +mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v2 +# for Confluent Schema Registry serde +mp.messaging.connector.smallrye-kafka.schema.registry.url=http://localhost:8081/apis/ccompat/v6 +---- + == Enabling / Disabling Dev Services for Apicurio Registry @@ -17,15 +26,24 @@ Dev Services for Apicurio Registry is automatically enabled unless: - `quarkus.apicurio-registry.devservices.enabled` is set to `false` - `mp.messaging.connector.smallrye-kafka.apicurio.registry.url` is configured -- all the Reactive Messaging Kafka channels have the `apicurio.registry.url` attribute set +- `mp.messaging.connector.smallrye-kafka.schema.registry.url` is configured +- all the Reactive Messaging Kafka channels have either the `apicurio.registry.url` attribute or the `schema.registry.url` attribute set Dev Services for Apicurio Registry relies on Docker to start the registry. If your environment does not support Docker, you will need to start the registry manually, or use an already running registry. -You can configure the registry URL for all Kafka channels in SmallRye Reactive Messaging with a single property: +In such case, you can configure the registry URL for all Kafka channels in SmallRye Reactive Messaging with a single property. +For Apicurio Registry serde, that is: [source,properties] ---- -mp.messaging.connector.smallrye-kafka.apicurio.registry.url=http://localhost:8081/apis/registry/v2 +mp.messaging.connector.smallrye-kafka.apicurio.registry.url=... your Apicuio Registry URL... +---- + +For Confluent Schema Registry serde, that is: + +[source,properties] +---- +mp.messaging.connector.smallrye-kafka.schema.registry.url=... your Confluent Schema Registry URL... ---- == Shared registry diff --git a/docs/src/main/asciidoc/kafka-schema-registry-avro.adoc b/docs/src/main/asciidoc/kafka-schema-registry-avro.adoc index d6d85dfe84dfa..e9cee4c02212e 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. @@ -52,19 +52,17 @@ include::includes/devtools/create-app.adoc[] [TIP] ==== If you use Confluent Schema Registry, you don't need the `quarkus-apicurio-registry-avro` extension. -Instead, you need the following dependencies and the Confluent Maven repository added -to your build file: +Instead, you need the `quarkus-confluent-registry-avro` extension and a few more dependencies. +Also, you need to add the Confluent Maven repository to your build file: [source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"] .pom.xml ---- ... - - io.quarkus - quarkus-avro + quarkus-confluent-registry-avro @@ -109,8 +107,7 @@ repositories { dependencies { ... - // Quarkus extension for generating Java code from Avro schemas - implementation("io.quarkus:quarkus-avro") + implementation("io.quarkus:quarkus-confluent-registry-avro") // Confluent registry libraries use JAX-RS client implementation("io.quarkus:quarkus-rest-client-reactive") @@ -312,7 +309,10 @@ 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. -There's no Dev Services support for Confluent Schema Registry. +Apicurio Registry, in addition to its native API, also exposes an endpoint that is API-compatible with Confluent Schema Registry. +Therefore, this automatic configuration works both for Apicurio Registry serde and Confluent Schema Registry serde. + +However, note that there's no Dev Services support for running Confluent Schema Registry itself. If you want to use a running instance of Confluent Schema Registry, configure its URL, together with the URL of a Kafka broker: [source,properties] 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 6f508df693bc2..e1c8c73b85c7e 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-confluent-registry-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 dfa6b6d3793cf..f403dd08ba5cc 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -99,7 +99,7 @@ kafka-streams mongodb-client avro - apicurio-registry-avro + schema-registry devservices diff --git a/extensions/schema-registry/apicurio/avro/deployment/pom.xml b/extensions/schema-registry/apicurio/avro/deployment/pom.xml new file mode 100644 index 0000000000000..3c0009c1b7cf9 --- /dev/null +++ b/extensions/schema-registry/apicurio/avro/deployment/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + + io.quarkus + quarkus-apicurio-registry-avro-parent + 999-SNAPSHOT + + + quarkus-apicurio-registry-avro-deployment + Quarkus - Apicurio Registry - Avro - Deployment + + + + io.quarkus + quarkus-apicurio-registry-avro + + + + io.quarkus + quarkus-apicurio-registry-common-deployment + + + io.quarkus + quarkus-avro-deployment + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + 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 new file mode 100644 index 0000000000000..1e029ff53218e --- /dev/null +++ b/extensions/schema-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/schema-registry/apicurio/avro/pom.xml similarity index 91% rename from extensions/apicurio-registry-avro/pom.xml rename to extensions/schema-registry/apicurio/avro/pom.xml index 3689c6ada15f2..85be4515a4d63 100644 --- a/extensions/apicurio-registry-avro/pom.xml +++ b/extensions/schema-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-parent io.quarkus 999-SNAPSHOT ../pom.xml diff --git a/extensions/apicurio-registry-avro/runtime/pom.xml b/extensions/schema-registry/apicurio/avro/runtime/pom.xml similarity index 75% rename from extensions/apicurio-registry-avro/runtime/pom.xml rename to extensions/schema-registry/apicurio/avro/runtime/pom.xml index 7f4be7fd6dbc6..e0e0e9b9a3981 100644 --- a/extensions/apicurio-registry-avro/runtime/pom.xml +++ b/extensions/schema-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,32 +24,15 @@ - - io.apicurio - apicurio-common-rest-client-vertx - - - io.quarkus - quarkus-kubernetes-service-binding - true - - + io.quarkus - quarkus-core + quarkus-apicurio-registry-common io.quarkus quarkus-avro - - io.quarkus - quarkus-vertx - - - org.apache.commons - commons-lang3 - diff --git a/extensions/apicurio-registry-avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/schema-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/schema-registry/apicurio/avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml diff --git a/extensions/apicurio-registry-avro/deployment/pom.xml b/extensions/schema-registry/apicurio/common/deployment/pom.xml similarity index 58% rename from extensions/apicurio-registry-avro/deployment/pom.xml rename to extensions/schema-registry/apicurio/common/deployment/pom.xml index b07b8f192566b..723a788758709 100644 --- a/extensions/apicurio-registry-avro/deployment/pom.xml +++ b/extensions/schema-registry/apicurio/common/deployment/pom.xml @@ -5,61 +5,37 @@ 4.0.0 + quarkus-apicurio-registry-common-parent io.quarkus - quarkus-apicurio-registry-avro-parent 999-SNAPSHOT + ../pom.xml - quarkus-apicurio-registry-avro-deployment - Quarkus - Apicurio Registry - Avro - Deployment + quarkus-apicurio-registry-common-deployment + Quarkus - Apicurio Registry - Common - Deployment io.quarkus - quarkus-apicurio-registry-avro + quarkus-apicurio-registry-common io.quarkus quarkus-core-deployment - io.quarkus - quarkus-avro-deployment + quarkus-schema-registry-devservice-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 + quarkus-smallrye-openapi-spi diff --git a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java b/extensions/schema-registry/apicurio/common/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java similarity index 86% rename from extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java rename to extensions/schema-registry/apicurio/common/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java index c1835061bac21..88e394e3691f3 100644 --- a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java +++ b/extensions/schema-registry/apicurio/common/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java @@ -1,6 +1,5 @@ -package io.quarkus.apicurio.registry.avro.binding; +package io.quarkus.apicurio.registry.binding; -import io.quarkus.apicurio.registry.binding.ServiceRegistryBindingConverter; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.Capability; import io.quarkus.deployment.annotations.BuildProducer; diff --git a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java b/extensions/schema-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/schema-registry/apicurio/common/deployment/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClientProcessor.java index 16cb347e8630d..7bb230d95463d 100644 --- a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java +++ b/extensions/schema-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/schema-registry/apicurio/common/pom.xml b/extensions/schema-registry/apicurio/common/pom.xml new file mode 100644 index 0000000000000..2f0628e909639 --- /dev/null +++ b/extensions/schema-registry/apicurio/common/pom.xml @@ -0,0 +1,22 @@ + + + + quarkus-apicurio-registry-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/schema-registry/apicurio/common/runtime/pom.xml b/extensions/schema-registry/apicurio/common/runtime/pom.xml new file mode 100644 index 0000000000000..fb0f236efdbc7 --- /dev/null +++ b/extensions/schema-registry/apicurio/common/runtime/pom.xml @@ -0,0 +1,57 @@ + + + 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-jdk + + + + + io.apicurio + apicurio-common-rest-client-vertx + + + org.apache.commons + commons-lang3 + + + + io.quarkus + quarkus-core + + + io.quarkus + quarkus-schema-registry-devservice + + + io.quarkus + quarkus-vertx + + + + io.quarkus + quarkus-kubernetes-service-binding + true + + + + diff --git a/extensions/apicurio-registry-avro/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 similarity index 100% rename from extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java rename to extensions/schema-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java diff --git a/extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryClient.java b/extensions/schema-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/schema-registry/apicurio/common/runtime/src/main/java/io/quarkus/apicurio/registry/common/ApicurioRegistryClient.java index ceae6a11f3a5c..1a072229c2fcd 100644 --- a/extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryClient.java +++ b/extensions/schema-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-avro/runtime/src/main/resources/META-INF/services/io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter b/extensions/schema-registry/apicurio/common/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/schema-registry/apicurio/common/runtime/src/main/resources/META-INF/services/io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter diff --git a/extensions/schema-registry/apicurio/pom.xml b/extensions/schema-registry/apicurio/pom.xml new file mode 100644 index 0000000000000..ce3c9d4de020f --- /dev/null +++ b/extensions/schema-registry/apicurio/pom.xml @@ -0,0 +1,21 @@ + + + + quarkus-schema-registry-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + 4.0.0 + quarkus-apicurio-registry-parent + Quarkus - Apicurio Registry + pom + + + common + avro + + diff --git a/extensions/schema-registry/confluent/avro/deployment/pom.xml b/extensions/schema-registry/confluent/avro/deployment/pom.xml new file mode 100644 index 0000000000000..c98b4f7c0e4ae --- /dev/null +++ b/extensions/schema-registry/confluent/avro/deployment/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + io.quarkus + quarkus-confluent-registry-avro-parent + 999-SNAPSHOT + + + quarkus-confluent-registry-avro-deployment + Quarkus - Confluent Schema Registry - Avro - Deployment + + + + io.quarkus + quarkus-confluent-registry-avro + + + + io.quarkus + quarkus-avro-deployment + + + io.quarkus + quarkus-confluent-registry-common-deployment + + + io.quarkus + quarkus-schema-registry-devservice-deployment + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/extensions/schema-registry/confluent/avro/deployment/src/main/java/io/quarkus/confluent/registry/avro/ConfluentRegistryAvroProcessor.java b/extensions/schema-registry/confluent/avro/deployment/src/main/java/io/quarkus/confluent/registry/avro/ConfluentRegistryAvroProcessor.java new file mode 100644 index 0000000000000..ee0f05e8a3a73 --- /dev/null +++ b/extensions/schema-registry/confluent/avro/deployment/src/main/java/io/quarkus/confluent/registry/avro/ConfluentRegistryAvroProcessor.java @@ -0,0 +1,30 @@ +package io.quarkus.confluent.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/schema-registry/confluent/avro/pom.xml b/extensions/schema-registry/confluent/avro/pom.xml new file mode 100644 index 0000000000000..aa04537073af1 --- /dev/null +++ b/extensions/schema-registry/confluent/avro/pom.xml @@ -0,0 +1,21 @@ + + + + quarkus-confluent-registry-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + 4.0.0 + quarkus-confluent-registry-avro-parent + Quarkus - Confluent Schema Registry - Avro + pom + + + deployment + runtime + + diff --git a/extensions/schema-registry/confluent/avro/runtime/pom.xml b/extensions/schema-registry/confluent/avro/runtime/pom.xml new file mode 100644 index 0000000000000..61a73137c31f0 --- /dev/null +++ b/extensions/schema-registry/confluent/avro/runtime/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + + io.quarkus + quarkus-confluent-registry-avro-parent + 999-SNAPSHOT + + + quarkus-confluent-registry-avro + Quarkus - Confluent Schema Registry - Avro - Runtime + + + + io.quarkus + quarkus-avro + + + io.quarkus + quarkus-confluent-registry-common + + + io.quarkus + quarkus-schema-registry-devservice + + + + + + + + io.quarkus + quarkus-bootstrap-maven-plugin + + + io.quarkus.confluent.registry.avro + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/extensions/schema-registry/confluent/avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/schema-registry/confluent/avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 0000000000000..0cbb47999d4f8 --- /dev/null +++ b/extensions/schema-registry/confluent/avro/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -0,0 +1,13 @@ +--- +artifact: ${project.groupId}:${project.artifactId}:${project.version} +name: "Confluent Schema Registry - 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/schema-registry/confluent/common/deployment/pom.xml b/extensions/schema-registry/confluent/common/deployment/pom.xml new file mode 100644 index 0000000000000..2c4608470b710 --- /dev/null +++ b/extensions/schema-registry/confluent/common/deployment/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + + quarkus-confluent-registry-common-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-confluent-registry-common-deployment + Quarkus - Confluent Schema Registry - Common - Deployment + + + + io.quarkus + quarkus-confluent-registry-common + + + + io.quarkus + quarkus-core-deployment + + + io.quarkus + quarkus-schema-registry-devservice-deployment + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/extensions/schema-registry/confluent/common/deployment/src/main/java/io/quarkus/confluent/registry/common/ConfluentRegistryClientProcessor.java b/extensions/schema-registry/confluent/common/deployment/src/main/java/io/quarkus/confluent/registry/common/ConfluentRegistryClientProcessor.java new file mode 100644 index 0000000000000..8a11694af4e2f --- /dev/null +++ b/extensions/schema-registry/confluent/common/deployment/src/main/java/io/quarkus/confluent/registry/common/ConfluentRegistryClientProcessor.java @@ -0,0 +1,54 @@ +package io.quarkus.confluent.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/schema-registry/confluent/common/pom.xml b/extensions/schema-registry/confluent/common/pom.xml new file mode 100644 index 0000000000000..9e6255a236371 --- /dev/null +++ b/extensions/schema-registry/confluent/common/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + + quarkus-confluent-registry-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-confluent-registry-common-parent + Quarkus - Confluent Schema Registry - Common + pom + + + deployment + runtime + + + diff --git a/extensions/schema-registry/confluent/common/runtime/pom.xml b/extensions/schema-registry/confluent/common/runtime/pom.xml new file mode 100644 index 0000000000000..9d192312c3236 --- /dev/null +++ b/extensions/schema-registry/confluent/common/runtime/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + + quarkus-confluent-registry-common-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-confluent-registry-common + Quarkus - Confluent Schema Registry - Common - Runtime + + + + io.quarkus + quarkus-core + + + io.quarkus + quarkus-schema-registry-devservice + + + + diff --git a/extensions/schema-registry/confluent/pom.xml b/extensions/schema-registry/confluent/pom.xml new file mode 100644 index 0000000000000..08e3f6c6262ee --- /dev/null +++ b/extensions/schema-registry/confluent/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + + + quarkus-schema-registry-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-confluent-registry-parent + Quarkus - Confluent Schema Registry + pom + + + common + avro + + diff --git a/extensions/schema-registry/devservice/deployment/pom.xml b/extensions/schema-registry/devservice/deployment/pom.xml new file mode 100644 index 0000000000000..e9d4bc9dc7df7 --- /dev/null +++ b/extensions/schema-registry/devservice/deployment/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + + quarkus-schema-registry-devservice-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-schema-registry-devservice-deployment + Quarkus - Schema Registry - DevService - Deployment + + + + io.quarkus + quarkus-schema-registry-devservice + + + + io.quarkus + quarkus-core-deployment + + + io.quarkus + quarkus-vertx-deployment + + + + io.quarkus + quarkus-devservices-deployment + + + + + + + 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/ApicurioRegistryDevServicesBuildTimeConfig.java b/extensions/schema-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/schema-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/ApicurioRegistryDevServicesBuildTimeConfig.java index 15f810d58363e..cdb5705db2476 100644 --- a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryDevServicesBuildTimeConfig.java +++ b/extensions/schema-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/schema-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/DevServicesApicurioRegistryProcessor.java similarity index 87% rename from extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/DevServicesApicurioRegistryProcessor.java rename to extensions/schema-registry/devservice/deployment/src/main/java/io/quarkus/apicurio/registry/devservice/DevServicesApicurioRegistryProcessor.java index 7456b684a2eb7..658ee0f385a85 100644 --- a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/DevServicesApicurioRegistryProcessor.java +++ b/extensions/schema-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; @@ -31,16 +32,14 @@ /** * 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). */ 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 CONFLUENT_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 +94,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 +116,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", + CONFLUENT_SCHEMA_REGISTRY_URL_CONFIG, baseUrl + "/apis/ccompat/v6"); } private void shutdownApicurioRegistry() { @@ -141,12 +142,18 @@ 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 (!hasKafkaChannelWithoutApicurioRegistry()) { + if (ConfigUtils.isPropertyPresent(CONFLUENT_SCHEMA_REGISTRY_URL_CONFIG)) { + log.debug("Not starting dev services for Apicurio Registry, " + CONFLUENT_SCHEMA_REGISTRY_URL_CONFIG + + " is configured."); + return null; + } + + if (!hasKafkaChannelWithoutRegistry()) { log.debug("Not starting dev services for Apicurio Registry, all the channels have a registry URL configured."); return null; } @@ -159,9 +166,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,11 +178,11 @@ 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())); }); } - private boolean hasKafkaChannelWithoutApicurioRegistry() { + private boolean hasKafkaChannelWithoutRegistry() { Config config = ConfigProvider.getConfig(); for (String name : config.getPropertyNames()) { boolean isIncoming = name.startsWith("mp.messaging.incoming."); @@ -185,7 +192,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/schema-registry/devservice/pom.xml b/extensions/schema-registry/devservice/pom.xml new file mode 100644 index 0000000000000..218ab03ab9dff --- /dev/null +++ b/extensions/schema-registry/devservice/pom.xml @@ -0,0 +1,22 @@ + + + + quarkus-schema-registry-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + 4.0.0 + quarkus-schema-registry-devservice-parent + Quarkus - Schema Registry - DevService + pom + + + deployment + runtime + + + diff --git a/extensions/schema-registry/devservice/runtime/pom.xml b/extensions/schema-registry/devservice/runtime/pom.xml new file mode 100644 index 0000000000000..a9008082c9df4 --- /dev/null +++ b/extensions/schema-registry/devservice/runtime/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + + quarkus-schema-registry-devservice-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-schema-registry-devservice + Quarkus - Schema Registry - DevService - Runtime + + + + io.quarkus + quarkus-core + + + io.quarkus + quarkus-vertx + + + + diff --git a/extensions/schema-registry/pom.xml b/extensions/schema-registry/pom.xml new file mode 100644 index 0000000000000..ac5f78da15335 --- /dev/null +++ b/extensions/schema-registry/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + + quarkus-extensions-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-schema-registry-parent + Quarkus - Schema Registry Parent + pom + + + apicurio + confluent + devservice + + diff --git a/extensions/smallrye-reactive-messaging-kafka/deployment/pom.xml b/extensions/smallrye-reactive-messaging-kafka/deployment/pom.xml index 2b4f1d74e145a..d474778d76ddd 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-confluent-registry-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 c52d919cd098c..04250bd0f7b8f 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.1.Final @@ -77,11 +77,15 @@ - + io.quarkus quarkus-apicurio-registry-avro + + io.quarkus + quarkus-confluent-registry-avro + @@ -209,6 +213,19 @@ + + io.quarkus + quarkus-confluent-registry-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 065092035cb61..8b7fc9bc2300b 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 eda85eda32cf3..d4907bbe9f11b 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 696167560eddb..0000000000000 --- 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 5030447a2e022..cde33e53f4a2c 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 418243f5d778d..7aaeea67e39aa 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 0000000000000..74e17f9f88d26 --- /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 0000000000000..024b9b7dc31e5 --- /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 9d7c69589620c..756bdfbda8437 100644 --- a/integration-tests/kafka-avro/pom.xml +++ b/integration-tests/kafka-avro/pom.xml @@ -37,19 +37,25 @@ quarkus-resteasy-jsonb - + io.quarkus quarkus-kafka-client + + + io.quarkus + quarkus-confluent-registry-avro + + io.quarkus quarkus-avro - + io.quarkus quarkus-rest-client @@ -80,6 +86,29 @@ io.apicurio apicurio-registry-utils-serde ${apicurio.version} + + + io.apicurio + apicurio-registry-client + + + org.jboss.spec.javax.interceptor + jboss-interceptors-api_1.2_spec + + + jakarta.activation + jakarta.activation-api + + + com.worldturner.medeia + medeia-validator-jackson + + + + + io.apicurio + apicurio-registry-client + ${apicurio.version} org.jboss.spec.javax.interceptor @@ -182,6 +211,19 @@ + + io.quarkus + quarkus-confluent-registry-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 c0f22a629a999..c1b0831aa2f29 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 c25a9e5a03922..9e0e521caa298 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.