From 12d10200b87d1a7a19600af461194acab4dad7a9 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Mon, 13 Jan 2025 16:22:23 +0100 Subject: [PATCH 01/24] new module --- json-schema-registry/build.gradle | 26 ++++++++++++++++++++++++++ settings.gradle | 1 + 2 files changed, 27 insertions(+) create mode 100644 json-schema-registry/build.gradle diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle new file mode 100644 index 00000000..369a9323 --- /dev/null +++ b/json-schema-registry/build.gradle @@ -0,0 +1,26 @@ +plugins { + id("io.micronaut.build.internal.json-schema-module") +} + +repositories { + mavenCentral() +} + +dependencies { + compileOnly(mn.micronaut.core.processor) + + implementation(projects.micronautJsonSchemaGenerator) + implementation(mnSerde.micronaut.serde.jackson) + implementation(mnValidation.validation) + + api(projects.micronautJsonSchemaAnnotations) + api(projects.micronautJsonSchemaCommon) + + testImplementation(mnTest.micronaut.test.junit5) + testImplementation(libs.junit.jupiter.api) + testRuntimeOnly(libs.junit.jupiter.engine) +} + +test { + useJUnitPlatform() +} diff --git a/settings.gradle b/settings.gradle index 18931922..b04c5f7a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -26,6 +26,7 @@ include 'json-schema-annotations' include 'json-schema-common' include 'json-schema-processor' include 'json-schema-generator' +include 'json-schema-registry' include 'test-suite' include 'test-suite-generator-java' include 'test-suite-groovy' From ac5c4c5c7604141a93c84dde2da41ba90a3ae556 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Wed, 22 Jan 2025 13:14:49 +0100 Subject: [PATCH 02/24] fix generated source directory --- .../build/internal/generator/BeanGeneratorTask.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/groovy/io/micronaut/build/internal/generator/BeanGeneratorTask.java b/buildSrc/src/main/groovy/io/micronaut/build/internal/generator/BeanGeneratorTask.java index 94c280af..f2e88985 100644 --- a/buildSrc/src/main/groovy/io/micronaut/build/internal/generator/BeanGeneratorTask.java +++ b/buildSrc/src/main/groovy/io/micronaut/build/internal/generator/BeanGeneratorTask.java @@ -88,8 +88,14 @@ public abstract class BeanGeneratorTask extends DefaultTask { @Internal public Provider getGeneratedSourcesDirectory() { - String lang = getLanguage().get(); - return lang.equalsIgnoreCase("JAVA") ? getOutputDirectory().dir("java/main") : getOutputDirectory().dir("kotlin/main"); + String lang = getLanguage().get().toUpperCase(); + var langPath = "src/main/" + switch (lang) { + case "JAVA" -> "java"; + case "KOTLIN" -> "kotlin"; + case "GROOVY" -> "groovy"; + default -> ""; + }; + return getOutputDirectory().dir(langPath); } @Inject From 29894eb803d78b363d7f5b26607106c1fbe0f52d Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Thu, 23 Jan 2025 11:57:22 +0100 Subject: [PATCH 03/24] confluent definition files --- json-schema-registry/build.gradle | 12 + .../src/main/resources/registry.json | 4103 +++++++++++++++++ .../resources/schema-registry-api-spec.yaml | 2770 +++++++++++ 3 files changed, 6885 insertions(+) create mode 100644 json-schema-registry/src/main/resources/registry.json create mode 100644 json-schema-registry/src/main/resources/schema-registry-api-spec.yaml diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle index 369a9323..c93b3001 100644 --- a/json-schema-registry/build.gradle +++ b/json-schema-registry/build.gradle @@ -1,5 +1,16 @@ plugins { id("io.micronaut.build.internal.json-schema-module") + id("io.micronaut.minimal.application") + id("io.micronaut.openapi") +} + +micronaut { + runtime "netty" + testRuntime "junit5" + openapi { + server(file("registry.json")) { + } + } } repositories { @@ -12,6 +23,7 @@ dependencies { implementation(projects.micronautJsonSchemaGenerator) implementation(mnSerde.micronaut.serde.jackson) implementation(mnValidation.validation) + implementation("io.micronaut.security:micronaut-security") api(projects.micronautJsonSchemaAnnotations) api(projects.micronautJsonSchemaCommon) diff --git a/json-schema-registry/src/main/resources/registry.json b/json-schema-registry/src/main/resources/registry.json new file mode 100644 index 00000000..6aa7ac94 --- /dev/null +++ b/json-schema-registry/src/main/resources/registry.json @@ -0,0 +1,4103 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Confluent Schema Registry", + "version": "v1" + }, + "paths": { + "/compatibility/subjects/{subject}/versions/{version}": { + "post": { + "tags": [ + "Compatibility (v1)" + ], + "summary": "Test schema compatibility against a particular schema subject-version", + "description": "Test input schema against a particular version of a subject's schema for compatibility. The compatibility level applied for the check is the configured compatibility level for the subject (http:get:: /config/(string: subject)). If this subject's compatibility level was never changed, then the global compatibility level applies (http:get:: /config).", + "operationId": "testCompatibilityBySubjectName_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Subject of the schema version against which compatibility is to be tested", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "version", + "in": "path", + "description": "Version of the subject's schema against which compatibility is to be tested. Valid values for versionId are between [1,2^31-1] or the string \"latest\".\"latest\" checks compatibility of the input schema with the last registered schema under the specified subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "normalize", + "in": "query", + "description": "Whether to normalize the given schema", + "schema": { + "type": "boolean" + } + }, + { + "name": "verbose", + "in": "query", + "description": "Whether to return detailed error messages", + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "description": "Schema", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/vnd.schemaregistry+json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Compatibility check result.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/CompatibilityCheckResponse" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/CompatibilityCheckResponse" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/CompatibilityCheckResponse" + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found. Error code 40402 indicates version not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "422": { + "description": "Unprocessable entity. Error code 42201 indicates an invalid schema or schema type. Error code 42202 indicates an invalid version.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/": { + "get": { + "summary": "Schema Registry Root Resource", + "description": "The Root resource is a no-op.", + "operationId": "get_1", + "responses": { + "default": { + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "string" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "string" + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "string" + } + } + }, + "description": "Default response for get." + } + } + }, + "post": { + "operationId": "post_1", + "requestBody": { + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "application/vnd.schemaregistry+json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "application/octet-stream": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, + "responses": { + "default": { + "description": "default response", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + } + } + }, + "/compatibility/subjects/{subject}/versions": { + "post": { + "tags": [ + "Compatibility (v1)" + ], + "summary": "Test schema compatibility against all schemas under a subject", + "description": "Test input schema against a subject's schemas for compatibility, based on the configured compatibility level of the subject. In other words, it will perform the same compatibility check as register for that subject. The compatibility level applied for the check is the configured compatibility level for the subject (http:get:: /config/(string: subject)). If this subject's compatibility level was never changed, then the global compatibility level applies (http:get:: /config).", + "operationId": "testCompatibilityForSubject_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Subject of the schema version against which compatibility is to be tested", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "normalize", + "in": "query", + "description": "Whether to normalize the given schema", + "schema": { + "type": "boolean" + } + }, + { + "name": "verbose", + "in": "query", + "description": "Whether to return detailed error messages", + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "description": "Schema", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/vnd.schemaregistry+json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Compatibility check result.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/CompatibilityCheckResponse" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/CompatibilityCheckResponse" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/CompatibilityCheckResponse" + } + } + } + }, + "422": { + "description": "Unprocessable Entity. Error code 42201 indicates an invalid schema or schema type. Error code 42202 indicates an invalid version.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/config": { + "get": { + "tags": [ + "Config (v1)" + ], + "summary": "Get global compatibility level", + "description": "Retrieves the global compatibility level.", + "operationId": "getTopLevelConfig_1", + "responses": { + "200": { + "description": "The global compatibility level.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/Config" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/Config" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/Config" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + }, + "put": { + "tags": [ + "Config (v1)" + ], + "summary": "Update global compatibility level", + "description": "Updates the global compatibility level. On success, echoes the original request back to the client.", + "operationId": "updateTopLevelConfig_1", + "requestBody": { + "description": "Config Update Request", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + }, + "application/vnd.schemaregistry+json": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The original request.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + } + } + }, + "422": { + "description": "Unprocessable Entity. Error code 42203 indicates invalid compatibility level.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store. Error code 50003 indicates a failure forwarding the request to the primary.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Config (v1)" + ], + "summary": "Delete global compatibility level", + "description": "Deletes the global compatibility level config and reverts to the default.", + "operationId": "deleteTopLevelConfig_1", + "responses": { + "200": { + "description": "Operation succeeded. Returns old global compatibility level.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "string", + "enum": [ + "NONE", + "BACKWARD", + "BACKWARD_TRANSITIVE", + "FORWARD", + "FORWARD_TRANSITIVE", + "FULL", + "FULL_TRANSITIVE" + ] + }, + "example": "FULL_TRANSITIVE" + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "string", + "enum": [ + "NONE", + "BACKWARD", + "BACKWARD_TRANSITIVE", + "FORWARD", + "FORWARD_TRANSITIVE", + "FULL", + "FULL_TRANSITIVE" + ] + }, + "example": "FULL_TRANSITIVE" + }, + "application/json; qs=0.5": { + "schema": { + "type": "string", + "enum": [ + "NONE", + "BACKWARD", + "BACKWARD_TRANSITIVE", + "FORWARD", + "FORWARD_TRANSITIVE", + "FULL", + "FULL_TRANSITIVE" + ] + }, + "example": "FULL_TRANSITIVE" + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/config/{subject}": { + "get": { + "tags": [ + "Config (v1)" + ], + "summary": "Get subject compatibility level", + "description": "Retrieves compatibility level for a subject.", + "operationId": "getSubjectLevelConfig_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "defaultToGlobal", + "in": "query", + "description": "Whether to return the global compatibility level if subject compatibility level not found", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "The subject compatibility level.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/Config" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/Config" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/Config" + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + }, + "put": { + "tags": [ + "Config (v1)" + ], + "summary": "Update subject compatibility level", + "description": "Update compatibility level for the specified subject. On success, echoes the original request back to the client.", + "operationId": "updateSubjectLevelConfig_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "Config Update Request", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + }, + "application/vnd.schemaregistry+json": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The original request.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ConfigUpdateRequest" + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "422": { + "description": "Unprocessable Entity. Error code 42203 indicates invalid compatibility level.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store. Error code 50003 indicates a failure forwarding the request to the primary.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Config (v1)" + ], + "summary": "Delete subject compatibility level", + "description": "Deletes the specified subject-level compatibility level config and reverts to the global default.", + "operationId": "deleteSubjectConfig_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Operation succeeded. Returns old compatibility level.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "string", + "enum": [ + "NONE", + "BACKWARD", + "BACKWARD_TRANSITIVE", + "FORWARD", + "FORWARD_TRANSITIVE", + "FULL", + "FULL_TRANSITIVE" + ] + }, + "example": "FULL_TRANSITIVE" + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "string", + "enum": [ + "NONE", + "BACKWARD", + "BACKWARD_TRANSITIVE", + "FORWARD", + "FORWARD_TRANSITIVE", + "FULL", + "FULL_TRANSITIVE" + ] + }, + "example": "FULL_TRANSITIVE" + }, + "application/json; qs=0.5": { + "schema": { + "type": "string", + "enum": [ + "NONE", + "BACKWARD", + "BACKWARD_TRANSITIVE", + "FORWARD", + "FORWARD_TRANSITIVE", + "FULL", + "FULL_TRANSITIVE" + ] + }, + "example": "FULL_TRANSITIVE" + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/contexts": { + "get": { + "tags": [ + "Contexts (v1)" + ], + "summary": "List contexts", + "description": "Retrieves a list of contexts.", + "operationId": "listContexts_1", + "responses": { + "200": { + "description": "The contexts.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "." + } + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "." + } + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "." + } + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store. ", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/mode": { + "get": { + "tags": [ + "Modes (v1)" + ], + "summary": "Get global mode", + "description": "Retrieves global mode.", + "operationId": "getTopLevelMode_1", + "responses": { + "200": { + "description": "The global mode", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/Mode" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/Mode" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/Mode" + } + } + } + }, + "500": { + "description": "Error code 50001 -- Error in the backend data store" + } + } + }, + "put": { + "tags": [ + "Modes (v1)" + ], + "summary": "Update global mode", + "description": "Update global mode. On success, echoes the original request back to the client.", + "operationId": "updateTopLevelMode_1", + "parameters": [ + { + "name": "force", + "in": "query", + "description": "Whether to force update if setting mode to IMPORT and schemas currently exist", + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "description": "Update Request", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + }, + "application/vnd.schemaregistry+json": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The original request.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + } + } + }, + "422": { + "description": "Unprocessable Entity. Error code 42204 indicates an invalid mode. Error code 42205 indicates operation not permitted.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store. Error code 50003 indicates a failure forwarding the request to the primary. Error code 50004 indicates unknown leader.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/mode/{subject}": { + "get": { + "tags": [ + "Modes (v1)" + ], + "summary": "Get subject mode", + "description": "Retrieves the subject mode.", + "operationId": "getMode_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "defaultToGlobal", + "in": "query", + "description": "Whether to return the global mode if subject mode not found", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "The subject mode.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/Mode" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/Mode" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/Mode" + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + }, + "put": { + "tags": [ + "Modes (v1)" + ], + "summary": "Update subject mode", + "description": "Update mode for the specified subject. On success, echoes the original request back to the client.", + "operationId": "updateMode_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "force", + "in": "query", + "description": "Whether to force update if setting mode to IMPORT and schemas currently exist", + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "description": "Update Request", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + }, + "application/vnd.schemaregistry+json": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The original request.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ModeUpdateRequest" + } + } + } + }, + "422": { + "description": "Unprocessable Entity. Error code 42204 indicates an invalid mode. Error code 42205 indicates operation not permitted.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store. Error code 50003 indicates a failure forwarding the request to the primary. Error code 50004 indicates unknown leader.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Modes (v1)" + ], + "summary": "Delete subject mode", + "description": "Deletes the specified subject-level mode and reverts to the global default.", + "operationId": "deleteSubjectMode_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Operation succeeded. Returns old mode.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/Mode" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/Mode" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/Mode" + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/schemas": { + "get": { + "tags": [ + "Schemas (v1)" + ], + "summary": "List schemas", + "description": "Get the schemas matching the specified parameters.", + "operationId": "getSchemas_1", + "parameters": [ + { + "name": "subjectPrefix", + "in": "query", + "description": "Filters results by the respective subject prefix", + "schema": { + "type": "string", + "default": "" + } + }, + { + "name": "aliases", + "in": "query", + "description": "Whether to include aliases in the search", + "schema": { + "type": "boolean", + "default": false + } + }, + { + "name": "deleted", + "in": "query", + "description": "Whether to return soft deleted schemas", + "schema": { + "type": "boolean", + "default": false + } + }, + { + "name": "latestOnly", + "in": "query", + "description": "Whether to return latest schema versions only for each matching subject", + "schema": { + "type": "boolean", + "default": false + } + }, + { + "name": "ruleType", + "in": "query", + "description": "Filters results by the given rule type", + "schema": { + "type": "string", + "default": "" + } + }, + { + "name": "offset", + "in": "query", + "description": "Pagination offset for results", + "schema": { + "type": "integer", + "format": "int32", + "default": 0 + } + }, + { + "name": "limit", + "in": "query", + "description": "Pagination size for results. Ignored if negative", + "schema": { + "type": "integer", + "format": "int32", + "default": -1 + } + } + ], + "responses": { + "200": { + "description": "List of schemas matching the specified parameters.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Schema" + } + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Schema" + } + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Schema" + } + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/schemas/ids/{id}": { + "get": { + "tags": [ + "Schemas (v1)" + ], + "summary": "Get schema string by ID", + "description": "Retrieves the schema string identified by the input ID.", + "operationId": "getSchema_1", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Globally unique identifier of the schema", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "subject", + "in": "query", + "description": "Name of the subject", + "schema": { + "type": "string" + } + }, + { + "name": "format", + "in": "query", + "description": "Desired output format, dependent on schema type", + "schema": { + "type": "string", + "default": "" + } + }, + { + "name": "findTags", + "in": "query", + "description": "Find tagged entities for the given tags or * for all tags", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "fetchMaxId", + "in": "query", + "description": "Whether to fetch the maximum schema identifier that exists", + "schema": { + "type": "boolean", + "default": false + } + } + ], + "responses": { + "200": { + "description": "The schema string.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/SchemaString" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/SchemaString" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/SchemaString" + } + } + } + }, + "404": { + "description": "Not Found. Error code 40403 indicates schema not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/schemas/ids/{id}/subjects": { + "get": { + "tags": [ + "Schemas (v1)" + ], + "summary": "List subjects associated to schema ID", + "description": "Retrieves all the subjects associated with a particular schema ID.", + "operationId": "getSubjects_1", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Globally unique identifier of the schema", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "subject", + "in": "query", + "description": "Filters results by the respective subject", + "schema": { + "type": "string" + } + }, + { + "name": "deleted", + "in": "query", + "description": "Whether to include subjects where the schema was deleted", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "List of subjects matching the specified parameters.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "User" + } + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "User" + } + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "User" + } + } + } + } + }, + "404": { + "description": "Not Found. Error code 40403 indicates schema not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/schemas/ids/{id}/versions": { + "get": { + "tags": [ + "Schemas (v1)" + ], + "summary": "List subject-versions associated to schema ID", + "description": "Get all the subject-version pairs associated with the input ID.", + "operationId": "getVersions_1", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Globally unique identifier of the schema", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "subject", + "in": "query", + "description": "Filters results by the respective subject", + "schema": { + "type": "string" + } + }, + { + "name": "deleted", + "in": "query", + "description": "Whether to include subject versions where the schema was deleted", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "List of subject versions matching the specified parameters.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SubjectVersion" + } + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SubjectVersion" + } + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SubjectVersion" + } + } + } + } + }, + "404": { + "description": "Not Found. Error code 40403 indicates schema not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/schemas/types": { + "get": { + "tags": [ + "Schemas (v1)" + ], + "summary": "List supported schema types", + "description": "Retrieve the schema types supported by this registry.", + "operationId": "getSchemaTypes_1", + "responses": { + "200": { + "description": "List of supported schema types.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "AVRO" + } + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "AVRO" + } + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "AVRO" + } + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/subjects": { + "get": { + "tags": [ + "Subjects (v1)" + ], + "summary": "List subjects", + "description": "Retrieves a list of registered subjects matching specified parameters.", + "operationId": "list_1", + "parameters": [ + { + "name": "subjectPrefix", + "in": "query", + "description": "Subject name prefix", + "schema": { + "type": "string", + "default": ":*:" + } + }, + { + "name": "deleted", + "in": "query", + "description": "Whether to look up deleted subjects", + "schema": { + "type": "boolean" + } + }, + { + "name": "deletedOnly", + "in": "query", + "description": "Whether to return deleted subjects only", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "List of subjects matching the specified parameters.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "User" + } + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "User" + } + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "array", + "items": { + "type": "string", + "example": "User" + } + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/subjects/{subject}": { + "post": { + "tags": [ + "Subjects (v1)" + ], + "summary": "Lookup schema under subject", + "description": "Check if a schema has already been registered under the specified subject. If so, this returns the schema string along with its globally unique identifier, its version under this subject and the subject name.", + "operationId": "lookUpSchemaUnderSubject_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Subject under which the schema will be registered", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "normalize", + "in": "query", + "description": "Whether to normalize the given schema", + "schema": { + "type": "boolean" + } + }, + { + "name": "format", + "in": "query", + "description": "Desired output format, dependent on schema type", + "schema": { + "type": "string", + "default": "" + } + }, + { + "name": "deleted", + "in": "query", + "description": "Whether to lookup deleted schemas", + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "description": "Schema", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/vnd.schemaregistry+json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "The schema.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/Schema" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/Schema" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/Schema" + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found. Error code 40403 indicates schema not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Subjects (v1)" + ], + "summary": "Delete subject", + "description": "Deletes the specified subject and its associated compatibility level if registered. It is recommended to use this API only when a topic needs to be recycled or in development environment.", + "operationId": "deleteSubject_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "permanent", + "in": "query", + "description": "Whether to perform a permanent delete", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Operation succeeded. Returns list of schema versions deleted", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "array", + "items": { + "type": "integer", + "format": "int32", + "example": 1 + } + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "array", + "items": { + "type": "integer", + "format": "int32", + "example": 1 + } + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "array", + "items": { + "type": "integer", + "format": "int32", + "example": 1 + } + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/subjects/{subject}/versions": { + "get": { + "tags": [ + "Subjects (v1)" + ], + "summary": "List versions under subject", + "description": "Retrieves a list of versions registered under the specified subject.", + "operationId": "listVersions_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "deleted", + "in": "query", + "description": "Whether to include deleted schemas", + "schema": { + "type": "boolean" + } + }, + { + "name": "deletedOnly", + "in": "query", + "description": "Whether to return deleted schemas only", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "List of version numbers matching the specified parameters.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "array", + "items": { + "type": "integer", + "format": "int32", + "example": 1 + } + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "array", + "items": { + "type": "integer", + "format": "int32", + "example": 1 + } + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "array", + "items": { + "type": "integer", + "format": "int32", + "example": 1 + } + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found. ", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + }, + "post": { + "tags": [ + "Subjects (v1)" + ], + "summary": "Register schema under a subject", + "description": "Register a new schema under the specified subject. If successfully registered, this returns the unique identifier of this schema in the registry. The returned identifier should be used to retrieve this schema from the schemas resource and is different from the schema's version which is associated with the subject. If the same schema is registered under a different subject, the same identifier will be returned. However, the version of the schema may be different under different subjects.\nA schema should be compatible with the previously registered schema or schemas (if there are any) as per the configured compatibility level. The configured compatibility level can be obtained by issuing a GET http:get:: /config/(string: subject). If that returns null, then GET http:get:: /config\nWhen there are multiple instances of Schema Registry running in the same cluster, the schema registration request will be forwarded to one of the instances designated as the primary. If the primary is not available, the client will get an error code indicating that the forwarding has failed.", + "operationId": "register_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "normalize", + "in": "query", + "description": "Whether to normalize the given schema", + "schema": { + "type": "boolean" + } + }, + { + "name": "format", + "in": "query", + "description": "Desired output format, dependent on schema type", + "schema": { + "type": "string", + "default": "" + } + } + ], + "requestBody": { + "description": "Schema", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/vnd.schemaregistry+json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Schema successfully registered.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaResponse" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaResponse" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaResponse" + } + } + } + }, + "409": { + "description": "Conflict. Incompatible schema.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "422": { + "description": "Unprocessable entity. Error code 42201 indicates an invalid schema or schema type. ", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.Error code 50002 indicates operation timed out. Error code 50003 indicates a failure forwarding the request to the primary.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/subjects/{subject}/versions/{version}": { + "get": { + "tags": [ + "Subjects (v1)" + ], + "summary": "Get schema by version", + "description": "Retrieves a specific version of the schema registered under this subject.", + "operationId": "getSchemaByVersion_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "version", + "in": "path", + "description": "Version of the schema to be returned. Valid values for versionId are between [1,2^31-1] or the string \"latest\". \"latest\" returns the last registered schema under the specified subject. Note that there may be a new latest schema that gets registered right after this request is served.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "format", + "in": "query", + "description": "Desired output format, dependent on schema type", + "schema": { + "type": "string", + "default": "" + } + }, + { + "name": "deleted", + "in": "query", + "description": "Whether to include deleted schema", + "schema": { + "type": "boolean" + } + }, + { + "name": "findTags", + "in": "query", + "description": "Find tagged entities for the given tags or * for all tags", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "The schema.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/Schema" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/Schema" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/Schema" + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found. Error code 40402 indicates version not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "422": { + "description": "Unprocessable Entity. Error code 42202 indicates an invalid version.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Subjects (v1)" + ], + "summary": "Delete schema version", + "description": "Deletes a specific version of the schema registered under this subject. This only deletes the version and the schema ID remains intact making it still possible to decode data using the schema ID. This API is recommended to be used only in development environments or under extreme circumstances where-in, its required to delete a previously registered schema for compatibility purposes or re-register previously registered schema.", + "operationId": "deleteSchemaVersion_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "version", + "in": "path", + "description": "Version of the schema to be returned. Valid values for versionId are between [1,2^31-1] or the string \"latest\". \"latest\" returns the last registered schema under the specified subject. Note that there may be a new latest schema that gets registered right after this request is served.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "permanent", + "in": "query", + "description": "Whether to perform a permanent delete", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Operation succeeded. Returns the schema version.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "integer", + "format": "int32", + "example": 1 + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "integer", + "format": "int32", + "example": 1 + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "integer", + "format": "int32", + "example": 1 + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found. Error code 40402 indicates version not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "422": { + "description": "Unprocessable Entity. Error code 42202 indicates an invalid version.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/subjects/{subject}/versions/{version}/referencedby": { + "get": { + "tags": [ + "Subjects (v1)" + ], + "summary": "List schemas referencing a schema", + "description": "Retrieves the IDs of schemas that reference the specified schema.", + "operationId": "getReferencedBy_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "version", + "in": "path", + "description": "Version of the schema to be returned. Valid values for versionId are between [1,2^31-1] or the string \"latest\". \"latest\" returns the last registered schema under the specified subject. Note that there may be a new latest schema that gets registered right after this request is served.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "List of IDs for schemas that reference the specified schema.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "array", + "items": { + "type": "integer", + "format": "int32", + "example": 100001 + } + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "array", + "items": { + "type": "integer", + "format": "int32", + "example": 100001 + } + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "array", + "items": { + "type": "integer", + "format": "int32", + "example": 100001 + } + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found. Error code 40402 indicates version not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "422": { + "description": "Unprocessable Entity. Error code 42202 indicates an invalid version.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/subjects/{subject}/versions/{version}/schema": { + "get": { + "tags": [ + "Subjects (v1)" + ], + "summary": "Get schema string by version", + "description": "Retrieves the schema for the specified version of this subject. Only the unescaped schema string is returned.", + "operationId": "getSchemaOnly_2", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "version", + "in": "path", + "description": "Version of the schema to be returned. Valid values for versionId are between [1,2^31-1] or the string \"latest\". \"latest\" returns the last registered schema under the specified subject. Note that there may be a new latest schema that gets registered right after this request is served.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "format", + "in": "query", + "description": "Desired output format, dependent on schema type", + "schema": { + "type": "string", + "default": "" + } + }, + { + "name": "deleted", + "in": "query", + "description": "Whether to include deleted schema", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "The schema string.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "string", + "example": "{\"schema\": \"{\"type\": \"string\"}\"}" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "string", + "example": "{\"schema\": \"{\"type\": \"string\"}\"}" + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "string", + "example": "{\"schema\": \"{\"type\": \"string\"}\"}" + } + } + } + }, + "404": { + "description": "Not Found. Error code 40401 indicates subject not found. Error code 40402 indicates version not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "422": { + "description": "Unprocessable Entity. Error code 42202 indicates an invalid version.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/v1/metadata/id": { + "get": { + "tags": [ + "Server Metadata (v1)" + ], + "summary": "Get the server metadata", + "operationId": "getClusterId_1", + "responses": { + "500": { + "description": "Error code 50001 -- Error in the backend data store\n" + } + } + } + }, + "/schemas/ids/{id}/schema": { + "get": { + "tags": [ + "Schemas (v1)" + ], + "summary": "Get schema by ID", + "description": "Retrieves the schema identified by the input ID.", + "operationId": "getSchemaOnly", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Globally unique identifier of the schema", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "subject", + "in": "query", + "description": "Name of the subject", + "schema": { + "type": "string" + } + }, + { + "name": "format", + "in": "query", + "description": "Desired output format, dependent on schema type", + "schema": { + "type": "string", + "default": "" + } + } + ], + "responses": { + "200": { + "description": "Raw schema string.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "type": "string", + "example": "{\"schema\": \"{\"type\": \"string\"}\"}" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "type": "string", + "example": "{\"schema\": \"{\"type\": \"string\"}\"}" + } + }, + "application/json; qs=0.5": { + "schema": { + "type": "string", + "example": "{\"schema\": \"{\"type\": \"string\"}\"}" + } + } + } + }, + "404": { + "description": "Not Found. Error code 40403 indicates schema not found.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + }, + "/v1/metadata/version": { + "get": { + "tags": [ + "Server Metadata (v1)" + ], + "summary": "Get Schema Registry server version", + "operationId": "getSchemaRegistryVersion_1", + "responses": { + "500": { + "description": "Error code 50001 -- Error in the backend data store\n" + } + } + } + }, + "/subjects/{subject}/metadata": { + "get": { + "summary": "Retrieve the latest version with the given metadata.", + "description": "Retrieve the latest version with the given metadata.", + "operationId": "getLatestWithMetadata_1", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Subject under which the schema will be registered", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "key", + "in": "query", + "description": "The metadata key", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "value", + "in": "query", + "description": "The metadata value", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "format", + "in": "query", + "description": "Desired output format, dependent on schema type", + "schema": { + "type": "string", + "default": "" + } + }, + { + "name": "deleted", + "in": "query", + "description": "Whether to lookup deleted schemas", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "The schema", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/Schema" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/Schema" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/Schema" + } + } + } + }, + "404": { + "description": "Error code 40401 -- Subject not found\nError code 40403 -- Schema not found" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/subjects/{subject}/versions/{version}/tags": { + "post": { + "tags": [ + "Subjects (v1)" + ], + "summary": "Create or remove schema embedded tags for a subject version", + "description": "Create new schema subject version with the provided field or record level schema tags embedded (or remove) in the schema string, as well as the given metadata and ruleset.", + "operationId": "modifyTags", + "parameters": [ + { + "name": "subject", + "in": "path", + "description": "Name of the subject", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "version", + "in": "path", + "description": "Version of the schema to be returned. Valid values for versionId are between [1,2^31-1] or the string \"latest\". \"latest\" returns the last registered schema under the specified subject. Note that there may be a new latest schema that gets registered right after this request is served.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "Tag schema request", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/TagSchemaRequest" + } + }, + "application/vnd.schemaregistry+json": { + "schema": { + "$ref": "#/components/schemas/TagSchemaRequest" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/TagSchemaRequest" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/TagSchemaRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Schema successfully registered.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaResponse" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaResponse" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/RegisterSchemaResponse" + } + } + } + }, + "409": { + "description": "Conflict. Incompatible schema.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "422": { + "description": "Unprocessable entity. Error code 42201 indicates an invalid schema or schema type. ", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + }, + "500": { + "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.Error code 50002 indicates operation timed out. Error code 50003 indicates a failure forwarding the request to the primary.", + "content": { + "application/vnd.schemaregistry.v1+json": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/vnd.schemaregistry+json; qs=0.9": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + }, + "application/json; qs=0.5": { + "schema": { + "$ref": "#/components/schemas/ErrorMessage" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "CompatibilityCheckResponse": { + "type": "object", + "properties": { + "is_compatible": { + "type": "boolean", + "description": "Whether the compared schemas are compatible" + }, + "messages": { + "type": "array", + "description": "Error messages", + "example": [], + "items": { + "type": "string", + "description": "Error messages", + "example": "[]" + } + } + }, + "description": "Compatibility check response" + }, + "RegisterSchemaRequest": { + "type": "object", + "properties": { + "version": { + "type": "integer", + "description": "Version number", + "format": "int32" + }, + "id": { + "type": "integer", + "description": "Globally unique identifier of the schema", + "format": "int32" + }, + "schemaType": { + "type": "string", + "description": "Schema type" + }, + "references": { + "type": "array", + "description": "References to other schemas", + "items": { + "$ref": "#/components/schemas/SchemaReference" + } + }, + "metadata": { + "$ref": "#/components/schemas/Metadata" + }, + "ruleSet": { + "$ref": "#/components/schemas/RuleSet" + }, + "schema": { + "type": "string", + "description": "Schema definition string" + }, + "schemaTagsToAdd": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SchemaTags" + } + }, + "schemaTagsToRemove": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SchemaTags" + } + }, + "propagateSchemaTags": { + "type": "boolean" + } + }, + "description": "Schema register request" + }, + "SchemaReference": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Reference name", + "example": "io.confluent.kafka.example.User" + }, + "subject": { + "type": "string", + "description": "Name of the referenced subject", + "example": "User" + }, + "version": { + "type": "integer", + "description": "Version number of the referenced subject", + "format": "int32", + "example": 1 + } + }, + "description": "Schema reference" + }, + "Config": { + "type": "object", + "properties": { + "compatibilityLevel": { + "type": "string", + "description": "Compatibility Level", + "example": "FULL_TRANSITIVE", + "enum": [ + "BACKWARD", + "BACKWARD_TRANSITIVE", + "FORWARD", + "FORWARD_TRANSITIVE", + "FULL", + "FULL_TRANSITIVE", + "NONE" + ] + }, + "alias": { + "type": "string" + }, + "normalize": { + "type": "boolean" + }, + "validateFields": { + "type": "boolean" + }, + "validateRules": { + "type": "boolean" + }, + "compatibilityGroup": { + "type": "string" + }, + "defaultMetadata": { + "$ref": "#/components/schemas/Metadata" + }, + "overrideMetadata": { + "$ref": "#/components/schemas/Metadata" + }, + "defaultRuleSet": { + "$ref": "#/components/schemas/RuleSet" + }, + "overrideRuleSet": { + "$ref": "#/components/schemas/RuleSet" + } + }, + "description": "Config" + }, + "ConfigUpdateRequest": { + "type": "object", + "properties": { + "alias": { + "type": "string" + }, + "normalize": { + "type": "boolean" + }, + "validateFields": { + "type": "boolean" + }, + "validateRules": { + "type": "boolean" + }, + "compatibility": { + "type": "string", + "description": "Compatibility Level", + "example": "FULL_TRANSITIVE", + "enum": [ + "BACKWARD", + "BACKWARD_TRANSITIVE", + "FORWARD", + "FORWARD_TRANSITIVE", + "FULL", + "FULL_TRANSITIVE", + "NONE" + ] + }, + "compatibilityGroup": { + "type": "string" + }, + "defaultMetadata": { + "$ref": "#/components/schemas/Metadata" + }, + "overrideMetadata": { + "$ref": "#/components/schemas/Metadata" + }, + "defaultRuleSet": { + "$ref": "#/components/schemas/RuleSet" + }, + "overrideRuleSet": { + "$ref": "#/components/schemas/RuleSet" + } + }, + "description": "Config update request" + }, + "Mode": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "description": "Schema Registry operating mode", + "example": "READWRITE", + "enum": [ + "READWRITE", + "READONLY", + "READONLY_OVERRIDE", + "IMPORT" + ] + } + }, + "description": "Schema Registry operating mode" + }, + "ModeUpdateRequest": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "description": "Schema Registry operating mode", + "example": "READWRITE", + "enum": [ + "READWRITE", + "READONLY", + "READONLY_OVERRIDE", + "IMPORT" + ] + } + }, + "description": "Mode update request" + }, + "SchemaString": { + "type": "object", + "properties": { + "schemaType": { + "type": "string", + "description": "Schema type", + "example": "AVRO" + }, + "schema": { + "type": "string", + "description": "Schema string identified by the ID", + "example": "{\"schema\": \"{\"type\": \"string\"}\"}" + }, + "references": { + "type": "array", + "description": "References to other schemas", + "items": { + "$ref": "#/components/schemas/SchemaReference" + } + }, + "metadata": { + "$ref": "#/components/schemas/Metadata" + }, + "ruleSet": { + "$ref": "#/components/schemas/RuleSet" + }, + "schemaTags": { + "type": "array", + "description": "Schema tags", + "items": { + "$ref": "#/components/schemas/SchemaTags" + } + }, + "maxId": { + "type": "integer", + "description": "Maximum ID", + "format": "int32", + "example": 1 + } + }, + "description": "Schema definition" + }, + "Schema": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "description": "Name of the subject", + "example": "User" + }, + "version": { + "type": "integer", + "description": "Version number", + "format": "int32", + "example": 1 + }, + "id": { + "type": "integer", + "description": "Globally unique identifier of the schema", + "format": "int32", + "example": 100001 + }, + "schemaType": { + "type": "string", + "description": "Schema type", + "example": "AVRO" + }, + "references": { + "type": "array", + "description": "References to other schemas", + "items": { + "$ref": "#/components/schemas/SchemaReference" + } + }, + "metadata": { + "$ref": "#/components/schemas/Metadata" + }, + "ruleset": { + "$ref": "#/components/schemas/RuleSet" + }, + "schema": { + "type": "string", + "description": "Schema definition string", + "example": "{\"schema\": \"{\"type\": \"string\"}\"}" + }, + "schemaTags": { + "type": "array", + "description": "Schema tags", + "items": { + "$ref": "#/components/schemas/SchemaTags" + } + }, + "ruleSet": { + "$ref": "#/components/schemas/RuleSet" + } + }, + "description": "Schema" + }, + "SubjectVersion": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "description": "Name of the subject", + "example": "User" + }, + "version": { + "type": "integer", + "description": "Version number", + "format": "int32", + "example": 1 + } + }, + "description": "Subject version pair" + }, + "ServerClusterId": { + "type": "object", + "properties": { + "scope": { + "type": "object", + "additionalProperties": { + "type": "object" + } + }, + "id": { + "type": "string" + } + } + }, + "RegisterSchemaResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Globally unique identifier of the schema", + "format": "int32", + "example": 100001 + }, + "version": { + "type": "integer", + "description": "Version number", + "format": "int32" + }, + "schemaType": { + "type": "string", + "description": "Schema type" + }, + "references": { + "type": "array", + "description": "References to other schemas", + "items": { + "$ref": "#/components/schemas/SchemaReference" + } + }, + "metadata": { + "$ref": "#/components/schemas/Metadata" + }, + "ruleSet": { + "$ref": "#/components/schemas/RuleSet" + }, + "schema": { + "type": "string", + "description": "Schema definition string" + } + }, + "description": "Schema register response" + }, + "ErrorMessage": { + "type": "object", + "properties": { + "error_code": { + "type": "integer", + "description": "Error code", + "format": "int32" + }, + "message": { + "type": "string", + "description": "Detailed error message" + } + }, + "description": "Error message" + }, + "SchemaRegistryServerVersion": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "commitId": { + "type": "string" + } + } + }, + "Metadata": { + "type": "object", + "properties": { + "tags": { + "type": "object", + "additionalProperties": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + } + }, + "properties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "sensitive": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": "User-defined metadata" + }, + "Rule": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Rule name" + }, + "doc": { + "type": "string", + "description": "Rule doc" + }, + "kind": { + "type": "string", + "description": "Rule kind", + "enum": [ + "TRANSFORM", + "CONDITION" + ] + }, + "mode": { + "type": "string", + "description": "Rule mode", + "enum": [ + "UPGRADE", + "DOWNGRADE", + "UPDOWN", + "WRITE", + "READ", + "WRITEREAD" + ] + }, + "type": { + "type": "string", + "description": "Rule type" + }, + "tags": { + "uniqueItems": true, + "type": "array", + "description": "The tags to which this rule applies", + "items": { + "type": "string", + "description": "The tags to which this rule applies" + } + }, + "params": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "Optional params for the rule" + }, + "description": "Optional params for the rule" + }, + "expr": { + "type": "string", + "description": "Rule expression" + }, + "onSuccess": { + "type": "string", + "description": "Rule action on success" + }, + "onFailure": { + "type": "string", + "description": "Rule action on failure" + }, + "disabled": { + "type": "boolean", + "description": "Whether the rule is disabled" + } + }, + "description": "Rule" + }, + "RuleSet": { + "type": "object", + "properties": { + "migrationRules": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Rule" + } + }, + "domainRules": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Rule" + } + } + }, + "description": "Schema rule set" + }, + "SchemaEntity": { + "type": "object", + "properties": { + "entityPath": { + "type": "string" + }, + "entityType": { + "type": "string", + "enum": [ + "sr_record", + "sr_field" + ] + } + } + }, + "SchemaTags": { + "type": "object", + "properties": { + "schemaEntity": { + "$ref": "#/components/schemas/SchemaEntity" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "ExtendedSchema": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "description": "Name of the subject", + "example": "User" + }, + "version": { + "type": "integer", + "description": "Version number", + "format": "int32", + "example": 1 + }, + "id": { + "type": "integer", + "description": "Globally unique identifier of the schema", + "format": "int32", + "example": 100001 + }, + "schemaType": { + "type": "string", + "description": "Schema type", + "example": "AVRO" + }, + "references": { + "type": "array", + "description": "References to other schemas", + "items": { + "$ref": "#/components/schemas/SchemaReference" + } + }, + "metadata": { + "$ref": "#/components/schemas/Metadata" + }, + "ruleset": { + "$ref": "#/components/schemas/RuleSet" + }, + "schema": { + "type": "string", + "description": "Schema definition string", + "example": "{\"schema\": \"{\"type\": \"string\"}\"}" + }, + "aliases": { + "type": "array", + "description": "Aliases for the given subject", + "items": { + "type": "string", + "description": "Aliases for the given subject" + } + }, + "ruleSet": { + "$ref": "#/components/schemas/RuleSet" + }, + "schemaTags": { + "type": "array", + "description": "Schema tags", + "items": { + "$ref": "#/components/schemas/SchemaTags" + } + } + }, + "description": "ExtendedSchema" + }, + "TagSchemaRequest": { + "type": "object", + "properties": { + "newVersion": { + "type": "integer", + "description": "The new version should be the latest version in the subject + 1. If set, the new version will be encoded to the schema metadata.", + "format": "int32" + }, + "tagsToAdd": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SchemaTags" + } + }, + "tagsToRemove": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SchemaTags" + } + }, + "metadata": { + "$ref": "#/components/schemas/Metadata" + }, + "ruleSet": { + "$ref": "#/components/schemas/RuleSet" + }, + "rulesToMerge": { + "$ref": "#/components/schemas/RuleSet" + }, + "rulesToRemove": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": "Schema tags register request" + } + } + } +} diff --git a/json-schema-registry/src/main/resources/schema-registry-api-spec.yaml b/json-schema-registry/src/main/resources/schema-registry-api-spec.yaml new file mode 100644 index 00000000..6ff22dac --- /dev/null +++ b/json-schema-registry/src/main/resources/schema-registry-api-spec.yaml @@ -0,0 +1,2770 @@ +openapi: 3.0.1 +info: + title: Confluent Schema Registry + version: v1 +paths: + /compatibility/subjects/{subject}/versions/{version}: + post: + tags: + - Compatibility (v1) + summary: Test schema compatibility against a particular schema subject-version + description: "Test input schema against a particular version of a subject's\ + \ schema for compatibility. The compatibility level applied for the check\ + \ is the configured compatibility level for the subject (http:get:: /config/(string:\ + \ subject)). If this subject's compatibility level was never changed, then\ + \ the global compatibility level applies (http:get:: /config)." + operationId: testCompatibilityBySubjectName_1 + parameters: + - name: subject + in: path + description: Subject of the schema version against which compatibility is + to be tested + required: true + schema: + type: string + - name: version + in: path + description: "Version of the subject's schema against which compatibility\ + \ is to be tested. Valid values for versionId are between [1,2^31-1] or\ + \ the string \"latest\".\"latest\" checks compatibility of the input schema\ + \ with the last registered schema under the specified subject" + required: true + schema: + type: string + - name: normalize + in: query + description: Whether to normalize the given schema + schema: + type: boolean + - name: verbose + in: query + description: Whether to return detailed error messages + schema: + type: boolean + requestBody: + description: Schema + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/vnd.schemaregistry+json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/octet-stream: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + required: true + responses: + "200": + description: Compatibility check result. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/CompatibilityCheckResponse' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/CompatibilityCheckResponse' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/CompatibilityCheckResponse' + "404": + description: Not Found. Error code 40401 indicates subject not found. Error + code 40402 indicates version not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "422": + description: Unprocessable entity. Error code 42201 indicates an invalid + schema or schema type. Error code 42202 indicates an invalid version. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /: + get: + summary: Schema Registry Root Resource + description: The Root resource is a no-op. + operationId: get_1 + responses: + default: + content: + application/vnd.schemaregistry.v1+json: + schema: + type: string + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: string + application/json; qs=0.5: + schema: + type: string + description: Default response for get. + post: + operationId: post_1 + requestBody: + content: + application/vnd.schemaregistry.v1+json: + schema: + type: object + additionalProperties: + type: string + application/vnd.schemaregistry+json: + schema: + type: object + additionalProperties: + type: string + application/json: + schema: + type: object + additionalProperties: + type: string + application/octet-stream: + schema: + type: object + additionalProperties: + type: string + responses: + default: + description: default response + content: + application/vnd.schemaregistry.v1+json: + schema: + type: object + additionalProperties: + type: string + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: object + additionalProperties: + type: string + application/json; qs=0.5: + schema: + type: object + additionalProperties: + type: string + /compatibility/subjects/{subject}/versions: + post: + tags: + - Compatibility (v1) + summary: Test schema compatibility against all schemas under a subject + description: "Test input schema against a subject's schemas for compatibility,\ + \ based on the configured compatibility level of the subject. In other words,\ + \ it will perform the same compatibility check as register for that subject.\ + \ The compatibility level applied for the check is the configured compatibility\ + \ level for the subject (http:get:: /config/(string: subject)). If this subject's\ + \ compatibility level was never changed, then the global compatibility level\ + \ applies (http:get:: /config)." + operationId: testCompatibilityForSubject_1 + parameters: + - name: subject + in: path + description: Subject of the schema version against which compatibility is + to be tested + required: true + schema: + type: string + - name: normalize + in: query + description: Whether to normalize the given schema + schema: + type: boolean + - name: verbose + in: query + description: Whether to return detailed error messages + schema: + type: boolean + requestBody: + description: Schema + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/vnd.schemaregistry+json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/octet-stream: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + required: true + responses: + "200": + description: Compatibility check result. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/CompatibilityCheckResponse' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/CompatibilityCheckResponse' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/CompatibilityCheckResponse' + "422": + description: Unprocessable Entity. Error code 42201 indicates an invalid + schema or schema type. Error code 42202 indicates an invalid version. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /config: + get: + tags: + - Config (v1) + summary: Get global compatibility level + description: Retrieves the global compatibility level. + operationId: getTopLevelConfig_1 + responses: + "200": + description: The global compatibility level. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/Config' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/Config' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/Config' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + put: + tags: + - Config (v1) + summary: Update global compatibility level + description: "Updates the global compatibility level. On success, echoes the\ + \ original request back to the client." + operationId: updateTopLevelConfig_1 + requestBody: + description: Config Update Request + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + application/vnd.schemaregistry+json: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + application/json: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + application/octet-stream: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + required: true + responses: + "200": + description: The original request. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + "422": + description: Unprocessable Entity. Error code 42203 indicates invalid compatibility + level. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. Error code 50003 indicates a failure forwarding + the request to the primary. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + delete: + tags: + - Config (v1) + summary: Delete global compatibility level + description: Deletes the global compatibility level config and reverts to the + default. + operationId: deleteTopLevelConfig_1 + responses: + "200": + description: Operation succeeded. Returns old global compatibility level. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: string + enum: + - NONE + - BACKWARD + - BACKWARD_TRANSITIVE + - FORWARD + - FORWARD_TRANSITIVE + - FULL + - FULL_TRANSITIVE + example: FULL_TRANSITIVE + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: string + enum: + - NONE + - BACKWARD + - BACKWARD_TRANSITIVE + - FORWARD + - FORWARD_TRANSITIVE + - FULL + - FULL_TRANSITIVE + example: FULL_TRANSITIVE + application/json; qs=0.5: + schema: + type: string + enum: + - NONE + - BACKWARD + - BACKWARD_TRANSITIVE + - FORWARD + - FORWARD_TRANSITIVE + - FULL + - FULL_TRANSITIVE + example: FULL_TRANSITIVE + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /config/{subject}: + get: + tags: + - Config (v1) + summary: Get subject compatibility level + description: Retrieves compatibility level for a subject. + operationId: getSubjectLevelConfig_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + - name: defaultToGlobal + in: query + description: Whether to return the global compatibility level if subject + compatibility level not found + schema: + type: boolean + responses: + "200": + description: The subject compatibility level. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/Config' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/Config' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/Config' + "404": + description: Not Found. Error code 40401 indicates subject not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + put: + tags: + - Config (v1) + summary: Update subject compatibility level + description: "Update compatibility level for the specified subject. On success,\ + \ echoes the original request back to the client." + operationId: updateSubjectLevelConfig_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + requestBody: + description: Config Update Request + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + application/vnd.schemaregistry+json: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + application/json: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + application/octet-stream: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + required: true + responses: + "200": + description: The original request. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ConfigUpdateRequest' + "404": + description: Not Found. Error code 40401 indicates subject not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "422": + description: Unprocessable Entity. Error code 42203 indicates invalid compatibility + level. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. Error code 50003 indicates a failure forwarding + the request to the primary. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + delete: + tags: + - Config (v1) + summary: Delete subject compatibility level + description: Deletes the specified subject-level compatibility level config + and reverts to the global default. + operationId: deleteSubjectConfig_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + responses: + "200": + description: Operation succeeded. Returns old compatibility level. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: string + enum: + - NONE + - BACKWARD + - BACKWARD_TRANSITIVE + - FORWARD + - FORWARD_TRANSITIVE + - FULL + - FULL_TRANSITIVE + example: FULL_TRANSITIVE + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: string + enum: + - NONE + - BACKWARD + - BACKWARD_TRANSITIVE + - FORWARD + - FORWARD_TRANSITIVE + - FULL + - FULL_TRANSITIVE + example: FULL_TRANSITIVE + application/json; qs=0.5: + schema: + type: string + enum: + - NONE + - BACKWARD + - BACKWARD_TRANSITIVE + - FORWARD + - FORWARD_TRANSITIVE + - FULL + - FULL_TRANSITIVE + example: FULL_TRANSITIVE + "404": + description: Not Found. Error code 40401 indicates subject not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /contexts: + get: + tags: + - Contexts (v1) + summary: List contexts + description: Retrieves a list of contexts. + operationId: listContexts_1 + responses: + "200": + description: The contexts. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: array + items: + type: string + example: "." + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: array + items: + type: string + example: "." + application/json; qs=0.5: + schema: + type: array + items: + type: string + example: "." + "500": + description: 'Internal Server Error. Error code 50001 indicates a failure + in the backend data store. ' + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /mode: + get: + tags: + - Modes (v1) + summary: Get global mode + description: Retrieves global mode. + operationId: getTopLevelMode_1 + responses: + "200": + description: The global mode + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/Mode' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/Mode' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/Mode' + "500": + description: Error code 50001 -- Error in the backend data store + put: + tags: + - Modes (v1) + summary: Update global mode + description: "Update global mode. On success, echoes the original request back\ + \ to the client." + operationId: updateTopLevelMode_1 + parameters: + - name: force + in: query + description: Whether to force update if setting mode to IMPORT and schemas + currently exist + schema: + type: boolean + requestBody: + description: Update Request + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + application/vnd.schemaregistry+json: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + application/json: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + application/octet-stream: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + required: true + responses: + "200": + description: The original request. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + "422": + description: Unprocessable Entity. Error code 42204 indicates an invalid + mode. Error code 42205 indicates operation not permitted. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. Error code 50003 indicates a failure forwarding + the request to the primary. Error code 50004 indicates unknown leader. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /mode/{subject}: + get: + tags: + - Modes (v1) + summary: Get subject mode + description: Retrieves the subject mode. + operationId: getMode_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + - name: defaultToGlobal + in: query + description: Whether to return the global mode if subject mode not found + schema: + type: boolean + responses: + "200": + description: The subject mode. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/Mode' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/Mode' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/Mode' + "404": + description: Not Found. Error code 40401 indicates subject not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + put: + tags: + - Modes (v1) + summary: Update subject mode + description: "Update mode for the specified subject. On success, echoes the\ + \ original request back to the client." + operationId: updateMode_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + - name: force + in: query + description: Whether to force update if setting mode to IMPORT and schemas + currently exist + schema: + type: boolean + requestBody: + description: Update Request + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + application/vnd.schemaregistry+json: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + application/json: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + application/octet-stream: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + required: true + responses: + "200": + description: The original request. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ModeUpdateRequest' + "422": + description: Unprocessable Entity. Error code 42204 indicates an invalid + mode. Error code 42205 indicates operation not permitted. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. Error code 50003 indicates a failure forwarding + the request to the primary. Error code 50004 indicates unknown leader. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + delete: + tags: + - Modes (v1) + summary: Delete subject mode + description: Deletes the specified subject-level mode and reverts to the global + default. + operationId: deleteSubjectMode_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + responses: + "200": + description: Operation succeeded. Returns old mode. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/Mode' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/Mode' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/Mode' + "404": + description: Not Found. Error code 40401 indicates subject not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /schemas: + get: + tags: + - Schemas (v1) + summary: List schemas + description: Get the schemas matching the specified parameters. + operationId: getSchemas_1 + parameters: + - name: subjectPrefix + in: query + description: Filters results by the respective subject prefix + schema: + type: string + default: "" + - name: aliases + in: query + description: Whether to include aliases in the search + schema: + type: boolean + default: false + - name: deleted + in: query + description: Whether to return soft deleted schemas + schema: + type: boolean + default: false + - name: latestOnly + in: query + description: Whether to return latest schema versions only for each matching + subject + schema: + type: boolean + default: false + - name: ruleType + in: query + description: Filters results by the given rule type + schema: + type: string + default: "" + - name: offset + in: query + description: Pagination offset for results + schema: + type: integer + format: int32 + default: 0 + - name: limit + in: query + description: Pagination size for results. Ignored if negative + schema: + type: integer + format: int32 + default: -1 + responses: + "200": + description: List of schemas matching the specified parameters. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: array + items: + $ref: '#/components/schemas/Schema' + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: array + items: + $ref: '#/components/schemas/Schema' + application/json; qs=0.5: + schema: + type: array + items: + $ref: '#/components/schemas/Schema' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /schemas/ids/{id}: + get: + tags: + - Schemas (v1) + summary: Get schema string by ID + description: Retrieves the schema string identified by the input ID. + operationId: getSchema_1 + parameters: + - name: id + in: path + description: Globally unique identifier of the schema + required: true + schema: + type: integer + format: int32 + - name: subject + in: query + description: Name of the subject + schema: + type: string + - name: format + in: query + description: "Desired output format, dependent on schema type" + schema: + type: string + default: "" + - name: findTags + in: query + description: Find tagged entities for the given tags or * for all tags + schema: + type: array + items: + type: string + - name: fetchMaxId + in: query + description: Whether to fetch the maximum schema identifier that exists + schema: + type: boolean + default: false + responses: + "200": + description: The schema string. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/SchemaString' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/SchemaString' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/SchemaString' + "404": + description: Not Found. Error code 40403 indicates schema not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /schemas/ids/{id}/subjects: + get: + tags: + - Schemas (v1) + summary: List subjects associated to schema ID + description: Retrieves all the subjects associated with a particular schema + ID. + operationId: getSubjects_1 + parameters: + - name: id + in: path + description: Globally unique identifier of the schema + required: true + schema: + type: integer + format: int32 + - name: subject + in: query + description: Filters results by the respective subject + schema: + type: string + - name: deleted + in: query + description: Whether to include subjects where the schema was deleted + schema: + type: boolean + responses: + "200": + description: List of subjects matching the specified parameters. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: array + items: + type: string + example: User + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: array + items: + type: string + example: User + application/json; qs=0.5: + schema: + type: array + items: + type: string + example: User + "404": + description: Not Found. Error code 40403 indicates schema not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /schemas/ids/{id}/versions: + get: + tags: + - Schemas (v1) + summary: List subject-versions associated to schema ID + description: Get all the subject-version pairs associated with the input ID. + operationId: getVersions_1 + parameters: + - name: id + in: path + description: Globally unique identifier of the schema + required: true + schema: + type: integer + format: int32 + - name: subject + in: query + description: Filters results by the respective subject + schema: + type: string + - name: deleted + in: query + description: Whether to include subject versions where the schema was deleted + schema: + type: boolean + responses: + "200": + description: List of subject versions matching the specified parameters. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: array + items: + $ref: '#/components/schemas/SubjectVersion' + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: array + items: + $ref: '#/components/schemas/SubjectVersion' + application/json; qs=0.5: + schema: + type: array + items: + $ref: '#/components/schemas/SubjectVersion' + "404": + description: Not Found. Error code 40403 indicates schema not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /schemas/types: + get: + tags: + - Schemas (v1) + summary: List supported schema types + description: Retrieve the schema types supported by this registry. + operationId: getSchemaTypes_1 + responses: + "200": + description: List of supported schema types. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: array + items: + type: string + example: AVRO + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: array + items: + type: string + example: AVRO + application/json; qs=0.5: + schema: + type: array + items: + type: string + example: AVRO + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /subjects: + get: + tags: + - Subjects (v1) + summary: List subjects + description: Retrieves a list of registered subjects matching specified parameters. + operationId: list_1 + parameters: + - name: subjectPrefix + in: query + description: Subject name prefix + schema: + type: string + default: ':*:' + - name: deleted + in: query + description: Whether to look up deleted subjects + schema: + type: boolean + - name: deletedOnly + in: query + description: Whether to return deleted subjects only + schema: + type: boolean + responses: + "200": + description: List of subjects matching the specified parameters. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: array + items: + type: string + example: User + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: array + items: + type: string + example: User + application/json; qs=0.5: + schema: + type: array + items: + type: string + example: User + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /subjects/{subject}: + post: + tags: + - Subjects (v1) + summary: Lookup schema under subject + description: "Check if a schema has already been registered under the specified\ + \ subject. If so, this returns the schema string along with its globally unique\ + \ identifier, its version under this subject and the subject name." + operationId: lookUpSchemaUnderSubject_1 + parameters: + - name: subject + in: path + description: Subject under which the schema will be registered + required: true + schema: + type: string + - name: normalize + in: query + description: Whether to normalize the given schema + schema: + type: boolean + - name: format + in: query + description: "Desired output format, dependent on schema type" + schema: + type: string + default: "" + - name: deleted + in: query + description: Whether to lookup deleted schemas + schema: + type: boolean + requestBody: + description: Schema + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/vnd.schemaregistry+json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/octet-stream: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + required: true + responses: + "200": + description: The schema. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/Schema' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/Schema' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/Schema' + "404": + description: Not Found. Error code 40401 indicates subject not found. Error + code 40403 indicates schema not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + delete: + tags: + - Subjects (v1) + summary: Delete subject + description: Deletes the specified subject and its associated compatibility + level if registered. It is recommended to use this API only when a topic needs + to be recycled or in development environment. + operationId: deleteSubject_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + - name: permanent + in: query + description: Whether to perform a permanent delete + schema: + type: boolean + responses: + "200": + description: Operation succeeded. Returns list of schema versions deleted + content: + application/vnd.schemaregistry.v1+json: + schema: + type: array + items: + type: integer + format: int32 + example: 1 + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: array + items: + type: integer + format: int32 + example: 1 + application/json; qs=0.5: + schema: + type: array + items: + type: integer + format: int32 + example: 1 + "404": + description: Not Found. Error code 40401 indicates subject not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /subjects/{subject}/versions: + get: + tags: + - Subjects (v1) + summary: List versions under subject + description: Retrieves a list of versions registered under the specified subject. + operationId: listVersions_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + - name: deleted + in: query + description: Whether to include deleted schemas + schema: + type: boolean + - name: deletedOnly + in: query + description: Whether to return deleted schemas only + schema: + type: boolean + responses: + "200": + description: List of version numbers matching the specified parameters. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: array + items: + type: integer + format: int32 + example: 1 + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: array + items: + type: integer + format: int32 + example: 1 + application/json; qs=0.5: + schema: + type: array + items: + type: integer + format: int32 + example: 1 + "404": + description: 'Not Found. Error code 40401 indicates subject not found. ' + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + post: + tags: + - Subjects (v1) + summary: Register schema under a subject + description: |- + Register a new schema under the specified subject. If successfully registered, this returns the unique identifier of this schema in the registry. The returned identifier should be used to retrieve this schema from the schemas resource and is different from the schema's version which is associated with the subject. If the same schema is registered under a different subject, the same identifier will be returned. However, the version of the schema may be different under different subjects. + A schema should be compatible with the previously registered schema or schemas (if there are any) as per the configured compatibility level. The configured compatibility level can be obtained by issuing a GET http:get:: /config/(string: subject). If that returns null, then GET http:get:: /config + When there are multiple instances of Schema Registry running in the same cluster, the schema registration request will be forwarded to one of the instances designated as the primary. If the primary is not available, the client will get an error code indicating that the forwarding has failed. + operationId: register_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + - name: normalize + in: query + description: Whether to normalize the given schema + schema: + type: boolean + - name: format + in: query + description: "Desired output format, dependent on schema type" + schema: + type: string + default: "" + requestBody: + description: Schema + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/vnd.schemaregistry+json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/json: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + application/octet-stream: + schema: + $ref: '#/components/schemas/RegisterSchemaRequest' + required: true + responses: + "200": + description: Schema successfully registered. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/RegisterSchemaResponse' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/RegisterSchemaResponse' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/RegisterSchemaResponse' + "409": + description: Conflict. Incompatible schema. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "422": + description: 'Unprocessable entity. Error code 42201 indicates an invalid + schema or schema type. ' + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store.Error code 50002 indicates operation timed out. + Error code 50003 indicates a failure forwarding the request to the primary. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /subjects/{subject}/versions/{version}: + get: + tags: + - Subjects (v1) + summary: Get schema by version + description: Retrieves a specific version of the schema registered under this + subject. + operationId: getSchemaByVersion_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + - name: version + in: path + description: "Version of the schema to be returned. Valid values for versionId\ + \ are between [1,2^31-1] or the string \"latest\". \"latest\" returns the\ + \ last registered schema under the specified subject. Note that there may\ + \ be a new latest schema that gets registered right after this request is\ + \ served." + required: true + schema: + type: string + - name: format + in: query + description: "Desired output format, dependent on schema type" + schema: + type: string + default: "" + - name: deleted + in: query + description: Whether to include deleted schema + schema: + type: boolean + - name: findTags + in: query + description: Find tagged entities for the given tags or * for all tags + schema: + type: array + items: + type: string + responses: + "200": + description: The schema. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/Schema' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/Schema' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/Schema' + "404": + description: Not Found. Error code 40401 indicates subject not found. Error + code 40402 indicates version not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "422": + description: Unprocessable Entity. Error code 42202 indicates an invalid + version. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + delete: + tags: + - Subjects (v1) + summary: Delete schema version + description: "Deletes a specific version of the schema registered under this\ + \ subject. This only deletes the version and the schema ID remains intact\ + \ making it still possible to decode data using the schema ID. This API is\ + \ recommended to be used only in development environments or under extreme\ + \ circumstances where-in, its required to delete a previously registered schema\ + \ for compatibility purposes or re-register previously registered schema." + operationId: deleteSchemaVersion_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + - name: version + in: path + description: "Version of the schema to be returned. Valid values for versionId\ + \ are between [1,2^31-1] or the string \"latest\". \"latest\" returns the\ + \ last registered schema under the specified subject. Note that there may\ + \ be a new latest schema that gets registered right after this request is\ + \ served." + required: true + schema: + type: string + - name: permanent + in: query + description: Whether to perform a permanent delete + schema: + type: boolean + responses: + "200": + description: Operation succeeded. Returns the schema version. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: integer + format: int32 + example: 1 + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: integer + format: int32 + example: 1 + application/json; qs=0.5: + schema: + type: integer + format: int32 + example: 1 + "404": + description: Not Found. Error code 40401 indicates subject not found. Error + code 40402 indicates version not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "422": + description: Unprocessable Entity. Error code 42202 indicates an invalid + version. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /subjects/{subject}/versions/{version}/referencedby: + get: + tags: + - Subjects (v1) + summary: List schemas referencing a schema + description: Retrieves the IDs of schemas that reference the specified schema. + operationId: getReferencedBy_1 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + - name: version + in: path + description: "Version of the schema to be returned. Valid values for versionId\ + \ are between [1,2^31-1] or the string \"latest\". \"latest\" returns the\ + \ last registered schema under the specified subject. Note that there may\ + \ be a new latest schema that gets registered right after this request is\ + \ served." + required: true + schema: + type: string + responses: + "200": + description: List of IDs for schemas that reference the specified schema. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: array + items: + type: integer + format: int32 + example: 100001 + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: array + items: + type: integer + format: int32 + example: 100001 + application/json; qs=0.5: + schema: + type: array + items: + type: integer + format: int32 + example: 100001 + "404": + description: Not Found. Error code 40401 indicates subject not found. Error + code 40402 indicates version not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "422": + description: Unprocessable Entity. Error code 42202 indicates an invalid + version. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /subjects/{subject}/versions/{version}/schema: + get: + tags: + - Subjects (v1) + summary: Get schema string by version + description: Retrieves the schema for the specified version of this subject. + Only the unescaped schema string is returned. + operationId: getSchemaOnly_2 + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + - name: version + in: path + description: "Version of the schema to be returned. Valid values for versionId\ + \ are between [1,2^31-1] or the string \"latest\". \"latest\" returns the\ + \ last registered schema under the specified subject. Note that there may\ + \ be a new latest schema that gets registered right after this request is\ + \ served." + required: true + schema: + type: string + - name: format + in: query + description: "Desired output format, dependent on schema type" + schema: + type: string + default: "" + - name: deleted + in: query + description: Whether to include deleted schema + schema: + type: boolean + responses: + "200": + description: The schema string. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: string + example: "{\"schema\": \"{\"type\": \"string\"}\"}" + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: string + example: "{\"schema\": \"{\"type\": \"string\"}\"}" + application/json; qs=0.5: + schema: + type: string + example: "{\"schema\": \"{\"type\": \"string\"}\"}" + "404": + description: Not Found. Error code 40401 indicates subject not found. Error + code 40402 indicates version not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "422": + description: Unprocessable Entity. Error code 42202 indicates an invalid + version. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /v1/metadata/id: + get: + tags: + - Server Metadata (v1) + summary: Get the server metadata + operationId: getClusterId_1 + responses: + "500": + description: | + Error code 50001 -- Error in the backend data store + /schemas/ids/{id}/schema: + get: + tags: + - Schemas (v1) + summary: Get schema by ID + description: Retrieves the schema identified by the input ID. + operationId: getSchemaOnly + parameters: + - name: id + in: path + description: Globally unique identifier of the schema + required: true + schema: + type: integer + format: int32 + - name: subject + in: query + description: Name of the subject + schema: + type: string + - name: format + in: query + description: "Desired output format, dependent on schema type" + schema: + type: string + default: "" + responses: + "200": + description: Raw schema string. + content: + application/vnd.schemaregistry.v1+json: + schema: + type: string + example: "{\"schema\": \"{\"type\": \"string\"}\"}" + application/vnd.schemaregistry+json; qs=0.9: + schema: + type: string + example: "{\"schema\": \"{\"type\": \"string\"}\"}" + application/json; qs=0.5: + schema: + type: string + example: "{\"schema\": \"{\"type\": \"string\"}\"}" + "404": + description: Not Found. Error code 40403 indicates schema not found. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + /v1/metadata/version: + get: + tags: + - Server Metadata (v1) + summary: Get Schema Registry server version + operationId: getSchemaRegistryVersion_1 + responses: + "500": + description: | + Error code 50001 -- Error in the backend data store + /subjects/{subject}/metadata: + get: + summary: Retrieve the latest version with the given metadata. + description: Retrieve the latest version with the given metadata. + operationId: getLatestWithMetadata_1 + parameters: + - name: subject + in: path + description: Subject under which the schema will be registered + required: true + schema: + type: string + - name: key + in: query + description: The metadata key + schema: + type: array + items: + type: string + - name: value + in: query + description: The metadata value + schema: + type: array + items: + type: string + - name: format + in: query + description: "Desired output format, dependent on schema type" + schema: + type: string + default: "" + - name: deleted + in: query + description: Whether to lookup deleted schemas + schema: + type: boolean + responses: + "200": + description: The schema + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/Schema' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/Schema' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/Schema' + "404": + description: |- + Error code 40401 -- Subject not found + Error code 40403 -- Schema not found + "500": + description: Internal server error + /subjects/{subject}/versions/{version}/tags: + post: + tags: + - Subjects (v1) + summary: Create or remove schema embedded tags for a subject version + description: "Create new schema subject version with the provided field or record\ + \ level schema tags embedded (or remove) in the schema string, as well as\ + \ the given metadata and ruleset." + operationId: modifyTags + parameters: + - name: subject + in: path + description: Name of the subject + required: true + schema: + type: string + - name: version + in: path + description: "Version of the schema to be returned. Valid values for versionId\ + \ are between [1,2^31-1] or the string \"latest\". \"latest\" returns the\ + \ last registered schema under the specified subject. Note that there may\ + \ be a new latest schema that gets registered right after this request is\ + \ served." + required: true + schema: + type: string + requestBody: + description: Tag schema request + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/TagSchemaRequest' + application/vnd.schemaregistry+json: + schema: + $ref: '#/components/schemas/TagSchemaRequest' + application/json: + schema: + $ref: '#/components/schemas/TagSchemaRequest' + application/octet-stream: + schema: + $ref: '#/components/schemas/TagSchemaRequest' + required: true + responses: + "200": + description: Schema successfully registered. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/RegisterSchemaResponse' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/RegisterSchemaResponse' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/RegisterSchemaResponse' + "409": + description: Conflict. Incompatible schema. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "422": + description: 'Unprocessable entity. Error code 42201 indicates an invalid + schema or schema type. ' + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' + "500": + description: Internal Server Error. Error code 50001 indicates a failure + in the backend data store.Error code 50002 indicates operation timed out. + Error code 50003 indicates a failure forwarding the request to the primary. + content: + application/vnd.schemaregistry.v1+json: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/vnd.schemaregistry+json; qs=0.9: + schema: + $ref: '#/components/schemas/ErrorMessage' + application/json; qs=0.5: + schema: + $ref: '#/components/schemas/ErrorMessage' +components: + schemas: + CompatibilityCheckResponse: + type: object + properties: + is_compatible: + type: boolean + description: Whether the compared schemas are compatible + messages: + type: array + description: Error messages + example: [] + items: + type: string + description: Error messages + example: "[]" + description: Compatibility check response + RegisterSchemaRequest: + type: object + properties: + version: + type: integer + description: Version number + format: int32 + id: + type: integer + description: Globally unique identifier of the schema + format: int32 + schemaType: + type: string + description: Schema type + references: + type: array + description: References to other schemas + items: + $ref: '#/components/schemas/SchemaReference' + metadata: + $ref: '#/components/schemas/Metadata' + ruleSet: + $ref: '#/components/schemas/RuleSet' + schema: + type: string + description: Schema definition string + schemaTagsToAdd: + type: array + items: + $ref: '#/components/schemas/SchemaTags' + schemaTagsToRemove: + type: array + items: + $ref: '#/components/schemas/SchemaTags' + propagateSchemaTags: + type: boolean + description: Schema register request + SchemaReference: + type: object + properties: + name: + type: string + description: Reference name + example: io.confluent.kafka.example.User + subject: + type: string + description: Name of the referenced subject + example: User + version: + type: integer + description: Version number of the referenced subject + format: int32 + example: 1 + description: Schema reference + Config: + type: object + properties: + compatibilityLevel: + type: string + description: Compatibility Level + example: FULL_TRANSITIVE + enum: + - BACKWARD + - BACKWARD_TRANSITIVE + - FORWARD + - FORWARD_TRANSITIVE + - FULL + - FULL_TRANSITIVE + - NONE + alias: + type: string + normalize: + type: boolean + validateFields: + type: boolean + validateRules: + type: boolean + compatibilityGroup: + type: string + defaultMetadata: + $ref: '#/components/schemas/Metadata' + overrideMetadata: + $ref: '#/components/schemas/Metadata' + defaultRuleSet: + $ref: '#/components/schemas/RuleSet' + overrideRuleSet: + $ref: '#/components/schemas/RuleSet' + description: Config + ConfigUpdateRequest: + type: object + properties: + alias: + type: string + normalize: + type: boolean + validateFields: + type: boolean + validateRules: + type: boolean + compatibility: + type: string + description: Compatibility Level + example: FULL_TRANSITIVE + enum: + - BACKWARD + - BACKWARD_TRANSITIVE + - FORWARD + - FORWARD_TRANSITIVE + - FULL + - FULL_TRANSITIVE + - NONE + compatibilityGroup: + type: string + defaultMetadata: + $ref: '#/components/schemas/Metadata' + overrideMetadata: + $ref: '#/components/schemas/Metadata' + defaultRuleSet: + $ref: '#/components/schemas/RuleSet' + overrideRuleSet: + $ref: '#/components/schemas/RuleSet' + description: Config update request + Mode: + type: object + properties: + mode: + type: string + description: Schema Registry operating mode + example: READWRITE + enum: + - READWRITE + - READONLY + - READONLY_OVERRIDE + - IMPORT + description: Schema Registry operating mode + ModeUpdateRequest: + type: object + properties: + mode: + type: string + description: Schema Registry operating mode + example: READWRITE + enum: + - READWRITE + - READONLY + - READONLY_OVERRIDE + - IMPORT + description: Mode update request + SchemaString: + type: object + properties: + schemaType: + type: string + description: Schema type + example: AVRO + schema: + type: string + description: Schema string identified by the ID + example: "{\"schema\": \"{\"type\": \"string\"}\"}" + references: + type: array + description: References to other schemas + items: + $ref: '#/components/schemas/SchemaReference' + metadata: + $ref: '#/components/schemas/Metadata' + ruleSet: + $ref: '#/components/schemas/RuleSet' + schemaTags: + type: array + description: Schema tags + items: + $ref: '#/components/schemas/SchemaTags' + maxId: + type: integer + description: Maximum ID + format: int32 + example: 1 + description: Schema definition + Schema: + type: object + properties: + subject: + type: string + description: Name of the subject + example: User + version: + type: integer + description: Version number + format: int32 + example: 1 + id: + type: integer + description: Globally unique identifier of the schema + format: int32 + example: 100001 + schemaType: + type: string + description: Schema type + example: AVRO + references: + type: array + description: References to other schemas + items: + $ref: '#/components/schemas/SchemaReference' + metadata: + $ref: '#/components/schemas/Metadata' + ruleset: + $ref: '#/components/schemas/RuleSet' + schema: + type: string + description: Schema definition string + example: "{\"schema\": \"{\"type\": \"string\"}\"}" + schemaTags: + type: array + description: Schema tags + items: + $ref: '#/components/schemas/SchemaTags' + ruleSet: + $ref: '#/components/schemas/RuleSet' + description: Schema + SubjectVersion: + type: object + properties: + subject: + type: string + description: Name of the subject + example: User + version: + type: integer + description: Version number + format: int32 + example: 1 + description: Subject version pair + ServerClusterId: + type: object + properties: + scope: + type: object + additionalProperties: + type: object + id: + type: string + RegisterSchemaResponse: + type: object + properties: + id: + type: integer + description: Globally unique identifier of the schema + format: int32 + example: 100001 + version: + type: integer + description: Version number + format: int32 + schemaType: + type: string + description: Schema type + references: + type: array + description: References to other schemas + items: + $ref: '#/components/schemas/SchemaReference' + metadata: + $ref: '#/components/schemas/Metadata' + ruleSet: + $ref: '#/components/schemas/RuleSet' + schema: + type: string + description: Schema definition string + description: Schema register response + ErrorMessage: + type: object + properties: + error_code: + type: integer + description: Error code + format: int32 + message: + type: string + description: Detailed error message + description: Error message + SchemaRegistryServerVersion: + type: object + properties: + version: + type: string + commitId: + type: string + Metadata: + type: object + properties: + tags: + type: object + additionalProperties: + uniqueItems: true + type: array + items: + type: string + properties: + type: object + additionalProperties: + type: string + sensitive: + uniqueItems: true + type: array + items: + type: string + description: User-defined metadata + Rule: + type: object + properties: + name: + type: string + description: Rule name + doc: + type: string + description: Rule doc + kind: + type: string + description: Rule kind + enum: + - TRANSFORM + - CONDITION + mode: + type: string + description: Rule mode + enum: + - UPGRADE + - DOWNGRADE + - UPDOWN + - WRITE + - READ + - WRITEREAD + type: + type: string + description: Rule type + tags: + uniqueItems: true + type: array + description: The tags to which this rule applies + items: + type: string + description: The tags to which this rule applies + params: + type: object + additionalProperties: + type: string + description: Optional params for the rule + description: Optional params for the rule + expr: + type: string + description: Rule expression + onSuccess: + type: string + description: Rule action on success + onFailure: + type: string + description: Rule action on failure + disabled: + type: boolean + description: Whether the rule is disabled + description: Rule + RuleSet: + type: object + properties: + migrationRules: + type: array + items: + $ref: '#/components/schemas/Rule' + domainRules: + type: array + items: + $ref: '#/components/schemas/Rule' + description: Schema rule set + SchemaEntity: + type: object + properties: + entityPath: + type: string + entityType: + type: string + enum: + - sr_record + - sr_field + SchemaTags: + type: object + properties: + schemaEntity: + $ref: '#/components/schemas/SchemaEntity' + tags: + type: array + items: + type: string + ExtendedSchema: + type: object + properties: + subject: + type: string + description: Name of the subject + example: User + version: + type: integer + description: Version number + format: int32 + example: 1 + id: + type: integer + description: Globally unique identifier of the schema + format: int32 + example: 100001 + schemaType: + type: string + description: Schema type + example: AVRO + references: + type: array + description: References to other schemas + items: + $ref: '#/components/schemas/SchemaReference' + metadata: + $ref: '#/components/schemas/Metadata' + ruleset: + $ref: '#/components/schemas/RuleSet' + schema: + type: string + description: Schema definition string + example: "{\"schema\": \"{\"type\": \"string\"}\"}" + aliases: + type: array + description: Aliases for the given subject + items: + type: string + description: Aliases for the given subject + ruleSet: + $ref: '#/components/schemas/RuleSet' + schemaTags: + type: array + description: Schema tags + items: + $ref: '#/components/schemas/SchemaTags' + description: ExtendedSchema + TagSchemaRequest: + type: object + properties: + newVersion: + type: integer + description: "The new version should be the latest version in the subject\ + \ + 1. If set, the new version will be encoded to the schema metadata." + format: int32 + tagsToAdd: + type: array + items: + $ref: '#/components/schemas/SchemaTags' + tagsToRemove: + type: array + items: + $ref: '#/components/schemas/SchemaTags' + metadata: + $ref: '#/components/schemas/Metadata' + ruleSet: + $ref: '#/components/schemas/RuleSet' + rulesToMerge: + $ref: '#/components/schemas/RuleSet' + rulesToRemove: + type: array + items: + type: string + description: Schema tags register request From 36944578b603000eceb93cad012322da89ce8174 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Thu, 6 Feb 2025 13:38:58 +0100 Subject: [PATCH 04/24] client service draft --- json-schema-registry/build.gradle | 39 +- .../registry/SchemaRegistryClient.java | 139 + .../registry/SchemaRegistryService.java | 41 + .../src/main/resources/application.yml | 4 + .../src/main/resources/registry.json | 4103 ----------------- .../resources/schema-registry-api-spec.yaml | 2770 ----------- .../registry/ConfluentClientTest.java | 40 + 7 files changed, 239 insertions(+), 6897 deletions(-) create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryService.java create mode 100644 json-schema-registry/src/main/resources/application.yml delete mode 100644 json-schema-registry/src/main/resources/registry.json delete mode 100644 json-schema-registry/src/main/resources/schema-registry-api-spec.yaml create mode 100644 json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle index c93b3001..f6519677 100644 --- a/json-schema-registry/build.gradle +++ b/json-schema-registry/build.gradle @@ -1,38 +1,29 @@ plugins { id("io.micronaut.build.internal.json-schema-module") - id("io.micronaut.minimal.application") - id("io.micronaut.openapi") -} - -micronaut { - runtime "netty" - testRuntime "junit5" - openapi { - server(file("registry.json")) { - } - } -} - -repositories { - mavenCentral() } dependencies { compileOnly(mn.micronaut.core.processor) + implementation(mn.micronaut.http) + implementation(mn.micronaut.http.client) + api(mn.micronaut.inject) - implementation(projects.micronautJsonSchemaGenerator) - implementation(mnSerde.micronaut.serde.jackson) - implementation(mnValidation.validation) - implementation("io.micronaut.security:micronaut-security") - - api(projects.micronautJsonSchemaAnnotations) - api(projects.micronautJsonSchemaCommon) - + testAnnotationProcessor(mn.micronaut.inject.java) + testImplementation(mn.micronaut.inject) + testImplementation(mn.micronaut.jackson.databind) + testImplementation(mnValidation.validation) testImplementation(mnTest.micronaut.test.junit5) testImplementation(libs.junit.jupiter.api) testRuntimeOnly(libs.junit.jupiter.engine) } -test { + +tasks.test { useJUnitPlatform() } + +sourceSets { + test { + java.srcDir('src/test/java') + } +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java new file mode 100644 index 00000000..3c1fe9d7 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -0,0 +1,139 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry; + +import io.micronaut.context.annotation.Value; +import io.micronaut.http.HttpRequest; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MediaType; +import io.micronaut.http.client.HttpClient; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.http.uri.UriBuilder; +import jakarta.inject.Singleton; + +import java.net.URI; +import java.util.Map; + +@Singleton +public class SchemaRegistryClient { + + private static final String HEADER_NAME = "Content-Type"; + private static final String HEADER_VALUE = "application/vnd.schemaregistry.v1+json"; + + private final HttpClient httpClient; + + @Value("${schema_registry.url}") + private String schemaRegistryUrl; + + public SchemaRegistryClient(@Client("/") HttpClient httpClient) { + this.httpClient = httpClient; + } + + /** + * Register a schema with the schema registry for a given subject. + * + * @param subject The subject (topic name, e.g., user-data) + * @param schema The Avro/JSON schema as a string + * @return The ID of the registered schema + */ + public int registerSchema(String subject, String schema) { + URI url = UriBuilder.of(schemaRegistryUrl) + .path("subjects") + .path(subject) + .path("versions") + .build(); + + Map body = Map.of("schema", schema); + + HttpRequest> request = HttpRequest.POST(url, body) + .header(HEADER_NAME, HEADER_VALUE) + .contentType(MediaType.APPLICATION_JSON); + + HttpResponse response = httpClient.toBlocking().exchange(request, Map.class); + + if (response.getStatus().getCode() == 200) { + Map responseBody = response.body(); + return (Integer) responseBody.get("id"); + } else { + throw new RuntimeException("Error registering schema: " + response.getStatus()); + } + } + + /** + * Get a schema for a given subject and version. + * + * @param subject The subject (e.g., user-data) + * @param version The version of the schema to retrieve (e.g., 1, 2, etc.) + * @return The schema in JSON format + */ + public String getSchema(String subject, int version) { + String url = schemaRegistryUrl + "/subjects/" + subject + "/versions/" + version; + + HttpRequest request = HttpRequest.GET(url) + .contentType(MediaType.APPLICATION_JSON); + + HttpResponse response = httpClient.toBlocking().exchange(request, Map.class); + + if (response.getStatus().getCode() == 200) { + Map responseBody = response.body(); + return (String) responseBody.get("schema"); + } else { + throw new RuntimeException("Error retrieving schema: " + response.getStatus()); + } + } + + /** + * Check if a schema is compatible with the latest schema for a given subject. + * + * @param subject The subject (e.g., user-data) + * @param schema The Avro/JSON schema as a string + * @return true if the schema is compatible, false otherwise + */ + public boolean checkCompatibility(String subject, String schema) { + String url = schemaRegistryUrl + "/compatibility/subjects/" + subject + "/versions/latest"; + + Map body = Map.of("schema", schema); + + HttpRequest> request = HttpRequest.POST(url, body) + .contentType(MediaType.APPLICATION_JSON); + + HttpResponse response = httpClient.toBlocking().exchange(request, Map.class); + + if (response.getStatus().getCode() == 200) { + Map responseBody = response.body(); + // Assuming response contains "is_compatible" field + return (Boolean) responseBody.get("is_compatible"); + } else { + throw new RuntimeException("Error checking compatibility: " + response.getStatus()); + } + } + + public void deleteSchema(String subject) { + // Delete the schema + } + + public void deleteSchemaVersion(String subject, int version) { + // Delete the schema version + } + + public void deleteAllVersions(String subject) { + // Delete all versions of the schema + } + + public void deleteAllSubjects() { + // Delete all subjects + } +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryService.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryService.java new file mode 100644 index 00000000..7fc3af65 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryService.java @@ -0,0 +1,41 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry; + +import jakarta.inject.Singleton; + +@Singleton +public class SchemaRegistryService { + private final SchemaRegistryClient schemaRegistryClient; + + public SchemaRegistryService(SchemaRegistryClient schemaRegistryClient) { + this.schemaRegistryClient = schemaRegistryClient; + } + +// public void registerSchema(String subject, String schema) { +// int schemaId = schemaRegistryClient.registerSchema(subject, schema); +// System.out.println("Registered schema with ID: " + schemaId); +// } +// +// public String getSchema(String subject, int version) { +// return schemaRegistryClient.getSchema(subject, version); +// } +// +// public boolean checkSchemaCompatibility(String subject, String schema) { +// return schemaRegistryClient.checkCompatibility(subject, schema); +// } + +} diff --git a/json-schema-registry/src/main/resources/application.yml b/json-schema-registry/src/main/resources/application.yml new file mode 100644 index 00000000..6074ccce --- /dev/null +++ b/json-schema-registry/src/main/resources/application.yml @@ -0,0 +1,4 @@ +schema_registry: + url: "http://144.24.55.159:8081" + username: "user" + password: "password" diff --git a/json-schema-registry/src/main/resources/registry.json b/json-schema-registry/src/main/resources/registry.json deleted file mode 100644 index 6aa7ac94..00000000 --- a/json-schema-registry/src/main/resources/registry.json +++ /dev/null @@ -1,4103 +0,0 @@ -{ - "openapi": "3.0.1", - "info": { - "title": "Confluent Schema Registry", - "version": "v1" - }, - "paths": { - "/compatibility/subjects/{subject}/versions/{version}": { - "post": { - "tags": [ - "Compatibility (v1)" - ], - "summary": "Test schema compatibility against a particular schema subject-version", - "description": "Test input schema against a particular version of a subject's schema for compatibility. The compatibility level applied for the check is the configured compatibility level for the subject (http:get:: /config/(string: subject)). If this subject's compatibility level was never changed, then the global compatibility level applies (http:get:: /config).", - "operationId": "testCompatibilityBySubjectName_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Subject of the schema version against which compatibility is to be tested", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "version", - "in": "path", - "description": "Version of the subject's schema against which compatibility is to be tested. Valid values for versionId are between [1,2^31-1] or the string \"latest\".\"latest\" checks compatibility of the input schema with the last registered schema under the specified subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "normalize", - "in": "query", - "description": "Whether to normalize the given schema", - "schema": { - "type": "boolean" - } - }, - { - "name": "verbose", - "in": "query", - "description": "Whether to return detailed error messages", - "schema": { - "type": "boolean" - } - } - ], - "requestBody": { - "description": "Schema", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/vnd.schemaregistry+json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/octet-stream": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Compatibility check result.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/CompatibilityCheckResponse" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/CompatibilityCheckResponse" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/CompatibilityCheckResponse" - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found. Error code 40402 indicates version not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "422": { - "description": "Unprocessable entity. Error code 42201 indicates an invalid schema or schema type. Error code 42202 indicates an invalid version.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/": { - "get": { - "summary": "Schema Registry Root Resource", - "description": "The Root resource is a no-op.", - "operationId": "get_1", - "responses": { - "default": { - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "string" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "string" - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "string" - } - } - }, - "description": "Default response for get." - } - } - }, - "post": { - "operationId": "post_1", - "requestBody": { - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "application/vnd.schemaregistry+json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "application/json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "application/octet-stream": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - }, - "responses": { - "default": { - "description": "default response", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - } - } - }, - "/compatibility/subjects/{subject}/versions": { - "post": { - "tags": [ - "Compatibility (v1)" - ], - "summary": "Test schema compatibility against all schemas under a subject", - "description": "Test input schema against a subject's schemas for compatibility, based on the configured compatibility level of the subject. In other words, it will perform the same compatibility check as register for that subject. The compatibility level applied for the check is the configured compatibility level for the subject (http:get:: /config/(string: subject)). If this subject's compatibility level was never changed, then the global compatibility level applies (http:get:: /config).", - "operationId": "testCompatibilityForSubject_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Subject of the schema version against which compatibility is to be tested", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "normalize", - "in": "query", - "description": "Whether to normalize the given schema", - "schema": { - "type": "boolean" - } - }, - { - "name": "verbose", - "in": "query", - "description": "Whether to return detailed error messages", - "schema": { - "type": "boolean" - } - } - ], - "requestBody": { - "description": "Schema", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/vnd.schemaregistry+json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/octet-stream": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Compatibility check result.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/CompatibilityCheckResponse" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/CompatibilityCheckResponse" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/CompatibilityCheckResponse" - } - } - } - }, - "422": { - "description": "Unprocessable Entity. Error code 42201 indicates an invalid schema or schema type. Error code 42202 indicates an invalid version.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/config": { - "get": { - "tags": [ - "Config (v1)" - ], - "summary": "Get global compatibility level", - "description": "Retrieves the global compatibility level.", - "operationId": "getTopLevelConfig_1", - "responses": { - "200": { - "description": "The global compatibility level.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/Config" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/Config" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/Config" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - }, - "put": { - "tags": [ - "Config (v1)" - ], - "summary": "Update global compatibility level", - "description": "Updates the global compatibility level. On success, echoes the original request back to the client.", - "operationId": "updateTopLevelConfig_1", - "requestBody": { - "description": "Config Update Request", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - }, - "application/vnd.schemaregistry+json": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - }, - "application/octet-stream": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "The original request.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - } - } - }, - "422": { - "description": "Unprocessable Entity. Error code 42203 indicates invalid compatibility level.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store. Error code 50003 indicates a failure forwarding the request to the primary.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - }, - "delete": { - "tags": [ - "Config (v1)" - ], - "summary": "Delete global compatibility level", - "description": "Deletes the global compatibility level config and reverts to the default.", - "operationId": "deleteTopLevelConfig_1", - "responses": { - "200": { - "description": "Operation succeeded. Returns old global compatibility level.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "string", - "enum": [ - "NONE", - "BACKWARD", - "BACKWARD_TRANSITIVE", - "FORWARD", - "FORWARD_TRANSITIVE", - "FULL", - "FULL_TRANSITIVE" - ] - }, - "example": "FULL_TRANSITIVE" - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "string", - "enum": [ - "NONE", - "BACKWARD", - "BACKWARD_TRANSITIVE", - "FORWARD", - "FORWARD_TRANSITIVE", - "FULL", - "FULL_TRANSITIVE" - ] - }, - "example": "FULL_TRANSITIVE" - }, - "application/json; qs=0.5": { - "schema": { - "type": "string", - "enum": [ - "NONE", - "BACKWARD", - "BACKWARD_TRANSITIVE", - "FORWARD", - "FORWARD_TRANSITIVE", - "FULL", - "FULL_TRANSITIVE" - ] - }, - "example": "FULL_TRANSITIVE" - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/config/{subject}": { - "get": { - "tags": [ - "Config (v1)" - ], - "summary": "Get subject compatibility level", - "description": "Retrieves compatibility level for a subject.", - "operationId": "getSubjectLevelConfig_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "defaultToGlobal", - "in": "query", - "description": "Whether to return the global compatibility level if subject compatibility level not found", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "The subject compatibility level.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/Config" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/Config" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/Config" - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - }, - "put": { - "tags": [ - "Config (v1)" - ], - "summary": "Update subject compatibility level", - "description": "Update compatibility level for the specified subject. On success, echoes the original request back to the client.", - "operationId": "updateSubjectLevelConfig_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "description": "Config Update Request", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - }, - "application/vnd.schemaregistry+json": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - }, - "application/octet-stream": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "The original request.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ConfigUpdateRequest" - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "422": { - "description": "Unprocessable Entity. Error code 42203 indicates invalid compatibility level.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store. Error code 50003 indicates a failure forwarding the request to the primary.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - }, - "delete": { - "tags": [ - "Config (v1)" - ], - "summary": "Delete subject compatibility level", - "description": "Deletes the specified subject-level compatibility level config and reverts to the global default.", - "operationId": "deleteSubjectConfig_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Operation succeeded. Returns old compatibility level.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "string", - "enum": [ - "NONE", - "BACKWARD", - "BACKWARD_TRANSITIVE", - "FORWARD", - "FORWARD_TRANSITIVE", - "FULL", - "FULL_TRANSITIVE" - ] - }, - "example": "FULL_TRANSITIVE" - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "string", - "enum": [ - "NONE", - "BACKWARD", - "BACKWARD_TRANSITIVE", - "FORWARD", - "FORWARD_TRANSITIVE", - "FULL", - "FULL_TRANSITIVE" - ] - }, - "example": "FULL_TRANSITIVE" - }, - "application/json; qs=0.5": { - "schema": { - "type": "string", - "enum": [ - "NONE", - "BACKWARD", - "BACKWARD_TRANSITIVE", - "FORWARD", - "FORWARD_TRANSITIVE", - "FULL", - "FULL_TRANSITIVE" - ] - }, - "example": "FULL_TRANSITIVE" - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/contexts": { - "get": { - "tags": [ - "Contexts (v1)" - ], - "summary": "List contexts", - "description": "Retrieves a list of contexts.", - "operationId": "listContexts_1", - "responses": { - "200": { - "description": "The contexts.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "." - } - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "." - } - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "." - } - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store. ", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/mode": { - "get": { - "tags": [ - "Modes (v1)" - ], - "summary": "Get global mode", - "description": "Retrieves global mode.", - "operationId": "getTopLevelMode_1", - "responses": { - "200": { - "description": "The global mode", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/Mode" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/Mode" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/Mode" - } - } - } - }, - "500": { - "description": "Error code 50001 -- Error in the backend data store" - } - } - }, - "put": { - "tags": [ - "Modes (v1)" - ], - "summary": "Update global mode", - "description": "Update global mode. On success, echoes the original request back to the client.", - "operationId": "updateTopLevelMode_1", - "parameters": [ - { - "name": "force", - "in": "query", - "description": "Whether to force update if setting mode to IMPORT and schemas currently exist", - "schema": { - "type": "boolean" - } - } - ], - "requestBody": { - "description": "Update Request", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - }, - "application/vnd.schemaregistry+json": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - }, - "application/octet-stream": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "The original request.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - } - } - }, - "422": { - "description": "Unprocessable Entity. Error code 42204 indicates an invalid mode. Error code 42205 indicates operation not permitted.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store. Error code 50003 indicates a failure forwarding the request to the primary. Error code 50004 indicates unknown leader.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/mode/{subject}": { - "get": { - "tags": [ - "Modes (v1)" - ], - "summary": "Get subject mode", - "description": "Retrieves the subject mode.", - "operationId": "getMode_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "defaultToGlobal", - "in": "query", - "description": "Whether to return the global mode if subject mode not found", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "The subject mode.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/Mode" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/Mode" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/Mode" - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - }, - "put": { - "tags": [ - "Modes (v1)" - ], - "summary": "Update subject mode", - "description": "Update mode for the specified subject. On success, echoes the original request back to the client.", - "operationId": "updateMode_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "force", - "in": "query", - "description": "Whether to force update if setting mode to IMPORT and schemas currently exist", - "schema": { - "type": "boolean" - } - } - ], - "requestBody": { - "description": "Update Request", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - }, - "application/vnd.schemaregistry+json": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - }, - "application/octet-stream": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "The original request.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ModeUpdateRequest" - } - } - } - }, - "422": { - "description": "Unprocessable Entity. Error code 42204 indicates an invalid mode. Error code 42205 indicates operation not permitted.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store. Error code 50003 indicates a failure forwarding the request to the primary. Error code 50004 indicates unknown leader.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - }, - "delete": { - "tags": [ - "Modes (v1)" - ], - "summary": "Delete subject mode", - "description": "Deletes the specified subject-level mode and reverts to the global default.", - "operationId": "deleteSubjectMode_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Operation succeeded. Returns old mode.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/Mode" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/Mode" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/Mode" - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/schemas": { - "get": { - "tags": [ - "Schemas (v1)" - ], - "summary": "List schemas", - "description": "Get the schemas matching the specified parameters.", - "operationId": "getSchemas_1", - "parameters": [ - { - "name": "subjectPrefix", - "in": "query", - "description": "Filters results by the respective subject prefix", - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "aliases", - "in": "query", - "description": "Whether to include aliases in the search", - "schema": { - "type": "boolean", - "default": false - } - }, - { - "name": "deleted", - "in": "query", - "description": "Whether to return soft deleted schemas", - "schema": { - "type": "boolean", - "default": false - } - }, - { - "name": "latestOnly", - "in": "query", - "description": "Whether to return latest schema versions only for each matching subject", - "schema": { - "type": "boolean", - "default": false - } - }, - { - "name": "ruleType", - "in": "query", - "description": "Filters results by the given rule type", - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "offset", - "in": "query", - "description": "Pagination offset for results", - "schema": { - "type": "integer", - "format": "int32", - "default": 0 - } - }, - { - "name": "limit", - "in": "query", - "description": "Pagination size for results. Ignored if negative", - "schema": { - "type": "integer", - "format": "int32", - "default": -1 - } - } - ], - "responses": { - "200": { - "description": "List of schemas matching the specified parameters.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Schema" - } - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Schema" - } - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Schema" - } - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/schemas/ids/{id}": { - "get": { - "tags": [ - "Schemas (v1)" - ], - "summary": "Get schema string by ID", - "description": "Retrieves the schema string identified by the input ID.", - "operationId": "getSchema_1", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Globally unique identifier of the schema", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "subject", - "in": "query", - "description": "Name of the subject", - "schema": { - "type": "string" - } - }, - { - "name": "format", - "in": "query", - "description": "Desired output format, dependent on schema type", - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "findTags", - "in": "query", - "description": "Find tagged entities for the given tags or * for all tags", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - }, - { - "name": "fetchMaxId", - "in": "query", - "description": "Whether to fetch the maximum schema identifier that exists", - "schema": { - "type": "boolean", - "default": false - } - } - ], - "responses": { - "200": { - "description": "The schema string.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/SchemaString" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/SchemaString" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/SchemaString" - } - } - } - }, - "404": { - "description": "Not Found. Error code 40403 indicates schema not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/schemas/ids/{id}/subjects": { - "get": { - "tags": [ - "Schemas (v1)" - ], - "summary": "List subjects associated to schema ID", - "description": "Retrieves all the subjects associated with a particular schema ID.", - "operationId": "getSubjects_1", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Globally unique identifier of the schema", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "subject", - "in": "query", - "description": "Filters results by the respective subject", - "schema": { - "type": "string" - } - }, - { - "name": "deleted", - "in": "query", - "description": "Whether to include subjects where the schema was deleted", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of subjects matching the specified parameters.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "User" - } - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "User" - } - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "User" - } - } - } - } - }, - "404": { - "description": "Not Found. Error code 40403 indicates schema not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/schemas/ids/{id}/versions": { - "get": { - "tags": [ - "Schemas (v1)" - ], - "summary": "List subject-versions associated to schema ID", - "description": "Get all the subject-version pairs associated with the input ID.", - "operationId": "getVersions_1", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Globally unique identifier of the schema", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "subject", - "in": "query", - "description": "Filters results by the respective subject", - "schema": { - "type": "string" - } - }, - { - "name": "deleted", - "in": "query", - "description": "Whether to include subject versions where the schema was deleted", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of subject versions matching the specified parameters.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SubjectVersion" - } - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SubjectVersion" - } - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SubjectVersion" - } - } - } - } - }, - "404": { - "description": "Not Found. Error code 40403 indicates schema not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/schemas/types": { - "get": { - "tags": [ - "Schemas (v1)" - ], - "summary": "List supported schema types", - "description": "Retrieve the schema types supported by this registry.", - "operationId": "getSchemaTypes_1", - "responses": { - "200": { - "description": "List of supported schema types.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "AVRO" - } - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "AVRO" - } - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "AVRO" - } - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/subjects": { - "get": { - "tags": [ - "Subjects (v1)" - ], - "summary": "List subjects", - "description": "Retrieves a list of registered subjects matching specified parameters.", - "operationId": "list_1", - "parameters": [ - { - "name": "subjectPrefix", - "in": "query", - "description": "Subject name prefix", - "schema": { - "type": "string", - "default": ":*:" - } - }, - { - "name": "deleted", - "in": "query", - "description": "Whether to look up deleted subjects", - "schema": { - "type": "boolean" - } - }, - { - "name": "deletedOnly", - "in": "query", - "description": "Whether to return deleted subjects only", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of subjects matching the specified parameters.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "User" - } - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "User" - } - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "array", - "items": { - "type": "string", - "example": "User" - } - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/subjects/{subject}": { - "post": { - "tags": [ - "Subjects (v1)" - ], - "summary": "Lookup schema under subject", - "description": "Check if a schema has already been registered under the specified subject. If so, this returns the schema string along with its globally unique identifier, its version under this subject and the subject name.", - "operationId": "lookUpSchemaUnderSubject_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Subject under which the schema will be registered", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "normalize", - "in": "query", - "description": "Whether to normalize the given schema", - "schema": { - "type": "boolean" - } - }, - { - "name": "format", - "in": "query", - "description": "Desired output format, dependent on schema type", - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "deleted", - "in": "query", - "description": "Whether to lookup deleted schemas", - "schema": { - "type": "boolean" - } - } - ], - "requestBody": { - "description": "Schema", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/vnd.schemaregistry+json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/octet-stream": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "The schema.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/Schema" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/Schema" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/Schema" - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found. Error code 40403 indicates schema not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - }, - "delete": { - "tags": [ - "Subjects (v1)" - ], - "summary": "Delete subject", - "description": "Deletes the specified subject and its associated compatibility level if registered. It is recommended to use this API only when a topic needs to be recycled or in development environment.", - "operationId": "deleteSubject_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "permanent", - "in": "query", - "description": "Whether to perform a permanent delete", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "Operation succeeded. Returns list of schema versions deleted", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "array", - "items": { - "type": "integer", - "format": "int32", - "example": 1 - } - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "array", - "items": { - "type": "integer", - "format": "int32", - "example": 1 - } - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "array", - "items": { - "type": "integer", - "format": "int32", - "example": 1 - } - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/subjects/{subject}/versions": { - "get": { - "tags": [ - "Subjects (v1)" - ], - "summary": "List versions under subject", - "description": "Retrieves a list of versions registered under the specified subject.", - "operationId": "listVersions_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "deleted", - "in": "query", - "description": "Whether to include deleted schemas", - "schema": { - "type": "boolean" - } - }, - { - "name": "deletedOnly", - "in": "query", - "description": "Whether to return deleted schemas only", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of version numbers matching the specified parameters.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "array", - "items": { - "type": "integer", - "format": "int32", - "example": 1 - } - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "array", - "items": { - "type": "integer", - "format": "int32", - "example": 1 - } - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "array", - "items": { - "type": "integer", - "format": "int32", - "example": 1 - } - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found. ", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - }, - "post": { - "tags": [ - "Subjects (v1)" - ], - "summary": "Register schema under a subject", - "description": "Register a new schema under the specified subject. If successfully registered, this returns the unique identifier of this schema in the registry. The returned identifier should be used to retrieve this schema from the schemas resource and is different from the schema's version which is associated with the subject. If the same schema is registered under a different subject, the same identifier will be returned. However, the version of the schema may be different under different subjects.\nA schema should be compatible with the previously registered schema or schemas (if there are any) as per the configured compatibility level. The configured compatibility level can be obtained by issuing a GET http:get:: /config/(string: subject). If that returns null, then GET http:get:: /config\nWhen there are multiple instances of Schema Registry running in the same cluster, the schema registration request will be forwarded to one of the instances designated as the primary. If the primary is not available, the client will get an error code indicating that the forwarding has failed.", - "operationId": "register_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "normalize", - "in": "query", - "description": "Whether to normalize the given schema", - "schema": { - "type": "boolean" - } - }, - { - "name": "format", - "in": "query", - "description": "Desired output format, dependent on schema type", - "schema": { - "type": "string", - "default": "" - } - } - ], - "requestBody": { - "description": "Schema", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/vnd.schemaregistry+json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - }, - "application/octet-stream": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Schema successfully registered.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaResponse" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaResponse" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaResponse" - } - } - } - }, - "409": { - "description": "Conflict. Incompatible schema.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "422": { - "description": "Unprocessable entity. Error code 42201 indicates an invalid schema or schema type. ", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.Error code 50002 indicates operation timed out. Error code 50003 indicates a failure forwarding the request to the primary.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/subjects/{subject}/versions/{version}": { - "get": { - "tags": [ - "Subjects (v1)" - ], - "summary": "Get schema by version", - "description": "Retrieves a specific version of the schema registered under this subject.", - "operationId": "getSchemaByVersion_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "version", - "in": "path", - "description": "Version of the schema to be returned. Valid values for versionId are between [1,2^31-1] or the string \"latest\". \"latest\" returns the last registered schema under the specified subject. Note that there may be a new latest schema that gets registered right after this request is served.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "format", - "in": "query", - "description": "Desired output format, dependent on schema type", - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "deleted", - "in": "query", - "description": "Whether to include deleted schema", - "schema": { - "type": "boolean" - } - }, - { - "name": "findTags", - "in": "query", - "description": "Find tagged entities for the given tags or * for all tags", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - ], - "responses": { - "200": { - "description": "The schema.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/Schema" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/Schema" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/Schema" - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found. Error code 40402 indicates version not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "422": { - "description": "Unprocessable Entity. Error code 42202 indicates an invalid version.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - }, - "delete": { - "tags": [ - "Subjects (v1)" - ], - "summary": "Delete schema version", - "description": "Deletes a specific version of the schema registered under this subject. This only deletes the version and the schema ID remains intact making it still possible to decode data using the schema ID. This API is recommended to be used only in development environments or under extreme circumstances where-in, its required to delete a previously registered schema for compatibility purposes or re-register previously registered schema.", - "operationId": "deleteSchemaVersion_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "version", - "in": "path", - "description": "Version of the schema to be returned. Valid values for versionId are between [1,2^31-1] or the string \"latest\". \"latest\" returns the last registered schema under the specified subject. Note that there may be a new latest schema that gets registered right after this request is served.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "permanent", - "in": "query", - "description": "Whether to perform a permanent delete", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "Operation succeeded. Returns the schema version.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "integer", - "format": "int32", - "example": 1 - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "integer", - "format": "int32", - "example": 1 - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "integer", - "format": "int32", - "example": 1 - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found. Error code 40402 indicates version not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "422": { - "description": "Unprocessable Entity. Error code 42202 indicates an invalid version.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/subjects/{subject}/versions/{version}/referencedby": { - "get": { - "tags": [ - "Subjects (v1)" - ], - "summary": "List schemas referencing a schema", - "description": "Retrieves the IDs of schemas that reference the specified schema.", - "operationId": "getReferencedBy_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "version", - "in": "path", - "description": "Version of the schema to be returned. Valid values for versionId are between [1,2^31-1] or the string \"latest\". \"latest\" returns the last registered schema under the specified subject. Note that there may be a new latest schema that gets registered right after this request is served.", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of IDs for schemas that reference the specified schema.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "array", - "items": { - "type": "integer", - "format": "int32", - "example": 100001 - } - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "array", - "items": { - "type": "integer", - "format": "int32", - "example": 100001 - } - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "array", - "items": { - "type": "integer", - "format": "int32", - "example": 100001 - } - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found. Error code 40402 indicates version not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "422": { - "description": "Unprocessable Entity. Error code 42202 indicates an invalid version.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/subjects/{subject}/versions/{version}/schema": { - "get": { - "tags": [ - "Subjects (v1)" - ], - "summary": "Get schema string by version", - "description": "Retrieves the schema for the specified version of this subject. Only the unescaped schema string is returned.", - "operationId": "getSchemaOnly_2", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "version", - "in": "path", - "description": "Version of the schema to be returned. Valid values for versionId are between [1,2^31-1] or the string \"latest\". \"latest\" returns the last registered schema under the specified subject. Note that there may be a new latest schema that gets registered right after this request is served.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "format", - "in": "query", - "description": "Desired output format, dependent on schema type", - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "deleted", - "in": "query", - "description": "Whether to include deleted schema", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "The schema string.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "string", - "example": "{\"schema\": \"{\"type\": \"string\"}\"}" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "string", - "example": "{\"schema\": \"{\"type\": \"string\"}\"}" - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "string", - "example": "{\"schema\": \"{\"type\": \"string\"}\"}" - } - } - } - }, - "404": { - "description": "Not Found. Error code 40401 indicates subject not found. Error code 40402 indicates version not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "422": { - "description": "Unprocessable Entity. Error code 42202 indicates an invalid version.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/v1/metadata/id": { - "get": { - "tags": [ - "Server Metadata (v1)" - ], - "summary": "Get the server metadata", - "operationId": "getClusterId_1", - "responses": { - "500": { - "description": "Error code 50001 -- Error in the backend data store\n" - } - } - } - }, - "/schemas/ids/{id}/schema": { - "get": { - "tags": [ - "Schemas (v1)" - ], - "summary": "Get schema by ID", - "description": "Retrieves the schema identified by the input ID.", - "operationId": "getSchemaOnly", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Globally unique identifier of the schema", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "subject", - "in": "query", - "description": "Name of the subject", - "schema": { - "type": "string" - } - }, - { - "name": "format", - "in": "query", - "description": "Desired output format, dependent on schema type", - "schema": { - "type": "string", - "default": "" - } - } - ], - "responses": { - "200": { - "description": "Raw schema string.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "type": "string", - "example": "{\"schema\": \"{\"type\": \"string\"}\"}" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "type": "string", - "example": "{\"schema\": \"{\"type\": \"string\"}\"}" - } - }, - "application/json; qs=0.5": { - "schema": { - "type": "string", - "example": "{\"schema\": \"{\"type\": \"string\"}\"}" - } - } - } - }, - "404": { - "description": "Not Found. Error code 40403 indicates schema not found.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - }, - "/v1/metadata/version": { - "get": { - "tags": [ - "Server Metadata (v1)" - ], - "summary": "Get Schema Registry server version", - "operationId": "getSchemaRegistryVersion_1", - "responses": { - "500": { - "description": "Error code 50001 -- Error in the backend data store\n" - } - } - } - }, - "/subjects/{subject}/metadata": { - "get": { - "summary": "Retrieve the latest version with the given metadata.", - "description": "Retrieve the latest version with the given metadata.", - "operationId": "getLatestWithMetadata_1", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Subject under which the schema will be registered", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "key", - "in": "query", - "description": "The metadata key", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - }, - { - "name": "value", - "in": "query", - "description": "The metadata value", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - }, - { - "name": "format", - "in": "query", - "description": "Desired output format, dependent on schema type", - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "deleted", - "in": "query", - "description": "Whether to lookup deleted schemas", - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "The schema", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/Schema" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/Schema" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/Schema" - } - } - } - }, - "404": { - "description": "Error code 40401 -- Subject not found\nError code 40403 -- Schema not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/subjects/{subject}/versions/{version}/tags": { - "post": { - "tags": [ - "Subjects (v1)" - ], - "summary": "Create or remove schema embedded tags for a subject version", - "description": "Create new schema subject version with the provided field or record level schema tags embedded (or remove) in the schema string, as well as the given metadata and ruleset.", - "operationId": "modifyTags", - "parameters": [ - { - "name": "subject", - "in": "path", - "description": "Name of the subject", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "version", - "in": "path", - "description": "Version of the schema to be returned. Valid values for versionId are between [1,2^31-1] or the string \"latest\". \"latest\" returns the last registered schema under the specified subject. Note that there may be a new latest schema that gets registered right after this request is served.", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "description": "Tag schema request", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/TagSchemaRequest" - } - }, - "application/vnd.schemaregistry+json": { - "schema": { - "$ref": "#/components/schemas/TagSchemaRequest" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/TagSchemaRequest" - } - }, - "application/octet-stream": { - "schema": { - "$ref": "#/components/schemas/TagSchemaRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Schema successfully registered.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaResponse" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaResponse" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/RegisterSchemaResponse" - } - } - } - }, - "409": { - "description": "Conflict. Incompatible schema.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "422": { - "description": "Unprocessable entity. Error code 42201 indicates an invalid schema or schema type. ", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - }, - "500": { - "description": "Internal Server Error. Error code 50001 indicates a failure in the backend data store.Error code 50002 indicates operation timed out. Error code 50003 indicates a failure forwarding the request to the primary.", - "content": { - "application/vnd.schemaregistry.v1+json": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/vnd.schemaregistry+json; qs=0.9": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - }, - "application/json; qs=0.5": { - "schema": { - "$ref": "#/components/schemas/ErrorMessage" - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "CompatibilityCheckResponse": { - "type": "object", - "properties": { - "is_compatible": { - "type": "boolean", - "description": "Whether the compared schemas are compatible" - }, - "messages": { - "type": "array", - "description": "Error messages", - "example": [], - "items": { - "type": "string", - "description": "Error messages", - "example": "[]" - } - } - }, - "description": "Compatibility check response" - }, - "RegisterSchemaRequest": { - "type": "object", - "properties": { - "version": { - "type": "integer", - "description": "Version number", - "format": "int32" - }, - "id": { - "type": "integer", - "description": "Globally unique identifier of the schema", - "format": "int32" - }, - "schemaType": { - "type": "string", - "description": "Schema type" - }, - "references": { - "type": "array", - "description": "References to other schemas", - "items": { - "$ref": "#/components/schemas/SchemaReference" - } - }, - "metadata": { - "$ref": "#/components/schemas/Metadata" - }, - "ruleSet": { - "$ref": "#/components/schemas/RuleSet" - }, - "schema": { - "type": "string", - "description": "Schema definition string" - }, - "schemaTagsToAdd": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SchemaTags" - } - }, - "schemaTagsToRemove": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SchemaTags" - } - }, - "propagateSchemaTags": { - "type": "boolean" - } - }, - "description": "Schema register request" - }, - "SchemaReference": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Reference name", - "example": "io.confluent.kafka.example.User" - }, - "subject": { - "type": "string", - "description": "Name of the referenced subject", - "example": "User" - }, - "version": { - "type": "integer", - "description": "Version number of the referenced subject", - "format": "int32", - "example": 1 - } - }, - "description": "Schema reference" - }, - "Config": { - "type": "object", - "properties": { - "compatibilityLevel": { - "type": "string", - "description": "Compatibility Level", - "example": "FULL_TRANSITIVE", - "enum": [ - "BACKWARD", - "BACKWARD_TRANSITIVE", - "FORWARD", - "FORWARD_TRANSITIVE", - "FULL", - "FULL_TRANSITIVE", - "NONE" - ] - }, - "alias": { - "type": "string" - }, - "normalize": { - "type": "boolean" - }, - "validateFields": { - "type": "boolean" - }, - "validateRules": { - "type": "boolean" - }, - "compatibilityGroup": { - "type": "string" - }, - "defaultMetadata": { - "$ref": "#/components/schemas/Metadata" - }, - "overrideMetadata": { - "$ref": "#/components/schemas/Metadata" - }, - "defaultRuleSet": { - "$ref": "#/components/schemas/RuleSet" - }, - "overrideRuleSet": { - "$ref": "#/components/schemas/RuleSet" - } - }, - "description": "Config" - }, - "ConfigUpdateRequest": { - "type": "object", - "properties": { - "alias": { - "type": "string" - }, - "normalize": { - "type": "boolean" - }, - "validateFields": { - "type": "boolean" - }, - "validateRules": { - "type": "boolean" - }, - "compatibility": { - "type": "string", - "description": "Compatibility Level", - "example": "FULL_TRANSITIVE", - "enum": [ - "BACKWARD", - "BACKWARD_TRANSITIVE", - "FORWARD", - "FORWARD_TRANSITIVE", - "FULL", - "FULL_TRANSITIVE", - "NONE" - ] - }, - "compatibilityGroup": { - "type": "string" - }, - "defaultMetadata": { - "$ref": "#/components/schemas/Metadata" - }, - "overrideMetadata": { - "$ref": "#/components/schemas/Metadata" - }, - "defaultRuleSet": { - "$ref": "#/components/schemas/RuleSet" - }, - "overrideRuleSet": { - "$ref": "#/components/schemas/RuleSet" - } - }, - "description": "Config update request" - }, - "Mode": { - "type": "object", - "properties": { - "mode": { - "type": "string", - "description": "Schema Registry operating mode", - "example": "READWRITE", - "enum": [ - "READWRITE", - "READONLY", - "READONLY_OVERRIDE", - "IMPORT" - ] - } - }, - "description": "Schema Registry operating mode" - }, - "ModeUpdateRequest": { - "type": "object", - "properties": { - "mode": { - "type": "string", - "description": "Schema Registry operating mode", - "example": "READWRITE", - "enum": [ - "READWRITE", - "READONLY", - "READONLY_OVERRIDE", - "IMPORT" - ] - } - }, - "description": "Mode update request" - }, - "SchemaString": { - "type": "object", - "properties": { - "schemaType": { - "type": "string", - "description": "Schema type", - "example": "AVRO" - }, - "schema": { - "type": "string", - "description": "Schema string identified by the ID", - "example": "{\"schema\": \"{\"type\": \"string\"}\"}" - }, - "references": { - "type": "array", - "description": "References to other schemas", - "items": { - "$ref": "#/components/schemas/SchemaReference" - } - }, - "metadata": { - "$ref": "#/components/schemas/Metadata" - }, - "ruleSet": { - "$ref": "#/components/schemas/RuleSet" - }, - "schemaTags": { - "type": "array", - "description": "Schema tags", - "items": { - "$ref": "#/components/schemas/SchemaTags" - } - }, - "maxId": { - "type": "integer", - "description": "Maximum ID", - "format": "int32", - "example": 1 - } - }, - "description": "Schema definition" - }, - "Schema": { - "type": "object", - "properties": { - "subject": { - "type": "string", - "description": "Name of the subject", - "example": "User" - }, - "version": { - "type": "integer", - "description": "Version number", - "format": "int32", - "example": 1 - }, - "id": { - "type": "integer", - "description": "Globally unique identifier of the schema", - "format": "int32", - "example": 100001 - }, - "schemaType": { - "type": "string", - "description": "Schema type", - "example": "AVRO" - }, - "references": { - "type": "array", - "description": "References to other schemas", - "items": { - "$ref": "#/components/schemas/SchemaReference" - } - }, - "metadata": { - "$ref": "#/components/schemas/Metadata" - }, - "ruleset": { - "$ref": "#/components/schemas/RuleSet" - }, - "schema": { - "type": "string", - "description": "Schema definition string", - "example": "{\"schema\": \"{\"type\": \"string\"}\"}" - }, - "schemaTags": { - "type": "array", - "description": "Schema tags", - "items": { - "$ref": "#/components/schemas/SchemaTags" - } - }, - "ruleSet": { - "$ref": "#/components/schemas/RuleSet" - } - }, - "description": "Schema" - }, - "SubjectVersion": { - "type": "object", - "properties": { - "subject": { - "type": "string", - "description": "Name of the subject", - "example": "User" - }, - "version": { - "type": "integer", - "description": "Version number", - "format": "int32", - "example": 1 - } - }, - "description": "Subject version pair" - }, - "ServerClusterId": { - "type": "object", - "properties": { - "scope": { - "type": "object", - "additionalProperties": { - "type": "object" - } - }, - "id": { - "type": "string" - } - } - }, - "RegisterSchemaResponse": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "description": "Globally unique identifier of the schema", - "format": "int32", - "example": 100001 - }, - "version": { - "type": "integer", - "description": "Version number", - "format": "int32" - }, - "schemaType": { - "type": "string", - "description": "Schema type" - }, - "references": { - "type": "array", - "description": "References to other schemas", - "items": { - "$ref": "#/components/schemas/SchemaReference" - } - }, - "metadata": { - "$ref": "#/components/schemas/Metadata" - }, - "ruleSet": { - "$ref": "#/components/schemas/RuleSet" - }, - "schema": { - "type": "string", - "description": "Schema definition string" - } - }, - "description": "Schema register response" - }, - "ErrorMessage": { - "type": "object", - "properties": { - "error_code": { - "type": "integer", - "description": "Error code", - "format": "int32" - }, - "message": { - "type": "string", - "description": "Detailed error message" - } - }, - "description": "Error message" - }, - "SchemaRegistryServerVersion": { - "type": "object", - "properties": { - "version": { - "type": "string" - }, - "commitId": { - "type": "string" - } - } - }, - "Metadata": { - "type": "object", - "properties": { - "tags": { - "type": "object", - "additionalProperties": { - "uniqueItems": true, - "type": "array", - "items": { - "type": "string" - } - } - }, - "properties": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "sensitive": { - "uniqueItems": true, - "type": "array", - "items": { - "type": "string" - } - } - }, - "description": "User-defined metadata" - }, - "Rule": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Rule name" - }, - "doc": { - "type": "string", - "description": "Rule doc" - }, - "kind": { - "type": "string", - "description": "Rule kind", - "enum": [ - "TRANSFORM", - "CONDITION" - ] - }, - "mode": { - "type": "string", - "description": "Rule mode", - "enum": [ - "UPGRADE", - "DOWNGRADE", - "UPDOWN", - "WRITE", - "READ", - "WRITEREAD" - ] - }, - "type": { - "type": "string", - "description": "Rule type" - }, - "tags": { - "uniqueItems": true, - "type": "array", - "description": "The tags to which this rule applies", - "items": { - "type": "string", - "description": "The tags to which this rule applies" - } - }, - "params": { - "type": "object", - "additionalProperties": { - "type": "string", - "description": "Optional params for the rule" - }, - "description": "Optional params for the rule" - }, - "expr": { - "type": "string", - "description": "Rule expression" - }, - "onSuccess": { - "type": "string", - "description": "Rule action on success" - }, - "onFailure": { - "type": "string", - "description": "Rule action on failure" - }, - "disabled": { - "type": "boolean", - "description": "Whether the rule is disabled" - } - }, - "description": "Rule" - }, - "RuleSet": { - "type": "object", - "properties": { - "migrationRules": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Rule" - } - }, - "domainRules": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Rule" - } - } - }, - "description": "Schema rule set" - }, - "SchemaEntity": { - "type": "object", - "properties": { - "entityPath": { - "type": "string" - }, - "entityType": { - "type": "string", - "enum": [ - "sr_record", - "sr_field" - ] - } - } - }, - "SchemaTags": { - "type": "object", - "properties": { - "schemaEntity": { - "$ref": "#/components/schemas/SchemaEntity" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "ExtendedSchema": { - "type": "object", - "properties": { - "subject": { - "type": "string", - "description": "Name of the subject", - "example": "User" - }, - "version": { - "type": "integer", - "description": "Version number", - "format": "int32", - "example": 1 - }, - "id": { - "type": "integer", - "description": "Globally unique identifier of the schema", - "format": "int32", - "example": 100001 - }, - "schemaType": { - "type": "string", - "description": "Schema type", - "example": "AVRO" - }, - "references": { - "type": "array", - "description": "References to other schemas", - "items": { - "$ref": "#/components/schemas/SchemaReference" - } - }, - "metadata": { - "$ref": "#/components/schemas/Metadata" - }, - "ruleset": { - "$ref": "#/components/schemas/RuleSet" - }, - "schema": { - "type": "string", - "description": "Schema definition string", - "example": "{\"schema\": \"{\"type\": \"string\"}\"}" - }, - "aliases": { - "type": "array", - "description": "Aliases for the given subject", - "items": { - "type": "string", - "description": "Aliases for the given subject" - } - }, - "ruleSet": { - "$ref": "#/components/schemas/RuleSet" - }, - "schemaTags": { - "type": "array", - "description": "Schema tags", - "items": { - "$ref": "#/components/schemas/SchemaTags" - } - } - }, - "description": "ExtendedSchema" - }, - "TagSchemaRequest": { - "type": "object", - "properties": { - "newVersion": { - "type": "integer", - "description": "The new version should be the latest version in the subject + 1. If set, the new version will be encoded to the schema metadata.", - "format": "int32" - }, - "tagsToAdd": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SchemaTags" - } - }, - "tagsToRemove": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SchemaTags" - } - }, - "metadata": { - "$ref": "#/components/schemas/Metadata" - }, - "ruleSet": { - "$ref": "#/components/schemas/RuleSet" - }, - "rulesToMerge": { - "$ref": "#/components/schemas/RuleSet" - }, - "rulesToRemove": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "description": "Schema tags register request" - } - } - } -} diff --git a/json-schema-registry/src/main/resources/schema-registry-api-spec.yaml b/json-schema-registry/src/main/resources/schema-registry-api-spec.yaml deleted file mode 100644 index 6ff22dac..00000000 --- a/json-schema-registry/src/main/resources/schema-registry-api-spec.yaml +++ /dev/null @@ -1,2770 +0,0 @@ -openapi: 3.0.1 -info: - title: Confluent Schema Registry - version: v1 -paths: - /compatibility/subjects/{subject}/versions/{version}: - post: - tags: - - Compatibility (v1) - summary: Test schema compatibility against a particular schema subject-version - description: "Test input schema against a particular version of a subject's\ - \ schema for compatibility. The compatibility level applied for the check\ - \ is the configured compatibility level for the subject (http:get:: /config/(string:\ - \ subject)). If this subject's compatibility level was never changed, then\ - \ the global compatibility level applies (http:get:: /config)." - operationId: testCompatibilityBySubjectName_1 - parameters: - - name: subject - in: path - description: Subject of the schema version against which compatibility is - to be tested - required: true - schema: - type: string - - name: version - in: path - description: "Version of the subject's schema against which compatibility\ - \ is to be tested. Valid values for versionId are between [1,2^31-1] or\ - \ the string \"latest\".\"latest\" checks compatibility of the input schema\ - \ with the last registered schema under the specified subject" - required: true - schema: - type: string - - name: normalize - in: query - description: Whether to normalize the given schema - schema: - type: boolean - - name: verbose - in: query - description: Whether to return detailed error messages - schema: - type: boolean - requestBody: - description: Schema - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/vnd.schemaregistry+json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/octet-stream: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - required: true - responses: - "200": - description: Compatibility check result. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/CompatibilityCheckResponse' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/CompatibilityCheckResponse' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/CompatibilityCheckResponse' - "404": - description: Not Found. Error code 40401 indicates subject not found. Error - code 40402 indicates version not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "422": - description: Unprocessable entity. Error code 42201 indicates an invalid - schema or schema type. Error code 42202 indicates an invalid version. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /: - get: - summary: Schema Registry Root Resource - description: The Root resource is a no-op. - operationId: get_1 - responses: - default: - content: - application/vnd.schemaregistry.v1+json: - schema: - type: string - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: string - application/json; qs=0.5: - schema: - type: string - description: Default response for get. - post: - operationId: post_1 - requestBody: - content: - application/vnd.schemaregistry.v1+json: - schema: - type: object - additionalProperties: - type: string - application/vnd.schemaregistry+json: - schema: - type: object - additionalProperties: - type: string - application/json: - schema: - type: object - additionalProperties: - type: string - application/octet-stream: - schema: - type: object - additionalProperties: - type: string - responses: - default: - description: default response - content: - application/vnd.schemaregistry.v1+json: - schema: - type: object - additionalProperties: - type: string - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: object - additionalProperties: - type: string - application/json; qs=0.5: - schema: - type: object - additionalProperties: - type: string - /compatibility/subjects/{subject}/versions: - post: - tags: - - Compatibility (v1) - summary: Test schema compatibility against all schemas under a subject - description: "Test input schema against a subject's schemas for compatibility,\ - \ based on the configured compatibility level of the subject. In other words,\ - \ it will perform the same compatibility check as register for that subject.\ - \ The compatibility level applied for the check is the configured compatibility\ - \ level for the subject (http:get:: /config/(string: subject)). If this subject's\ - \ compatibility level was never changed, then the global compatibility level\ - \ applies (http:get:: /config)." - operationId: testCompatibilityForSubject_1 - parameters: - - name: subject - in: path - description: Subject of the schema version against which compatibility is - to be tested - required: true - schema: - type: string - - name: normalize - in: query - description: Whether to normalize the given schema - schema: - type: boolean - - name: verbose - in: query - description: Whether to return detailed error messages - schema: - type: boolean - requestBody: - description: Schema - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/vnd.schemaregistry+json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/octet-stream: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - required: true - responses: - "200": - description: Compatibility check result. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/CompatibilityCheckResponse' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/CompatibilityCheckResponse' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/CompatibilityCheckResponse' - "422": - description: Unprocessable Entity. Error code 42201 indicates an invalid - schema or schema type. Error code 42202 indicates an invalid version. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /config: - get: - tags: - - Config (v1) - summary: Get global compatibility level - description: Retrieves the global compatibility level. - operationId: getTopLevelConfig_1 - responses: - "200": - description: The global compatibility level. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/Config' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/Config' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/Config' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - put: - tags: - - Config (v1) - summary: Update global compatibility level - description: "Updates the global compatibility level. On success, echoes the\ - \ original request back to the client." - operationId: updateTopLevelConfig_1 - requestBody: - description: Config Update Request - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - application/vnd.schemaregistry+json: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - application/json: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - application/octet-stream: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - required: true - responses: - "200": - description: The original request. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - "422": - description: Unprocessable Entity. Error code 42203 indicates invalid compatibility - level. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. Error code 50003 indicates a failure forwarding - the request to the primary. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - delete: - tags: - - Config (v1) - summary: Delete global compatibility level - description: Deletes the global compatibility level config and reverts to the - default. - operationId: deleteTopLevelConfig_1 - responses: - "200": - description: Operation succeeded. Returns old global compatibility level. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: string - enum: - - NONE - - BACKWARD - - BACKWARD_TRANSITIVE - - FORWARD - - FORWARD_TRANSITIVE - - FULL - - FULL_TRANSITIVE - example: FULL_TRANSITIVE - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: string - enum: - - NONE - - BACKWARD - - BACKWARD_TRANSITIVE - - FORWARD - - FORWARD_TRANSITIVE - - FULL - - FULL_TRANSITIVE - example: FULL_TRANSITIVE - application/json; qs=0.5: - schema: - type: string - enum: - - NONE - - BACKWARD - - BACKWARD_TRANSITIVE - - FORWARD - - FORWARD_TRANSITIVE - - FULL - - FULL_TRANSITIVE - example: FULL_TRANSITIVE - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /config/{subject}: - get: - tags: - - Config (v1) - summary: Get subject compatibility level - description: Retrieves compatibility level for a subject. - operationId: getSubjectLevelConfig_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - - name: defaultToGlobal - in: query - description: Whether to return the global compatibility level if subject - compatibility level not found - schema: - type: boolean - responses: - "200": - description: The subject compatibility level. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/Config' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/Config' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/Config' - "404": - description: Not Found. Error code 40401 indicates subject not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - put: - tags: - - Config (v1) - summary: Update subject compatibility level - description: "Update compatibility level for the specified subject. On success,\ - \ echoes the original request back to the client." - operationId: updateSubjectLevelConfig_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - requestBody: - description: Config Update Request - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - application/vnd.schemaregistry+json: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - application/json: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - application/octet-stream: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - required: true - responses: - "200": - description: The original request. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ConfigUpdateRequest' - "404": - description: Not Found. Error code 40401 indicates subject not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "422": - description: Unprocessable Entity. Error code 42203 indicates invalid compatibility - level. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. Error code 50003 indicates a failure forwarding - the request to the primary. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - delete: - tags: - - Config (v1) - summary: Delete subject compatibility level - description: Deletes the specified subject-level compatibility level config - and reverts to the global default. - operationId: deleteSubjectConfig_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - responses: - "200": - description: Operation succeeded. Returns old compatibility level. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: string - enum: - - NONE - - BACKWARD - - BACKWARD_TRANSITIVE - - FORWARD - - FORWARD_TRANSITIVE - - FULL - - FULL_TRANSITIVE - example: FULL_TRANSITIVE - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: string - enum: - - NONE - - BACKWARD - - BACKWARD_TRANSITIVE - - FORWARD - - FORWARD_TRANSITIVE - - FULL - - FULL_TRANSITIVE - example: FULL_TRANSITIVE - application/json; qs=0.5: - schema: - type: string - enum: - - NONE - - BACKWARD - - BACKWARD_TRANSITIVE - - FORWARD - - FORWARD_TRANSITIVE - - FULL - - FULL_TRANSITIVE - example: FULL_TRANSITIVE - "404": - description: Not Found. Error code 40401 indicates subject not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /contexts: - get: - tags: - - Contexts (v1) - summary: List contexts - description: Retrieves a list of contexts. - operationId: listContexts_1 - responses: - "200": - description: The contexts. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: array - items: - type: string - example: "." - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: array - items: - type: string - example: "." - application/json; qs=0.5: - schema: - type: array - items: - type: string - example: "." - "500": - description: 'Internal Server Error. Error code 50001 indicates a failure - in the backend data store. ' - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /mode: - get: - tags: - - Modes (v1) - summary: Get global mode - description: Retrieves global mode. - operationId: getTopLevelMode_1 - responses: - "200": - description: The global mode - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/Mode' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/Mode' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/Mode' - "500": - description: Error code 50001 -- Error in the backend data store - put: - tags: - - Modes (v1) - summary: Update global mode - description: "Update global mode. On success, echoes the original request back\ - \ to the client." - operationId: updateTopLevelMode_1 - parameters: - - name: force - in: query - description: Whether to force update if setting mode to IMPORT and schemas - currently exist - schema: - type: boolean - requestBody: - description: Update Request - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - application/vnd.schemaregistry+json: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - application/json: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - application/octet-stream: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - required: true - responses: - "200": - description: The original request. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - "422": - description: Unprocessable Entity. Error code 42204 indicates an invalid - mode. Error code 42205 indicates operation not permitted. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. Error code 50003 indicates a failure forwarding - the request to the primary. Error code 50004 indicates unknown leader. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /mode/{subject}: - get: - tags: - - Modes (v1) - summary: Get subject mode - description: Retrieves the subject mode. - operationId: getMode_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - - name: defaultToGlobal - in: query - description: Whether to return the global mode if subject mode not found - schema: - type: boolean - responses: - "200": - description: The subject mode. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/Mode' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/Mode' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/Mode' - "404": - description: Not Found. Error code 40401 indicates subject not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - put: - tags: - - Modes (v1) - summary: Update subject mode - description: "Update mode for the specified subject. On success, echoes the\ - \ original request back to the client." - operationId: updateMode_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - - name: force - in: query - description: Whether to force update if setting mode to IMPORT and schemas - currently exist - schema: - type: boolean - requestBody: - description: Update Request - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - application/vnd.schemaregistry+json: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - application/json: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - application/octet-stream: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - required: true - responses: - "200": - description: The original request. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ModeUpdateRequest' - "422": - description: Unprocessable Entity. Error code 42204 indicates an invalid - mode. Error code 42205 indicates operation not permitted. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. Error code 50003 indicates a failure forwarding - the request to the primary. Error code 50004 indicates unknown leader. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - delete: - tags: - - Modes (v1) - summary: Delete subject mode - description: Deletes the specified subject-level mode and reverts to the global - default. - operationId: deleteSubjectMode_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - responses: - "200": - description: Operation succeeded. Returns old mode. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/Mode' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/Mode' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/Mode' - "404": - description: Not Found. Error code 40401 indicates subject not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /schemas: - get: - tags: - - Schemas (v1) - summary: List schemas - description: Get the schemas matching the specified parameters. - operationId: getSchemas_1 - parameters: - - name: subjectPrefix - in: query - description: Filters results by the respective subject prefix - schema: - type: string - default: "" - - name: aliases - in: query - description: Whether to include aliases in the search - schema: - type: boolean - default: false - - name: deleted - in: query - description: Whether to return soft deleted schemas - schema: - type: boolean - default: false - - name: latestOnly - in: query - description: Whether to return latest schema versions only for each matching - subject - schema: - type: boolean - default: false - - name: ruleType - in: query - description: Filters results by the given rule type - schema: - type: string - default: "" - - name: offset - in: query - description: Pagination offset for results - schema: - type: integer - format: int32 - default: 0 - - name: limit - in: query - description: Pagination size for results. Ignored if negative - schema: - type: integer - format: int32 - default: -1 - responses: - "200": - description: List of schemas matching the specified parameters. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: array - items: - $ref: '#/components/schemas/Schema' - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: array - items: - $ref: '#/components/schemas/Schema' - application/json; qs=0.5: - schema: - type: array - items: - $ref: '#/components/schemas/Schema' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /schemas/ids/{id}: - get: - tags: - - Schemas (v1) - summary: Get schema string by ID - description: Retrieves the schema string identified by the input ID. - operationId: getSchema_1 - parameters: - - name: id - in: path - description: Globally unique identifier of the schema - required: true - schema: - type: integer - format: int32 - - name: subject - in: query - description: Name of the subject - schema: - type: string - - name: format - in: query - description: "Desired output format, dependent on schema type" - schema: - type: string - default: "" - - name: findTags - in: query - description: Find tagged entities for the given tags or * for all tags - schema: - type: array - items: - type: string - - name: fetchMaxId - in: query - description: Whether to fetch the maximum schema identifier that exists - schema: - type: boolean - default: false - responses: - "200": - description: The schema string. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/SchemaString' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/SchemaString' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/SchemaString' - "404": - description: Not Found. Error code 40403 indicates schema not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /schemas/ids/{id}/subjects: - get: - tags: - - Schemas (v1) - summary: List subjects associated to schema ID - description: Retrieves all the subjects associated with a particular schema - ID. - operationId: getSubjects_1 - parameters: - - name: id - in: path - description: Globally unique identifier of the schema - required: true - schema: - type: integer - format: int32 - - name: subject - in: query - description: Filters results by the respective subject - schema: - type: string - - name: deleted - in: query - description: Whether to include subjects where the schema was deleted - schema: - type: boolean - responses: - "200": - description: List of subjects matching the specified parameters. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: array - items: - type: string - example: User - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: array - items: - type: string - example: User - application/json; qs=0.5: - schema: - type: array - items: - type: string - example: User - "404": - description: Not Found. Error code 40403 indicates schema not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /schemas/ids/{id}/versions: - get: - tags: - - Schemas (v1) - summary: List subject-versions associated to schema ID - description: Get all the subject-version pairs associated with the input ID. - operationId: getVersions_1 - parameters: - - name: id - in: path - description: Globally unique identifier of the schema - required: true - schema: - type: integer - format: int32 - - name: subject - in: query - description: Filters results by the respective subject - schema: - type: string - - name: deleted - in: query - description: Whether to include subject versions where the schema was deleted - schema: - type: boolean - responses: - "200": - description: List of subject versions matching the specified parameters. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: array - items: - $ref: '#/components/schemas/SubjectVersion' - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: array - items: - $ref: '#/components/schemas/SubjectVersion' - application/json; qs=0.5: - schema: - type: array - items: - $ref: '#/components/schemas/SubjectVersion' - "404": - description: Not Found. Error code 40403 indicates schema not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /schemas/types: - get: - tags: - - Schemas (v1) - summary: List supported schema types - description: Retrieve the schema types supported by this registry. - operationId: getSchemaTypes_1 - responses: - "200": - description: List of supported schema types. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: array - items: - type: string - example: AVRO - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: array - items: - type: string - example: AVRO - application/json; qs=0.5: - schema: - type: array - items: - type: string - example: AVRO - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /subjects: - get: - tags: - - Subjects (v1) - summary: List subjects - description: Retrieves a list of registered subjects matching specified parameters. - operationId: list_1 - parameters: - - name: subjectPrefix - in: query - description: Subject name prefix - schema: - type: string - default: ':*:' - - name: deleted - in: query - description: Whether to look up deleted subjects - schema: - type: boolean - - name: deletedOnly - in: query - description: Whether to return deleted subjects only - schema: - type: boolean - responses: - "200": - description: List of subjects matching the specified parameters. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: array - items: - type: string - example: User - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: array - items: - type: string - example: User - application/json; qs=0.5: - schema: - type: array - items: - type: string - example: User - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /subjects/{subject}: - post: - tags: - - Subjects (v1) - summary: Lookup schema under subject - description: "Check if a schema has already been registered under the specified\ - \ subject. If so, this returns the schema string along with its globally unique\ - \ identifier, its version under this subject and the subject name." - operationId: lookUpSchemaUnderSubject_1 - parameters: - - name: subject - in: path - description: Subject under which the schema will be registered - required: true - schema: - type: string - - name: normalize - in: query - description: Whether to normalize the given schema - schema: - type: boolean - - name: format - in: query - description: "Desired output format, dependent on schema type" - schema: - type: string - default: "" - - name: deleted - in: query - description: Whether to lookup deleted schemas - schema: - type: boolean - requestBody: - description: Schema - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/vnd.schemaregistry+json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/octet-stream: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - required: true - responses: - "200": - description: The schema. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/Schema' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/Schema' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/Schema' - "404": - description: Not Found. Error code 40401 indicates subject not found. Error - code 40403 indicates schema not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - delete: - tags: - - Subjects (v1) - summary: Delete subject - description: Deletes the specified subject and its associated compatibility - level if registered. It is recommended to use this API only when a topic needs - to be recycled or in development environment. - operationId: deleteSubject_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - - name: permanent - in: query - description: Whether to perform a permanent delete - schema: - type: boolean - responses: - "200": - description: Operation succeeded. Returns list of schema versions deleted - content: - application/vnd.schemaregistry.v1+json: - schema: - type: array - items: - type: integer - format: int32 - example: 1 - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: array - items: - type: integer - format: int32 - example: 1 - application/json; qs=0.5: - schema: - type: array - items: - type: integer - format: int32 - example: 1 - "404": - description: Not Found. Error code 40401 indicates subject not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /subjects/{subject}/versions: - get: - tags: - - Subjects (v1) - summary: List versions under subject - description: Retrieves a list of versions registered under the specified subject. - operationId: listVersions_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - - name: deleted - in: query - description: Whether to include deleted schemas - schema: - type: boolean - - name: deletedOnly - in: query - description: Whether to return deleted schemas only - schema: - type: boolean - responses: - "200": - description: List of version numbers matching the specified parameters. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: array - items: - type: integer - format: int32 - example: 1 - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: array - items: - type: integer - format: int32 - example: 1 - application/json; qs=0.5: - schema: - type: array - items: - type: integer - format: int32 - example: 1 - "404": - description: 'Not Found. Error code 40401 indicates subject not found. ' - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - post: - tags: - - Subjects (v1) - summary: Register schema under a subject - description: |- - Register a new schema under the specified subject. If successfully registered, this returns the unique identifier of this schema in the registry. The returned identifier should be used to retrieve this schema from the schemas resource and is different from the schema's version which is associated with the subject. If the same schema is registered under a different subject, the same identifier will be returned. However, the version of the schema may be different under different subjects. - A schema should be compatible with the previously registered schema or schemas (if there are any) as per the configured compatibility level. The configured compatibility level can be obtained by issuing a GET http:get:: /config/(string: subject). If that returns null, then GET http:get:: /config - When there are multiple instances of Schema Registry running in the same cluster, the schema registration request will be forwarded to one of the instances designated as the primary. If the primary is not available, the client will get an error code indicating that the forwarding has failed. - operationId: register_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - - name: normalize - in: query - description: Whether to normalize the given schema - schema: - type: boolean - - name: format - in: query - description: "Desired output format, dependent on schema type" - schema: - type: string - default: "" - requestBody: - description: Schema - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/vnd.schemaregistry+json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/json: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - application/octet-stream: - schema: - $ref: '#/components/schemas/RegisterSchemaRequest' - required: true - responses: - "200": - description: Schema successfully registered. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/RegisterSchemaResponse' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/RegisterSchemaResponse' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/RegisterSchemaResponse' - "409": - description: Conflict. Incompatible schema. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "422": - description: 'Unprocessable entity. Error code 42201 indicates an invalid - schema or schema type. ' - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store.Error code 50002 indicates operation timed out. - Error code 50003 indicates a failure forwarding the request to the primary. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /subjects/{subject}/versions/{version}: - get: - tags: - - Subjects (v1) - summary: Get schema by version - description: Retrieves a specific version of the schema registered under this - subject. - operationId: getSchemaByVersion_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - - name: version - in: path - description: "Version of the schema to be returned. Valid values for versionId\ - \ are between [1,2^31-1] or the string \"latest\". \"latest\" returns the\ - \ last registered schema under the specified subject. Note that there may\ - \ be a new latest schema that gets registered right after this request is\ - \ served." - required: true - schema: - type: string - - name: format - in: query - description: "Desired output format, dependent on schema type" - schema: - type: string - default: "" - - name: deleted - in: query - description: Whether to include deleted schema - schema: - type: boolean - - name: findTags - in: query - description: Find tagged entities for the given tags or * for all tags - schema: - type: array - items: - type: string - responses: - "200": - description: The schema. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/Schema' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/Schema' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/Schema' - "404": - description: Not Found. Error code 40401 indicates subject not found. Error - code 40402 indicates version not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "422": - description: Unprocessable Entity. Error code 42202 indicates an invalid - version. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - delete: - tags: - - Subjects (v1) - summary: Delete schema version - description: "Deletes a specific version of the schema registered under this\ - \ subject. This only deletes the version and the schema ID remains intact\ - \ making it still possible to decode data using the schema ID. This API is\ - \ recommended to be used only in development environments or under extreme\ - \ circumstances where-in, its required to delete a previously registered schema\ - \ for compatibility purposes or re-register previously registered schema." - operationId: deleteSchemaVersion_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - - name: version - in: path - description: "Version of the schema to be returned. Valid values for versionId\ - \ are between [1,2^31-1] or the string \"latest\". \"latest\" returns the\ - \ last registered schema under the specified subject. Note that there may\ - \ be a new latest schema that gets registered right after this request is\ - \ served." - required: true - schema: - type: string - - name: permanent - in: query - description: Whether to perform a permanent delete - schema: - type: boolean - responses: - "200": - description: Operation succeeded. Returns the schema version. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: integer - format: int32 - example: 1 - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: integer - format: int32 - example: 1 - application/json; qs=0.5: - schema: - type: integer - format: int32 - example: 1 - "404": - description: Not Found. Error code 40401 indicates subject not found. Error - code 40402 indicates version not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "422": - description: Unprocessable Entity. Error code 42202 indicates an invalid - version. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /subjects/{subject}/versions/{version}/referencedby: - get: - tags: - - Subjects (v1) - summary: List schemas referencing a schema - description: Retrieves the IDs of schemas that reference the specified schema. - operationId: getReferencedBy_1 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - - name: version - in: path - description: "Version of the schema to be returned. Valid values for versionId\ - \ are between [1,2^31-1] or the string \"latest\". \"latest\" returns the\ - \ last registered schema under the specified subject. Note that there may\ - \ be a new latest schema that gets registered right after this request is\ - \ served." - required: true - schema: - type: string - responses: - "200": - description: List of IDs for schemas that reference the specified schema. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: array - items: - type: integer - format: int32 - example: 100001 - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: array - items: - type: integer - format: int32 - example: 100001 - application/json; qs=0.5: - schema: - type: array - items: - type: integer - format: int32 - example: 100001 - "404": - description: Not Found. Error code 40401 indicates subject not found. Error - code 40402 indicates version not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "422": - description: Unprocessable Entity. Error code 42202 indicates an invalid - version. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /subjects/{subject}/versions/{version}/schema: - get: - tags: - - Subjects (v1) - summary: Get schema string by version - description: Retrieves the schema for the specified version of this subject. - Only the unescaped schema string is returned. - operationId: getSchemaOnly_2 - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - - name: version - in: path - description: "Version of the schema to be returned. Valid values for versionId\ - \ are between [1,2^31-1] or the string \"latest\". \"latest\" returns the\ - \ last registered schema under the specified subject. Note that there may\ - \ be a new latest schema that gets registered right after this request is\ - \ served." - required: true - schema: - type: string - - name: format - in: query - description: "Desired output format, dependent on schema type" - schema: - type: string - default: "" - - name: deleted - in: query - description: Whether to include deleted schema - schema: - type: boolean - responses: - "200": - description: The schema string. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: string - example: "{\"schema\": \"{\"type\": \"string\"}\"}" - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: string - example: "{\"schema\": \"{\"type\": \"string\"}\"}" - application/json; qs=0.5: - schema: - type: string - example: "{\"schema\": \"{\"type\": \"string\"}\"}" - "404": - description: Not Found. Error code 40401 indicates subject not found. Error - code 40402 indicates version not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "422": - description: Unprocessable Entity. Error code 42202 indicates an invalid - version. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /v1/metadata/id: - get: - tags: - - Server Metadata (v1) - summary: Get the server metadata - operationId: getClusterId_1 - responses: - "500": - description: | - Error code 50001 -- Error in the backend data store - /schemas/ids/{id}/schema: - get: - tags: - - Schemas (v1) - summary: Get schema by ID - description: Retrieves the schema identified by the input ID. - operationId: getSchemaOnly - parameters: - - name: id - in: path - description: Globally unique identifier of the schema - required: true - schema: - type: integer - format: int32 - - name: subject - in: query - description: Name of the subject - schema: - type: string - - name: format - in: query - description: "Desired output format, dependent on schema type" - schema: - type: string - default: "" - responses: - "200": - description: Raw schema string. - content: - application/vnd.schemaregistry.v1+json: - schema: - type: string - example: "{\"schema\": \"{\"type\": \"string\"}\"}" - application/vnd.schemaregistry+json; qs=0.9: - schema: - type: string - example: "{\"schema\": \"{\"type\": \"string\"}\"}" - application/json; qs=0.5: - schema: - type: string - example: "{\"schema\": \"{\"type\": \"string\"}\"}" - "404": - description: Not Found. Error code 40403 indicates schema not found. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - /v1/metadata/version: - get: - tags: - - Server Metadata (v1) - summary: Get Schema Registry server version - operationId: getSchemaRegistryVersion_1 - responses: - "500": - description: | - Error code 50001 -- Error in the backend data store - /subjects/{subject}/metadata: - get: - summary: Retrieve the latest version with the given metadata. - description: Retrieve the latest version with the given metadata. - operationId: getLatestWithMetadata_1 - parameters: - - name: subject - in: path - description: Subject under which the schema will be registered - required: true - schema: - type: string - - name: key - in: query - description: The metadata key - schema: - type: array - items: - type: string - - name: value - in: query - description: The metadata value - schema: - type: array - items: - type: string - - name: format - in: query - description: "Desired output format, dependent on schema type" - schema: - type: string - default: "" - - name: deleted - in: query - description: Whether to lookup deleted schemas - schema: - type: boolean - responses: - "200": - description: The schema - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/Schema' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/Schema' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/Schema' - "404": - description: |- - Error code 40401 -- Subject not found - Error code 40403 -- Schema not found - "500": - description: Internal server error - /subjects/{subject}/versions/{version}/tags: - post: - tags: - - Subjects (v1) - summary: Create or remove schema embedded tags for a subject version - description: "Create new schema subject version with the provided field or record\ - \ level schema tags embedded (or remove) in the schema string, as well as\ - \ the given metadata and ruleset." - operationId: modifyTags - parameters: - - name: subject - in: path - description: Name of the subject - required: true - schema: - type: string - - name: version - in: path - description: "Version of the schema to be returned. Valid values for versionId\ - \ are between [1,2^31-1] or the string \"latest\". \"latest\" returns the\ - \ last registered schema under the specified subject. Note that there may\ - \ be a new latest schema that gets registered right after this request is\ - \ served." - required: true - schema: - type: string - requestBody: - description: Tag schema request - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/TagSchemaRequest' - application/vnd.schemaregistry+json: - schema: - $ref: '#/components/schemas/TagSchemaRequest' - application/json: - schema: - $ref: '#/components/schemas/TagSchemaRequest' - application/octet-stream: - schema: - $ref: '#/components/schemas/TagSchemaRequest' - required: true - responses: - "200": - description: Schema successfully registered. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/RegisterSchemaResponse' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/RegisterSchemaResponse' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/RegisterSchemaResponse' - "409": - description: Conflict. Incompatible schema. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "422": - description: 'Unprocessable entity. Error code 42201 indicates an invalid - schema or schema type. ' - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' - "500": - description: Internal Server Error. Error code 50001 indicates a failure - in the backend data store.Error code 50002 indicates operation timed out. - Error code 50003 indicates a failure forwarding the request to the primary. - content: - application/vnd.schemaregistry.v1+json: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/vnd.schemaregistry+json; qs=0.9: - schema: - $ref: '#/components/schemas/ErrorMessage' - application/json; qs=0.5: - schema: - $ref: '#/components/schemas/ErrorMessage' -components: - schemas: - CompatibilityCheckResponse: - type: object - properties: - is_compatible: - type: boolean - description: Whether the compared schemas are compatible - messages: - type: array - description: Error messages - example: [] - items: - type: string - description: Error messages - example: "[]" - description: Compatibility check response - RegisterSchemaRequest: - type: object - properties: - version: - type: integer - description: Version number - format: int32 - id: - type: integer - description: Globally unique identifier of the schema - format: int32 - schemaType: - type: string - description: Schema type - references: - type: array - description: References to other schemas - items: - $ref: '#/components/schemas/SchemaReference' - metadata: - $ref: '#/components/schemas/Metadata' - ruleSet: - $ref: '#/components/schemas/RuleSet' - schema: - type: string - description: Schema definition string - schemaTagsToAdd: - type: array - items: - $ref: '#/components/schemas/SchemaTags' - schemaTagsToRemove: - type: array - items: - $ref: '#/components/schemas/SchemaTags' - propagateSchemaTags: - type: boolean - description: Schema register request - SchemaReference: - type: object - properties: - name: - type: string - description: Reference name - example: io.confluent.kafka.example.User - subject: - type: string - description: Name of the referenced subject - example: User - version: - type: integer - description: Version number of the referenced subject - format: int32 - example: 1 - description: Schema reference - Config: - type: object - properties: - compatibilityLevel: - type: string - description: Compatibility Level - example: FULL_TRANSITIVE - enum: - - BACKWARD - - BACKWARD_TRANSITIVE - - FORWARD - - FORWARD_TRANSITIVE - - FULL - - FULL_TRANSITIVE - - NONE - alias: - type: string - normalize: - type: boolean - validateFields: - type: boolean - validateRules: - type: boolean - compatibilityGroup: - type: string - defaultMetadata: - $ref: '#/components/schemas/Metadata' - overrideMetadata: - $ref: '#/components/schemas/Metadata' - defaultRuleSet: - $ref: '#/components/schemas/RuleSet' - overrideRuleSet: - $ref: '#/components/schemas/RuleSet' - description: Config - ConfigUpdateRequest: - type: object - properties: - alias: - type: string - normalize: - type: boolean - validateFields: - type: boolean - validateRules: - type: boolean - compatibility: - type: string - description: Compatibility Level - example: FULL_TRANSITIVE - enum: - - BACKWARD - - BACKWARD_TRANSITIVE - - FORWARD - - FORWARD_TRANSITIVE - - FULL - - FULL_TRANSITIVE - - NONE - compatibilityGroup: - type: string - defaultMetadata: - $ref: '#/components/schemas/Metadata' - overrideMetadata: - $ref: '#/components/schemas/Metadata' - defaultRuleSet: - $ref: '#/components/schemas/RuleSet' - overrideRuleSet: - $ref: '#/components/schemas/RuleSet' - description: Config update request - Mode: - type: object - properties: - mode: - type: string - description: Schema Registry operating mode - example: READWRITE - enum: - - READWRITE - - READONLY - - READONLY_OVERRIDE - - IMPORT - description: Schema Registry operating mode - ModeUpdateRequest: - type: object - properties: - mode: - type: string - description: Schema Registry operating mode - example: READWRITE - enum: - - READWRITE - - READONLY - - READONLY_OVERRIDE - - IMPORT - description: Mode update request - SchemaString: - type: object - properties: - schemaType: - type: string - description: Schema type - example: AVRO - schema: - type: string - description: Schema string identified by the ID - example: "{\"schema\": \"{\"type\": \"string\"}\"}" - references: - type: array - description: References to other schemas - items: - $ref: '#/components/schemas/SchemaReference' - metadata: - $ref: '#/components/schemas/Metadata' - ruleSet: - $ref: '#/components/schemas/RuleSet' - schemaTags: - type: array - description: Schema tags - items: - $ref: '#/components/schemas/SchemaTags' - maxId: - type: integer - description: Maximum ID - format: int32 - example: 1 - description: Schema definition - Schema: - type: object - properties: - subject: - type: string - description: Name of the subject - example: User - version: - type: integer - description: Version number - format: int32 - example: 1 - id: - type: integer - description: Globally unique identifier of the schema - format: int32 - example: 100001 - schemaType: - type: string - description: Schema type - example: AVRO - references: - type: array - description: References to other schemas - items: - $ref: '#/components/schemas/SchemaReference' - metadata: - $ref: '#/components/schemas/Metadata' - ruleset: - $ref: '#/components/schemas/RuleSet' - schema: - type: string - description: Schema definition string - example: "{\"schema\": \"{\"type\": \"string\"}\"}" - schemaTags: - type: array - description: Schema tags - items: - $ref: '#/components/schemas/SchemaTags' - ruleSet: - $ref: '#/components/schemas/RuleSet' - description: Schema - SubjectVersion: - type: object - properties: - subject: - type: string - description: Name of the subject - example: User - version: - type: integer - description: Version number - format: int32 - example: 1 - description: Subject version pair - ServerClusterId: - type: object - properties: - scope: - type: object - additionalProperties: - type: object - id: - type: string - RegisterSchemaResponse: - type: object - properties: - id: - type: integer - description: Globally unique identifier of the schema - format: int32 - example: 100001 - version: - type: integer - description: Version number - format: int32 - schemaType: - type: string - description: Schema type - references: - type: array - description: References to other schemas - items: - $ref: '#/components/schemas/SchemaReference' - metadata: - $ref: '#/components/schemas/Metadata' - ruleSet: - $ref: '#/components/schemas/RuleSet' - schema: - type: string - description: Schema definition string - description: Schema register response - ErrorMessage: - type: object - properties: - error_code: - type: integer - description: Error code - format: int32 - message: - type: string - description: Detailed error message - description: Error message - SchemaRegistryServerVersion: - type: object - properties: - version: - type: string - commitId: - type: string - Metadata: - type: object - properties: - tags: - type: object - additionalProperties: - uniqueItems: true - type: array - items: - type: string - properties: - type: object - additionalProperties: - type: string - sensitive: - uniqueItems: true - type: array - items: - type: string - description: User-defined metadata - Rule: - type: object - properties: - name: - type: string - description: Rule name - doc: - type: string - description: Rule doc - kind: - type: string - description: Rule kind - enum: - - TRANSFORM - - CONDITION - mode: - type: string - description: Rule mode - enum: - - UPGRADE - - DOWNGRADE - - UPDOWN - - WRITE - - READ - - WRITEREAD - type: - type: string - description: Rule type - tags: - uniqueItems: true - type: array - description: The tags to which this rule applies - items: - type: string - description: The tags to which this rule applies - params: - type: object - additionalProperties: - type: string - description: Optional params for the rule - description: Optional params for the rule - expr: - type: string - description: Rule expression - onSuccess: - type: string - description: Rule action on success - onFailure: - type: string - description: Rule action on failure - disabled: - type: boolean - description: Whether the rule is disabled - description: Rule - RuleSet: - type: object - properties: - migrationRules: - type: array - items: - $ref: '#/components/schemas/Rule' - domainRules: - type: array - items: - $ref: '#/components/schemas/Rule' - description: Schema rule set - SchemaEntity: - type: object - properties: - entityPath: - type: string - entityType: - type: string - enum: - - sr_record - - sr_field - SchemaTags: - type: object - properties: - schemaEntity: - $ref: '#/components/schemas/SchemaEntity' - tags: - type: array - items: - type: string - ExtendedSchema: - type: object - properties: - subject: - type: string - description: Name of the subject - example: User - version: - type: integer - description: Version number - format: int32 - example: 1 - id: - type: integer - description: Globally unique identifier of the schema - format: int32 - example: 100001 - schemaType: - type: string - description: Schema type - example: AVRO - references: - type: array - description: References to other schemas - items: - $ref: '#/components/schemas/SchemaReference' - metadata: - $ref: '#/components/schemas/Metadata' - ruleset: - $ref: '#/components/schemas/RuleSet' - schema: - type: string - description: Schema definition string - example: "{\"schema\": \"{\"type\": \"string\"}\"}" - aliases: - type: array - description: Aliases for the given subject - items: - type: string - description: Aliases for the given subject - ruleSet: - $ref: '#/components/schemas/RuleSet' - schemaTags: - type: array - description: Schema tags - items: - $ref: '#/components/schemas/SchemaTags' - description: ExtendedSchema - TagSchemaRequest: - type: object - properties: - newVersion: - type: integer - description: "The new version should be the latest version in the subject\ - \ + 1. If set, the new version will be encoded to the schema metadata." - format: int32 - tagsToAdd: - type: array - items: - $ref: '#/components/schemas/SchemaTags' - tagsToRemove: - type: array - items: - $ref: '#/components/schemas/SchemaTags' - metadata: - $ref: '#/components/schemas/Metadata' - ruleSet: - $ref: '#/components/schemas/RuleSet' - rulesToMerge: - $ref: '#/components/schemas/RuleSet' - rulesToRemove: - type: array - items: - type: string - description: Schema tags register request diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java new file mode 100644 index 00000000..ec30272e --- /dev/null +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -0,0 +1,40 @@ +package io.micronaut.jsonschema.registry; + +import io.micronaut.http.HttpRequest; +import io.micronaut.http.client.HttpClient; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.http.uri.UriBuilder; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import org.junit.jupiter.api.Test; + +import jakarta.inject.Inject; + +import java.net.URI; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@MicronautTest +public class ConfluentClientTest { + + @Inject + @Client("http://144.24.55.159:8081") + HttpClient client; // (2) + + @Test + void testConfluentResponse() { + String subject = "human"; + String version = "latest"; + URI url = UriBuilder.of("/subjects") + .path(subject) + .path("versions") + .path(version) + .build(); + + HttpRequest request = HttpRequest.GET(url); + // .header("Content-Type", "application/vnd.schemaregistry.v1+json"); + + String response = client.toBlocking().retrieve(request); + assertEquals(""" + {"subject":"human","version":1,"id":2,"schemaType":"JSON","schema":"{\\"$schema\\":\\"http://json-schema.org/draft-07/schema#\\",\\"type\\":\\"object\\",\\"properties\\":{\\"name\\":{\\"type\\":\\"string\\"}}}"}""", response); + } +} From 41337bbcc8c8acd32abbab6a83acd8d83fd26a7d Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Thu, 6 Feb 2025 14:56:08 +0100 Subject: [PATCH 05/24] clean up interface --- json-schema-registry/build.gradle | 2 +- .../registry/SchemaRegistryClient.java | 152 +++++++++--------- .../registry/SchemaRegistryService.java | 14 -- .../registry/ConfluentClientTest.java | 47 +++--- .../src/test/resources/human.schema.json | 7 + 5 files changed, 108 insertions(+), 114 deletions(-) create mode 100644 json-schema-registry/src/test/resources/human.schema.json diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle index f6519677..e4936538 100644 --- a/json-schema-registry/build.gradle +++ b/json-schema-registry/build.gradle @@ -6,11 +6,11 @@ dependencies { compileOnly(mn.micronaut.core.processor) implementation(mn.micronaut.http) implementation(mn.micronaut.http.client) + implementation(mn.micronaut.jackson.databind) api(mn.micronaut.inject) testAnnotationProcessor(mn.micronaut.inject.java) testImplementation(mn.micronaut.inject) - testImplementation(mn.micronaut.jackson.databind) testImplementation(mnValidation.validation) testImplementation(mnTest.micronaut.test.junit5) testImplementation(libs.junit.jupiter.api) diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 3c1fe9d7..4d0273b8 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -15,125 +15,119 @@ */ package io.micronaut.jsonschema.registry; -import io.micronaut.context.annotation.Value; +import com.fasterxml.jackson.core.JsonProcessingException; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; -import io.micronaut.http.MediaType; import io.micronaut.http.client.HttpClient; import io.micronaut.http.client.annotation.Client; import io.micronaut.http.uri.UriBuilder; +import com.fasterxml.jackson.databind.json.JsonMapper; import jakarta.inject.Singleton; import java.net.URI; -import java.util.Map; +import java.util.HashMap; +/** + * A client for the Confluent Schema Registry. + * + * @author Elif Kurtay + * @since 1.5.0 + */ @Singleton public class SchemaRegistryClient { private static final String HEADER_NAME = "Content-Type"; private static final String HEADER_VALUE = "application/vnd.schemaregistry.v1+json"; - private final HttpClient httpClient; + private final HttpClient client; + private JsonMapper jsonMapper; - @Value("${schema_registry.url}") - private String schemaRegistryUrl; + //@Property(name="schema_registry.url") + protected String schemaRegistryUrl = "http://144.24.55.159:8081"; - public SchemaRegistryClient(@Client("/") HttpClient httpClient) { - this.httpClient = httpClient; + public SchemaRegistryClient(@Client() HttpClient httpClient) { + this.client = httpClient; + this.jsonMapper = new JsonMapper(); } /** - * Register a schema with the schema registry for a given subject. + * SCHEMAS ----------------------------------------------------------- + * TODO: + * - GET /schemas/ids/{int: id} + * - GET /schemas/ids/{int: id}/schema + * - GET /schemas/types/ + * - GET /schemas/ids/{int: id}/versions + */ + + /** + * SUBJECTS ----------------------------------------------------------- + * TODO: + * - GET /subjects + * - GET /subjects/(string: subject)/versions + * - DELETE /subjects/(string: subject) + * + GET /subjects/(string: subject)/versions/(versionId: version) + * - GET /subjects/(string: subject)/versions/(versionId: version)/schema + * - POST /subjects/(string: subject)/versions + * - POST /subjects/(string: subject) + * - DELETE /subjects/(string: subject)/versions/(versionId: version) + * - GET /subjects/(string: subject)/versions/{versionId: version}/referencedby + * - GET /subjects/(string: subject)/metadata + */ + + /** + * Get a specific version of the schema registered under this subject. * * @param subject The subject (topic name, e.g., user-data) - * @param schema The Avro/JSON schema as a string - * @return The ID of the registered schema + * @param version The version number or 'latest' as a string + * @return The requested schema */ - public int registerSchema(String subject, String schema) { + public String getWithSubjectAndVersion(String subject, String version) { URI url = UriBuilder.of(schemaRegistryUrl) .path("subjects") .path(subject) .path("versions") + .path(version) .build(); - Map body = Map.of("schema", schema); - - HttpRequest> request = HttpRequest.POST(url, body) - .header(HEADER_NAME, HEADER_VALUE) - .contentType(MediaType.APPLICATION_JSON); - - HttpResponse response = httpClient.toBlocking().exchange(request, Map.class); + HttpRequest request = HttpRequest.GET(url); + HttpResponse response = client.toBlocking().exchange(request, String.class); if (response.getStatus().getCode() == 200) { - Map responseBody = response.body(); - return (Integer) responseBody.get("id"); + try { + HashMap HashMappedResponse = jsonMapper.readValue(response.body(), HashMap.class); + return HashMappedResponse.get("schema").toString(); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } } else { throw new RuntimeException("Error registering schema: " + response.getStatus()); } } /** - * Get a schema for a given subject and version. - * - * @param subject The subject (e.g., user-data) - * @param version The version of the schema to retrieve (e.g., 1, 2, etc.) - * @return The schema in JSON format + * MODE ----------------------------------------------------------- + * TODO: + * - GET /mode + * - PUT /mode + * - GET /mode/(string: subject) + * - PUT /mode/(string: subject) + * - DELETE /mode/(string: subject) */ - public String getSchema(String subject, int version) { - String url = schemaRegistryUrl + "/subjects/" + subject + "/versions/" + version; - - HttpRequest request = HttpRequest.GET(url) - .contentType(MediaType.APPLICATION_JSON); - - HttpResponse response = httpClient.toBlocking().exchange(request, Map.class); - - if (response.getStatus().getCode() == 200) { - Map responseBody = response.body(); - return (String) responseBody.get("schema"); - } else { - throw new RuntimeException("Error retrieving schema: " + response.getStatus()); - } - } /** - * Check if a schema is compatible with the latest schema for a given subject. - * - * @param subject The subject (e.g., user-data) - * @param schema The Avro/JSON schema as a string - * @return true if the schema is compatible, false otherwise + * COMPATIBILITY ----------------------------------------------------------- + * TODO: + * - POST /compatibility/subjects/(string: subject)/versions/(versionId: version) + * - POST /compatibility/subjects/(string: subject)/versions */ - public boolean checkCompatibility(String subject, String schema) { - String url = schemaRegistryUrl + "/compatibility/subjects/" + subject + "/versions/latest"; - - Map body = Map.of("schema", schema); - - HttpRequest> request = HttpRequest.POST(url, body) - .contentType(MediaType.APPLICATION_JSON); - - HttpResponse response = httpClient.toBlocking().exchange(request, Map.class); - - if (response.getStatus().getCode() == 200) { - Map responseBody = response.body(); - // Assuming response contains "is_compatible" field - return (Boolean) responseBody.get("is_compatible"); - } else { - throw new RuntimeException("Error checking compatibility: " + response.getStatus()); - } - } - public void deleteSchema(String subject) { - // Delete the schema - } - - public void deleteSchemaVersion(String subject, int version) { - // Delete the schema version - } - - public void deleteAllVersions(String subject) { - // Delete all versions of the schema - } - - public void deleteAllSubjects() { - // Delete all subjects - } + /** + * CONFIG ----------------------------------------------------------- + * TODO: + * - PUT /config + * - GET /config + * - PUT /config/(string: subject) + * - GET /config/(string: subject) + * - DELETE /config/(string: subject) + */ } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryService.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryService.java index 7fc3af65..56c40106 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryService.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryService.java @@ -24,18 +24,4 @@ public class SchemaRegistryService { public SchemaRegistryService(SchemaRegistryClient schemaRegistryClient) { this.schemaRegistryClient = schemaRegistryClient; } - -// public void registerSchema(String subject, String schema) { -// int schemaId = schemaRegistryClient.registerSchema(subject, schema); -// System.out.println("Registered schema with ID: " + schemaId); -// } -// -// public String getSchema(String subject, int version) { -// return schemaRegistryClient.getSchema(subject, version); -// } -// -// public boolean checkSchemaCompatibility(String subject, String schema) { -// return schemaRegistryClient.checkCompatibility(subject, schema); -// } - } diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index ec30272e..0c0c358c 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -1,40 +1,47 @@ package io.micronaut.jsonschema.registry; -import io.micronaut.http.HttpRequest; -import io.micronaut.http.client.HttpClient; -import io.micronaut.http.client.annotation.Client; -import io.micronaut.http.uri.UriBuilder; +import com.fasterxml.jackson.databind.json.JsonMapper; +import io.micronaut.core.io.ResourceLoader; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; import jakarta.inject.Inject; -import java.net.URI; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Optional; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; @MicronautTest public class ConfluentClientTest { @Inject - @Client("http://144.24.55.159:8081") - HttpClient client; // (2) + ResourceLoader resourceLoader; + + @Inject + SchemaRegistryClient schemaRegistryClient; + + JsonMapper jsonMapper = new JsonMapper(); @Test - void testConfluentResponse() { + void testSchemaRegistryClient() throws IOException { String subject = "human"; String version = "latest"; - URI url = UriBuilder.of("/subjects") - .path(subject) - .path("versions") - .path(version) - .build(); - - HttpRequest request = HttpRequest.GET(url); - // .header("Content-Type", "application/vnd.schemaregistry.v1+json"); - - String response = client.toBlocking().retrieve(request); - assertEquals(""" - {"subject":"human","version":1,"id":2,"schemaType":"JSON","schema":"{\\"$schema\\":\\"http://json-schema.org/draft-07/schema#\\",\\"type\\":\\"object\\",\\"properties\\":{\\"name\\":{\\"type\\":\\"string\\"}}}"}""", response); + String schema = schemaRegistryClient.getWithSubjectAndVersion(subject, version); + + String expected = getExpectedResponse("human.schema.json"); + Map mappedExpected = jsonMapper.readValue(expected, Map.class); + assertEquals(mappedExpected.get("schema").toString(), schema); + } + + private String getExpectedResponse(String filename) throws IOException { + Optional expectedOptional = resourceLoader.getResourceAsStream(filename); + assertTrue(expectedOptional.isPresent()); + String expected = new String(expectedOptional.get().readAllBytes(), StandardCharsets.UTF_8); + return expected.replaceAll("\\s+", "").trim(); } } diff --git a/json-schema-registry/src/test/resources/human.schema.json b/json-schema-registry/src/test/resources/human.schema.json new file mode 100644 index 00000000..ceeede55 --- /dev/null +++ b/json-schema-registry/src/test/resources/human.schema.json @@ -0,0 +1,7 @@ +{ + "subject": "human", + "version": 1, + "id": 2, + "schemaType": "JSON", + "schema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\"}}}" +} From 8a06409356c76cfa4d8a4f5752205f4bf1d18ddc Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Thu, 6 Feb 2025 17:43:00 +0100 Subject: [PATCH 06/24] configuration properties added --- json-schema-registry/build.gradle | 4 +- .../registry/SchemaRegistryClient.java | 10 ++--- .../registry/SchemaRegistryConfig.java | 45 +++++++++++++++++++ .../src/main/resources/application.properties | 3 ++ .../src/main/resources/application.yml | 4 -- .../registry/ConfluentClientTest.java | 12 +++-- 6 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java create mode 100644 json-schema-registry/src/main/resources/application.properties delete mode 100644 json-schema-registry/src/main/resources/application.yml diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle index e4936538..aa9a09a1 100644 --- a/json-schema-registry/build.gradle +++ b/json-schema-registry/build.gradle @@ -7,11 +7,13 @@ dependencies { implementation(mn.micronaut.http) implementation(mn.micronaut.http.client) implementation(mn.micronaut.jackson.databind) + implementation(mnSerde.micronaut.serde.jackson) + implementation(mnValidation.validation) + api(mn.micronaut.inject) testAnnotationProcessor(mn.micronaut.inject.java) testImplementation(mn.micronaut.inject) - testImplementation(mnValidation.validation) testImplementation(mnTest.micronaut.test.junit5) testImplementation(libs.junit.jupiter.api) testRuntimeOnly(libs.junit.jupiter.engine) diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 4d0273b8..6835d978 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -16,6 +16,7 @@ package io.micronaut.jsonschema.registry; import com.fasterxml.jackson.core.JsonProcessingException; +import io.micronaut.context.annotation.Property; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; import io.micronaut.http.client.HttpClient; @@ -39,13 +40,12 @@ public class SchemaRegistryClient { private static final String HEADER_NAME = "Content-Type"; private static final String HEADER_VALUE = "application/vnd.schemaregistry.v1+json"; + private final SchemaRegistryConfig config; private final HttpClient client; private JsonMapper jsonMapper; - //@Property(name="schema_registry.url") - protected String schemaRegistryUrl = "http://144.24.55.159:8081"; - - public SchemaRegistryClient(@Client() HttpClient httpClient) { + public SchemaRegistryClient(SchemaRegistryConfig config, @Client HttpClient httpClient) { + this.config = config; this.client = httpClient; this.jsonMapper = new JsonMapper(); } @@ -82,7 +82,7 @@ public SchemaRegistryClient(@Client() HttpClient httpClient) { * @return The requested schema */ public String getWithSubjectAndVersion(String subject, String version) { - URI url = UriBuilder.of(schemaRegistryUrl) + URI url = UriBuilder.of(config.getUrl()) .path("subjects") .path(subject) .path("versions") diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java new file mode 100644 index 00000000..33b08674 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -0,0 +1,45 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry; + +import io.micronaut.context.annotation.ConfigurationProperties; +import io.micronaut.context.annotation.Parameter; +import io.micronaut.serde.annotation.Serdeable; +import jakarta.validation.constraints.NotBlank; + +@Serdeable +@ConfigurationProperties("registry") +public class SchemaRegistryConfig { + @NotBlank + private String url; + + public SchemaRegistryConfig() { + } + + public SchemaRegistryConfig(@Parameter String url) { + if (url != null) { + this.url = url; + } + } + + public String getUrl() { + return url; + } + + public void setUrl(String schemaRegistryUrl) { + this.url = schemaRegistryUrl; + } +} diff --git a/json-schema-registry/src/main/resources/application.properties b/json-schema-registry/src/main/resources/application.properties new file mode 100644 index 00000000..f6288e3e --- /dev/null +++ b/json-schema-registry/src/main/resources/application.properties @@ -0,0 +1,3 @@ +schema-registry.url=http://144.24.55.159:8081 +schema-registry.username="user" +schema-registry.password="password" diff --git a/json-schema-registry/src/main/resources/application.yml b/json-schema-registry/src/main/resources/application.yml deleted file mode 100644 index 6074ccce..00000000 --- a/json-schema-registry/src/main/resources/application.yml +++ /dev/null @@ -1,4 +0,0 @@ -schema_registry: - url: "http://144.24.55.159:8081" - username: "user" - password: "password" diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index 0c0c358c..af10d809 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -1,6 +1,7 @@ package io.micronaut.jsonschema.registry; import com.fasterxml.jackson.databind.json.JsonMapper; +import io.micronaut.context.ApplicationContext; import io.micronaut.core.io.ResourceLoader; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; @@ -10,6 +11,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -22,13 +24,16 @@ public class ConfluentClientTest { @Inject ResourceLoader resourceLoader; - @Inject - SchemaRegistryClient schemaRegistryClient; - JsonMapper jsonMapper = new JsonMapper(); @Test void testSchemaRegistryClient() throws IOException { + Map items = new HashMap<>(); + items.put("registry.url", "http://144.24.55.159:8081"); + + ApplicationContext ctx = ApplicationContext.run(items); + SchemaRegistryClient schemaRegistryClient = ctx.getBean(SchemaRegistryClient.class); + String subject = "human"; String version = "latest"; String schema = schemaRegistryClient.getWithSubjectAndVersion(subject, version); @@ -36,6 +41,7 @@ void testSchemaRegistryClient() throws IOException { String expected = getExpectedResponse("human.schema.json"); Map mappedExpected = jsonMapper.readValue(expected, Map.class); assertEquals(mappedExpected.get("schema").toString(), schema); + ctx.close(); } private String getExpectedResponse(String filename) throws IOException { From 21a9daf5250acaf2603a27a2415df027f85c6f36 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Fri, 7 Feb 2025 15:07:01 +0100 Subject: [PATCH 07/24] switch to declarative client --- ...stryService.java => RegistryResponse.java} | 17 ++--- .../registry/SchemaRegistryClient.java | 67 ++++--------------- .../registry/SchemaRegistryConfig.java | 28 ++++++-- .../registry/SchemaRegistryController.java | 56 ++++++++++++++++ .../src/main/resources/application.properties | 3 - .../registry/ConfluentClientTest.java | 13 ++-- 6 files changed, 107 insertions(+), 77 deletions(-) rename json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/{SchemaRegistryService.java => RegistryResponse.java} (69%) create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java delete mode 100644 json-schema-registry/src/main/resources/application.properties diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryService.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/RegistryResponse.java similarity index 69% rename from json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryService.java rename to json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/RegistryResponse.java index 56c40106..7d06b15b 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryService.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/RegistryResponse.java @@ -15,13 +15,14 @@ */ package io.micronaut.jsonschema.registry; -import jakarta.inject.Singleton; +import io.micronaut.serde.annotation.Serdeable; -@Singleton -public class SchemaRegistryService { - private final SchemaRegistryClient schemaRegistryClient; - - public SchemaRegistryService(SchemaRegistryClient schemaRegistryClient) { - this.schemaRegistryClient = schemaRegistryClient; - } +@Serdeable +public record RegistryResponse( + String subject, + int id, + int version, + String schemaType, + String schema +) { } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 6835d978..ea4b1f10 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -15,18 +15,14 @@ */ package io.micronaut.jsonschema.registry; -import com.fasterxml.jackson.core.JsonProcessingException; -import io.micronaut.context.annotation.Property; -import io.micronaut.http.HttpRequest; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.client.HttpClient; +import io.micronaut.context.annotation.Requires; +import io.micronaut.core.async.annotation.SingleResult; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.Header; +import io.micronaut.http.annotation.PathVariable; import io.micronaut.http.client.annotation.Client; -import io.micronaut.http.uri.UriBuilder; -import com.fasterxml.jackson.databind.json.JsonMapper; import jakarta.inject.Singleton; - -import java.net.URI; -import java.util.HashMap; +import jakarta.validation.constraints.NotBlank; /** * A client for the Confluent Schema Registry. @@ -34,21 +30,11 @@ * @author Elif Kurtay * @since 1.5.0 */ +@Client("${registry.url}") +@Requires(beans = SchemaRegistryConfig.class) +@Header(name = "Content-Type", value = "application/vnd.schemaregistry.v1+json") @Singleton -public class SchemaRegistryClient { - - private static final String HEADER_NAME = "Content-Type"; - private static final String HEADER_VALUE = "application/vnd.schemaregistry.v1+json"; - - private final SchemaRegistryConfig config; - private final HttpClient client; - private JsonMapper jsonMapper; - - public SchemaRegistryClient(SchemaRegistryConfig config, @Client HttpClient httpClient) { - this.config = config; - this.client = httpClient; - this.jsonMapper = new JsonMapper(); - } +public interface SchemaRegistryClient { /** * SCHEMAS ----------------------------------------------------------- @@ -74,35 +60,10 @@ public SchemaRegistryClient(SchemaRegistryConfig config, @Client HttpClient http * - GET /subjects/(string: subject)/metadata */ - /** - * Get a specific version of the schema registered under this subject. - * - * @param subject The subject (topic name, e.g., user-data) - * @param version The version number or 'latest' as a string - * @return The requested schema - */ - public String getWithSubjectAndVersion(String subject, String version) { - URI url = UriBuilder.of(config.getUrl()) - .path("subjects") - .path(subject) - .path("versions") - .path(version) - .build(); - - HttpRequest request = HttpRequest.GET(url); - - HttpResponse response = client.toBlocking().exchange(request, String.class); - if (response.getStatus().getCode() == 200) { - try { - HashMap HashMappedResponse = jsonMapper.readValue(response.body(), HashMap.class); - return HashMappedResponse.get("schema").toString(); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } else { - throw new RuntimeException("Error registering schema: " + response.getStatus()); - } - } + @Get("/subjects/{subject}/versions/latest") + @SingleResult + RegistryResponse getSubjectWithVersion(@PathVariable @NotBlank String subject, + @Header String authorization); /** * MODE ----------------------------------------------------------- diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index 33b08674..97e53483 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -24,17 +24,15 @@ @ConfigurationProperties("registry") public class SchemaRegistryConfig { @NotBlank - private String url; + public String url; + @NotBlank + private String username; + @NotBlank + private String password; public SchemaRegistryConfig() { } - public SchemaRegistryConfig(@Parameter String url) { - if (url != null) { - this.url = url; - } - } - public String getUrl() { return url; } @@ -42,4 +40,20 @@ public String getUrl() { public void setUrl(String schemaRegistryUrl) { this.url = schemaRegistryUrl; } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java new file mode 100644 index 00000000..9f24def3 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry; + +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +import java.util.Base64; + +/** + * A controller for the Confluent Schema Registry Client. + * + * @author Elif Kurtay + * @since 1.5.0 + */ +@Singleton +public class SchemaRegistryController { + private final SchemaRegistryClient client; + private final SchemaRegistryConfig config; + private final String basicAuth; + + @Inject + public SchemaRegistryController(SchemaRegistryClient client, SchemaRegistryConfig config) { + this.client = client; + this.config = config; + basicAuth = basicAuth(); + } + + private String basicAuth() { + return "Basic " + Base64.getEncoder().encodeToString((config.getUsername() + ":" + config.getPassword()).getBytes()); + } + + /** + * Get a specific version of the schema registered under this subject. + * + * @param subject The subject (topic name, e.g., user-data) + * @param version The version number or 'latest' as a string + * @return The requested schema + */ + public RegistryResponse getSubjectWithVersion(String subject, String version) { + return client.getSubjectWithVersion(subject, basicAuth); + } +} diff --git a/json-schema-registry/src/main/resources/application.properties b/json-schema-registry/src/main/resources/application.properties deleted file mode 100644 index f6288e3e..00000000 --- a/json-schema-registry/src/main/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -schema-registry.url=http://144.24.55.159:8081 -schema-registry.username="user" -schema-registry.password="password" diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index af10d809..0bcc94d2 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -27,20 +27,21 @@ public class ConfluentClientTest { JsonMapper jsonMapper = new JsonMapper(); @Test - void testSchemaRegistryClient() throws IOException { + void testSchemaRegistryController() throws IOException { Map items = new HashMap<>(); items.put("registry.url", "http://144.24.55.159:8081"); + items.put("registry.username", "micronaut"); + items.put("registry.password", "test"); ApplicationContext ctx = ApplicationContext.run(items); - SchemaRegistryClient schemaRegistryClient = ctx.getBean(SchemaRegistryClient.class); - + SchemaRegistryController controller = ctx.getBean(SchemaRegistryController.class); String subject = "human"; String version = "latest"; - String schema = schemaRegistryClient.getWithSubjectAndVersion(subject, version); + RegistryResponse response = controller.getSubjectWithVersion(subject, version); String expected = getExpectedResponse("human.schema.json"); - Map mappedExpected = jsonMapper.readValue(expected, Map.class); - assertEquals(mappedExpected.get("schema").toString(), schema); + RegistryResponse mappedExpected = jsonMapper.readValue(expected, RegistryResponse.class); + assertEquals(mappedExpected, response); ctx.close(); } From f4a284ddff480bb2bee3ce70e3c90faacbdf11f1 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Fri, 7 Feb 2025 17:42:23 +0100 Subject: [PATCH 08/24] new responses and broken filter --- .../registry/SchemaRegistryClient.java | 187 +++++++++++++++--- .../registry/SchemaRegistryClientFilter.java | 38 ++++ .../registry/SchemaRegistryConfig.java | 1 - .../registry/SchemaRegistryController.java | 7 +- .../registry/types/CompatibilityResponse.java | 24 +++ .../registry/types/ModeResponse.java | 29 +++ .../jsonschema/registry/types/SchemaType.java | 25 +++ .../registry/types/SubjectRequestBody.java | 37 ++++ .../SubjectResponse.java} | 6 +- .../registry/ConfluentClientTest.java | 7 +- 10 files changed, 324 insertions(+), 37 deletions(-) create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientFilter.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/CompatibilityResponse.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ModeResponse.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java rename json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/{RegistryResponse.java => types/SubjectResponse.java} (87%) diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index ea4b1f10..0042cac4 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -17,71 +17,182 @@ import io.micronaut.context.annotation.Requires; import io.micronaut.core.async.annotation.SingleResult; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Delete; import io.micronaut.http.annotation.Get; import io.micronaut.http.annotation.Header; import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.annotation.Put; import io.micronaut.http.client.annotation.Client; +import io.micronaut.jsonschema.registry.types.CompatibilityResponse; +import io.micronaut.jsonschema.registry.types.ModeResponse; +import io.micronaut.jsonschema.registry.types.SchemaType; +import io.micronaut.jsonschema.registry.types.SubjectResponse; +import io.micronaut.jsonschema.registry.types.SubjectRequestBody; import jakarta.inject.Singleton; -import jakarta.validation.constraints.NotBlank; + +import java.util.HashMap; +import java.util.List; /** * A client for the Confluent Schema Registry. + * TODO: create schema response? * * @author Elif Kurtay * @since 1.5.0 */ -@Client("${registry.url}") +@Client(value = "${registry.url}") @Requires(beans = SchemaRegistryConfig.class) @Header(name = "Content-Type", value = "application/vnd.schemaregistry.v1+json") @Singleton public interface SchemaRegistryClient { /** - * SCHEMAS ----------------------------------------------------------- - * TODO: - * - GET /schemas/ids/{int: id} - * - GET /schemas/ids/{int: id}/schema - * - GET /schemas/types/ - * - GET /schemas/ids/{int: id}/versions + * SCHEMAS. ----------------------------------------------------------- + * + GET /schemas/ids/{int: id} + * + GET /schemas/ids/{int: id}/schema + * + GET /schemas/types/ + * + GET /schemas/ids/{int: id}/versions */ + @Get("/schemas/ids/{id}") + @SingleResult + String getSchemaWithId(@PathVariable int id, + @Header String authorization); + + @Get("/schemas/ids/{id}/schema") + @SingleResult + String getSchemaStringWithId(@PathVariable int id, + @Header String authorization); + + @Get("/schemas/ids/{id}/versions") + @SingleResult + List getSchemaVersionsWithId(@PathVariable int id, + @Header String authorization); + + @Get("/schemas/types") + @SingleResult + List getSchemaTypes(@Header String authorization); + /** * SUBJECTS ----------------------------------------------------------- - * TODO: - * - GET /subjects - * - GET /subjects/(string: subject)/versions - * - DELETE /subjects/(string: subject) + * + GET /subjects + * + GET /subjects/(string: subject)/versions + * + DELETE /subjects/(string: subject) * + GET /subjects/(string: subject)/versions/(versionId: version) - * - GET /subjects/(string: subject)/versions/(versionId: version)/schema - * - POST /subjects/(string: subject)/versions - * - POST /subjects/(string: subject) - * - DELETE /subjects/(string: subject)/versions/(versionId: version) - * - GET /subjects/(string: subject)/versions/{versionId: version}/referencedby - * - GET /subjects/(string: subject)/metadata + * + GET /subjects/(string: subject)/versions/(versionId: version)/schema + * + POST /subjects/(string: subject)/versions + * + POST /subjects/(string: subject) + * + DELETE /subjects/(string: subject)/versions/(versionId: version) + * + GET /subjects/(string: subject)/versions/{versionId: version}/referencedby + * + GET /subjects/(string: subject)/metadata */ - @Get("/subjects/{subject}/versions/latest") + @Get("/subjects") + @SingleResult + List getSubjects(@Header String authorization); + + @Get("/subjects/{subject}/versions") + @SingleResult + List getSubjectVersions(@PathVariable String subject, + @Header String authorization); + + @Delete("/subjects/{subject}") + @SingleResult + List deleteSubject(@PathVariable String subject, + @Header String authorization); + + @Get("/subjects/{subject}/versions/{version}") + @SingleResult + SubjectResponse getSubjectWithVersion(@PathVariable String subject, + @PathVariable String version); + + @Get("/subjects/{subject}/versions/{version}/schema") + @SingleResult + String getSchemaWithSubjectAndVersion(@PathVariable String subject, + @PathVariable String version, + @Header String authorization); + + @Post("/subjects/{subject}/versions") + @SingleResult + HashMap registerNewVersion(@PathVariable String subject, + @Body SubjectRequestBody schemaBody, + @Header String authorization); + + @Post("/subjects/{subject}") + @SingleResult + SubjectResponse createSubject(@PathVariable String subject, + @Body SubjectRequestBody schemaBody, + @Header String authorization); + + @Delete("/subjects/{subject}/versions/{version}") + @SingleResult + int deleteSubjectVersion(@PathVariable String subject, + @PathVariable String version, + @Header String authorization); + + @Get("/subjects/{subject}/versions/{version}/referencedby") + @SingleResult + List getSubjectVersionReferencedBy(@PathVariable String subject, + @PathVariable String version, + @Header String authorization); + + @Get("/subjects/{subject}/metadata") @SingleResult - RegistryResponse getSubjectWithVersion(@PathVariable @NotBlank String subject, - @Header String authorization); + SubjectResponse getSubjectMetadata(@PathVariable String subject, + @Header String authorization); + /** * MODE ----------------------------------------------------------- - * TODO: - * - GET /mode - * - PUT /mode - * - GET /mode/(string: subject) - * - PUT /mode/(string: subject) - * - DELETE /mode/(string: subject) + * + GET /mode + * + PUT /mode + * + GET /mode/(string: subject) + * + PUT /mode/(string: subject) + * + DELETE /mode/(string: subject) */ + @Get("/mode") + @SingleResult + ModeResponse getMode(@Header String authorization); + + @Put("/mode") + @SingleResult + ModeResponse setMode(@Body ModeResponse mode, @Header String authorization); + + @Get("/mode/{subject}") + @SingleResult + ModeResponse getModeForSubject(@PathVariable String subject, @Header String authorization); + + @Put("/mode/{subject}") + @SingleResult + ModeResponse setModeForSubject(@PathVariable String subject, @Body ModeResponse mode, @Header String authorization); + + @Delete("/mode/{subject}") + @SingleResult + ModeResponse deleteModeForSubject(@PathVariable String subject, @Header String authorization); + + /** * COMPATIBILITY ----------------------------------------------------------- - * TODO: * - POST /compatibility/subjects/(string: subject)/versions/(versionId: version) * - POST /compatibility/subjects/(string: subject)/versions */ + @Post("/compatibility/subjects/{subject}/versions/{version}") + @SingleResult + CompatibilityResponse checkCompatibilityForSubjectVersion(@PathVariable String subject, + @PathVariable String version, + @Body SubjectRequestBody compatibilityRequest, + @Header String authorization); + + @Post("/compatibility/subjects/{subject}/versions") + @SingleResult + CompatibilityResponse checkCompatibilityForSubject(@PathVariable String subject, + @Body SubjectRequestBody compatibilityRequest, + @Header String authorization); + /** * CONFIG ----------------------------------------------------------- * TODO: @@ -91,4 +202,24 @@ RegistryResponse getSubjectWithVersion(@PathVariable @NotBlank String subject, * - GET /config/(string: subject) * - DELETE /config/(string: subject) */ + + @Put("/config") + @SingleResult + String setConfig(@Body String config, @Header String authorization); + + @Get("/config") + @SingleResult + String getConfig(@Header String authorization); + + @Put("/config/{subject}") + @SingleResult + String setConfigForSubject(@PathVariable String subject, @Body String config, @Header String authorization); + + @Get("/config/{subject}") + @SingleResult + String getConfigForSubject(@PathVariable String subject, @Header String authorization); + + @Delete("/config/{subject}") + @SingleResult + void deleteConfigForSubject(@PathVariable String subject, @Header String authorization); } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientFilter.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientFilter.java new file mode 100644 index 00000000..ecf025c5 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientFilter.java @@ -0,0 +1,38 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry; + +import io.micronaut.context.annotation.Requires; +import io.micronaut.http.MutableHttpRequest; +import io.micronaut.http.annotation.ClientFilter; +import io.micronaut.http.annotation.RequestFilter; + +@ClientFilter("${registry.url}/**") +@Requires(beans = SchemaRegistryConfig.class) +@Requires(property = "registry.username") +@Requires(property = "registry.password") +public class SchemaRegistryClientFilter { + private final SchemaRegistryConfig config; + + public SchemaRegistryClientFilter(SchemaRegistryConfig config) { + this.config = config; + } + + @RequestFilter + public void doFilter(MutableHttpRequest request) { + request.basicAuth(config.getUsername(), config.getPassword()); + } +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index 97e53483..685dce60 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -16,7 +16,6 @@ package io.micronaut.jsonschema.registry; import io.micronaut.context.annotation.ConfigurationProperties; -import io.micronaut.context.annotation.Parameter; import io.micronaut.serde.annotation.Serdeable; import jakarta.validation.constraints.NotBlank; diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java index 9f24def3..81b1692b 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java @@ -15,6 +15,7 @@ */ package io.micronaut.jsonschema.registry; +import io.micronaut.jsonschema.registry.types.SubjectResponse; import jakarta.inject.Inject; import jakarta.inject.Singleton; @@ -50,7 +51,9 @@ private String basicAuth() { * @param version The version number or 'latest' as a string * @return The requested schema */ - public RegistryResponse getSubjectWithVersion(String subject, String version) { - return client.getSubjectWithVersion(subject, basicAuth); + public SubjectResponse getSubjectWithVersion(String subject, String version) { + return client.getSubjectWithVersion(subject, version); } + + } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/CompatibilityResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/CompatibilityResponse.java new file mode 100644 index 00000000..3761c1f0 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/CompatibilityResponse.java @@ -0,0 +1,24 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.types; + +import io.micronaut.serde.annotation.Serdeable; + +@Serdeable +public record CompatibilityResponse( + boolean is_compatible +) { +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ModeResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ModeResponse.java new file mode 100644 index 00000000..87709a2b --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ModeResponse.java @@ -0,0 +1,29 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.types; + +import io.micronaut.serde.annotation.Serdeable; + +@Serdeable +public record ModeResponse( + ModeType mode +) { + enum ModeType { + IMPORT, + READONLY, + READWRITE + } +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java new file mode 100644 index 00000000..1e81c9c5 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java @@ -0,0 +1,25 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.types; + +import io.micronaut.serde.annotation.Serdeable; + +@Serdeable +public enum SchemaType { + AVRO, + JSON, + PROTOBUF +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java new file mode 100644 index 00000000..cd735e07 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.types; + +import io.micronaut.serde.annotation.Serdeable; + +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +@Serdeable +public record SubjectRequestBody( + String schema, + SchemaType schemaType, + List references, + HashMap metadata, + Set ruleSet +) { + public record ReferenceType( + String name, + String subject, + String version) { + } +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/RegistryResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java similarity index 87% rename from json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/RegistryResponse.java rename to json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java index 7d06b15b..7d71e89d 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/RegistryResponse.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.jsonschema.registry; +package io.micronaut.jsonschema.registry.types; import io.micronaut.serde.annotation.Serdeable; @Serdeable -public record RegistryResponse( +public record SubjectResponse( String subject, int id, int version, - String schemaType, + SchemaType schemaType, String schema ) { } diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index 0bcc94d2..b1a286fe 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import io.micronaut.context.ApplicationContext; import io.micronaut.core.io.ResourceLoader; +import io.micronaut.jsonschema.registry.types.SubjectResponse; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; @@ -34,13 +35,13 @@ void testSchemaRegistryController() throws IOException { items.put("registry.password", "test"); ApplicationContext ctx = ApplicationContext.run(items); - SchemaRegistryController controller = ctx.getBean(SchemaRegistryController.class); + SchemaRegistryClient client = ctx.getBean(SchemaRegistryClient.class); String subject = "human"; String version = "latest"; - RegistryResponse response = controller.getSubjectWithVersion(subject, version); + SubjectResponse response = client.getSubjectWithVersion(subject, version); String expected = getExpectedResponse("human.schema.json"); - RegistryResponse mappedExpected = jsonMapper.readValue(expected, RegistryResponse.class); + SubjectResponse mappedExpected = jsonMapper.readValue(expected, SubjectResponse.class); assertEquals(mappedExpected, response); ctx.close(); } From 9ee9d84e2ed280a596cdd7ad3d9e95666bc28263 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Mon, 10 Feb 2025 12:20:00 +0100 Subject: [PATCH 09/24] declarative with filter auth --- json-schema-registry/build.gradle | 4 +- .../registry/SchemaRegistryClient.java | 72 +++++++++---------- ...va => SchemaRegistryClientAuthFilter.java} | 6 +- .../registry/SchemaRegistryConfig.java | 8 --- .../registry/SchemaRegistryController.java | 20 ------ .../jsonschema/registry/types/SchemaType.java | 25 ------- .../registry/types/SubjectRequestBody.java | 6 ++ .../registry/types/SubjectResponse.java | 5 ++ 8 files changed, 50 insertions(+), 96 deletions(-) rename json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/{SchemaRegistryClientFilter.java => SchemaRegistryClientAuthFilter.java} (89%) delete mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle index aa9a09a1..3e4e73e6 100644 --- a/json-schema-registry/build.gradle +++ b/json-schema-registry/build.gradle @@ -4,13 +4,15 @@ plugins { dependencies { compileOnly(mn.micronaut.core.processor) + implementation(mn.micronaut.http) implementation(mn.micronaut.http.client) implementation(mn.micronaut.jackson.databind) implementation(mnSerde.micronaut.serde.jackson) implementation(mnValidation.validation) - api(mn.micronaut.inject) + annotationProcessor(mn.micronaut.http.validation) + annotationProcessor(mnSerde.micronaut.serde.processor) testAnnotationProcessor(mn.micronaut.inject.java) testImplementation(mn.micronaut.inject) diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 0042cac4..5f0286a4 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -27,7 +27,6 @@ import io.micronaut.http.client.annotation.Client; import io.micronaut.jsonschema.registry.types.CompatibilityResponse; import io.micronaut.jsonschema.registry.types.ModeResponse; -import io.micronaut.jsonschema.registry.types.SchemaType; import io.micronaut.jsonschema.registry.types.SubjectResponse; import io.micronaut.jsonschema.registry.types.SubjectRequestBody; import jakarta.inject.Singleton; @@ -44,6 +43,7 @@ */ @Client(value = "${registry.url}") @Requires(beans = SchemaRegistryConfig.class) +@Requires(property = "registry.url") @Header(name = "Content-Type", value = "application/vnd.schemaregistry.v1+json") @Singleton public interface SchemaRegistryClient { @@ -58,22 +58,19 @@ public interface SchemaRegistryClient { @Get("/schemas/ids/{id}") @SingleResult - String getSchemaWithId(@PathVariable int id, - @Header String authorization); + String getSchemaWithId(@PathVariable int id); @Get("/schemas/ids/{id}/schema") @SingleResult - String getSchemaStringWithId(@PathVariable int id, - @Header String authorization); + String getSchemaStringWithId(@PathVariable int id); @Get("/schemas/ids/{id}/versions") @SingleResult - List getSchemaVersionsWithId(@PathVariable int id, - @Header String authorization); + List getSchemaVersionsWithId(@PathVariable int id); @Get("/schemas/types") @SingleResult - List getSchemaTypes(@Header String authorization); + List getSchemaTypes(); /** * SUBJECTS ----------------------------------------------------------- @@ -91,18 +88,23 @@ List getSchemaVersionsWithId(@PathVariable int id, @Get("/subjects") @SingleResult - List getSubjects(@Header String authorization); + List getSubjects(); @Get("/subjects/{subject}/versions") @SingleResult - List getSubjectVersions(@PathVariable String subject, - @Header String authorization); + List getSubjectVersions(@PathVariable String subject); @Delete("/subjects/{subject}") @SingleResult - List deleteSubject(@PathVariable String subject, - @Header String authorization); + List deleteSubject(@PathVariable String subject); + /** + * Get a specific version of the schema registered under this subject. + * + * @param subject The subject (topic name, e.g., user-data) + * @param version The version number or 'latest' as a string + * @return The requested schema + */ @Get("/subjects/{subject}/versions/{version}") @SingleResult SubjectResponse getSubjectWithVersion(@PathVariable String subject, @@ -111,37 +113,31 @@ SubjectResponse getSubjectWithVersion(@PathVariable String subject, @Get("/subjects/{subject}/versions/{version}/schema") @SingleResult String getSchemaWithSubjectAndVersion(@PathVariable String subject, - @PathVariable String version, - @Header String authorization); + @PathVariable String version); @Post("/subjects/{subject}/versions") @SingleResult HashMap registerNewVersion(@PathVariable String subject, - @Body SubjectRequestBody schemaBody, - @Header String authorization); + @Body SubjectRequestBody schemaBody); @Post("/subjects/{subject}") @SingleResult SubjectResponse createSubject(@PathVariable String subject, - @Body SubjectRequestBody schemaBody, - @Header String authorization); + @Body SubjectRequestBody schemaBody); @Delete("/subjects/{subject}/versions/{version}") @SingleResult int deleteSubjectVersion(@PathVariable String subject, - @PathVariable String version, - @Header String authorization); + @PathVariable String version); @Get("/subjects/{subject}/versions/{version}/referencedby") @SingleResult List getSubjectVersionReferencedBy(@PathVariable String subject, - @PathVariable String version, - @Header String authorization); + @PathVariable String version); @Get("/subjects/{subject}/metadata") @SingleResult - SubjectResponse getSubjectMetadata(@PathVariable String subject, - @Header String authorization); + SubjectResponse getSubjectMetadata(@PathVariable String subject); /** @@ -155,23 +151,23 @@ SubjectResponse getSubjectMetadata(@PathVariable String subject, @Get("/mode") @SingleResult - ModeResponse getMode(@Header String authorization); + ModeResponse getMode(); @Put("/mode") @SingleResult - ModeResponse setMode(@Body ModeResponse mode, @Header String authorization); + ModeResponse setMode(@Body ModeResponse mode); @Get("/mode/{subject}") @SingleResult - ModeResponse getModeForSubject(@PathVariable String subject, @Header String authorization); + ModeResponse getModeForSubject(@PathVariable String subject); @Put("/mode/{subject}") @SingleResult - ModeResponse setModeForSubject(@PathVariable String subject, @Body ModeResponse mode, @Header String authorization); + ModeResponse setModeForSubject(@PathVariable String subject, @Body ModeResponse mode); @Delete("/mode/{subject}") @SingleResult - ModeResponse deleteModeForSubject(@PathVariable String subject, @Header String authorization); + ModeResponse deleteModeForSubject(@PathVariable String subject); /** @@ -184,14 +180,12 @@ SubjectResponse getSubjectMetadata(@PathVariable String subject, @SingleResult CompatibilityResponse checkCompatibilityForSubjectVersion(@PathVariable String subject, @PathVariable String version, - @Body SubjectRequestBody compatibilityRequest, - @Header String authorization); + @Body SubjectRequestBody compatibilityRequest); @Post("/compatibility/subjects/{subject}/versions") @SingleResult CompatibilityResponse checkCompatibilityForSubject(@PathVariable String subject, - @Body SubjectRequestBody compatibilityRequest, - @Header String authorization); + @Body SubjectRequestBody compatibilityRequest); /** * CONFIG ----------------------------------------------------------- @@ -205,21 +199,21 @@ CompatibilityResponse checkCompatibilityForSubject(@PathVariable String subject, @Put("/config") @SingleResult - String setConfig(@Body String config, @Header String authorization); + String setConfig(@Body String config); @Get("/config") @SingleResult - String getConfig(@Header String authorization); + String getConfig(); @Put("/config/{subject}") @SingleResult - String setConfigForSubject(@PathVariable String subject, @Body String config, @Header String authorization); + String setConfigForSubject(@PathVariable String subject, @Body String config); @Get("/config/{subject}") @SingleResult - String getConfigForSubject(@PathVariable String subject, @Header String authorization); + String getConfigForSubject(@PathVariable String subject); @Delete("/config/{subject}") @SingleResult - void deleteConfigForSubject(@PathVariable String subject, @Header String authorization); + void deleteConfigForSubject(@PathVariable String subject); } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientFilter.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java similarity index 89% rename from json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientFilter.java rename to json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java index ecf025c5..dcbff8f1 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientFilter.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java @@ -20,14 +20,14 @@ import io.micronaut.http.annotation.ClientFilter; import io.micronaut.http.annotation.RequestFilter; -@ClientFilter("${registry.url}/**") +@ClientFilter("/**") @Requires(beans = SchemaRegistryConfig.class) @Requires(property = "registry.username") @Requires(property = "registry.password") -public class SchemaRegistryClientFilter { +public class SchemaRegistryClientAuthFilter { private final SchemaRegistryConfig config; - public SchemaRegistryClientFilter(SchemaRegistryConfig config) { + public SchemaRegistryClientAuthFilter(SchemaRegistryConfig config) { this.config = config; } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index 685dce60..b6623b96 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -32,14 +32,6 @@ public class SchemaRegistryConfig { public SchemaRegistryConfig() { } - public String getUrl() { - return url; - } - - public void setUrl(String schemaRegistryUrl) { - this.url = schemaRegistryUrl; - } - public String getUsername() { return username; } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java index 81b1692b..4ba3f630 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java @@ -19,8 +19,6 @@ import jakarta.inject.Inject; import jakarta.inject.Singleton; -import java.util.Base64; - /** * A controller for the Confluent Schema Registry Client. * @@ -31,29 +29,11 @@ public class SchemaRegistryController { private final SchemaRegistryClient client; private final SchemaRegistryConfig config; - private final String basicAuth; @Inject public SchemaRegistryController(SchemaRegistryClient client, SchemaRegistryConfig config) { this.client = client; this.config = config; - basicAuth = basicAuth(); - } - - private String basicAuth() { - return "Basic " + Base64.getEncoder().encodeToString((config.getUsername() + ":" + config.getPassword()).getBytes()); } - /** - * Get a specific version of the schema registered under this subject. - * - * @param subject The subject (topic name, e.g., user-data) - * @param version The version number or 'latest' as a string - * @return The requested schema - */ - public SubjectResponse getSubjectWithVersion(String subject, String version) { - return client.getSubjectWithVersion(subject, version); - } - - } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java deleted file mode 100644 index 1e81c9c5..00000000 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2017-2025 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.jsonschema.registry.types; - -import io.micronaut.serde.annotation.Serdeable; - -@Serdeable -public enum SchemaType { - AVRO, - JSON, - PROTOBUF -} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java index cd735e07..567259d0 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java @@ -34,4 +34,10 @@ public record ReferenceType( String subject, String version) { } + + public enum SchemaType { + AVRO, + JSON, + PROTOBUF + } } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java index 7d71e89d..c43094c8 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java @@ -25,4 +25,9 @@ public record SubjectResponse( SchemaType schemaType, String schema ) { + public enum SchemaType { + AVRO, + JSON, + PROTOBUF + } } From cb80b92b2a23b4545b273389632bb95747d3eec2 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Tue, 11 Feb 2025 12:23:35 +0100 Subject: [PATCH 10/24] GeneratedFromSchema annotation --- .../jsonschema/GeneratedFromSchema.java | 37 +++++++++++++++++++ .../jsonschema/generator/SourceGenerator.java | 18 +++++++-- .../generator/AbstractGeneratorSpec.groovy | 1 + .../generator/SimpleGeneratorSpec.groovy | 27 ++++++++++++++ .../registry/SchemaRegistryConfig.java | 9 +++++ .../jsonschema/registry/types/SchemaType.java | 7 ++++ .../registry/types/SubjectResponse.java | 5 --- 7 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java diff --git a/json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java b/json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java new file mode 100644 index 00000000..a712023b --- /dev/null +++ b/json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * An annotation that signals that the object was generated from json schema. + * + * @since 1.5.0 + * @author Elif Kurtay + */ +@Target({ ElementType.TYPE }) +public @interface GeneratedFromSchema { + + /** + * The title of the JSON schema file used to generate the object. + * + * @return The fileName + */ + String fileName() default ""; + +} diff --git a/json-schema-generator/src/main/java/io/micronaut/jsonschema/generator/SourceGenerator.java b/json-schema-generator/src/main/java/io/micronaut/jsonschema/generator/SourceGenerator.java index 08491e6c..1ae5f9f0 100644 --- a/json-schema-generator/src/main/java/io/micronaut/jsonschema/generator/SourceGenerator.java +++ b/json-schema-generator/src/main/java/io/micronaut/jsonschema/generator/SourceGenerator.java @@ -18,6 +18,7 @@ import io.micronaut.core.annotation.Internal; import io.micronaut.inject.processing.ProcessingException; import io.micronaut.inject.visitor.VisitorContext; +import io.micronaut.jsonschema.GeneratedFromSchema; import io.micronaut.jsonschema.generator.aggregator.AnnotationsAggregator; import io.micronaut.jsonschema.generator.loaders.FileLoader; import io.micronaut.jsonschema.generator.utils.GeneratorContext; @@ -303,7 +304,9 @@ private File generateFromSchema(Schema jsonSchema, Path outputPath, String packa public EnumDef buildEnum(Schema jsonSchema, String builderClassName) { EnumDef.EnumDefBuilder enumBuilder = EnumDef.builder(builderClassName) .addModifiers(Modifier.PUBLIC) - .addAnnotation(ClassTypeDef.of(SERDEABLE_ANN)); + .addAnnotation(ClassTypeDef.of(SERDEABLE_ANN)) + .addAnnotation(getGeneratedFromSchemaAnn()); + boolean isComplexEnum = false; LinkedHashMap cases = new LinkedHashMap<>(); LinkedHashMap enumValues = new LinkedHashMap<>(); @@ -378,7 +381,8 @@ public EnumDef buildEnum(Schema jsonSchema, String builderClassName) { private RecordDef buildRecord(Schema jsonSchema, String builderClassName) { RecordDef.RecordDefBuilder objectBuilder = RecordDef.builder(builderClassName) .addModifiers(Modifier.PUBLIC) - .addAnnotation(ClassTypeDef.of(SERDEABLE_ANN)); + .addAnnotation(ClassTypeDef.of(SERDEABLE_ANN)) + .addAnnotation(getGeneratedFromSchemaAnn()); addFields(jsonSchema, objectBuilder); return objectBuilder.build(); @@ -387,7 +391,8 @@ private RecordDef buildRecord(Schema jsonSchema, String builderClassName) { private ClassDef buildClass(Schema jsonSchema, String builderClassName) { ClassDef.ClassDefBuilder objectBuilder = ClassDef.builder(builderClassName) .addModifiers(Modifier.PUBLIC) - .addAnnotation(ClassTypeDef.of(SERDEABLE_ANN)); + .addAnnotation(ClassTypeDef.of(SERDEABLE_ANN)) + .addAnnotation(getGeneratedFromSchemaAnn()); if (context.hasDefinition(inputFileName + "/superClass")) { var superClass = context.getDefinitionType(inputFileName + "/superClass"); @@ -421,7 +426,8 @@ private ClassDef buildClass(Schema jsonSchema, String builderClassName) { private InterfaceDef buildInterface(Schema jsonSchema, String builderClassName) { InterfaceDef.InterfaceDefBuilder objectBuilder = InterfaceDef.builder(builderClassName) .addModifiers(Modifier.PUBLIC) - .addAnnotation(ClassTypeDef.of(SERDEABLE_ANN)); + .addAnnotation(ClassTypeDef.of(SERDEABLE_ANN)) + .addAnnotation(getGeneratedFromSchemaAnn()); if (jsonSchema.hasDiscriminator()) { // top level interface addDiscriminatorAnnotations(jsonSchema, objectBuilder); @@ -632,4 +638,8 @@ public static String getOutputPackageName() { public static VisitorContext.Language getLanguage() { return language; } + + private static AnnotationDef getGeneratedFromSchemaAnn() { + return AnnotationDef.builder(ClassTypeDef.of(GeneratedFromSchema.class)).addMember("fileName", inputFileName).build(); + } } diff --git a/json-schema-generator/src/test/groovy/io/micronaut/jsonschema/generator/AbstractGeneratorSpec.groovy b/json-schema-generator/src/test/groovy/io/micronaut/jsonschema/generator/AbstractGeneratorSpec.groovy index 97f56c32..9ab43fb6 100644 --- a/json-schema-generator/src/test/groovy/io/micronaut/jsonschema/generator/AbstractGeneratorSpec.groovy +++ b/json-schema-generator/src/test/groovy/io/micronaut/jsonschema/generator/AbstractGeneratorSpec.groovy @@ -16,6 +16,7 @@ class AbstractGeneratorSpec extends Specification { TypeDeclaration generateType(String className, String jsonSchema) { SourceGenerator generator = new SourceGenerator("java") + SourceGenerator.setInputFileName("test.schema.json") Path outputPath = new File("output").toPath() // Define the base output path String packageName = "com.example.project"; // Example package name diff --git a/json-schema-generator/src/test/groovy/io/micronaut/jsonschema/generator/SimpleGeneratorSpec.groovy b/json-schema-generator/src/test/groovy/io/micronaut/jsonschema/generator/SimpleGeneratorSpec.groovy index 11b9e0ee..21ad7759 100644 --- a/json-schema-generator/src/test/groovy/io/micronaut/jsonschema/generator/SimpleGeneratorSpec.groovy +++ b/json-schema-generator/src/test/groovy/io/micronaut/jsonschema/generator/SimpleGeneratorSpec.groovy @@ -27,6 +27,9 @@ class SimpleGeneratorSpec extends AbstractGeneratorSpec { then: content == """ @Serdeable + @GeneratedFromSchema( + fileName = "test.schema.json" + ) public enum Status { ACTIVE("active"), @@ -118,6 +121,9 @@ class SimpleGeneratorSpec extends AbstractGeneratorSpec { then: content == """ @Serdeable + @GeneratedFromSchema( + fileName = "test.schema.json" + ) public record Llama( @NotNull @Min(0) int age, @NotNull @Size(min = 1) String name, @@ -159,6 +165,9 @@ class SimpleGeneratorSpec extends AbstractGeneratorSpec { then: content == """ @Serdeable + @GeneratedFromSchema( + fileName = "test.schema.json" + ) public record Llama( @Min(0) int age, Llama name, @@ -207,20 +216,32 @@ class SimpleGeneratorSpec extends AbstractGeneratorSpec { then: content == """ @Serdeable + @GeneratedFromSchema( + fileName = "test.schema.json" + ) public record Default( @Min(0) int age, Defaults defaults ) { @Serdeable + @GeneratedFromSchema( + fileName = "test.schema.json" + ) public record Defaults( Run run ) { @Serdeable + @GeneratedFromSchema( + fileName = "test.schema.json" + ) public record Run( Shell shell, @JsonProperty("working-directory") @Pattern(regexp = "^[a-zA-Z]*") String workingDirectory ) { @Serdeable + @GeneratedFromSchema( + fileName = "test.schema.json" + ) public enum Shell { BASH("bash"), @@ -296,6 +317,9 @@ class SimpleGeneratorSpec extends AbstractGeneratorSpec { then: content == """ @Serdeable + @GeneratedFromSchema( + fileName = "test.schema.json" + ) public class Llama2 { /** * The age @@ -395,6 +419,9 @@ class SimpleGeneratorSpec extends AbstractGeneratorSpec { then: content == """ @Serdeable + @GeneratedFromSchema( + fileName = "test.schema.json" + ) public record Llama3( @NotNull @Size(min = 1) String name, @NotNull String foo, diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index b6623b96..500085c9 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -28,6 +28,7 @@ public class SchemaRegistryConfig { private String username; @NotBlank private String password; + private boolean pushToRegistryEnabled = true; public SchemaRegistryConfig() { } @@ -47,4 +48,12 @@ public String getPassword() { public void setPassword(String password) { this.password = password; } + + public boolean isPushToRegistryEnabled() { + return pushToRegistryEnabled; + } + + public void setPushToRegistryEnabled(boolean pushToRegistryEnabled) { + this.pushToRegistryEnabled = pushToRegistryEnabled; + } } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java new file mode 100644 index 00000000..190415d2 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java @@ -0,0 +1,7 @@ +package io.micronaut.jsonschema.registry.types; + +public enum SchemaType { + AVRO, + JSON, + PROTOBUF +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java index c43094c8..7d71e89d 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java @@ -25,9 +25,4 @@ public record SubjectResponse( SchemaType schemaType, String schema ) { - public enum SchemaType { - AVRO, - JSON, - PROTOBUF - } } From b64b3b3d6462f3d983e0cc4374fafcf99679bf63 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Tue, 11 Feb 2025 14:50:09 +0100 Subject: [PATCH 11/24] push local to registry --- json-schema-registry/build.gradle | 1 + .../registry/SchemaRegistryClient.java | 86 ++++++++++++++----- .../registry/SchemaRegistryController.java | 39 --------- .../registry/SchemaRegistryManager.java | 79 +++++++++++++++++ .../registry/types/SubjectRequestBody.java | 6 -- .../registry/ConfluentClientTest.java | 38 +++++++- 6 files changed, 182 insertions(+), 67 deletions(-) delete mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle index 3e4e73e6..f2fef98b 100644 --- a/json-schema-registry/build.gradle +++ b/json-schema-registry/build.gradle @@ -5,6 +5,7 @@ plugins { dependencies { compileOnly(mn.micronaut.core.processor) + implementation(projects.micronautJsonSchemaAnnotations) implementation(mn.micronaut.http) implementation(mn.micronaut.http.client) implementation(mn.micronaut.jackson.databind) diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 5f0286a4..f0a3bbf4 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -36,7 +36,12 @@ /** * A client for the Confluent Schema Registry. - * TODO: create schema response? + * + *

Supports the operations defined in the + * Schema Registry API. + * + *

The client is configured with the {@link SchemaRegistryConfig} file for its host address + * and authentication. the configuration parameters are expected to be configured in the application context. * * @author Elif Kurtay * @since 1.5.0 @@ -48,52 +53,75 @@ @Singleton public interface SchemaRegistryClient { +// SCHEMA OPERATIONS ----------------------------------------------------------- + /** - * SCHEMAS. ----------------------------------------------------------- - * + GET /schemas/ids/{int: id} - * + GET /schemas/ids/{int: id}/schema - * + GET /schemas/types/ - * + GET /schemas/ids/{int: id}/versions + * Get the schema string identified by the input ID. + * + * @param id The unique identifier of the schema + * @return The schema string identified by the input ID */ - @Get("/schemas/ids/{id}") @SingleResult - String getSchemaWithId(@PathVariable int id); + String getSchemaStringWithId(@PathVariable int id); + /** + * Retrieves only the schema identified by the input ID. + * + * @param id The unique identifier of the schema + * @return Schema identified by the ID + */ @Get("/schemas/ids/{id}/schema") @SingleResult - String getSchemaStringWithId(@PathVariable int id); + String getSchemaWithId(@PathVariable int id); + /** + * Get the subject-version pairs identified by the input ID. + * + * @param id The unique identifier of the schema + * @return The subject-version pairs + */ @Get("/schemas/ids/{id}/versions") @SingleResult List getSchemaVersionsWithId(@PathVariable int id); + /** + * Get the schema types that are registered with Schema Registry. + * + * @return The list of schema types + */ @Get("/schemas/types") @SingleResult List getSchemaTypes(); + + // SUBJECTS ----------------------------------------------------------- + /** - * SUBJECTS ----------------------------------------------------------- - * + GET /subjects - * + GET /subjects/(string: subject)/versions - * + DELETE /subjects/(string: subject) - * + GET /subjects/(string: subject)/versions/(versionId: version) - * + GET /subjects/(string: subject)/versions/(versionId: version)/schema - * + POST /subjects/(string: subject)/versions - * + POST /subjects/(string: subject) - * + DELETE /subjects/(string: subject)/versions/(versionId: version) - * + GET /subjects/(string: subject)/versions/{versionId: version}/referencedby - * + GET /subjects/(string: subject)/metadata + * Get the list of subjects that are registered with Schema Registry. + * + * @return The list of subject names */ - @Get("/subjects") @SingleResult List getSubjects(); + /** + * Get the list of versions of the schema registered under this subject. + * + * @param subject The subject (topic name, e.g., user-data) + * @return The list of versions + */ @Get("/subjects/{subject}/versions") @SingleResult List getSubjectVersions(@PathVariable String subject); + /** + * Delete the subject and all its versions. + * + * @param subject The subject (topic name, e.g., user-data) + * @return The list of versions that were deleted + */ @Delete("/subjects/{subject}") @SingleResult List deleteSubject(@PathVariable String subject); @@ -110,16 +138,32 @@ public interface SchemaRegistryClient { SubjectResponse getSubjectWithVersion(@PathVariable String subject, @PathVariable String version); + /** + * Get the schema string registered under this subject and version. + * + * @param subject The subject (topic name, e.g., user-data) + * @param version The version number or 'latest' as a string + * @return The requested schema + */ @Get("/subjects/{subject}/versions/{version}/schema") @SingleResult String getSchemaWithSubjectAndVersion(@PathVariable String subject, @PathVariable String version); + /** + * Register a new schema under the specified subject. (Essentially, create a new schema.) + * If successfully registered, this returns the unique identifier of this schema in the registry. + * + * @param subject The subject (topic name, e.g., user-data) + * @param schemaBody The new schema wished to be registered in the form of {@link SubjectRequestBody} + * @return The globally unique identifier of the schema + */ @Post("/subjects/{subject}/versions") @SingleResult HashMap registerNewVersion(@PathVariable String subject, @Body SubjectRequestBody schemaBody); + @Post("/subjects/{subject}") @SingleResult SubjectResponse createSubject(@PathVariable String subject, diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java deleted file mode 100644 index 4ba3f630..00000000 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryController.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2017-2025 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.jsonschema.registry; - -import io.micronaut.jsonschema.registry.types.SubjectResponse; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; - -/** - * A controller for the Confluent Schema Registry Client. - * - * @author Elif Kurtay - * @since 1.5.0 - */ -@Singleton -public class SchemaRegistryController { - private final SchemaRegistryClient client; - private final SchemaRegistryConfig config; - - @Inject - public SchemaRegistryController(SchemaRegistryClient client, SchemaRegistryConfig config) { - this.client = client; - this.config = config; - } - -} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java new file mode 100644 index 00000000..4150f9f9 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java @@ -0,0 +1,79 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry; + +import io.micronaut.context.annotation.Context; +import io.micronaut.core.beans.BeanIntrospector; +import io.micronaut.jsonschema.GeneratedFromSchema; +import io.micronaut.jsonschema.registry.types.SchemaType; +import io.micronaut.jsonschema.registry.types.SubjectRequestBody; +import jakarta.inject.Inject; + +import java.io.InputStream; +import java.util.HashSet; +import java.util.Set; + +/** + * A controller for the Confluent Schema Registry Client. + * + * @author Elif Kurtay + * @since 1.5.0 + */ +@Context +public class SchemaRegistryManager { + private final SchemaRegistryClient client; + + @Inject + public SchemaRegistryManager(SchemaRegistryClient client, SchemaRegistryConfig config) { + this.client = client; + if (config.isPushToRegistryEnabled()) { + pushToRegistry(); + } + } + + private void pushToRegistry() { + // push all schemas to registry + Set uniqueFileNames = new HashSet<>(); + BeanIntrospector.SHARED.findIntrospections(GeneratedFromSchema.class).forEach(beanIntrospection -> { + beanIntrospection.getAnnotation(GeneratedFromSchema.class) + .stringValue("fileName") + .ifPresent(uniqueFileNames::add); + }); + + // for each unique filename, get schema from file + uniqueFileNames.forEach(filename -> { + try (InputStream inputStream = getClass().getResourceAsStream(filename)) { + // get local schema file + assert inputStream != null; + var schemaString = new String(inputStream.readAllBytes()); + + // get schema from registry + var subjectName = filename.substring( + filename.contains("/") ? filename.lastIndexOf('/') : 0, + filename.contains(".") ? filename.indexOf('.') : filename.length()); + var responseSchemaString = client.getSchemaWithSubjectAndVersion(subjectName, "latest"); + // compare local vs registry, if different, push to registry + if (!schemaString.equals(responseSchemaString)) { + client.registerNewVersion( + subjectName, + new SubjectRequestBody(schemaString, SchemaType.JSON, null, null, null)); + } + } catch (Exception e) { + throw new RuntimeException("Error pushing schema to registry", e); + } + }); + } +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java index 567259d0..cd735e07 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java @@ -34,10 +34,4 @@ public record ReferenceType( String subject, String version) { } - - public enum SchemaType { - AVRO, - JSON, - PROTOBUF - } } diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index b1a286fe..fc5bbd21 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -13,6 +13,7 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -28,7 +29,7 @@ public class ConfluentClientTest { JsonMapper jsonMapper = new JsonMapper(); @Test - void testSchemaRegistryController() throws IOException { + void testGetSubjectWithVersion() throws IOException { Map items = new HashMap<>(); items.put("registry.url", "http://144.24.55.159:8081"); items.put("registry.username", "micronaut"); @@ -46,6 +47,41 @@ void testSchemaRegistryController() throws IOException { ctx.close(); } + @Test + void testGetSchemaWithSubjectAndVersion() throws IOException { + Map items = new HashMap<>(); + items.put("registry.url", "http://144.24.55.159:8081"); + items.put("registry.username", "micronaut"); + items.put("registry.password", "test"); + + ApplicationContext ctx = ApplicationContext.run(items); + SchemaRegistryClient client = ctx.getBean(SchemaRegistryClient.class); + String subject = "human"; + String version = "latest"; + String response = client.getSchemaWithSubjectAndVersion(subject, version); + + String expected = getExpectedResponse("human.schema.json"); + SubjectResponse mappedExpected = jsonMapper.readValue(expected, SubjectResponse.class); + assertEquals(mappedExpected.schema(), response); + ctx.close(); + } + + @Test + void testGetSubjectVersions() throws IOException { + Map items = new HashMap<>(); + items.put("registry.url", "http://144.24.55.159:8081"); + items.put("registry.username", "micronaut"); + items.put("registry.password", "test"); + + ApplicationContext ctx = ApplicationContext.run(items); + SchemaRegistryClient client = ctx.getBean(SchemaRegistryClient.class); + String subject = "human"; + List response = client.getSubjectVersions(subject); + + assertEquals(List.of(1), response); + ctx.close(); + } + private String getExpectedResponse(String filename) throws IOException { Optional expectedOptional = resourceLoader.getResourceAsStream(filename); assertTrue(expectedOptional.isPresent()); From 1ef41b2679c8ad6e0a05b150a8fc512065c15382 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Tue, 11 Feb 2025 15:55:46 +0100 Subject: [PATCH 12/24] re-org --- .../registry/SchemaRegistryClient.java | 190 ++++++++++++------ .../registry/SchemaRegistryManager.java | 14 +- .../registry/types/CompatibilityResponse.java | 24 --- .../registry/types/ModeResponse.java | 29 --- .../jsonschema/registry/types/Responses.java | 92 +++++++++ .../jsonschema/registry/types/SchemaType.java | 7 - .../registry/types/SubjectRequestBody.java | 2 +- .../registry/types/SubjectResponse.java | 28 --- .../registry/ConfluentClientTest.java | 8 +- 9 files changed, 241 insertions(+), 153 deletions(-) delete mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/CompatibilityResponse.java delete mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ModeResponse.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java delete mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java delete mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index f0a3bbf4..d8f23a6e 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -25,13 +25,10 @@ import io.micronaut.http.annotation.Post; import io.micronaut.http.annotation.Put; import io.micronaut.http.client.annotation.Client; -import io.micronaut.jsonschema.registry.types.CompatibilityResponse; -import io.micronaut.jsonschema.registry.types.ModeResponse; -import io.micronaut.jsonschema.registry.types.SubjectResponse; +import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.jsonschema.registry.types.SubjectRequestBody; import jakarta.inject.Singleton; -import java.util.HashMap; import java.util.List; /** @@ -53,7 +50,7 @@ @Singleton public interface SchemaRegistryClient { -// SCHEMA OPERATIONS ----------------------------------------------------------- +// SCHEMA OPERATIONS --------------------------------------------------------------------------- /** * Get the schema string identified by the input ID. @@ -63,7 +60,7 @@ public interface SchemaRegistryClient { */ @Get("/schemas/ids/{id}") @SingleResult - String getSchemaStringWithId(@PathVariable int id); + Responses.Schema getSchemaWithId(@PathVariable int id); /** * Retrieves only the schema identified by the input ID. @@ -73,7 +70,7 @@ public interface SchemaRegistryClient { */ @Get("/schemas/ids/{id}/schema") @SingleResult - String getSchemaWithId(@PathVariable int id); + String getSchemaStringWithId(@PathVariable int id); /** * Get the subject-version pairs identified by the input ID. @@ -83,7 +80,7 @@ public interface SchemaRegistryClient { */ @Get("/schemas/ids/{id}/versions") @SingleResult - List getSchemaVersionsWithId(@PathVariable int id); + List getSchemaVersionsWithId(@PathVariable int id); /** * Get the schema types that are registered with Schema Registry. @@ -92,10 +89,10 @@ public interface SchemaRegistryClient { */ @Get("/schemas/types") @SingleResult - List getSchemaTypes(); + List getSchemaTypes(); - // SUBJECTS ----------------------------------------------------------- + // SUBJECTS ------------------------------------------------------------------------------------ /** * Get the list of subjects that are registered with Schema Registry. @@ -135,15 +132,15 @@ public interface SchemaRegistryClient { */ @Get("/subjects/{subject}/versions/{version}") @SingleResult - SubjectResponse getSubjectWithVersion(@PathVariable String subject, - @PathVariable String version); + Responses.Subject getSubjectWithVersion(@PathVariable String subject, + @PathVariable String version); /** * Get the schema string registered under this subject and version. * * @param subject The subject (topic name, e.g., user-data) * @param version The version number or 'latest' as a string - * @return The requested schema + * @return The requested schema string (unescaped) */ @Get("/subjects/{subject}/versions/{version}/schema") @SingleResult @@ -160,104 +157,185 @@ String getSchemaWithSubjectAndVersion(@PathVariable String subject, */ @Post("/subjects/{subject}/versions") @SingleResult - HashMap registerNewVersion(@PathVariable String subject, - @Body SubjectRequestBody schemaBody); - + Responses.Id registerNewVersion(@PathVariable String subject, + @Body SubjectRequestBody schemaBody); + /** + * Checks if a schema has already been registered under the specified subject. + * + * @param subject Subject under which the schema will be registered + * @param schemaBody The new schema wished to be registered in the form of {@link SubjectRequestBody} + * @return the schema string along with its globally unique identifier, its version under this subject and the subject name. + */ @Post("/subjects/{subject}") @SingleResult - SubjectResponse createSubject(@PathVariable String subject, - @Body SubjectRequestBody schemaBody); + Responses.Subject createSubject(@PathVariable String subject, + @Body SubjectRequestBody schemaBody); + /** + * Deletes a specific version of the schema registered under this subject. + * + * @param subject Subject under which the schema is registered + * @param version The version number or 'latest' as a string + * @return The version number that was deleted + */ @Delete("/subjects/{subject}/versions/{version}") @SingleResult int deleteSubjectVersion(@PathVariable String subject, @PathVariable String version); + /** + * Get the list of versions that reference this schema. + * + * @param subject Subject under which the schema is registered + * @param version The version number or 'latest' as a string + * @return The list of versions that reference this schema + */ @Get("/subjects/{subject}/versions/{version}/referencedby") @SingleResult List getSubjectVersionReferencedBy(@PathVariable String subject, @PathVariable String version); + /** + * Get the metadata for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The metadata for the specified subject + */ @Get("/subjects/{subject}/metadata") @SingleResult - SubjectResponse getSubjectMetadata(@PathVariable String subject); + Responses.Subject getSubjectMetadata(@PathVariable String subject); + // MODE ---------------------------------------------------------------------------------------- /** - * MODE ----------------------------------------------------------- - * + GET /mode - * + PUT /mode - * + GET /mode/(string: subject) - * + PUT /mode/(string: subject) - * + DELETE /mode/(string: subject) + * Get the global compatibility mode. + * + * @return The global compatibility mode */ - @Get("/mode") @SingleResult - ModeResponse getMode(); + Responses.Mode getMode(); + /** + * Set the global compatibility mode. + * + * @param mode The new global compatibility mode + * @return The new global compatibility mode + */ @Put("/mode") @SingleResult - ModeResponse setMode(@Body ModeResponse mode); + Responses.Mode setMode(@Body Responses.Mode mode); + /** + * Get the compatibility mode for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The compatibility mode for the specified subject + */ @Get("/mode/{subject}") @SingleResult - ModeResponse getModeForSubject(@PathVariable String subject); + Responses.Mode getModeForSubject(@PathVariable String subject); + /** + * Set the compatibility mode for the specified subject. + * + * @param subject Subject under which the schema is registered + * @param mode The new compatibility mode for the specified subject + * @return The new compatibility mode for the specified subject + */ @Put("/mode/{subject}") @SingleResult - ModeResponse setModeForSubject(@PathVariable String subject, @Body ModeResponse mode); + Responses.Mode setModeForSubject(@PathVariable String subject, @Body Responses.Mode mode); + /** + * Delete the compatibility mode for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The compatibility mode that was deleted + */ @Delete("/mode/{subject}") @SingleResult - ModeResponse deleteModeForSubject(@PathVariable String subject); + Responses.Mode deleteModeForSubject(@PathVariable String subject); + // COMPATIBILITY --------------------------------------------------------------------------- /** - * COMPATIBILITY ----------------------------------------------------------- - * - POST /compatibility/subjects/(string: subject)/versions/(versionId: version) - * - POST /compatibility/subjects/(string: subject)/versions + * Test input schema against a particular version of a subject’s schema for compatibility. + * + * @param subject Subject under which the schema is registered + * @param version The version number or 'latest' as a string + * @param compatibilityRequest The new schema wished to be registered in the form of {@link SubjectRequestBody} + * @return Whether the new schema is compatible with the specified subject and version */ - @Post("/compatibility/subjects/{subject}/versions/{version}") @SingleResult - CompatibilityResponse checkCompatibilityForSubjectVersion(@PathVariable String subject, - @PathVariable String version, - @Body SubjectRequestBody compatibilityRequest); + Responses.Compatibility checkCompatibilityForSubjectVersion(@PathVariable String subject, + @PathVariable String version, + @Body SubjectRequestBody compatibilityRequest); + /** + * Perform a compatibility check on the schema against one or more versions in the subject, + * depending on how the compatibility is set. + * + * @param subject Subject under which the schema is registered + * @param compatibilityRequest The new schema to be checked in the form of {@link SubjectRequestBody} + * @return Whether the new schema is compatible with the specified subject + */ @Post("/compatibility/subjects/{subject}/versions") @SingleResult - CompatibilityResponse checkCompatibilityForSubject(@PathVariable String subject, - @Body SubjectRequestBody compatibilityRequest); + Responses.Compatibility checkCompatibilityForSubject(@PathVariable String subject, + @Body SubjectRequestBody compatibilityRequest); + + // CONFIG ---------------------------------------------------------------------------------- /** - * CONFIG ----------------------------------------------------------- - * TODO: - * - PUT /config - * - GET /config - * - PUT /config/(string: subject) - * - GET /config/(string: subject) - * - DELETE /config/(string: subject) + * Get the global configuration. + * + * @return The global configuration */ + @Get("/config") + @SingleResult + Responses.Config getConfig(); + /** + * Set the global configuration. + * + * @param config The new global configuration + * @return The new global configuration + */ @Put("/config") @SingleResult - String setConfig(@Body String config); + Responses.Config setConfig(@Body Responses.Config config); - @Get("/config") + /** + * Get the configuration for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The configuration for the specified subject + */ + @Get("/config/{subject}") @SingleResult - String getConfig(); + Responses.Config getConfigForSubject(@PathVariable String subject); + /** + * Set the configuration for the specified subject. + * + * @param subject Subject under which the schema is registered + * @param config The new configuration for the specified subject + * @return The new configuration for the specified subject + */ @Put("/config/{subject}") @SingleResult - String setConfigForSubject(@PathVariable String subject, @Body String config); - - @Get("/config/{subject}") - @SingleResult - String getConfigForSubject(@PathVariable String subject); + Responses.Config setConfigForSubject(@PathVariable String subject, @Body Responses.Config config); + /** + * Delete the configuration for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The configuration that was deleted + */ @Delete("/config/{subject}") @SingleResult - void deleteConfigForSubject(@PathVariable String subject); + Responses.Config deleteConfigForSubject(@PathVariable String subject); } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java index 4150f9f9..6ae8b882 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java @@ -16,9 +16,10 @@ package io.micronaut.jsonschema.registry; import io.micronaut.context.annotation.Context; +import io.micronaut.context.annotation.Requires; import io.micronaut.core.beans.BeanIntrospector; import io.micronaut.jsonschema.GeneratedFromSchema; -import io.micronaut.jsonschema.registry.types.SchemaType; +import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.jsonschema.registry.types.SubjectRequestBody; import jakarta.inject.Inject; @@ -27,11 +28,13 @@ import java.util.Set; /** - * A controller for the Confluent Schema Registry Client. + * A manager for the Confluent Schema Registry Client. * * @author Elif Kurtay * @since 1.5.0 */ +@Requires(beans = SchemaRegistryClient.class) +@Requires(beans = SchemaRegistryConfig.class) @Context public class SchemaRegistryManager { private final SchemaRegistryClient client; @@ -67,9 +70,12 @@ private void pushToRegistry() { var responseSchemaString = client.getSchemaWithSubjectAndVersion(subjectName, "latest"); // compare local vs registry, if different, push to registry if (!schemaString.equals(responseSchemaString)) { - client.registerNewVersion( + var response = client.registerNewVersion( subjectName, - new SubjectRequestBody(schemaString, SchemaType.JSON, null, null, null)); + new SubjectRequestBody(schemaString, Responses.SchemaType.JSON, null, null, null)); + if (response.id() == -1) { + throw new RuntimeException("Error pushing schema to registry"); + } } } catch (Exception e) { throw new RuntimeException("Error pushing schema to registry", e); diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/CompatibilityResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/CompatibilityResponse.java deleted file mode 100644 index 3761c1f0..00000000 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/CompatibilityResponse.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2017-2025 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.jsonschema.registry.types; - -import io.micronaut.serde.annotation.Serdeable; - -@Serdeable -public record CompatibilityResponse( - boolean is_compatible -) { -} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ModeResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ModeResponse.java deleted file mode 100644 index 87709a2b..00000000 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ModeResponse.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2017-2025 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.jsonschema.registry.types; - -import io.micronaut.serde.annotation.Serdeable; - -@Serdeable -public record ModeResponse( - ModeType mode -) { - enum ModeType { - IMPORT, - READONLY, - READWRITE - } -} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java new file mode 100644 index 00000000..f4bf43c0 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java @@ -0,0 +1,92 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.types; + +import com.fasterxml.jackson.annotation.JsonAlias; +import io.micronaut.core.annotation.Introspected; +import io.micronaut.serde.annotation.Serdeable; + +@Serdeable +public interface Responses { + enum SchemaType { + AVRO, + JSON, + PROTOBUF + } + + record Id( + int id + ) { + } + + record Schema( + String schema + ) { + } + + record SubjectVersion( + String subject, + int version + ) { + } + + @Introspected + record Subject( + String subject, + int id, + int version, + SchemaType schemaType, + String schema + ) { + } + + record Mode( + ModeType mode + ) { + enum ModeType { + IMPORT, + READONLY, + READWRITE + } + } + + record Compatibility( + boolean is_compatible + ) { + } + + enum CompatibilityLevel { + NONE, + BACKWARD, + BACKWARD_TRANSITIVE, + FORWARD, + FORWARD_TRANSITIVE, + FULL, + FULL_TRANSITIVE + } + + record Config( + String alias, + boolean normalize, + @JsonAlias("compatibilityLevel") CompatibilityLevel compatibility, + String compatibilityGroup, + Object defaultMetadata, + Object overrideMetadata, + Object defaultRuleSet, + Object overrideRuleSet + ) { + } +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java deleted file mode 100644 index 190415d2..00000000 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SchemaType.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.micronaut.jsonschema.registry.types; - -public enum SchemaType { - AVRO, - JSON, - PROTOBUF -} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java index cd735e07..6c11848a 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java @@ -24,7 +24,7 @@ @Serdeable public record SubjectRequestBody( String schema, - SchemaType schemaType, + Responses.SchemaType schemaType, List references, HashMap metadata, Set ruleSet diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java deleted file mode 100644 index 7d71e89d..00000000 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectResponse.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2017-2025 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.jsonschema.registry.types; - -import io.micronaut.serde.annotation.Serdeable; - -@Serdeable -public record SubjectResponse( - String subject, - int id, - int version, - SchemaType schemaType, - String schema -) { -} diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index fc5bbd21..0d6e309d 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import io.micronaut.context.ApplicationContext; import io.micronaut.core.io.ResourceLoader; -import io.micronaut.jsonschema.registry.types.SubjectResponse; +import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; @@ -39,10 +39,10 @@ void testGetSubjectWithVersion() throws IOException { SchemaRegistryClient client = ctx.getBean(SchemaRegistryClient.class); String subject = "human"; String version = "latest"; - SubjectResponse response = client.getSubjectWithVersion(subject, version); + Responses.Subject response = client.getSubjectWithVersion(subject, version); String expected = getExpectedResponse("human.schema.json"); - SubjectResponse mappedExpected = jsonMapper.readValue(expected, SubjectResponse.class); + Responses.Subject mappedExpected = jsonMapper.readValue(expected, Responses.Subject.class); assertEquals(mappedExpected, response); ctx.close(); } @@ -61,7 +61,7 @@ void testGetSchemaWithSubjectAndVersion() throws IOException { String response = client.getSchemaWithSubjectAndVersion(subject, version); String expected = getExpectedResponse("human.schema.json"); - SubjectResponse mappedExpected = jsonMapper.readValue(expected, SubjectResponse.class); + Responses.Subject mappedExpected = jsonMapper.readValue(expected, Responses.Subject.class); assertEquals(mappedExpected.schema(), response); ctx.close(); } From a7af47c180f0d562de63d209c01b1f5c914e8046 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Wed, 12 Feb 2025 17:24:15 +0100 Subject: [PATCH 13/24] controller tests --- json-schema-registry/build.gradle | 1 + .../registry/SchemaRegistryClient.java | 24 ++-- .../SchemaRegistryClientAuthFilter.java | 11 ++ .../registry/SchemaRegistryConfig.java | 40 +++++- .../registry/SchemaRegistryManager.java | 2 +- .../jsonschema/registry/types/Responses.java | 70 +++++++++- .../registry/types/SubjectRequestBody.java | 23 +++- .../jsonschema/registry/ClientTest.java | 72 ++++++++++ .../registry/ConfluentClientTest.java | 100 +++++++------- .../jsonschema/registry/TestController.java | 127 ++++++++++++++++++ 10 files changed, 407 insertions(+), 63 deletions(-) create mode 100644 json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java create mode 100644 json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/TestController.java diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle index f2fef98b..30881580 100644 --- a/json-schema-registry/build.gradle +++ b/json-schema-registry/build.gradle @@ -17,6 +17,7 @@ dependencies { testAnnotationProcessor(mn.micronaut.inject.java) testImplementation(mn.micronaut.inject) + testImplementation(mn.micronaut.http.server.netty) testImplementation(mnTest.micronaut.test.junit5) testImplementation(libs.junit.jupiter.api) testRuntimeOnly(libs.junit.jupiter.engine) diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index d8f23a6e..5007ae96 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -17,10 +17,11 @@ import io.micronaut.context.annotation.Requires; import io.micronaut.core.async.annotation.SingleResult; +import io.micronaut.http.MediaType; import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Consumes; import io.micronaut.http.annotation.Delete; import io.micronaut.http.annotation.Get; -import io.micronaut.http.annotation.Header; import io.micronaut.http.annotation.PathVariable; import io.micronaut.http.annotation.Post; import io.micronaut.http.annotation.Put; @@ -32,10 +33,10 @@ import java.util.List; /** - * A client for the Confluent Schema Registry. + * A client for the Confluent SchemaJson Registry. * *

Supports the operations defined in the - * Schema Registry API. + * SchemaJson Registry API. * *

The client is configured with the {@link SchemaRegistryConfig} file for its host address * and authentication. the configuration parameters are expected to be configured in the application context. @@ -46,7 +47,8 @@ @Client(value = "${registry.url}") @Requires(beans = SchemaRegistryConfig.class) @Requires(property = "registry.url") -@Header(name = "Content-Type", value = "application/vnd.schemaregistry.v1+json") +//@Header(name = "Content-Type", value = "application/vnd.schemaregistry.v1+json") +@Consumes(MediaType.APPLICATION_JSON) @Singleton public interface SchemaRegistryClient { @@ -60,13 +62,13 @@ public interface SchemaRegistryClient { */ @Get("/schemas/ids/{id}") @SingleResult - Responses.Schema getSchemaWithId(@PathVariable int id); + Responses.SchemaJson getSchemaWithId(@PathVariable int id); /** * Retrieves only the schema identified by the input ID. * * @param id The unique identifier of the schema - * @return Schema identified by the ID + * @return SchemaJson identified by the ID */ @Get("/schemas/ids/{id}/schema") @SingleResult @@ -83,7 +85,7 @@ public interface SchemaRegistryClient { List getSchemaVersionsWithId(@PathVariable int id); /** - * Get the schema types that are registered with Schema Registry. + * Get the schema types that are registered with SchemaJson Registry. * * @return The list of schema types */ @@ -95,7 +97,7 @@ public interface SchemaRegistryClient { // SUBJECTS ------------------------------------------------------------------------------------ /** - * Get the list of subjects that are registered with Schema Registry. + * Get the list of subjects that are registered with SchemaJson Registry. * * @return The list of subject names */ @@ -169,7 +171,7 @@ Responses.Id registerNewVersion(@PathVariable String subject, */ @Post("/subjects/{subject}") @SingleResult - Responses.Subject createSubject(@PathVariable String subject, + Responses.Subject checkSubject(@PathVariable String subject, @Body SubjectRequestBody schemaBody); /** @@ -261,10 +263,10 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, // COMPATIBILITY --------------------------------------------------------------------------- /** - * Test input schema against a particular version of a subject’s schema for compatibility. + * Test input schema against a particular version of a subject's schema for compatibility. * * @param subject Subject under which the schema is registered - * @param version The version number or 'latest' as a string + * @param version The version number or 'latest' as a string * @param compatibilityRequest The new schema wished to be registered in the form of {@link SubjectRequestBody} * @return Whether the new schema is compatible with the specified subject and version */ diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java index dcbff8f1..a66f9fa7 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java @@ -20,6 +20,12 @@ import io.micronaut.http.annotation.ClientFilter; import io.micronaut.http.annotation.RequestFilter; +/** + * A client filter that adds basic auth to all requests. + * + * @since 1.4.0 + * @author Elif Kurtay + */ @ClientFilter("/**") @Requires(beans = SchemaRegistryConfig.class) @Requires(property = "registry.username") @@ -31,6 +37,11 @@ public SchemaRegistryClientAuthFilter(SchemaRegistryConfig config) { this.config = config; } + /** + * Do basic auth on all requests. + * + * @param request The request + */ @RequestFilter public void doFilter(MutableHttpRequest request) { request.basicAuth(config.getUsername(), config.getPassword()); diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index 500085c9..11a43619 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -19,11 +19,17 @@ import io.micronaut.serde.annotation.Serdeable; import jakarta.validation.constraints.NotBlank; +/** + * Configuration for the schema registry. + * + * @since 1.5.0 + * @author Elif Kurtay + */ @Serdeable @ConfigurationProperties("registry") public class SchemaRegistryConfig { @NotBlank - public String url; + private String url; @NotBlank private String username; @NotBlank @@ -33,26 +39,58 @@ public class SchemaRegistryConfig { public SchemaRegistryConfig() { } + /** + * @return The URL of the schema registry + */ + public @NotBlank String getUrl() { + return url; + } + + /** + * @param url The URL of the schema registry + */ + public void setUrl(@NotBlank String url) { + this.url = url; + } + + /** + * @return The username to authenticate with + */ public String getUsername() { return username; } + /** + * @param username The username to authenticate with + */ public void setUsername(String username) { this.username = username; } + /** + * @return The password to authenticate with + */ public String getPassword() { return password; } + /** + * @param password The password to authenticate with + */ public void setPassword(String password) { this.password = password; } + /** + * @return Whether to push to the registry + */ public boolean isPushToRegistryEnabled() { return pushToRegistryEnabled; } + /** + * @param pushToRegistryEnabled Whether to push to the registry + */ public void setPushToRegistryEnabled(boolean pushToRegistryEnabled) { this.pushToRegistryEnabled = pushToRegistryEnabled; } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java index 6ae8b882..b5da71ff 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java @@ -28,7 +28,7 @@ import java.util.Set; /** - * A manager for the Confluent Schema Registry Client. + * A manager for the Confluent SchemaJson Registry Client. * * @author Elif Kurtay * @since 1.5.0 diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java index f4bf43c0..f539d10d 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java @@ -19,30 +19,64 @@ import io.micronaut.core.annotation.Introspected; import io.micronaut.serde.annotation.Serdeable; +/** + * Response types for the JSON Schema Registry Client. + */ @Serdeable public interface Responses { + /** + * The Schema Types available on the registry. + */ enum SchemaType { AVRO, JSON, PROTOBUF } + /** + * The ID of a schema. + * + * @param id The ID + */ + @Introspected record Id( int id ) { } - record Schema( + /** + * The JSON Schema in string. + * + * @param schema The schema string + */ + @Introspected + record SchemaJson( String schema ) { } + /** + * The (subject,version) pairs available at the registry. + * + * @param subject The subject name + * @param version The version of the subject + */ + @Introspected record SubjectVersion( String subject, int version ) { } + /** + * The subject details available at the registry. + * + * @param subject The subject name + * @param id The unique global ID of the schema + * @param version The version of the schema + * @param schemaType The type of the schema + * @param schema The schema string + */ @Introspected record Subject( String subject, @@ -53,21 +87,39 @@ record Subject( ) { } + /** + * The mode of the registry. + * + * @param mode The mode type + */ + @Introspected record Mode( ModeType mode ) { - enum ModeType { + /** + * The mode type. + */ + public enum ModeType { IMPORT, READONLY, READWRITE } } + /** + * The compatibility of the schema. + * + * @param is_compatible Whether the two schemas are compatible + */ + @Introspected record Compatibility( boolean is_compatible ) { } + /** + * The compatibility level. + */ enum CompatibilityLevel { NONE, BACKWARD, @@ -78,6 +130,20 @@ enum CompatibilityLevel { FULL_TRANSITIVE } + /** + * The configuration of the registry. + * + * @param alias The alias of the registry + * @param normalize Whether to normalize the schema + * @param compatibility The compatibility level + * @param compatibilityGroup The compatibility group + * (used for compatibility checks) + * @param defaultMetadata The default metadata + * @param overrideMetadata The override metadata + * @param defaultRuleSet The default rule set + * @param overrideRuleSet The override rule set + */ + @Introspected record Config( String alias, boolean normalize, diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java index 6c11848a..f031f310 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java @@ -15,20 +15,39 @@ */ package io.micronaut.jsonschema.registry.types; +import io.micronaut.core.annotation.Introspected; import io.micronaut.serde.annotation.Serdeable; -import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; +/** + * Represents a request body for a subject in the Schema Registry. + * + * @param schema The schema. + * @param schemaType The schema type. + * @param references The references. + * @param metadata The metadata. + * @param ruleSet The rule set. + */ @Serdeable +@Introspected public record SubjectRequestBody( String schema, Responses.SchemaType schemaType, List references, - HashMap metadata, + Map metadata, Set ruleSet ) { + /** + * The reference type used in the schema registry. + * + * @param name The reference name. + * @param subject The subject name. + * @param version The subject version. + */ + @Introspected public record ReferenceType( String name, String subject, diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java new file mode 100644 index 00000000..42199f14 --- /dev/null +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java @@ -0,0 +1,72 @@ +package io.micronaut.jsonschema.registry; + +import com.fasterxml.jackson.databind.json.JsonMapper; +import io.micronaut.context.annotation.Property; +import io.micronaut.core.io.ResourceLoader; +import io.micronaut.jsonschema.registry.types.Responses; +import io.micronaut.jsonschema.registry.types.SubjectRequestBody; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@MicronautTest +@Property(name = "registry.url", value = "/test/") +public class ClientTest { + + @Inject + ResourceLoader resourceLoader; + @Inject + SchemaRegistryClient client; + + Responses.Subject exampleSubject; + + @Test + void testAddNewSubject() throws IOException { + prepareTestData(); + // register new subject + var body = new SubjectRequestBody(exampleSubject.schema(), Responses.SchemaType.JSON, List.of(), Map.of(), Set.of()); + var response = client.registerNewVersion(exampleSubject.subject(), body); + + // check subject is correctly registered + assertEquals(2, response.id()); + assertEquals(1, client.getSubjects().size()); + assertEquals(List.of(1), client.getSubjectVersions(exampleSubject.subject())); + assertEquals(exampleSubject, client.getSubjectWithVersion(exampleSubject.subject(), "1")); + assertEquals(exampleSubject, client.getSubjectWithVersion(exampleSubject.subject(), "latest")); + assertEquals(exampleSubject, client.checkSubject(exampleSubject.subject(), body)); + assertEquals(1, client.getSubjects().size()); + + // delete non-existing version + assertEquals(-1, client.deleteSubjectVersion(exampleSubject.subject(), "2")); + + // delete subject + assertEquals(List.of(1), client.deleteSubject(exampleSubject.subject())); + assertEquals(0, client.getSubjects().size()); + } + + @Test + void testGetSubjects() { + var response = client.getSubjects(); + assertEquals(0, response.size()); + } + + public void prepareTestData() throws IOException { + JsonMapper jsonMapper = new JsonMapper(); + Optional expectedOptional = resourceLoader.getResourceAsStream("human.schema.json"); + assertTrue(expectedOptional.isPresent()); + String expected = new String(expectedOptional.get().readAllBytes(), StandardCharsets.UTF_8); + expected = expected.replaceAll("\\s+", "").trim(); + exampleSubject = jsonMapper.readValue(expected, Responses.Subject.class); + } +} diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index 0d6e309d..97cda0ac 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -1,7 +1,7 @@ package io.micronaut.jsonschema.registry; import com.fasterxml.jackson.databind.json.JsonMapper; -import io.micronaut.context.ApplicationContext; +import io.micronaut.context.annotation.Property; import io.micronaut.core.io.ResourceLoader; import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; @@ -12,74 +12,82 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Optional; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; +/** + * Tests for the ConfluentClient for Schema Registry. + * Checking the response types from the client. + */ @MicronautTest +@Property(name = "registry.url", value = "http://144.24.55.159:8081/") +@Property(name = "registry.username", value = "micronaut") +@Property(name = "registry.password", value = "test") public class ConfluentClientTest { @Inject ResourceLoader resourceLoader; + @Inject + SchemaRegistryClient client; JsonMapper jsonMapper = new JsonMapper(); @Test - void testGetSubjectWithVersion() throws IOException { - Map items = new HashMap<>(); - items.put("registry.url", "http://144.24.55.159:8081"); - items.put("registry.username", "micronaut"); - items.put("registry.password", "test"); - - ApplicationContext ctx = ApplicationContext.run(items); - SchemaRegistryClient client = ctx.getBean(SchemaRegistryClient.class); - String subject = "human"; - String version = "latest"; - Responses.Subject response = client.getSubjectWithVersion(subject, version); + void testGetWithSchemas() { + var response = client.getSchemaWithId(1); + assertEquals(new Responses.SchemaJson("\"string\""), response); - String expected = getExpectedResponse("human.schema.json"); - Responses.Subject mappedExpected = jsonMapper.readValue(expected, Responses.Subject.class); - assertEquals(mappedExpected, response); - ctx.close(); + var response2 = client.getSchemaStringWithId(1); + assertEquals("\"string\"", response2); + + var response3 = client.getSchemaVersionsWithId(1); + assertEquals(List.of(new Responses.SubjectVersion("my_subject", 1)), response3); + + var response4 = client.getSchemaTypes(); + assertEquals(List.of(Responses.SchemaType.JSON, Responses.SchemaType.PROTOBUF, Responses.SchemaType.AVRO), response4); } @Test - void testGetSchemaWithSubjectAndVersion() throws IOException { - Map items = new HashMap<>(); - items.put("registry.url", "http://144.24.55.159:8081"); - items.put("registry.username", "micronaut"); - items.put("registry.password", "test"); - - ApplicationContext ctx = ApplicationContext.run(items); - SchemaRegistryClient client = ctx.getBean(SchemaRegistryClient.class); - String subject = "human"; - String version = "latest"; - String response = client.getSchemaWithSubjectAndVersion(subject, version); + void testConfigGetters() { + var response1 = client.getConfig(); + assertEquals(new Responses.Config(null, false, Responses.CompatibilityLevel.BACKWARD, + null, null, null, null, null), response1); + } - String expected = getExpectedResponse("human.schema.json"); - Responses.Subject mappedExpected = jsonMapper.readValue(expected, Responses.Subject.class); - assertEquals(mappedExpected.schema(), response); - ctx.close(); + @Test + void testModeGetters() { + var response1 = client.getMode(); + assertEquals(new Responses.Mode(Responses.Mode.ModeType.READWRITE), response1); + assertNull(client.getModeForSubject("human")); } @Test - void testGetSubjectVersions() throws IOException { - Map items = new HashMap<>(); - items.put("registry.url", "http://144.24.55.159:8081"); - items.put("registry.username", "micronaut"); - items.put("registry.password", "test"); - - ApplicationContext ctx = ApplicationContext.run(items); - SchemaRegistryClient client = ctx.getBean(SchemaRegistryClient.class); - String subject = "human"; - List response = client.getSubjectVersions(subject); - - assertEquals(List.of(1), response); - ctx.close(); + void testGetSubject() throws IOException { + var response1 = client.getSubjects(); + assertEquals(List.of("human", "my_subject"), response1); + + List response2 = client.getSubjectVersions("human"); + assertEquals(List.of(1), response2); + + // prepare expected response + String expected = getExpectedResponse("human.schema.json"); + Responses.Subject subjectExpected = jsonMapper.readValue(expected, Responses.Subject.class); + + Responses.Subject response3 = client.getSubjectWithVersion("human", "latest"); + assertEquals(subjectExpected, response3); + + String response4 = client.getSchemaWithSubjectAndVersion("human", "latest"); + assertEquals(subjectExpected.schema(), response4); + + var response5 = client.getSubjectVersionReferencedBy("human", "latest"); + assertEquals(List.of(), response5); + + Responses.Subject response6 = client.getSubjectMetadata("human"); + assertNull(response6); } private String getExpectedResponse(String filename) throws IOException { diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/TestController.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/TestController.java new file mode 100644 index 00000000..cae1cd8a --- /dev/null +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/TestController.java @@ -0,0 +1,127 @@ +package io.micronaut.jsonschema.registry; + +import io.micronaut.core.async.annotation.SingleResult; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Consumes; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Delete; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Post; +import io.micronaut.jsonschema.registry.types.Responses; +import io.micronaut.jsonschema.registry.types.SubjectRequestBody; + +import java.util.ArrayList; +import java.util.List; + +@Controller("/test") +@Consumes(MediaType.APPLICATION_JSON) +public class TestController { + private final List subjects = new ArrayList<>(); + private int idCounter = 2; + + @Post("/subjects/{subject}/versions") + @SingleResult + Responses.Id registerNewVersion(@PathVariable String subject, + @Body SubjectRequestBody schemaBody) { + // check if subject already exists and get its latest version + var existingSubject = getExistingLatestSubject(subject); + var version = 1; + if (existingSubject != null) { + if (existingSubject.schema().equals(schemaBody.schema())) { + return new Responses.Id(existingSubject.id()); + } + version = existingSubject.version() + 1; + } + var newSubject = new Responses.Subject(subject, idCounter, version, schemaBody.schemaType(), schemaBody.schema()); + subjects.add(newSubject); + idCounter++; + return new Responses.Id(newSubject.id()); + } + + @Get("/subjects") + @SingleResult + List getSubjects() { + return subjects.stream() + .map(Responses.Subject::subject) + .distinct() + .toList(); + } + + @Get("/subjects/{subject}/versions") + @SingleResult + List getSubjectVersions(@PathVariable String subject) { + return subjects.stream() + .filter(s -> s.subject().equals(subject)) + .map(Responses.Subject::version) + .toList(); + } + + @Delete("/subjects/{subject}") + @SingleResult + List deleteSubject(@PathVariable String subject) { + var deletedVersions = subjects.stream() + .filter(s -> s.subject().equals(subject)) + .map(Responses.Subject::version) + .toList(); + subjects.removeIf(s -> s.subject().equals(subject)); + return deletedVersions; + } + + @Get("/subjects/{subject}/versions/{version}") + @SingleResult + Responses.Subject getSubjectWithVersion(@PathVariable String subject, + @PathVariable String version) { + if (version.equals("latest")) { + return getExistingLatestSubject(subject); + } + return subjects.stream() + .filter(s -> s.subject().equals(subject) && s.version() == Integer.parseInt(version)) + .findFirst() + .orElse(null); + } + + @Get("/subjects/{subject}/versions/{version}/schema") + @SingleResult + String getSchemaWithSubjectAndVersion(@PathVariable String subject, + @PathVariable String version) { + var subjectResponse = getSubjectWithVersion(subject, version); + return subjectResponse != null ? subjectResponse.schema() : null; + } + + @Post("/subjects/{subject}") + @SingleResult + Responses.Subject checkSubject(@PathVariable String subject, + @Body SubjectRequestBody schemaBody) { + return subjects.stream() + .filter(s -> s.subject().equals(subject) && s.schema().equals(schemaBody.schema())) + .findFirst().orElse(null); + } + + @Delete("/subjects/{subject}/versions/{version}") + @SingleResult + int deleteSubjectVersion(@PathVariable String subject, + @PathVariable String version) { + if (version.equals("latest")) { + var latest = getExistingLatestSubject(subject); + if (latest != null) { + subjects.remove(latest); + return latest.version(); + } + return -1; + } + int versionInt = Integer.parseInt(version); + if (!subjects.removeIf(s -> s.subject().equals(subject) && s.version() == versionInt)) { + return -1; + } + return versionInt; + } + + private Responses.Subject getExistingLatestSubject(String subject) { + return subjects.stream() + .filter(s -> s.subject().equals(subject)) + .max((s1, s2) -> Integer.compare(s2.version(), s1.version())) + .orElse(null); + } +} From ae6a4f3d89073f6a403c4750a77af5cb48969a82 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Thu, 13 Feb 2025 13:26:34 +0100 Subject: [PATCH 14/24] filter matcher --- .../jsonschema/GeneratedFromSchema.java | 3 + .../registry/SchemaRegistryClient.java | 10 +- .../registry/SchemaRegistryConfig.java | 15 +- .../registry/basicauth/BasicAuth.java | 33 ++ .../SchemaRegistryBasicAuthClient.java | 345 ++++++++++++++++++ .../SchemaRegistryClientAuthFilter.java | 13 +- .../jsonschema/registry/types/ConfigKeys.java | 24 ++ .../jsonschema/registry/ClientTest.java | 3 +- .../registry/ConfluentClientTest.java | 10 +- src/main/docs/guide/generator/support.adoc | 2 +- 10 files changed, 435 insertions(+), 23 deletions(-) create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/BasicAuth.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java rename json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/{ => basicauth}/SchemaRegistryClientAuthFilter.java (82%) create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java diff --git a/json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java b/json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java index a712023b..ea95435d 100644 --- a/json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java +++ b/json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java @@ -16,6 +16,8 @@ package io.micronaut.jsonschema; import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** @@ -24,6 +26,7 @@ * @since 1.5.0 * @author Elif Kurtay */ +@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE }) public @interface GeneratedFromSchema { diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 5007ae96..62d48fee 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -26,14 +26,14 @@ import io.micronaut.http.annotation.Post; import io.micronaut.http.annotation.Put; import io.micronaut.http.client.annotation.Client; +import io.micronaut.jsonschema.registry.types.ConfigKeys; import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.jsonschema.registry.types.SubjectRequestBody; -import jakarta.inject.Singleton; import java.util.List; /** - * A client for the Confluent SchemaJson Registry. + * A client for the Confluent Json Schema Registry. * *

Supports the operations defined in the * SchemaJson Registry API. @@ -44,12 +44,10 @@ * @author Elif Kurtay * @since 1.5.0 */ -@Client(value = "${registry.url}") +@Client(value = "${" + ConfigKeys.ORIGIN + "}") @Requires(beans = SchemaRegistryConfig.class) -@Requires(property = "registry.url") -//@Header(name = "Content-Type", value = "application/vnd.schemaregistry.v1+json") +@Requires(property = ConfigKeys.ORIGIN) @Consumes(MediaType.APPLICATION_JSON) -@Singleton public interface SchemaRegistryClient { // SCHEMA OPERATIONS --------------------------------------------------------------------------- diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index 11a43619..0d61dbdd 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -16,6 +16,7 @@ package io.micronaut.jsonschema.registry; import io.micronaut.context.annotation.ConfigurationProperties; +import io.micronaut.jsonschema.registry.types.ConfigKeys; import io.micronaut.serde.annotation.Serdeable; import jakarta.validation.constraints.NotBlank; @@ -26,10 +27,10 @@ * @author Elif Kurtay */ @Serdeable -@ConfigurationProperties("registry") +@ConfigurationProperties(ConfigKeys.CONFIG_NAME) public class SchemaRegistryConfig { @NotBlank - private String url; + private String origin; @NotBlank private String username; @NotBlank @@ -42,15 +43,15 @@ public SchemaRegistryConfig() { /** * @return The URL of the schema registry */ - public @NotBlank String getUrl() { - return url; + public @NotBlank String getOrigin() { + return origin; } /** - * @param url The URL of the schema registry + * @param origin The URL of the schema registry */ - public void setUrl(@NotBlank String url) { - this.url = url; + public void setOrigin(@NotBlank String origin) { + this.origin = origin; } /** diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/BasicAuth.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/BasicAuth.java new file mode 100644 index 00000000..46e5a38a --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/BasicAuth.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.basicauth; + +import io.micronaut.http.annotation.FilterMatcher; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@FilterMatcher +@Documented +@Retention(RUNTIME) +@Target({TYPE, PARAMETER}) +public @interface BasicAuth { +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java new file mode 100644 index 00000000..2a038fa8 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java @@ -0,0 +1,345 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.basicauth; + +import io.micronaut.context.annotation.Requires; +import io.micronaut.core.async.annotation.SingleResult; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Consumes; +import io.micronaut.http.annotation.Delete; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.annotation.Put; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.jsonschema.registry.SchemaRegistryConfig; +import io.micronaut.jsonschema.registry.types.ConfigKeys; +import io.micronaut.jsonschema.registry.types.Responses; +import io.micronaut.jsonschema.registry.types.SubjectRequestBody; +import jakarta.inject.Singleton; + +import java.util.List; + +/** + * A client for the Confluent Json Schema Registry. + * + *

Supports the operations defined in the + * SchemaJson Registry API. + * + *

The client is configured with the {@link SchemaRegistryConfig} file for its host address + * and authentication. the configuration parameters are expected to be configured in the application context. + * + * @author Elif Kurtay + * @since 1.5.0 + */ +@BasicAuth +@Client(value = "${" + ConfigKeys.ORIGIN + "}") +@Requires(beans = SchemaRegistryConfig.class) +@Requires(property = ConfigKeys.ORIGIN) +@Consumes(MediaType.APPLICATION_JSON) +@Singleton +public interface SchemaRegistryBasicAuthClient { + +// SCHEMA OPERATIONS --------------------------------------------------------------------------- + + /** + * Get the schema string identified by the input ID. + * + * @param id The unique identifier of the schema + * @return The schema string identified by the input ID + */ + @Get("/schemas/ids/{id}") + @SingleResult + Responses.SchemaJson getSchemaWithId(@PathVariable int id); + + /** + * Retrieves only the schema identified by the input ID. + * + * @param id The unique identifier of the schema + * @return SchemaJson identified by the ID + */ + @Get("/schemas/ids/{id}/schema") + @SingleResult + String getSchemaStringWithId(@PathVariable int id); + + /** + * Get the subject-version pairs identified by the input ID. + * + * @param id The unique identifier of the schema + * @return The subject-version pairs + */ + @Get("/schemas/ids/{id}/versions") + @SingleResult + List getSchemaVersionsWithId(@PathVariable int id); + + /** + * Get the schema types that are registered with SchemaJson Registry. + * + * @return The list of schema types + */ + @Get("/schemas/types") + @SingleResult + List getSchemaTypes(); + + + // SUBJECTS ------------------------------------------------------------------------------------ + + /** + * Get the list of subjects that are registered with SchemaJson Registry. + * + * @return The list of subject names + */ + @Get("/subjects") + @SingleResult + List getSubjects(); + + /** + * Get the list of versions of the schema registered under this subject. + * + * @param subject The subject (topic name, e.g., user-data) + * @return The list of versions + */ + @Get("/subjects/{subject}/versions") + @SingleResult + List getSubjectVersions(@PathVariable String subject); + + /** + * Delete the subject and all its versions. + * + * @param subject The subject (topic name, e.g., user-data) + * @return The list of versions that were deleted + */ + @Delete("/subjects/{subject}") + @SingleResult + List deleteSubject(@PathVariable String subject); + + /** + * Get a specific version of the schema registered under this subject. + * + * @param subject The subject (topic name, e.g., user-data) + * @param version The version number or 'latest' as a string + * @return The requested schema + */ + @Get("/subjects/{subject}/versions/{version}") + @SingleResult + Responses.Subject getSubjectWithVersion(@PathVariable String subject, + @PathVariable String version); + + /** + * Get the schema string registered under this subject and version. + * + * @param subject The subject (topic name, e.g., user-data) + * @param version The version number or 'latest' as a string + * @return The requested schema string (unescaped) + */ + @Get("/subjects/{subject}/versions/{version}/schema") + @SingleResult + String getSchemaWithSubjectAndVersion(@PathVariable String subject, + @PathVariable String version); + + /** + * Register a new schema under the specified subject. (Essentially, create a new schema.) + * If successfully registered, this returns the unique identifier of this schema in the registry. + * + * @param subject The subject (topic name, e.g., user-data) + * @param schemaBody The new schema wished to be registered in the form of {@link SubjectRequestBody} + * @return The globally unique identifier of the schema + */ + @Post("/subjects/{subject}/versions") + @SingleResult + Responses.Id registerNewVersion(@PathVariable String subject, + @Body SubjectRequestBody schemaBody); + + /** + * Checks if a schema has already been registered under the specified subject. + * + * @param subject Subject under which the schema will be registered + * @param schemaBody The new schema wished to be registered in the form of {@link SubjectRequestBody} + * @return the schema string along with its globally unique identifier, its version under this subject and the subject name. + */ + @Post("/subjects/{subject}") + @SingleResult + Responses.Subject checkSubject(@PathVariable String subject, + @Body SubjectRequestBody schemaBody); + + /** + * Deletes a specific version of the schema registered under this subject. + * + * @param subject Subject under which the schema is registered + * @param version The version number or 'latest' as a string + * @return The version number that was deleted + */ + @Delete("/subjects/{subject}/versions/{version}") + @SingleResult + int deleteSubjectVersion(@PathVariable String subject, + @PathVariable String version); + + /** + * Get the list of versions that reference this schema. + * + * @param subject Subject under which the schema is registered + * @param version The version number or 'latest' as a string + * @return The list of versions that reference this schema + */ + @Get("/subjects/{subject}/versions/{version}/referencedby") + @SingleResult + List getSubjectVersionReferencedBy(@PathVariable String subject, + @PathVariable String version); + + /** + * Get the metadata for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The metadata for the specified subject + */ + @Get("/subjects/{subject}/metadata") + @SingleResult + Responses.Subject getSubjectMetadata(@PathVariable String subject); + + // MODE ---------------------------------------------------------------------------------------- + + /** + * Get the global compatibility mode. + * + * @return The global compatibility mode + */ + @Get("/mode") + @SingleResult + Responses.Mode getMode(); + + /** + * Set the global compatibility mode. + * + * @param mode The new global compatibility mode + * @return The new global compatibility mode + */ + @Put("/mode") + @SingleResult + Responses.Mode setMode(@Body Responses.Mode mode); + + /** + * Get the compatibility mode for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The compatibility mode for the specified subject + */ + @Get("/mode/{subject}") + @SingleResult + Responses.Mode getModeForSubject(@PathVariable String subject); + + /** + * Set the compatibility mode for the specified subject. + * + * @param subject Subject under which the schema is registered + * @param mode The new compatibility mode for the specified subject + * @return The new compatibility mode for the specified subject + */ + @Put("/mode/{subject}") + @SingleResult + Responses.Mode setModeForSubject(@PathVariable String subject, @Body Responses.Mode mode); + + /** + * Delete the compatibility mode for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The compatibility mode that was deleted + */ + @Delete("/mode/{subject}") + @SingleResult + Responses.Mode deleteModeForSubject(@PathVariable String subject); + + // COMPATIBILITY --------------------------------------------------------------------------- + + /** + * Test input schema against a particular version of a subject's schema for compatibility. + * + * @param subject Subject under which the schema is registered + * @param version The version number or 'latest' as a string + * @param compatibilityRequest The new schema wished to be registered in the form of {@link SubjectRequestBody} + * @return Whether the new schema is compatible with the specified subject and version + */ + @Post("/compatibility/subjects/{subject}/versions/{version}") + @SingleResult + Responses.Compatibility checkCompatibilityForSubjectVersion(@PathVariable String subject, + @PathVariable String version, + @Body SubjectRequestBody compatibilityRequest); + + /** + * Perform a compatibility check on the schema against one or more versions in the subject, + * depending on how the compatibility is set. + * + * @param subject Subject under which the schema is registered + * @param compatibilityRequest The new schema to be checked in the form of {@link SubjectRequestBody} + * @return Whether the new schema is compatible with the specified subject + */ + @Post("/compatibility/subjects/{subject}/versions") + @SingleResult + Responses.Compatibility checkCompatibilityForSubject(@PathVariable String subject, + @Body SubjectRequestBody compatibilityRequest); + + // CONFIG ---------------------------------------------------------------------------------- + + /** + * Get the global configuration. + * + * @return The global configuration + */ + @Get("/config") + @SingleResult + Responses.Config getConfig(); + + /** + * Set the global configuration. + * + * @param config The new global configuration + * @return The new global configuration + */ + @Put("/config") + @SingleResult + Responses.Config setConfig(@Body Responses.Config config); + + /** + * Get the configuration for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The configuration for the specified subject + */ + @Get("/config/{subject}") + @SingleResult + Responses.Config getConfigForSubject(@PathVariable String subject); + + /** + * Set the configuration for the specified subject. + * + * @param subject Subject under which the schema is registered + * @param config The new configuration for the specified subject + * @return The new configuration for the specified subject + */ + @Put("/config/{subject}") + @SingleResult + Responses.Config setConfigForSubject(@PathVariable String subject, @Body Responses.Config config); + + /** + * Delete the configuration for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The configuration that was deleted + */ + @Delete("/config/{subject}") + @SingleResult + Responses.Config deleteConfigForSubject(@PathVariable String subject); +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryClientAuthFilter.java similarity index 82% rename from json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java rename to json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryClientAuthFilter.java index a66f9fa7..55636874 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryClientAuthFilter.java @@ -13,12 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.jsonschema.registry; +package io.micronaut.jsonschema.registry.basicauth; import io.micronaut.context.annotation.Requires; import io.micronaut.http.MutableHttpRequest; import io.micronaut.http.annotation.ClientFilter; import io.micronaut.http.annotation.RequestFilter; +import io.micronaut.jsonschema.registry.SchemaRegistryConfig; +import io.micronaut.jsonschema.registry.types.ConfigKeys; +import jakarta.inject.Singleton; /** * A client filter that adds basic auth to all requests. @@ -26,10 +29,12 @@ * @since 1.4.0 * @author Elif Kurtay */ -@ClientFilter("/**") @Requires(beans = SchemaRegistryConfig.class) -@Requires(property = "registry.username") -@Requires(property = "registry.password") +@Requires(property = ConfigKeys.USERNAME) +@Requires(property = ConfigKeys.PASSWORD) +@BasicAuth +@Singleton +@ClientFilter("/**") public class SchemaRegistryClientAuthFilter { private final SchemaRegistryConfig config; diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java new file mode 100644 index 00000000..f771c802 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java @@ -0,0 +1,24 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.types; + +public final class ConfigKeys { + public static final String CONFIG_NAME = "schema.registry"; + public static final String ORIGIN = CONFIG_NAME + ".origin"; + public static final String USERNAME = CONFIG_NAME + ".username"; + public static final String PASSWORD = CONFIG_NAME + ".password"; + public static final String PUSH_TO_REGISTRY_ENABLED = CONFIG_NAME + ".push-to-registry-enabled"; +} diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java index 42199f14..c4e449b9 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import io.micronaut.context.annotation.Property; import io.micronaut.core.io.ResourceLoader; +import io.micronaut.jsonschema.registry.types.ConfigKeys; import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.jsonschema.registry.types.SubjectRequestBody; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; @@ -21,7 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @MicronautTest -@Property(name = "registry.url", value = "/test/") +@Property(name = ConfigKeys.ORIGIN, value = "/test/") public class ClientTest { @Inject diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index 97cda0ac..e0cb2950 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import io.micronaut.context.annotation.Property; import io.micronaut.core.io.ResourceLoader; +import io.micronaut.jsonschema.registry.basicauth.SchemaRegistryBasicAuthClient; +import io.micronaut.jsonschema.registry.types.ConfigKeys; import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; @@ -24,15 +26,15 @@ * Checking the response types from the client. */ @MicronautTest -@Property(name = "registry.url", value = "http://144.24.55.159:8081/") -@Property(name = "registry.username", value = "micronaut") -@Property(name = "registry.password", value = "test") +@Property(name = ConfigKeys.ORIGIN, value = "http://144.24.55.159:8081/") +@Property(name = ConfigKeys.USERNAME, value = "micronaut") +@Property(name = ConfigKeys.PASSWORD, value = "test") public class ConfluentClientTest { @Inject ResourceLoader resourceLoader; @Inject - SchemaRegistryClient client; + SchemaRegistryBasicAuthClient client; JsonMapper jsonMapper = new JsonMapper(); diff --git a/src/main/docs/guide/generator/support.adoc b/src/main/docs/guide/generator/support.adoc index eb26a8da..cb1dc290 100644 --- a/src/main/docs/guide/generator/support.adoc +++ b/src/main/docs/guide/generator/support.adoc @@ -10,7 +10,7 @@ The following JSON schema keywords are processed by the generation: | `description` | ✅ | | `properties` | ✅ | | `$comment` | ❌ | -| `$ref` | ✅ | Self, local, remote, and url references are accepted. However, for remote references, the generation needs to be given the top local input directory during configuration. +| `$ref` | ✅ | Self, local, remote, and origin references are accepted. However, for remote references, the generation needs to be given the top local input directory during configuration. | `$dynamicRef` | ❌ | | `$defs` | ✅ | The `definitions` keyword is also accepted. | `format` | ✅ | Teh closest existing class is decided as the type of object when the format is given. For example, for a `""type": "string", "format": "date""` schema, a `LocalDate` object is created in Java. Supported format keywords are: `date`, `date-time`, `time`, `duration`, `ipv4`, `ipv6`, `uuid`, `uri`, `iri`, and `json-pointer`. From 0d00ba0dafbe26a5cd20429ba900681305f98969 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Thu, 13 Feb 2025 13:26:34 +0100 Subject: [PATCH 15/24] filter matcher --- .../jsonschema/GeneratedFromSchema.java | 3 + .../registry/SchemaRegistryClient.java | 10 +- .../registry/SchemaRegistryConfig.java | 15 +- .../registry/basicauth/BasicAuth.java | 33 ++ .../SchemaRegistryBasicAuthClient.java | 345 ++++++++++++++++++ .../SchemaRegistryClientAuthFilter.java | 13 +- .../jsonschema/registry/types/ConfigKeys.java | 24 ++ .../jsonschema/registry/ClientTest.java | 3 +- .../registry/ConfluentClientTest.java | 10 +- 9 files changed, 434 insertions(+), 22 deletions(-) create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/BasicAuth.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java rename json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/{ => basicauth}/SchemaRegistryClientAuthFilter.java (82%) create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java diff --git a/json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java b/json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java index a712023b..ea95435d 100644 --- a/json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java +++ b/json-schema-annotations/src/main/java/io/micronaut/jsonschema/GeneratedFromSchema.java @@ -16,6 +16,8 @@ package io.micronaut.jsonschema; import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** @@ -24,6 +26,7 @@ * @since 1.5.0 * @author Elif Kurtay */ +@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE }) public @interface GeneratedFromSchema { diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 5007ae96..62d48fee 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -26,14 +26,14 @@ import io.micronaut.http.annotation.Post; import io.micronaut.http.annotation.Put; import io.micronaut.http.client.annotation.Client; +import io.micronaut.jsonschema.registry.types.ConfigKeys; import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.jsonschema.registry.types.SubjectRequestBody; -import jakarta.inject.Singleton; import java.util.List; /** - * A client for the Confluent SchemaJson Registry. + * A client for the Confluent Json Schema Registry. * *

Supports the operations defined in the * SchemaJson Registry API. @@ -44,12 +44,10 @@ * @author Elif Kurtay * @since 1.5.0 */ -@Client(value = "${registry.url}") +@Client(value = "${" + ConfigKeys.ORIGIN + "}") @Requires(beans = SchemaRegistryConfig.class) -@Requires(property = "registry.url") -//@Header(name = "Content-Type", value = "application/vnd.schemaregistry.v1+json") +@Requires(property = ConfigKeys.ORIGIN) @Consumes(MediaType.APPLICATION_JSON) -@Singleton public interface SchemaRegistryClient { // SCHEMA OPERATIONS --------------------------------------------------------------------------- diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index 11a43619..0d61dbdd 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -16,6 +16,7 @@ package io.micronaut.jsonschema.registry; import io.micronaut.context.annotation.ConfigurationProperties; +import io.micronaut.jsonschema.registry.types.ConfigKeys; import io.micronaut.serde.annotation.Serdeable; import jakarta.validation.constraints.NotBlank; @@ -26,10 +27,10 @@ * @author Elif Kurtay */ @Serdeable -@ConfigurationProperties("registry") +@ConfigurationProperties(ConfigKeys.CONFIG_NAME) public class SchemaRegistryConfig { @NotBlank - private String url; + private String origin; @NotBlank private String username; @NotBlank @@ -42,15 +43,15 @@ public SchemaRegistryConfig() { /** * @return The URL of the schema registry */ - public @NotBlank String getUrl() { - return url; + public @NotBlank String getOrigin() { + return origin; } /** - * @param url The URL of the schema registry + * @param origin The URL of the schema registry */ - public void setUrl(@NotBlank String url) { - this.url = url; + public void setOrigin(@NotBlank String origin) { + this.origin = origin; } /** diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/BasicAuth.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/BasicAuth.java new file mode 100644 index 00000000..46e5a38a --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/BasicAuth.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.basicauth; + +import io.micronaut.http.annotation.FilterMatcher; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@FilterMatcher +@Documented +@Retention(RUNTIME) +@Target({TYPE, PARAMETER}) +public @interface BasicAuth { +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java new file mode 100644 index 00000000..2a038fa8 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java @@ -0,0 +1,345 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.basicauth; + +import io.micronaut.context.annotation.Requires; +import io.micronaut.core.async.annotation.SingleResult; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Consumes; +import io.micronaut.http.annotation.Delete; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.annotation.Put; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.jsonschema.registry.SchemaRegistryConfig; +import io.micronaut.jsonschema.registry.types.ConfigKeys; +import io.micronaut.jsonschema.registry.types.Responses; +import io.micronaut.jsonschema.registry.types.SubjectRequestBody; +import jakarta.inject.Singleton; + +import java.util.List; + +/** + * A client for the Confluent Json Schema Registry. + * + *

Supports the operations defined in the + * SchemaJson Registry API. + * + *

The client is configured with the {@link SchemaRegistryConfig} file for its host address + * and authentication. the configuration parameters are expected to be configured in the application context. + * + * @author Elif Kurtay + * @since 1.5.0 + */ +@BasicAuth +@Client(value = "${" + ConfigKeys.ORIGIN + "}") +@Requires(beans = SchemaRegistryConfig.class) +@Requires(property = ConfigKeys.ORIGIN) +@Consumes(MediaType.APPLICATION_JSON) +@Singleton +public interface SchemaRegistryBasicAuthClient { + +// SCHEMA OPERATIONS --------------------------------------------------------------------------- + + /** + * Get the schema string identified by the input ID. + * + * @param id The unique identifier of the schema + * @return The schema string identified by the input ID + */ + @Get("/schemas/ids/{id}") + @SingleResult + Responses.SchemaJson getSchemaWithId(@PathVariable int id); + + /** + * Retrieves only the schema identified by the input ID. + * + * @param id The unique identifier of the schema + * @return SchemaJson identified by the ID + */ + @Get("/schemas/ids/{id}/schema") + @SingleResult + String getSchemaStringWithId(@PathVariable int id); + + /** + * Get the subject-version pairs identified by the input ID. + * + * @param id The unique identifier of the schema + * @return The subject-version pairs + */ + @Get("/schemas/ids/{id}/versions") + @SingleResult + List getSchemaVersionsWithId(@PathVariable int id); + + /** + * Get the schema types that are registered with SchemaJson Registry. + * + * @return The list of schema types + */ + @Get("/schemas/types") + @SingleResult + List getSchemaTypes(); + + + // SUBJECTS ------------------------------------------------------------------------------------ + + /** + * Get the list of subjects that are registered with SchemaJson Registry. + * + * @return The list of subject names + */ + @Get("/subjects") + @SingleResult + List getSubjects(); + + /** + * Get the list of versions of the schema registered under this subject. + * + * @param subject The subject (topic name, e.g., user-data) + * @return The list of versions + */ + @Get("/subjects/{subject}/versions") + @SingleResult + List getSubjectVersions(@PathVariable String subject); + + /** + * Delete the subject and all its versions. + * + * @param subject The subject (topic name, e.g., user-data) + * @return The list of versions that were deleted + */ + @Delete("/subjects/{subject}") + @SingleResult + List deleteSubject(@PathVariable String subject); + + /** + * Get a specific version of the schema registered under this subject. + * + * @param subject The subject (topic name, e.g., user-data) + * @param version The version number or 'latest' as a string + * @return The requested schema + */ + @Get("/subjects/{subject}/versions/{version}") + @SingleResult + Responses.Subject getSubjectWithVersion(@PathVariable String subject, + @PathVariable String version); + + /** + * Get the schema string registered under this subject and version. + * + * @param subject The subject (topic name, e.g., user-data) + * @param version The version number or 'latest' as a string + * @return The requested schema string (unescaped) + */ + @Get("/subjects/{subject}/versions/{version}/schema") + @SingleResult + String getSchemaWithSubjectAndVersion(@PathVariable String subject, + @PathVariable String version); + + /** + * Register a new schema under the specified subject. (Essentially, create a new schema.) + * If successfully registered, this returns the unique identifier of this schema in the registry. + * + * @param subject The subject (topic name, e.g., user-data) + * @param schemaBody The new schema wished to be registered in the form of {@link SubjectRequestBody} + * @return The globally unique identifier of the schema + */ + @Post("/subjects/{subject}/versions") + @SingleResult + Responses.Id registerNewVersion(@PathVariable String subject, + @Body SubjectRequestBody schemaBody); + + /** + * Checks if a schema has already been registered under the specified subject. + * + * @param subject Subject under which the schema will be registered + * @param schemaBody The new schema wished to be registered in the form of {@link SubjectRequestBody} + * @return the schema string along with its globally unique identifier, its version under this subject and the subject name. + */ + @Post("/subjects/{subject}") + @SingleResult + Responses.Subject checkSubject(@PathVariable String subject, + @Body SubjectRequestBody schemaBody); + + /** + * Deletes a specific version of the schema registered under this subject. + * + * @param subject Subject under which the schema is registered + * @param version The version number or 'latest' as a string + * @return The version number that was deleted + */ + @Delete("/subjects/{subject}/versions/{version}") + @SingleResult + int deleteSubjectVersion(@PathVariable String subject, + @PathVariable String version); + + /** + * Get the list of versions that reference this schema. + * + * @param subject Subject under which the schema is registered + * @param version The version number or 'latest' as a string + * @return The list of versions that reference this schema + */ + @Get("/subjects/{subject}/versions/{version}/referencedby") + @SingleResult + List getSubjectVersionReferencedBy(@PathVariable String subject, + @PathVariable String version); + + /** + * Get the metadata for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The metadata for the specified subject + */ + @Get("/subjects/{subject}/metadata") + @SingleResult + Responses.Subject getSubjectMetadata(@PathVariable String subject); + + // MODE ---------------------------------------------------------------------------------------- + + /** + * Get the global compatibility mode. + * + * @return The global compatibility mode + */ + @Get("/mode") + @SingleResult + Responses.Mode getMode(); + + /** + * Set the global compatibility mode. + * + * @param mode The new global compatibility mode + * @return The new global compatibility mode + */ + @Put("/mode") + @SingleResult + Responses.Mode setMode(@Body Responses.Mode mode); + + /** + * Get the compatibility mode for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The compatibility mode for the specified subject + */ + @Get("/mode/{subject}") + @SingleResult + Responses.Mode getModeForSubject(@PathVariable String subject); + + /** + * Set the compatibility mode for the specified subject. + * + * @param subject Subject under which the schema is registered + * @param mode The new compatibility mode for the specified subject + * @return The new compatibility mode for the specified subject + */ + @Put("/mode/{subject}") + @SingleResult + Responses.Mode setModeForSubject(@PathVariable String subject, @Body Responses.Mode mode); + + /** + * Delete the compatibility mode for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The compatibility mode that was deleted + */ + @Delete("/mode/{subject}") + @SingleResult + Responses.Mode deleteModeForSubject(@PathVariable String subject); + + // COMPATIBILITY --------------------------------------------------------------------------- + + /** + * Test input schema against a particular version of a subject's schema for compatibility. + * + * @param subject Subject under which the schema is registered + * @param version The version number or 'latest' as a string + * @param compatibilityRequest The new schema wished to be registered in the form of {@link SubjectRequestBody} + * @return Whether the new schema is compatible with the specified subject and version + */ + @Post("/compatibility/subjects/{subject}/versions/{version}") + @SingleResult + Responses.Compatibility checkCompatibilityForSubjectVersion(@PathVariable String subject, + @PathVariable String version, + @Body SubjectRequestBody compatibilityRequest); + + /** + * Perform a compatibility check on the schema against one or more versions in the subject, + * depending on how the compatibility is set. + * + * @param subject Subject under which the schema is registered + * @param compatibilityRequest The new schema to be checked in the form of {@link SubjectRequestBody} + * @return Whether the new schema is compatible with the specified subject + */ + @Post("/compatibility/subjects/{subject}/versions") + @SingleResult + Responses.Compatibility checkCompatibilityForSubject(@PathVariable String subject, + @Body SubjectRequestBody compatibilityRequest); + + // CONFIG ---------------------------------------------------------------------------------- + + /** + * Get the global configuration. + * + * @return The global configuration + */ + @Get("/config") + @SingleResult + Responses.Config getConfig(); + + /** + * Set the global configuration. + * + * @param config The new global configuration + * @return The new global configuration + */ + @Put("/config") + @SingleResult + Responses.Config setConfig(@Body Responses.Config config); + + /** + * Get the configuration for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The configuration for the specified subject + */ + @Get("/config/{subject}") + @SingleResult + Responses.Config getConfigForSubject(@PathVariable String subject); + + /** + * Set the configuration for the specified subject. + * + * @param subject Subject under which the schema is registered + * @param config The new configuration for the specified subject + * @return The new configuration for the specified subject + */ + @Put("/config/{subject}") + @SingleResult + Responses.Config setConfigForSubject(@PathVariable String subject, @Body Responses.Config config); + + /** + * Delete the configuration for the specified subject. + * + * @param subject Subject under which the schema is registered + * @return The configuration that was deleted + */ + @Delete("/config/{subject}") + @SingleResult + Responses.Config deleteConfigForSubject(@PathVariable String subject); +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryClientAuthFilter.java similarity index 82% rename from json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java rename to json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryClientAuthFilter.java index a66f9fa7..55636874 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClientAuthFilter.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryClientAuthFilter.java @@ -13,12 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.jsonschema.registry; +package io.micronaut.jsonschema.registry.basicauth; import io.micronaut.context.annotation.Requires; import io.micronaut.http.MutableHttpRequest; import io.micronaut.http.annotation.ClientFilter; import io.micronaut.http.annotation.RequestFilter; +import io.micronaut.jsonschema.registry.SchemaRegistryConfig; +import io.micronaut.jsonschema.registry.types.ConfigKeys; +import jakarta.inject.Singleton; /** * A client filter that adds basic auth to all requests. @@ -26,10 +29,12 @@ * @since 1.4.0 * @author Elif Kurtay */ -@ClientFilter("/**") @Requires(beans = SchemaRegistryConfig.class) -@Requires(property = "registry.username") -@Requires(property = "registry.password") +@Requires(property = ConfigKeys.USERNAME) +@Requires(property = ConfigKeys.PASSWORD) +@BasicAuth +@Singleton +@ClientFilter("/**") public class SchemaRegistryClientAuthFilter { private final SchemaRegistryConfig config; diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java new file mode 100644 index 00000000..f771c802 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java @@ -0,0 +1,24 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.types; + +public final class ConfigKeys { + public static final String CONFIG_NAME = "schema.registry"; + public static final String ORIGIN = CONFIG_NAME + ".origin"; + public static final String USERNAME = CONFIG_NAME + ".username"; + public static final String PASSWORD = CONFIG_NAME + ".password"; + public static final String PUSH_TO_REGISTRY_ENABLED = CONFIG_NAME + ".push-to-registry-enabled"; +} diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java index 42199f14..c4e449b9 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import io.micronaut.context.annotation.Property; import io.micronaut.core.io.ResourceLoader; +import io.micronaut.jsonschema.registry.types.ConfigKeys; import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.jsonschema.registry.types.SubjectRequestBody; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; @@ -21,7 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @MicronautTest -@Property(name = "registry.url", value = "/test/") +@Property(name = ConfigKeys.ORIGIN, value = "/test/") public class ClientTest { @Inject diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index 97cda0ac..e0cb2950 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import io.micronaut.context.annotation.Property; import io.micronaut.core.io.ResourceLoader; +import io.micronaut.jsonschema.registry.basicauth.SchemaRegistryBasicAuthClient; +import io.micronaut.jsonschema.registry.types.ConfigKeys; import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; @@ -24,15 +26,15 @@ * Checking the response types from the client. */ @MicronautTest -@Property(name = "registry.url", value = "http://144.24.55.159:8081/") -@Property(name = "registry.username", value = "micronaut") -@Property(name = "registry.password", value = "test") +@Property(name = ConfigKeys.ORIGIN, value = "http://144.24.55.159:8081/") +@Property(name = ConfigKeys.USERNAME, value = "micronaut") +@Property(name = ConfigKeys.PASSWORD, value = "test") public class ConfluentClientTest { @Inject ResourceLoader resourceLoader; @Inject - SchemaRegistryClient client; + SchemaRegistryBasicAuthClient client; JsonMapper jsonMapper = new JsonMapper(); From 5c7244c362f519c37d57fb867b2d0b78ed36cdb5 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Thu, 13 Feb 2025 14:16:49 +0100 Subject: [PATCH 16/24] basic auth and no auth clients --- .../registry/SchemaRegistryManager.java | 5 +- .../registry/SchemaRegistryNoAuthClient.java | 40 +++ .../SchemaRegistryBasicAuthClient.java | 305 +----------------- .../jsonschema/registry/ClientTest.java | 2 +- 4 files changed, 46 insertions(+), 306 deletions(-) create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryNoAuthClient.java diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java index b5da71ff..626760b2 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java @@ -15,7 +15,6 @@ */ package io.micronaut.jsonschema.registry; -import io.micronaut.context.annotation.Context; import io.micronaut.context.annotation.Requires; import io.micronaut.core.beans.BeanIntrospector; import io.micronaut.jsonschema.GeneratedFromSchema; @@ -35,11 +34,11 @@ */ @Requires(beans = SchemaRegistryClient.class) @Requires(beans = SchemaRegistryConfig.class) -@Context +//@Context public class SchemaRegistryManager { + @Inject private final SchemaRegistryClient client; - @Inject public SchemaRegistryManager(SchemaRegistryClient client, SchemaRegistryConfig config) { this.client = client; if (config.isPushToRegistryEnabled()) { diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryNoAuthClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryNoAuthClient.java new file mode 100644 index 00000000..0a69d7b3 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryNoAuthClient.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry; + +import io.micronaut.context.annotation.Requires; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Consumes; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.jsonschema.registry.types.ConfigKeys; + +/** + * A client for the Confluent Json Schema Registry without authentication. + * + *

Supports the operations defined in the + * SchemaJson Registry API. + * + *

The client is configured with the {@link SchemaRegistryConfig} file for its host address. + * + * @author Elif Kurtay + * @since 1.5.0 + */ +@Client(value = "${" + ConfigKeys.ORIGIN + "}") +@Requires(beans = SchemaRegistryConfig.class) +@Requires(property = ConfigKeys.ORIGIN) +@Consumes(MediaType.APPLICATION_JSON) +public interface SchemaRegistryNoAuthClient extends SchemaRegistryClient { +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java index 2a038fa8..e7bdd8c7 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java @@ -16,26 +16,16 @@ package io.micronaut.jsonschema.registry.basicauth; import io.micronaut.context.annotation.Requires; -import io.micronaut.core.async.annotation.SingleResult; import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Body; import io.micronaut.http.annotation.Consumes; -import io.micronaut.http.annotation.Delete; -import io.micronaut.http.annotation.Get; -import io.micronaut.http.annotation.PathVariable; -import io.micronaut.http.annotation.Post; -import io.micronaut.http.annotation.Put; import io.micronaut.http.client.annotation.Client; +import io.micronaut.jsonschema.registry.SchemaRegistryClient; import io.micronaut.jsonschema.registry.SchemaRegistryConfig; import io.micronaut.jsonschema.registry.types.ConfigKeys; -import io.micronaut.jsonschema.registry.types.Responses; -import io.micronaut.jsonschema.registry.types.SubjectRequestBody; import jakarta.inject.Singleton; -import java.util.List; - /** - * A client for the Confluent Json Schema Registry. + * A client for the Confluent Json Schema Registry with basic HTTP authentication. * *

Supports the operations defined in the * SchemaJson Registry API. @@ -52,294 +42,5 @@ @Requires(property = ConfigKeys.ORIGIN) @Consumes(MediaType.APPLICATION_JSON) @Singleton -public interface SchemaRegistryBasicAuthClient { - -// SCHEMA OPERATIONS --------------------------------------------------------------------------- - - /** - * Get the schema string identified by the input ID. - * - * @param id The unique identifier of the schema - * @return The schema string identified by the input ID - */ - @Get("/schemas/ids/{id}") - @SingleResult - Responses.SchemaJson getSchemaWithId(@PathVariable int id); - - /** - * Retrieves only the schema identified by the input ID. - * - * @param id The unique identifier of the schema - * @return SchemaJson identified by the ID - */ - @Get("/schemas/ids/{id}/schema") - @SingleResult - String getSchemaStringWithId(@PathVariable int id); - - /** - * Get the subject-version pairs identified by the input ID. - * - * @param id The unique identifier of the schema - * @return The subject-version pairs - */ - @Get("/schemas/ids/{id}/versions") - @SingleResult - List getSchemaVersionsWithId(@PathVariable int id); - - /** - * Get the schema types that are registered with SchemaJson Registry. - * - * @return The list of schema types - */ - @Get("/schemas/types") - @SingleResult - List getSchemaTypes(); - - - // SUBJECTS ------------------------------------------------------------------------------------ - - /** - * Get the list of subjects that are registered with SchemaJson Registry. - * - * @return The list of subject names - */ - @Get("/subjects") - @SingleResult - List getSubjects(); - - /** - * Get the list of versions of the schema registered under this subject. - * - * @param subject The subject (topic name, e.g., user-data) - * @return The list of versions - */ - @Get("/subjects/{subject}/versions") - @SingleResult - List getSubjectVersions(@PathVariable String subject); - - /** - * Delete the subject and all its versions. - * - * @param subject The subject (topic name, e.g., user-data) - * @return The list of versions that were deleted - */ - @Delete("/subjects/{subject}") - @SingleResult - List deleteSubject(@PathVariable String subject); - - /** - * Get a specific version of the schema registered under this subject. - * - * @param subject The subject (topic name, e.g., user-data) - * @param version The version number or 'latest' as a string - * @return The requested schema - */ - @Get("/subjects/{subject}/versions/{version}") - @SingleResult - Responses.Subject getSubjectWithVersion(@PathVariable String subject, - @PathVariable String version); - - /** - * Get the schema string registered under this subject and version. - * - * @param subject The subject (topic name, e.g., user-data) - * @param version The version number or 'latest' as a string - * @return The requested schema string (unescaped) - */ - @Get("/subjects/{subject}/versions/{version}/schema") - @SingleResult - String getSchemaWithSubjectAndVersion(@PathVariable String subject, - @PathVariable String version); - - /** - * Register a new schema under the specified subject. (Essentially, create a new schema.) - * If successfully registered, this returns the unique identifier of this schema in the registry. - * - * @param subject The subject (topic name, e.g., user-data) - * @param schemaBody The new schema wished to be registered in the form of {@link SubjectRequestBody} - * @return The globally unique identifier of the schema - */ - @Post("/subjects/{subject}/versions") - @SingleResult - Responses.Id registerNewVersion(@PathVariable String subject, - @Body SubjectRequestBody schemaBody); - - /** - * Checks if a schema has already been registered under the specified subject. - * - * @param subject Subject under which the schema will be registered - * @param schemaBody The new schema wished to be registered in the form of {@link SubjectRequestBody} - * @return the schema string along with its globally unique identifier, its version under this subject and the subject name. - */ - @Post("/subjects/{subject}") - @SingleResult - Responses.Subject checkSubject(@PathVariable String subject, - @Body SubjectRequestBody schemaBody); - - /** - * Deletes a specific version of the schema registered under this subject. - * - * @param subject Subject under which the schema is registered - * @param version The version number or 'latest' as a string - * @return The version number that was deleted - */ - @Delete("/subjects/{subject}/versions/{version}") - @SingleResult - int deleteSubjectVersion(@PathVariable String subject, - @PathVariable String version); - - /** - * Get the list of versions that reference this schema. - * - * @param subject Subject under which the schema is registered - * @param version The version number or 'latest' as a string - * @return The list of versions that reference this schema - */ - @Get("/subjects/{subject}/versions/{version}/referencedby") - @SingleResult - List getSubjectVersionReferencedBy(@PathVariable String subject, - @PathVariable String version); - - /** - * Get the metadata for the specified subject. - * - * @param subject Subject under which the schema is registered - * @return The metadata for the specified subject - */ - @Get("/subjects/{subject}/metadata") - @SingleResult - Responses.Subject getSubjectMetadata(@PathVariable String subject); - - // MODE ---------------------------------------------------------------------------------------- - - /** - * Get the global compatibility mode. - * - * @return The global compatibility mode - */ - @Get("/mode") - @SingleResult - Responses.Mode getMode(); - - /** - * Set the global compatibility mode. - * - * @param mode The new global compatibility mode - * @return The new global compatibility mode - */ - @Put("/mode") - @SingleResult - Responses.Mode setMode(@Body Responses.Mode mode); - - /** - * Get the compatibility mode for the specified subject. - * - * @param subject Subject under which the schema is registered - * @return The compatibility mode for the specified subject - */ - @Get("/mode/{subject}") - @SingleResult - Responses.Mode getModeForSubject(@PathVariable String subject); - - /** - * Set the compatibility mode for the specified subject. - * - * @param subject Subject under which the schema is registered - * @param mode The new compatibility mode for the specified subject - * @return The new compatibility mode for the specified subject - */ - @Put("/mode/{subject}") - @SingleResult - Responses.Mode setModeForSubject(@PathVariable String subject, @Body Responses.Mode mode); - - /** - * Delete the compatibility mode for the specified subject. - * - * @param subject Subject under which the schema is registered - * @return The compatibility mode that was deleted - */ - @Delete("/mode/{subject}") - @SingleResult - Responses.Mode deleteModeForSubject(@PathVariable String subject); - - // COMPATIBILITY --------------------------------------------------------------------------- - - /** - * Test input schema against a particular version of a subject's schema for compatibility. - * - * @param subject Subject under which the schema is registered - * @param version The version number or 'latest' as a string - * @param compatibilityRequest The new schema wished to be registered in the form of {@link SubjectRequestBody} - * @return Whether the new schema is compatible with the specified subject and version - */ - @Post("/compatibility/subjects/{subject}/versions/{version}") - @SingleResult - Responses.Compatibility checkCompatibilityForSubjectVersion(@PathVariable String subject, - @PathVariable String version, - @Body SubjectRequestBody compatibilityRequest); - - /** - * Perform a compatibility check on the schema against one or more versions in the subject, - * depending on how the compatibility is set. - * - * @param subject Subject under which the schema is registered - * @param compatibilityRequest The new schema to be checked in the form of {@link SubjectRequestBody} - * @return Whether the new schema is compatible with the specified subject - */ - @Post("/compatibility/subjects/{subject}/versions") - @SingleResult - Responses.Compatibility checkCompatibilityForSubject(@PathVariable String subject, - @Body SubjectRequestBody compatibilityRequest); - - // CONFIG ---------------------------------------------------------------------------------- - - /** - * Get the global configuration. - * - * @return The global configuration - */ - @Get("/config") - @SingleResult - Responses.Config getConfig(); - - /** - * Set the global configuration. - * - * @param config The new global configuration - * @return The new global configuration - */ - @Put("/config") - @SingleResult - Responses.Config setConfig(@Body Responses.Config config); - - /** - * Get the configuration for the specified subject. - * - * @param subject Subject under which the schema is registered - * @return The configuration for the specified subject - */ - @Get("/config/{subject}") - @SingleResult - Responses.Config getConfigForSubject(@PathVariable String subject); - - /** - * Set the configuration for the specified subject. - * - * @param subject Subject under which the schema is registered - * @param config The new configuration for the specified subject - * @return The new configuration for the specified subject - */ - @Put("/config/{subject}") - @SingleResult - Responses.Config setConfigForSubject(@PathVariable String subject, @Body Responses.Config config); - - /** - * Delete the configuration for the specified subject. - * - * @param subject Subject under which the schema is registered - * @return The configuration that was deleted - */ - @Delete("/config/{subject}") - @SingleResult - Responses.Config deleteConfigForSubject(@PathVariable String subject); +public interface SchemaRegistryBasicAuthClient extends SchemaRegistryClient { } diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java index c4e449b9..89941e82 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java @@ -28,7 +28,7 @@ public class ClientTest { @Inject ResourceLoader resourceLoader; @Inject - SchemaRegistryClient client; + SchemaRegistryNoAuthClient client; Responses.Subject exampleSubject; From bea2d80bdea8f4032e5bfb282fe4fe78c93bf4ed Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Thu, 13 Feb 2025 15:28:21 +0100 Subject: [PATCH 17/24] fix multiple clients --- .../registry/SchemaRegistryClient.java | 4 ++ .../registry/SchemaRegistryConfig.java | 15 ++++++ .../registry/SchemaRegistryManager.java | 3 +- .../registry/SchemaRegistryNoAuthClient.java | 40 ---------------- .../{basicauth => auth}/BasicAuth.java | 2 +- .../SchemaRegistryClientBasicAuthFilter.java} | 11 +++-- .../SchemaRegistryBasicAuthClient.java | 46 ------------------- .../jsonschema/registry/types/ConfigKeys.java | 3 +- .../jsonschema/registry/ClientTest.java | 2 +- .../registry/ConfluentClientTest.java | 4 +- 10 files changed, 34 insertions(+), 96 deletions(-) delete mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryNoAuthClient.java rename json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/{basicauth => auth}/BasicAuth.java (95%) rename json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/{basicauth/SchemaRegistryClientAuthFilter.java => auth/SchemaRegistryClientBasicAuthFilter.java} (80%) delete mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 62d48fee..30655402 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -26,9 +26,11 @@ import io.micronaut.http.annotation.Post; import io.micronaut.http.annotation.Put; import io.micronaut.http.client.annotation.Client; +import io.micronaut.jsonschema.registry.auth.BasicAuth; import io.micronaut.jsonschema.registry.types.ConfigKeys; import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.jsonschema.registry.types.SubjectRequestBody; +import jakarta.inject.Singleton; import java.util.List; @@ -48,6 +50,8 @@ @Requires(beans = SchemaRegistryConfig.class) @Requires(property = ConfigKeys.ORIGIN) @Consumes(MediaType.APPLICATION_JSON) +@BasicAuth +@Singleton public interface SchemaRegistryClient { // SCHEMA OPERATIONS --------------------------------------------------------------------------- diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index 0d61dbdd..7a4091c5 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -36,6 +36,7 @@ public class SchemaRegistryConfig { @NotBlank private String password; private boolean pushToRegistryEnabled = true; + private boolean basicAuthEnabled = false; public SchemaRegistryConfig() { } @@ -95,4 +96,18 @@ public boolean isPushToRegistryEnabled() { public void setPushToRegistryEnabled(boolean pushToRegistryEnabled) { this.pushToRegistryEnabled = pushToRegistryEnabled; } + + /** + * @return Whether basic auth is enabled + */ + public boolean isBasicAuthEnabled() { + return basicAuthEnabled; + } + + /** + * @param basicAuthEnabled Whether basic auth will be enabled + */ + public void setBasicAuthEnabled(boolean basicAuthEnabled) { + this.basicAuthEnabled = basicAuthEnabled; + } } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java index 626760b2..3fa301dc 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java @@ -15,6 +15,7 @@ */ package io.micronaut.jsonschema.registry; +import io.micronaut.context.annotation.Context; import io.micronaut.context.annotation.Requires; import io.micronaut.core.beans.BeanIntrospector; import io.micronaut.jsonschema.GeneratedFromSchema; @@ -34,7 +35,7 @@ */ @Requires(beans = SchemaRegistryClient.class) @Requires(beans = SchemaRegistryConfig.class) -//@Context +@Context public class SchemaRegistryManager { @Inject private final SchemaRegistryClient client; diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryNoAuthClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryNoAuthClient.java deleted file mode 100644 index 0a69d7b3..00000000 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryNoAuthClient.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2017-2025 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.jsonschema.registry; - -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Consumes; -import io.micronaut.http.client.annotation.Client; -import io.micronaut.jsonschema.registry.types.ConfigKeys; - -/** - * A client for the Confluent Json Schema Registry without authentication. - * - *

Supports the operations defined in the - * SchemaJson Registry API. - * - *

The client is configured with the {@link SchemaRegistryConfig} file for its host address. - * - * @author Elif Kurtay - * @since 1.5.0 - */ -@Client(value = "${" + ConfigKeys.ORIGIN + "}") -@Requires(beans = SchemaRegistryConfig.class) -@Requires(property = ConfigKeys.ORIGIN) -@Consumes(MediaType.APPLICATION_JSON) -public interface SchemaRegistryNoAuthClient extends SchemaRegistryClient { -} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/BasicAuth.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/BasicAuth.java similarity index 95% rename from json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/BasicAuth.java rename to json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/BasicAuth.java index 46e5a38a..8bab6afc 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/BasicAuth.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/BasicAuth.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.jsonschema.registry.basicauth; +package io.micronaut.jsonschema.registry.auth; import io.micronaut.http.annotation.FilterMatcher; diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryClientAuthFilter.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryClientBasicAuthFilter.java similarity index 80% rename from json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryClientAuthFilter.java rename to json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryClientBasicAuthFilter.java index 55636874..bf3c0dbc 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryClientAuthFilter.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryClientBasicAuthFilter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.jsonschema.registry.basicauth; +package io.micronaut.jsonschema.registry.auth; import io.micronaut.context.annotation.Requires; import io.micronaut.http.MutableHttpRequest; @@ -32,13 +32,14 @@ @Requires(beans = SchemaRegistryConfig.class) @Requires(property = ConfigKeys.USERNAME) @Requires(property = ConfigKeys.PASSWORD) +@Requires(property = ConfigKeys.BASIC_AUTH_ENABLED) @BasicAuth @Singleton @ClientFilter("/**") -public class SchemaRegistryClientAuthFilter { +public class SchemaRegistryClientBasicAuthFilter { private final SchemaRegistryConfig config; - public SchemaRegistryClientAuthFilter(SchemaRegistryConfig config) { + public SchemaRegistryClientBasicAuthFilter(SchemaRegistryConfig config) { this.config = config; } @@ -49,6 +50,8 @@ public SchemaRegistryClientAuthFilter(SchemaRegistryConfig config) { */ @RequestFilter public void doFilter(MutableHttpRequest request) { - request.basicAuth(config.getUsername(), config.getPassword()); + if (config.isBasicAuthEnabled()) { + request.basicAuth(config.getUsername(), config.getPassword()); + } } } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java deleted file mode 100644 index e7bdd8c7..00000000 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/basicauth/SchemaRegistryBasicAuthClient.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2017-2025 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.jsonschema.registry.basicauth; - -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Consumes; -import io.micronaut.http.client.annotation.Client; -import io.micronaut.jsonschema.registry.SchemaRegistryClient; -import io.micronaut.jsonschema.registry.SchemaRegistryConfig; -import io.micronaut.jsonschema.registry.types.ConfigKeys; -import jakarta.inject.Singleton; - -/** - * A client for the Confluent Json Schema Registry with basic HTTP authentication. - * - *

Supports the operations defined in the - * SchemaJson Registry API. - * - *

The client is configured with the {@link SchemaRegistryConfig} file for its host address - * and authentication. the configuration parameters are expected to be configured in the application context. - * - * @author Elif Kurtay - * @since 1.5.0 - */ -@BasicAuth -@Client(value = "${" + ConfigKeys.ORIGIN + "}") -@Requires(beans = SchemaRegistryConfig.class) -@Requires(property = ConfigKeys.ORIGIN) -@Consumes(MediaType.APPLICATION_JSON) -@Singleton -public interface SchemaRegistryBasicAuthClient extends SchemaRegistryClient { -} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java index f771c802..cbac15d3 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java @@ -20,5 +20,6 @@ public final class ConfigKeys { public static final String ORIGIN = CONFIG_NAME + ".origin"; public static final String USERNAME = CONFIG_NAME + ".username"; public static final String PASSWORD = CONFIG_NAME + ".password"; - public static final String PUSH_TO_REGISTRY_ENABLED = CONFIG_NAME + ".push-to-registry-enabled"; + public static final String BASIC_AUTH_ENABLED = CONFIG_NAME + ".basicAuthEnabled"; + public static final String PUSH_TO_REGISTRY_ENABLED = CONFIG_NAME + ".pushToRegistryEnabled"; } diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java index 89941e82..c4e449b9 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java @@ -28,7 +28,7 @@ public class ClientTest { @Inject ResourceLoader resourceLoader; @Inject - SchemaRegistryNoAuthClient client; + SchemaRegistryClient client; Responses.Subject exampleSubject; diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index e0cb2950..b60134ae 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import io.micronaut.context.annotation.Property; import io.micronaut.core.io.ResourceLoader; -import io.micronaut.jsonschema.registry.basicauth.SchemaRegistryBasicAuthClient; import io.micronaut.jsonschema.registry.types.ConfigKeys; import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; @@ -29,12 +28,13 @@ @Property(name = ConfigKeys.ORIGIN, value = "http://144.24.55.159:8081/") @Property(name = ConfigKeys.USERNAME, value = "micronaut") @Property(name = ConfigKeys.PASSWORD, value = "test") +@Property(name = ConfigKeys.BASIC_AUTH_ENABLED, value = "true") public class ConfluentClientTest { @Inject ResourceLoader resourceLoader; @Inject - SchemaRegistryBasicAuthClient client; + SchemaRegistryClient client; JsonMapper jsonMapper = new JsonMapper(); From 5c68e30d43f16c61414fa91f0b6a65817a0ff893 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Mon, 17 Feb 2025 15:31:21 +0100 Subject: [PATCH 18/24] manager check and disable --- json-schema-registry/build.gradle | 15 ++ .../registry/SchemaRegistryClient.java | 4 +- .../registry/SchemaRegistryConfig.java | 16 +-- .../registry/SchemaRegistryManager.java | 46 +++--- .../jsonschema/registry/auth/BasicAuth.java | 3 + .../jsonschema/registry/types/ConfigKeys.java | 2 +- .../jsonschema/registry/ClientTest.java | 4 +- .../registry/ConfluentClientTest.java | 4 +- .../src/test/resources/animal.schema.json | 131 ++++++++++++++++++ .../{human.schema.json => human.json} | 0 test-suite-generator-java/build.gradle | 4 +- 11 files changed, 192 insertions(+), 37 deletions(-) create mode 100644 json-schema-registry/src/test/resources/animal.schema.json rename json-schema-registry/src/test/resources/{human.schema.json => human.json} (100%) diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle index 30881580..e670e844 100644 --- a/json-schema-registry/build.gradle +++ b/json-schema-registry/build.gradle @@ -1,5 +1,8 @@ +import io.micronaut.build.internal.generator.BeanGeneratorTask + plugins { id("io.micronaut.build.internal.json-schema-module") + id("io.micronaut.build.internal.test-suite-generator-java") } dependencies { @@ -28,8 +31,20 @@ tasks.test { useJUnitPlatform() } +def animalGenerator = tasks.register("generateAnimals", BeanGeneratorTask) { + language = "java" + classpath.from(configurations.beanGenerator) + jsonFile.convention(layout.projectDirectory.file("src/test/resources/animal.schema.json")) + outputDirectory.convention(layout.buildDirectory.dir("generated/jsonSchema")) + packageName.convention("io.micronaut.jsonschema.generator.animals") +} + +tasks.named("generateAnimals") { +} + sourceSets { test { java.srcDir('src/test/java') + java.srcDir(animalGenerator.map(BeanGeneratorTask::getGeneratedSourcesDirectory)) } } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 30655402..8144146d 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -46,9 +46,9 @@ * @author Elif Kurtay * @since 1.5.0 */ -@Client(value = "${" + ConfigKeys.ORIGIN + "}") +@Client(value = "${" + ConfigKeys.HOST_URL + "}") @Requires(beans = SchemaRegistryConfig.class) -@Requires(property = ConfigKeys.ORIGIN) +@Requires(property = ConfigKeys.HOST_URL) @Consumes(MediaType.APPLICATION_JSON) @BasicAuth @Singleton diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index 7a4091c5..ce1badcd 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -30,13 +30,13 @@ @ConfigurationProperties(ConfigKeys.CONFIG_NAME) public class SchemaRegistryConfig { @NotBlank - private String origin; + private String url; @NotBlank private String username; @NotBlank private String password; - private boolean pushToRegistryEnabled = true; - private boolean basicAuthEnabled = false; + private boolean pushToRegistryEnabled = false; + private boolean basicAuthEnabled = true; public SchemaRegistryConfig() { } @@ -44,15 +44,15 @@ public SchemaRegistryConfig() { /** * @return The URL of the schema registry */ - public @NotBlank String getOrigin() { - return origin; + public @NotBlank String getUrl() { + return url; } /** - * @param origin The URL of the schema registry + * @param url The URL of the schema registry */ - public void setOrigin(@NotBlank String origin) { - this.origin = origin; + public void setUrl(@NotBlank String url) { + this.url = url; } /** diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java index 3fa301dc..f24681ad 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java @@ -18,6 +18,7 @@ import io.micronaut.context.annotation.Context; import io.micronaut.context.annotation.Requires; import io.micronaut.core.beans.BeanIntrospector; +import io.micronaut.core.io.ResourceLoader; import io.micronaut.jsonschema.GeneratedFromSchema; import io.micronaut.jsonschema.registry.types.Responses; import io.micronaut.jsonschema.registry.types.SubjectRequestBody; @@ -35,11 +36,12 @@ */ @Requires(beans = SchemaRegistryClient.class) @Requires(beans = SchemaRegistryConfig.class) +@Requires(beans = ResourceLoader.class) @Context public class SchemaRegistryManager { - @Inject - private final SchemaRegistryClient client; + SchemaRegistryClient client; + @Inject public SchemaRegistryManager(SchemaRegistryClient client, SchemaRegistryConfig config) { this.client = client; if (config.isPushToRegistryEnabled()) { @@ -58,27 +60,31 @@ private void pushToRegistry() { // for each unique filename, get schema from file uniqueFileNames.forEach(filename -> { - try (InputStream inputStream = getClass().getResourceAsStream(filename)) { + String schemaString = null; + try (InputStream inputStream = getClass().getResourceAsStream("/" + filename)) { // get local schema file - assert inputStream != null; - var schemaString = new String(inputStream.readAllBytes()); - - // get schema from registry - var subjectName = filename.substring( - filename.contains("/") ? filename.lastIndexOf('/') : 0, - filename.contains(".") ? filename.indexOf('.') : filename.length()); - var responseSchemaString = client.getSchemaWithSubjectAndVersion(subjectName, "latest"); - // compare local vs registry, if different, push to registry - if (!schemaString.equals(responseSchemaString)) { - var response = client.registerNewVersion( - subjectName, - new SubjectRequestBody(schemaString, Responses.SchemaType.JSON, null, null, null)); - if (response.id() == -1) { - throw new RuntimeException("Error pushing schema to registry"); - } + if (inputStream == null) { + System.err.println("Resource not found: " + filename); + return; } + schemaString = new String(inputStream.readAllBytes()) + .replaceAll("\"", "\\\\\""); } catch (Exception e) { - throw new RuntimeException("Error pushing schema to registry", e); + throw new RuntimeException("Error loading resource " + filename, e); + } + // get schema from registry + var subjectName = filename.substring( + filename.contains("/") ? filename.lastIndexOf('/') : 0, + filename.contains(".") ? filename.indexOf('.') : filename.length()); + String responseSchemaString = client.getSchemaWithSubjectAndVersion(subjectName, "latest"); + // compare local vs registry, if different, push to registry + if (!schemaString.equals(responseSchemaString)) { + var response = client.registerNewVersion( + subjectName, + new SubjectRequestBody(schemaString, Responses.SchemaType.JSON, null, null, null)); + if (response.id() == -1) { + System.err.println("Error pushing schema to registry: " + filename); + } } }); } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/BasicAuth.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/BasicAuth.java index 8bab6afc..f43a5a6d 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/BasicAuth.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/BasicAuth.java @@ -25,6 +25,9 @@ import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +/** + * An annotation that can be applied to a client to indicate that basic auth should be used. + */ @FilterMatcher @Documented @Retention(RUNTIME) diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java index cbac15d3..089cb4ee 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java @@ -17,7 +17,7 @@ public final class ConfigKeys { public static final String CONFIG_NAME = "schema.registry"; - public static final String ORIGIN = CONFIG_NAME + ".origin"; + public static final String HOST_URL = CONFIG_NAME + ".url"; public static final String USERNAME = CONFIG_NAME + ".username"; public static final String PASSWORD = CONFIG_NAME + ".password"; public static final String BASIC_AUTH_ENABLED = CONFIG_NAME + ".basicAuthEnabled"; diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java index c4e449b9..81442184 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java @@ -22,7 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @MicronautTest -@Property(name = ConfigKeys.ORIGIN, value = "/test/") +@Property(name = ConfigKeys.HOST_URL, value = "/test/") public class ClientTest { @Inject @@ -64,7 +64,7 @@ void testGetSubjects() { public void prepareTestData() throws IOException { JsonMapper jsonMapper = new JsonMapper(); - Optional expectedOptional = resourceLoader.getResourceAsStream("human.schema.json"); + Optional expectedOptional = resourceLoader.getResourceAsStream("human.json"); assertTrue(expectedOptional.isPresent()); String expected = new String(expectedOptional.get().readAllBytes(), StandardCharsets.UTF_8); expected = expected.replaceAll("\\s+", "").trim(); diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index b60134ae..94b4110c 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -25,7 +25,7 @@ * Checking the response types from the client. */ @MicronautTest -@Property(name = ConfigKeys.ORIGIN, value = "http://144.24.55.159:8081/") +@Property(name = ConfigKeys.HOST_URL, value = "http://144.24.55.159:8081/") @Property(name = ConfigKeys.USERNAME, value = "micronaut") @Property(name = ConfigKeys.PASSWORD, value = "test") @Property(name = ConfigKeys.BASIC_AUTH_ENABLED, value = "true") @@ -76,7 +76,7 @@ void testGetSubject() throws IOException { assertEquals(List.of(1), response2); // prepare expected response - String expected = getExpectedResponse("human.schema.json"); + String expected = getExpectedResponse("human.json"); Responses.Subject subjectExpected = jsonMapper.readValue(expected, Responses.Subject.class); Responses.Subject response3 = client.getSubjectWithVersion("human", "latest"); diff --git a/json-schema-registry/src/test/resources/animal.schema.json b/json-schema-registry/src/test/resources/animal.schema.json new file mode 100644 index 00000000..3cfa07e3 --- /dev/null +++ b/json-schema-registry/src/test/resources/animal.schema.json @@ -0,0 +1,131 @@ +{ + "$schema":"https://json-schema.org/draft/2020-12/schema", + "$id":"https://example.com/schemas/llama.schema.json", + "title":"Animal", + "description":"An animal.", + "type":["object"], + "properties":{ + "id": { + "description": "Unique id for the animal.", + "$ref": "#/definitions/id" + }, + "birthdate":{ + "description":"The birthdate", + "$ref": "#/definitions/date" + }, + "name":{ + "description":"The name", + "type":"string", + "minLength":1 + } + }, + "discriminator": { + "propertyName": "resourceType", + "mapping": { + "Cat": "#/definitions/Cat", + "Dog": "#/definitions/Dog", + "Fish": "#/definitions/Fish", + "Human": "#/oneOf/Human" + } + }, + "oneOf": [{ + "$ref": "#/definitions/Cat" + },{ + "$ref": "#/definitions/Dog" + },{ + "$ref": "#/definitions/Fish" + }, { + "title": "Human", + "type": "object", + "properties": { + "resourceType": { + "const": "Human" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "sport": { + "type": "string" + } + } + }], + "$defs": { + "id": { + "pattern": "^[A-Za-z0-9\\-\\.]{1,64}$", + "type": "string", + "description": "Any combination of letters, numerals, \"-\" and \".\", with a length limit of 64 characters. (This might be an integer, an unprefixed OID, UUID or any other identifier pattern that meets these constraints.) Ids are case-insensitive." + }, + "date": { + "pattern": "^([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1]))?)?$", + "type": "string", + "description": "A date or partial date (e.g. just year or year + month). There is no UTC offset. The format is a union of the schema types gYear, gYearMonth and date. Dates SHALL be valid dates." + }, + "boolean": { + "pattern": "^true|false$", + "type": "boolean", + "description": "Value of \"true\" or \"false\"" + }, + "Cat": { + "description": "The definition of a cat.", + "properties": { + "resourceType": { + "description": "This is a Cat resource.", + "const": "Cat" + }, + "hasMate": { + "description": "True when the cat has found their mate.", + "$ref": "#/definitions/boolean" + } + }, + "type": ["object"], + "additionalProperties": false + }, + "Dog": { + "description": "The definition of a dog.", + "properties": { + "resourceType": { + "description": "This is a Dog resource.", + "const": "Dog" + }, + "hasMate": { + "description": "True when the dog has found their mate.", + "const": true + }, + "nickname" : { + "description": "A nickname of a good doggo.", + "type": "string" + }, + "enemies" : { + "description": "A list of the dog's cat enemies.", + "type": "array", + "items": { + "$ref": "#/definitions/Cat" + } + } + }, + "type": "object", + "additionalProperties": {"type": "string"} + }, + "Fish": { + "description": "The definition of a fish.", + "properties": { + "resourceType": { + "description": "This is a Fish resource.", + "const": "Fish" + }, + "friends" : { + "description": "A list of the fish's aquarium friends.", + "type": "array", + "items": { + "$ref": "#" + } + } + }, + "type": "object", + "additionalProperties": true + } + } +} diff --git a/json-schema-registry/src/test/resources/human.schema.json b/json-schema-registry/src/test/resources/human.json similarity index 100% rename from json-schema-registry/src/test/resources/human.schema.json rename to json-schema-registry/src/test/resources/human.json diff --git a/test-suite-generator-java/build.gradle b/test-suite-generator-java/build.gradle index 9b1bc290..12cc0719 100644 --- a/test-suite-generator-java/build.gradle +++ b/test-suite-generator-java/build.gradle @@ -31,7 +31,7 @@ dependencies { testRuntimeOnly(libs.junit.jupiter.engine) } -def beanGenerator = tasks.register("generateAnimals", BeanGeneratorTask) { +def animalGenerator = tasks.register("generateAnimals", BeanGeneratorTask) { language = "java" classpath.from(configurations.beanGenerator) jsonFile.convention(layout.projectDirectory.file("src/test/resources/animal.schema.json")) @@ -94,7 +94,7 @@ tasks.withType(Checkstyle).configureEach { sourceSets { test { java.srcDir('src/test/java') - java.srcDir(beanGenerator.map(BeanGeneratorTask::getGeneratedSourcesDirectory)) + java.srcDir(animalGenerator.map(BeanGeneratorTask::getGeneratedSourcesDirectory)) java.srcDir(foodGenerator.map(BeanGeneratorTask::getGeneratedSourcesDirectory)) java.srcDir(githubGenerator.map(BeanGeneratorTask::getGeneratedSourcesDirectory)) java.srcDir(wordPressGenerator.map(BeanGeneratorTask::getGeneratedSourcesDirectory)) From d9791d565eb5299ccdd01f7317bd32768b98644c Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Thu, 20 Feb 2025 15:28:45 +0100 Subject: [PATCH 19/24] Code review --- json-schema-registry/build.gradle | 10 +- .../registry/SchemaRegistryClient.java | 46 +++-- .../registry/SchemaRegistryConfig.java | 10 +- .../registry/SchemaRegistryManager.java | 6 +- .../SchemaRegistryClientBasicAuthFilter.java | 5 +- .../CompatibilityLevel.java} | 24 ++- .../registry/model/CompatibilityResponse.java | 31 ++++ .../registry/model/ConfigResponse.java | 47 ++++++ .../jsonschema/registry/model/IdResponse.java | 29 ++++ .../registry/model/ModeResponse.java | 39 +++++ .../registry/model/SchemaResponse.java | 31 ++++ .../jsonschema/registry/model/SchemaType.java | 28 ++++ .../{types => model}/SubjectRequestBody.java | 4 +- .../registry/model/SubjectResponse.java | 39 +++++ .../model/SubjectVersionResponse.java | 30 ++++ .../jsonschema/registry/types/Responses.java | 158 ------------------ .../jsonschema/registry/ClientTest.java | 15 +- .../registry/ConfluentClientTest.java | 33 ++-- ...er.java => MockSchemaRegistryService.java} | 31 ++-- 19 files changed, 379 insertions(+), 237 deletions(-) rename json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/{types/ConfigKeys.java => model/CompatibilityLevel.java} (53%) create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/CompatibilityResponse.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ConfigResponse.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/IdResponse.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ModeResponse.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaResponse.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaType.java rename json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/{types => model}/SubjectRequestBody.java (94%) create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectResponse.java create mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectVersionResponse.java delete mode 100644 json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java rename json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/{TestController.java => MockSchemaRegistryService.java} (78%) diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle index e670e844..946644e8 100644 --- a/json-schema-registry/build.gradle +++ b/json-schema-registry/build.gradle @@ -43,8 +43,16 @@ tasks.named("generateAnimals") { } sourceSets { + main { + resources { + srcDirs(java.srcDir(animalGenerator.map(BeanGeneratorTask::getGeneratedSourcesDirectory))) + } + } test { java.srcDir('src/test/java') - java.srcDir(animalGenerator.map(BeanGeneratorTask::getGeneratedSourcesDirectory)) } } + +tasks.withType(Checkstyle).configureEach { + enabled = false +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 8144146d..4a483d01 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -27,9 +27,7 @@ import io.micronaut.http.annotation.Put; import io.micronaut.http.client.annotation.Client; import io.micronaut.jsonschema.registry.auth.BasicAuth; -import io.micronaut.jsonschema.registry.types.ConfigKeys; -import io.micronaut.jsonschema.registry.types.Responses; -import io.micronaut.jsonschema.registry.types.SubjectRequestBody; +import io.micronaut.jsonschema.registry.model.*; import jakarta.inject.Singleton; import java.util.List; @@ -46,9 +44,9 @@ * @author Elif Kurtay * @since 1.5.0 */ -@Client(value = "${" + ConfigKeys.HOST_URL + "}") @Requires(beans = SchemaRegistryConfig.class) -@Requires(property = ConfigKeys.HOST_URL) +@Requires(property = SchemaRegistryConfig.HOST_URL) +@Client(value = "${" + SchemaRegistryConfig.HOST_URL + "}") @Consumes(MediaType.APPLICATION_JSON) @BasicAuth @Singleton @@ -64,7 +62,7 @@ public interface SchemaRegistryClient { */ @Get("/schemas/ids/{id}") @SingleResult - Responses.SchemaJson getSchemaWithId(@PathVariable int id); + SchemaResponse getSchemaWithId(@PathVariable int id); /** * Retrieves only the schema identified by the input ID. @@ -84,7 +82,7 @@ public interface SchemaRegistryClient { */ @Get("/schemas/ids/{id}/versions") @SingleResult - List getSchemaVersionsWithId(@PathVariable int id); + List getSchemaVersionsWithId(@PathVariable int id); /** * Get the schema types that are registered with SchemaJson Registry. @@ -93,7 +91,7 @@ public interface SchemaRegistryClient { */ @Get("/schemas/types") @SingleResult - List getSchemaTypes(); + List getSchemaTypes(); // SUBJECTS ------------------------------------------------------------------------------------ @@ -136,7 +134,7 @@ public interface SchemaRegistryClient { */ @Get("/subjects/{subject}/versions/{version}") @SingleResult - Responses.Subject getSubjectWithVersion(@PathVariable String subject, + SubjectResponse getSubjectWithVersion(@PathVariable String subject, @PathVariable String version); /** @@ -161,7 +159,7 @@ String getSchemaWithSubjectAndVersion(@PathVariable String subject, */ @Post("/subjects/{subject}/versions") @SingleResult - Responses.Id registerNewVersion(@PathVariable String subject, + IdResponse registerNewVersion(@PathVariable String subject, @Body SubjectRequestBody schemaBody); /** @@ -173,7 +171,7 @@ Responses.Id registerNewVersion(@PathVariable String subject, */ @Post("/subjects/{subject}") @SingleResult - Responses.Subject checkSubject(@PathVariable String subject, + SubjectResponse checkSubject(@PathVariable String subject, @Body SubjectRequestBody schemaBody); /** @@ -208,7 +206,7 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, */ @Get("/subjects/{subject}/metadata") @SingleResult - Responses.Subject getSubjectMetadata(@PathVariable String subject); + SubjectResponse getSubjectMetadata(@PathVariable String subject); // MODE ---------------------------------------------------------------------------------------- @@ -219,7 +217,7 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, */ @Get("/mode") @SingleResult - Responses.Mode getMode(); + ModeResponse getMode(); /** * Set the global compatibility mode. @@ -229,7 +227,7 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, */ @Put("/mode") @SingleResult - Responses.Mode setMode(@Body Responses.Mode mode); + ModeResponse setMode(@Body ModeResponse mode); /** * Get the compatibility mode for the specified subject. @@ -239,7 +237,7 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, */ @Get("/mode/{subject}") @SingleResult - Responses.Mode getModeForSubject(@PathVariable String subject); + ModeResponse getModeForSubject(@PathVariable String subject); /** * Set the compatibility mode for the specified subject. @@ -250,7 +248,7 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, */ @Put("/mode/{subject}") @SingleResult - Responses.Mode setModeForSubject(@PathVariable String subject, @Body Responses.Mode mode); + ModeResponse setModeForSubject(@PathVariable String subject, @Body ModeResponse mode); /** * Delete the compatibility mode for the specified subject. @@ -260,7 +258,7 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, */ @Delete("/mode/{subject}") @SingleResult - Responses.Mode deleteModeForSubject(@PathVariable String subject); + ModeResponse deleteModeForSubject(@PathVariable String subject); // COMPATIBILITY --------------------------------------------------------------------------- @@ -274,7 +272,7 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, */ @Post("/compatibility/subjects/{subject}/versions/{version}") @SingleResult - Responses.Compatibility checkCompatibilityForSubjectVersion(@PathVariable String subject, + CompatibilityResponse checkCompatibilityForSubjectVersion(@PathVariable String subject, @PathVariable String version, @Body SubjectRequestBody compatibilityRequest); @@ -288,7 +286,7 @@ Responses.Compatibility checkCompatibilityForSubjectVersion(@PathVariable String */ @Post("/compatibility/subjects/{subject}/versions") @SingleResult - Responses.Compatibility checkCompatibilityForSubject(@PathVariable String subject, + CompatibilityResponse checkCompatibilityForSubject(@PathVariable String subject, @Body SubjectRequestBody compatibilityRequest); // CONFIG ---------------------------------------------------------------------------------- @@ -300,7 +298,7 @@ Responses.Compatibility checkCompatibilityForSubject(@PathVariable String subjec */ @Get("/config") @SingleResult - Responses.Config getConfig(); + ConfigResponse getConfig(); /** * Set the global configuration. @@ -310,7 +308,7 @@ Responses.Compatibility checkCompatibilityForSubject(@PathVariable String subjec */ @Put("/config") @SingleResult - Responses.Config setConfig(@Body Responses.Config config); + ConfigResponse setConfig(@Body ConfigResponse config); /** * Get the configuration for the specified subject. @@ -320,7 +318,7 @@ Responses.Compatibility checkCompatibilityForSubject(@PathVariable String subjec */ @Get("/config/{subject}") @SingleResult - Responses.Config getConfigForSubject(@PathVariable String subject); + ConfigResponse getConfigForSubject(@PathVariable String subject); /** * Set the configuration for the specified subject. @@ -331,7 +329,7 @@ Responses.Compatibility checkCompatibilityForSubject(@PathVariable String subjec */ @Put("/config/{subject}") @SingleResult - Responses.Config setConfigForSubject(@PathVariable String subject, @Body Responses.Config config); + ConfigResponse setConfigForSubject(@PathVariable String subject, @Body ConfigResponse config); /** * Delete the configuration for the specified subject. @@ -341,5 +339,5 @@ Responses.Compatibility checkCompatibilityForSubject(@PathVariable String subjec */ @Delete("/config/{subject}") @SingleResult - Responses.Config deleteConfigForSubject(@PathVariable String subject); + ConfigResponse deleteConfigForSubject(@PathVariable String subject); } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index ce1badcd..d96d803f 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -16,10 +16,11 @@ package io.micronaut.jsonschema.registry; import io.micronaut.context.annotation.ConfigurationProperties; -import io.micronaut.jsonschema.registry.types.ConfigKeys; import io.micronaut.serde.annotation.Serdeable; import jakarta.validation.constraints.NotBlank; +import static io.micronaut.jsonschema.registry.SchemaRegistryConfig.PREFIX; + /** * Configuration for the schema registry. * @@ -27,8 +28,13 @@ * @author Elif Kurtay */ @Serdeable -@ConfigurationProperties(ConfigKeys.CONFIG_NAME) +@ConfigurationProperties(PREFIX) public class SchemaRegistryConfig { + public static final String PREFIX = "schema.registry"; + public static final String HOST_URL = PREFIX + ".url"; + public static final String BASIC_AUTH_ENABLED = PREFIX + ".basicAuthEnabled"; + public static final String PUSH_TO_REGISTRY_ENABLED = PREFIX + ".pushToRegistryEnabled"; + @NotBlank private String url; @NotBlank diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java index f24681ad..80df598f 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java @@ -20,8 +20,8 @@ import io.micronaut.core.beans.BeanIntrospector; import io.micronaut.core.io.ResourceLoader; import io.micronaut.jsonschema.GeneratedFromSchema; -import io.micronaut.jsonschema.registry.types.Responses; -import io.micronaut.jsonschema.registry.types.SubjectRequestBody; +import io.micronaut.jsonschema.registry.model.SchemaType; +import io.micronaut.jsonschema.registry.model.SubjectRequestBody; import jakarta.inject.Inject; import java.io.InputStream; @@ -81,7 +81,7 @@ private void pushToRegistry() { if (!schemaString.equals(responseSchemaString)) { var response = client.registerNewVersion( subjectName, - new SubjectRequestBody(schemaString, Responses.SchemaType.JSON, null, null, null)); + new SubjectRequestBody(schemaString, SchemaType.JSON, null, null, null)); if (response.id() == -1) { System.err.println("Error pushing schema to registry: " + filename); } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryClientBasicAuthFilter.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryClientBasicAuthFilter.java index bf3c0dbc..5990f91d 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryClientBasicAuthFilter.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryClientBasicAuthFilter.java @@ -20,7 +20,6 @@ import io.micronaut.http.annotation.ClientFilter; import io.micronaut.http.annotation.RequestFilter; import io.micronaut.jsonschema.registry.SchemaRegistryConfig; -import io.micronaut.jsonschema.registry.types.ConfigKeys; import jakarta.inject.Singleton; /** @@ -30,9 +29,7 @@ * @author Elif Kurtay */ @Requires(beans = SchemaRegistryConfig.class) -@Requires(property = ConfigKeys.USERNAME) -@Requires(property = ConfigKeys.PASSWORD) -@Requires(property = ConfigKeys.BASIC_AUTH_ENABLED) +@Requires(property = SchemaRegistryConfig.BASIC_AUTH_ENABLED) @BasicAuth @Singleton @ClientFilter("/**") diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/CompatibilityLevel.java similarity index 53% rename from json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java rename to json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/CompatibilityLevel.java index 089cb4ee..a6850c4a 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/ConfigKeys.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/CompatibilityLevel.java @@ -13,13 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.jsonschema.registry.types; +package io.micronaut.jsonschema.registry.model; -public final class ConfigKeys { - public static final String CONFIG_NAME = "schema.registry"; - public static final String HOST_URL = CONFIG_NAME + ".url"; - public static final String USERNAME = CONFIG_NAME + ".username"; - public static final String PASSWORD = CONFIG_NAME + ".password"; - public static final String BASIC_AUTH_ENABLED = CONFIG_NAME + ".basicAuthEnabled"; - public static final String PUSH_TO_REGISTRY_ENABLED = CONFIG_NAME + ".pushToRegistryEnabled"; +import io.micronaut.serde.annotation.Serdeable; + +/** + * The compatibility levels of the schema registry. + * Defaults to BACKWARD. + */ +@Serdeable +public enum CompatibilityLevel { + NONE, + BACKWARD, + BACKWARD_TRANSITIVE, + FORWARD, + FORWARD_TRANSITIVE, + FULL, + FULL_TRANSITIVE } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/CompatibilityResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/CompatibilityResponse.java new file mode 100644 index 00000000..e1d5ccc1 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/CompatibilityResponse.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.model; + +import io.micronaut.core.annotation.Introspected; +import io.micronaut.serde.annotation.Serdeable; + +/** + * The compatibility of the schema. + * + * @param is_compatible Whether the two schemas are compatible + */ +@Introspected +@Serdeable +public record CompatibilityResponse( + boolean is_compatible +) { +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ConfigResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ConfigResponse.java new file mode 100644 index 00000000..d2a990cd --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ConfigResponse.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.model; + +import com.fasterxml.jackson.annotation.JsonAlias; +import io.micronaut.core.annotation.Introspected; +import io.micronaut.serde.annotation.Serdeable; + +/** + * The configuration of the registry. + * + * @param alias The alias of the registry + * @param normalize Whether to normalize the schema + * @param compatibility The compatibility level + * @param compatibilityGroup The compatibility group + * (used for compatibility checks) + * @param defaultMetadata The default metadata + * @param overrideMetadata The override metadata + * @param defaultRuleSet The default rule set + * @param overrideRuleSet The override rule set + */ +@Introspected +@Serdeable +public record ConfigResponse( + String alias, + boolean normalize, + @JsonAlias("compatibilityLevel") CompatibilityLevel compatibility, + String compatibilityGroup, + Object defaultMetadata, + Object overrideMetadata, + Object defaultRuleSet, + Object overrideRuleSet +) { +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/IdResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/IdResponse.java new file mode 100644 index 00000000..a2a0c4b9 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/IdResponse.java @@ -0,0 +1,29 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.model; + +import io.micronaut.core.annotation.Introspected; +import io.micronaut.serde.annotation.Serdeable; + +/** + * The ID of a schema. + * + * @param id The ID + */ +@Introspected +@Serdeable +public record IdResponse(int id) { +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ModeResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ModeResponse.java new file mode 100644 index 00000000..522355f2 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ModeResponse.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.model; + +import io.micronaut.core.annotation.Introspected; +import io.micronaut.serde.annotation.Serdeable; + +/** + * The mode of the registry. + * + * @param mode The mode type + */ +@Introspected +@Serdeable +public record ModeResponse( + ModeType mode +) { + /** + * The mode type. + */ + public enum ModeType { + IMPORT, + READONLY, + READWRITE + } +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaResponse.java new file mode 100644 index 00000000..90897793 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaResponse.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.model; + +import io.micronaut.core.annotation.Introspected; +import io.micronaut.serde.annotation.Serdeable; + +/** + * The JSON Schema in string. + * + * @param schema The schema string + */ +@Introspected +@Serdeable +public record SchemaResponse( + String schema +) { +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaType.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaType.java new file mode 100644 index 00000000..5becedf4 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaType.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.model; + +import io.micronaut.serde.annotation.Serdeable; + +/** + * The Schema Types available on the registry. + */ +@Serdeable +public enum SchemaType { + AVRO, + JSON, + PROTOBUF +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectRequestBody.java similarity index 94% rename from json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java rename to json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectRequestBody.java index f031f310..7ee74421 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/SubjectRequestBody.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectRequestBody.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.jsonschema.registry.types; +package io.micronaut.jsonschema.registry.model; import io.micronaut.core.annotation.Introspected; import io.micronaut.serde.annotation.Serdeable; @@ -35,7 +35,7 @@ @Introspected public record SubjectRequestBody( String schema, - Responses.SchemaType schemaType, + SchemaType schemaType, List references, Map metadata, Set ruleSet diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectResponse.java new file mode 100644 index 00000000..ba5868f9 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectResponse.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.model; + +import io.micronaut.core.annotation.Introspected; +import io.micronaut.serde.annotation.Serdeable; + +/** + * The subject details available at the registry. + * + * @param subject The subject name + * @param id The unique global ID of the schema + * @param version The version of the schema + * @param schemaType The type of the schema + * @param schema The schema string + */ +@Introspected +@Serdeable +public record SubjectResponse( + String subject, + int id, + int version, + SchemaType schemaType, + String schema +) { +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectVersionResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectVersionResponse.java new file mode 100644 index 00000000..93c6d358 --- /dev/null +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectVersionResponse.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017-2025 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.jsonschema.registry.model; + +import io.micronaut.core.annotation.Introspected; +import io.micronaut.serde.annotation.Serdeable; + +/** + * The (subject,version) pairs available at the registry. + * + * @param subject The subject name + * @param version The version of the subject + */ +@Introspected +@Serdeable +public record SubjectVersionResponse(String subject, int version) { +} diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java deleted file mode 100644 index f539d10d..00000000 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/types/Responses.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2017-2025 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micronaut.jsonschema.registry.types; - -import com.fasterxml.jackson.annotation.JsonAlias; -import io.micronaut.core.annotation.Introspected; -import io.micronaut.serde.annotation.Serdeable; - -/** - * Response types for the JSON Schema Registry Client. - */ -@Serdeable -public interface Responses { - /** - * The Schema Types available on the registry. - */ - enum SchemaType { - AVRO, - JSON, - PROTOBUF - } - - /** - * The ID of a schema. - * - * @param id The ID - */ - @Introspected - record Id( - int id - ) { - } - - /** - * The JSON Schema in string. - * - * @param schema The schema string - */ - @Introspected - record SchemaJson( - String schema - ) { - } - - /** - * The (subject,version) pairs available at the registry. - * - * @param subject The subject name - * @param version The version of the subject - */ - @Introspected - record SubjectVersion( - String subject, - int version - ) { - } - - /** - * The subject details available at the registry. - * - * @param subject The subject name - * @param id The unique global ID of the schema - * @param version The version of the schema - * @param schemaType The type of the schema - * @param schema The schema string - */ - @Introspected - record Subject( - String subject, - int id, - int version, - SchemaType schemaType, - String schema - ) { - } - - /** - * The mode of the registry. - * - * @param mode The mode type - */ - @Introspected - record Mode( - ModeType mode - ) { - /** - * The mode type. - */ - public enum ModeType { - IMPORT, - READONLY, - READWRITE - } - } - - /** - * The compatibility of the schema. - * - * @param is_compatible Whether the two schemas are compatible - */ - @Introspected - record Compatibility( - boolean is_compatible - ) { - } - - /** - * The compatibility level. - */ - enum CompatibilityLevel { - NONE, - BACKWARD, - BACKWARD_TRANSITIVE, - FORWARD, - FORWARD_TRANSITIVE, - FULL, - FULL_TRANSITIVE - } - - /** - * The configuration of the registry. - * - * @param alias The alias of the registry - * @param normalize Whether to normalize the schema - * @param compatibility The compatibility level - * @param compatibilityGroup The compatibility group - * (used for compatibility checks) - * @param defaultMetadata The default metadata - * @param overrideMetadata The override metadata - * @param defaultRuleSet The default rule set - * @param overrideRuleSet The override rule set - */ - @Introspected - record Config( - String alias, - boolean normalize, - @JsonAlias("compatibilityLevel") CompatibilityLevel compatibility, - String compatibilityGroup, - Object defaultMetadata, - Object overrideMetadata, - Object defaultRuleSet, - Object overrideRuleSet - ) { - } -} diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java index 81442184..aa43a235 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java @@ -3,9 +3,9 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import io.micronaut.context.annotation.Property; import io.micronaut.core.io.ResourceLoader; -import io.micronaut.jsonschema.registry.types.ConfigKeys; -import io.micronaut.jsonschema.registry.types.Responses; -import io.micronaut.jsonschema.registry.types.SubjectRequestBody; +import io.micronaut.jsonschema.registry.model.SchemaType; +import io.micronaut.jsonschema.registry.model.SubjectRequestBody; +import io.micronaut.jsonschema.registry.model.SubjectResponse; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import jakarta.inject.Inject; import org.junit.jupiter.api.Test; @@ -22,7 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @MicronautTest -@Property(name = ConfigKeys.HOST_URL, value = "/test/") +@Property(name = SchemaRegistryConfig.HOST_URL, value = "/test/") +@Property(name = "schema.registry.mock.service", value = "true") public class ClientTest { @Inject @@ -30,13 +31,13 @@ public class ClientTest { @Inject SchemaRegistryClient client; - Responses.Subject exampleSubject; + SubjectResponse exampleSubject; @Test void testAddNewSubject() throws IOException { prepareTestData(); // register new subject - var body = new SubjectRequestBody(exampleSubject.schema(), Responses.SchemaType.JSON, List.of(), Map.of(), Set.of()); + var body = new SubjectRequestBody(exampleSubject.schema(), SchemaType.JSON, List.of(), Map.of(), Set.of()); var response = client.registerNewVersion(exampleSubject.subject(), body); // check subject is correctly registered @@ -68,6 +69,6 @@ public void prepareTestData() throws IOException { assertTrue(expectedOptional.isPresent()); String expected = new String(expectedOptional.get().readAllBytes(), StandardCharsets.UTF_8); expected = expected.replaceAll("\\s+", "").trim(); - exampleSubject = jsonMapper.readValue(expected, Responses.Subject.class); + exampleSubject = jsonMapper.readValue(expected, SubjectResponse.class); } } diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java index 94b4110c..63bfb4d6 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java @@ -3,8 +3,13 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import io.micronaut.context.annotation.Property; import io.micronaut.core.io.ResourceLoader; -import io.micronaut.jsonschema.registry.types.ConfigKeys; -import io.micronaut.jsonschema.registry.types.Responses; +import io.micronaut.jsonschema.registry.model.CompatibilityLevel; +import io.micronaut.jsonschema.registry.model.ConfigResponse; +import io.micronaut.jsonschema.registry.model.ModeResponse; +import io.micronaut.jsonschema.registry.model.SchemaResponse; +import io.micronaut.jsonschema.registry.model.SchemaType; +import io.micronaut.jsonschema.registry.model.SubjectResponse; +import io.micronaut.jsonschema.registry.model.SubjectVersionResponse; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; @@ -25,10 +30,10 @@ * Checking the response types from the client. */ @MicronautTest -@Property(name = ConfigKeys.HOST_URL, value = "http://144.24.55.159:8081/") -@Property(name = ConfigKeys.USERNAME, value = "micronaut") -@Property(name = ConfigKeys.PASSWORD, value = "test") -@Property(name = ConfigKeys.BASIC_AUTH_ENABLED, value = "true") +@Property(name = SchemaRegistryConfig.HOST_URL, value = "http://144.24.55.159:8081/") +@Property(name = SchemaRegistryConfig.PREFIX + ".username", value = "micronaut") +@Property(name = SchemaRegistryConfig.PREFIX + ".password", value = "test") +@Property(name = SchemaRegistryConfig.BASIC_AUTH_ENABLED, value = "true") public class ConfluentClientTest { @Inject @@ -41,29 +46,29 @@ public class ConfluentClientTest { @Test void testGetWithSchemas() { var response = client.getSchemaWithId(1); - assertEquals(new Responses.SchemaJson("\"string\""), response); + assertEquals(new SchemaResponse("\"string\""), response); var response2 = client.getSchemaStringWithId(1); assertEquals("\"string\"", response2); var response3 = client.getSchemaVersionsWithId(1); - assertEquals(List.of(new Responses.SubjectVersion("my_subject", 1)), response3); + assertEquals(List.of(new SubjectVersionResponse("my_subject", 1)), response3); var response4 = client.getSchemaTypes(); - assertEquals(List.of(Responses.SchemaType.JSON, Responses.SchemaType.PROTOBUF, Responses.SchemaType.AVRO), response4); + assertEquals(List.of(SchemaType.JSON, SchemaType.PROTOBUF, SchemaType.AVRO), response4); } @Test void testConfigGetters() { var response1 = client.getConfig(); - assertEquals(new Responses.Config(null, false, Responses.CompatibilityLevel.BACKWARD, + assertEquals(new ConfigResponse(null, false, CompatibilityLevel.BACKWARD, null, null, null, null, null), response1); } @Test void testModeGetters() { var response1 = client.getMode(); - assertEquals(new Responses.Mode(Responses.Mode.ModeType.READWRITE), response1); + assertEquals(new ModeResponse(ModeResponse.ModeType.READWRITE), response1); assertNull(client.getModeForSubject("human")); } @@ -77,9 +82,9 @@ void testGetSubject() throws IOException { // prepare expected response String expected = getExpectedResponse("human.json"); - Responses.Subject subjectExpected = jsonMapper.readValue(expected, Responses.Subject.class); + SubjectResponse subjectExpected = jsonMapper.readValue(expected, SubjectResponse.class); - Responses.Subject response3 = client.getSubjectWithVersion("human", "latest"); + SubjectResponse response3 = client.getSubjectWithVersion("human", "latest"); assertEquals(subjectExpected, response3); String response4 = client.getSchemaWithSubjectAndVersion("human", "latest"); @@ -88,7 +93,7 @@ void testGetSubject() throws IOException { var response5 = client.getSubjectVersionReferencedBy("human", "latest"); assertEquals(List.of(), response5); - Responses.Subject response6 = client.getSubjectMetadata("human"); + SubjectResponse response6 = client.getSubjectMetadata("human"); assertNull(response6); } diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/TestController.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/MockSchemaRegistryService.java similarity index 78% rename from json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/TestController.java rename to json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/MockSchemaRegistryService.java index cae1cd8a..bb9ceed2 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/TestController.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/MockSchemaRegistryService.java @@ -1,5 +1,6 @@ package io.micronaut.jsonschema.registry; +import io.micronaut.context.annotation.Requires; import io.micronaut.core.async.annotation.SingleResult; import io.micronaut.http.MediaType; import io.micronaut.http.annotation.Body; @@ -9,42 +10,44 @@ import io.micronaut.http.annotation.Get; import io.micronaut.http.annotation.PathVariable; import io.micronaut.http.annotation.Post; -import io.micronaut.jsonschema.registry.types.Responses; -import io.micronaut.jsonschema.registry.types.SubjectRequestBody; +import io.micronaut.jsonschema.registry.model.IdResponse; +import io.micronaut.jsonschema.registry.model.SubjectRequestBody; +import io.micronaut.jsonschema.registry.model.SubjectResponse; import java.util.ArrayList; import java.util.List; @Controller("/test") @Consumes(MediaType.APPLICATION_JSON) -public class TestController { - private final List subjects = new ArrayList<>(); +@Requires(property = "schema.registry.mock.service", value = "true") +public class MockSchemaRegistryService { + private final List subjects = new ArrayList<>(); private int idCounter = 2; @Post("/subjects/{subject}/versions") @SingleResult - Responses.Id registerNewVersion(@PathVariable String subject, + IdResponse registerNewVersion(@PathVariable String subject, @Body SubjectRequestBody schemaBody) { // check if subject already exists and get its latest version var existingSubject = getExistingLatestSubject(subject); var version = 1; if (existingSubject != null) { if (existingSubject.schema().equals(schemaBody.schema())) { - return new Responses.Id(existingSubject.id()); + return new IdResponse(existingSubject.id()); } version = existingSubject.version() + 1; } - var newSubject = new Responses.Subject(subject, idCounter, version, schemaBody.schemaType(), schemaBody.schema()); + var newSubject = new SubjectResponse(subject, idCounter, version, schemaBody.schemaType(), schemaBody.schema()); subjects.add(newSubject); idCounter++; - return new Responses.Id(newSubject.id()); + return new IdResponse(newSubject.id()); } @Get("/subjects") @SingleResult List getSubjects() { return subjects.stream() - .map(Responses.Subject::subject) + .map(SubjectResponse::subject) .distinct() .toList(); } @@ -54,7 +57,7 @@ List getSubjects() { List getSubjectVersions(@PathVariable String subject) { return subjects.stream() .filter(s -> s.subject().equals(subject)) - .map(Responses.Subject::version) + .map(SubjectResponse::version) .toList(); } @@ -63,7 +66,7 @@ List getSubjectVersions(@PathVariable String subject) { List deleteSubject(@PathVariable String subject) { var deletedVersions = subjects.stream() .filter(s -> s.subject().equals(subject)) - .map(Responses.Subject::version) + .map(SubjectResponse::version) .toList(); subjects.removeIf(s -> s.subject().equals(subject)); return deletedVersions; @@ -71,7 +74,7 @@ List deleteSubject(@PathVariable String subject) { @Get("/subjects/{subject}/versions/{version}") @SingleResult - Responses.Subject getSubjectWithVersion(@PathVariable String subject, + SubjectResponse getSubjectWithVersion(@PathVariable String subject, @PathVariable String version) { if (version.equals("latest")) { return getExistingLatestSubject(subject); @@ -92,7 +95,7 @@ String getSchemaWithSubjectAndVersion(@PathVariable String subject, @Post("/subjects/{subject}") @SingleResult - Responses.Subject checkSubject(@PathVariable String subject, + SubjectResponse checkSubject(@PathVariable String subject, @Body SubjectRequestBody schemaBody) { return subjects.stream() .filter(s -> s.subject().equals(subject) && s.schema().equals(schemaBody.schema())) @@ -118,7 +121,7 @@ int deleteSubjectVersion(@PathVariable String subject, return versionInt; } - private Responses.Subject getExistingLatestSubject(String subject) { + private SubjectResponse getExistingLatestSubject(String subject) { return subjects.stream() .filter(s -> s.subject().equals(subject)) .max((s1, s2) -> Integer.compare(s2.version(), s1.version())) From 35472b2f3e7d531557253288f567f08f7e6daea9 Mon Sep 17 00:00:00 2001 From: Andriy Dmytruk Date: Fri, 21 Feb 2025 11:14:12 -0500 Subject: [PATCH 20/24] Minor changes --- .../registry/SchemaRegistryClient.java | 30 ---------- .../registry/SchemaRegistryManager.java | 59 +++++++++++-------- .../registry/model/SubjectRequestBody.java | 4 +- .../src/test/resources/animal.schema.json | 4 +- 4 files changed, 38 insertions(+), 59 deletions(-) diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 4a483d01..2c1b7359 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -16,10 +16,7 @@ package io.micronaut.jsonschema.registry; import io.micronaut.context.annotation.Requires; -import io.micronaut.core.async.annotation.SingleResult; -import io.micronaut.http.MediaType; import io.micronaut.http.annotation.Body; -import io.micronaut.http.annotation.Consumes; import io.micronaut.http.annotation.Delete; import io.micronaut.http.annotation.Get; import io.micronaut.http.annotation.PathVariable; @@ -47,7 +44,6 @@ @Requires(beans = SchemaRegistryConfig.class) @Requires(property = SchemaRegistryConfig.HOST_URL) @Client(value = "${" + SchemaRegistryConfig.HOST_URL + "}") -@Consumes(MediaType.APPLICATION_JSON) @BasicAuth @Singleton public interface SchemaRegistryClient { @@ -61,7 +57,6 @@ public interface SchemaRegistryClient { * @return The schema string identified by the input ID */ @Get("/schemas/ids/{id}") - @SingleResult SchemaResponse getSchemaWithId(@PathVariable int id); /** @@ -71,7 +66,6 @@ public interface SchemaRegistryClient { * @return SchemaJson identified by the ID */ @Get("/schemas/ids/{id}/schema") - @SingleResult String getSchemaStringWithId(@PathVariable int id); /** @@ -81,7 +75,6 @@ public interface SchemaRegistryClient { * @return The subject-version pairs */ @Get("/schemas/ids/{id}/versions") - @SingleResult List getSchemaVersionsWithId(@PathVariable int id); /** @@ -90,7 +83,6 @@ public interface SchemaRegistryClient { * @return The list of schema types */ @Get("/schemas/types") - @SingleResult List getSchemaTypes(); @@ -102,7 +94,6 @@ public interface SchemaRegistryClient { * @return The list of subject names */ @Get("/subjects") - @SingleResult List getSubjects(); /** @@ -112,7 +103,6 @@ public interface SchemaRegistryClient { * @return The list of versions */ @Get("/subjects/{subject}/versions") - @SingleResult List getSubjectVersions(@PathVariable String subject); /** @@ -122,7 +112,6 @@ public interface SchemaRegistryClient { * @return The list of versions that were deleted */ @Delete("/subjects/{subject}") - @SingleResult List deleteSubject(@PathVariable String subject); /** @@ -133,7 +122,6 @@ public interface SchemaRegistryClient { * @return The requested schema */ @Get("/subjects/{subject}/versions/{version}") - @SingleResult SubjectResponse getSubjectWithVersion(@PathVariable String subject, @PathVariable String version); @@ -145,7 +133,6 @@ SubjectResponse getSubjectWithVersion(@PathVariable String subject, * @return The requested schema string (unescaped) */ @Get("/subjects/{subject}/versions/{version}/schema") - @SingleResult String getSchemaWithSubjectAndVersion(@PathVariable String subject, @PathVariable String version); @@ -158,7 +145,6 @@ String getSchemaWithSubjectAndVersion(@PathVariable String subject, * @return The globally unique identifier of the schema */ @Post("/subjects/{subject}/versions") - @SingleResult IdResponse registerNewVersion(@PathVariable String subject, @Body SubjectRequestBody schemaBody); @@ -170,7 +156,6 @@ IdResponse registerNewVersion(@PathVariable String subject, * @return the schema string along with its globally unique identifier, its version under this subject and the subject name. */ @Post("/subjects/{subject}") - @SingleResult SubjectResponse checkSubject(@PathVariable String subject, @Body SubjectRequestBody schemaBody); @@ -182,7 +167,6 @@ SubjectResponse checkSubject(@PathVariable String subject, * @return The version number that was deleted */ @Delete("/subjects/{subject}/versions/{version}") - @SingleResult int deleteSubjectVersion(@PathVariable String subject, @PathVariable String version); @@ -194,7 +178,6 @@ int deleteSubjectVersion(@PathVariable String subject, * @return The list of versions that reference this schema */ @Get("/subjects/{subject}/versions/{version}/referencedby") - @SingleResult List getSubjectVersionReferencedBy(@PathVariable String subject, @PathVariable String version); @@ -205,7 +188,6 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, * @return The metadata for the specified subject */ @Get("/subjects/{subject}/metadata") - @SingleResult SubjectResponse getSubjectMetadata(@PathVariable String subject); // MODE ---------------------------------------------------------------------------------------- @@ -216,7 +198,6 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, * @return The global compatibility mode */ @Get("/mode") - @SingleResult ModeResponse getMode(); /** @@ -226,7 +207,6 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, * @return The new global compatibility mode */ @Put("/mode") - @SingleResult ModeResponse setMode(@Body ModeResponse mode); /** @@ -236,7 +216,6 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, * @return The compatibility mode for the specified subject */ @Get("/mode/{subject}") - @SingleResult ModeResponse getModeForSubject(@PathVariable String subject); /** @@ -247,7 +226,6 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, * @return The new compatibility mode for the specified subject */ @Put("/mode/{subject}") - @SingleResult ModeResponse setModeForSubject(@PathVariable String subject, @Body ModeResponse mode); /** @@ -257,7 +235,6 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, * @return The compatibility mode that was deleted */ @Delete("/mode/{subject}") - @SingleResult ModeResponse deleteModeForSubject(@PathVariable String subject); // COMPATIBILITY --------------------------------------------------------------------------- @@ -271,7 +248,6 @@ List getSubjectVersionReferencedBy(@PathVariable String subject, * @return Whether the new schema is compatible with the specified subject and version */ @Post("/compatibility/subjects/{subject}/versions/{version}") - @SingleResult CompatibilityResponse checkCompatibilityForSubjectVersion(@PathVariable String subject, @PathVariable String version, @Body SubjectRequestBody compatibilityRequest); @@ -285,7 +261,6 @@ CompatibilityResponse checkCompatibilityForSubjectVersion(@PathVariable String s * @return Whether the new schema is compatible with the specified subject */ @Post("/compatibility/subjects/{subject}/versions") - @SingleResult CompatibilityResponse checkCompatibilityForSubject(@PathVariable String subject, @Body SubjectRequestBody compatibilityRequest); @@ -297,7 +272,6 @@ CompatibilityResponse checkCompatibilityForSubject(@PathVariable String subject, * @return The global configuration */ @Get("/config") - @SingleResult ConfigResponse getConfig(); /** @@ -307,7 +281,6 @@ CompatibilityResponse checkCompatibilityForSubject(@PathVariable String subject, * @return The new global configuration */ @Put("/config") - @SingleResult ConfigResponse setConfig(@Body ConfigResponse config); /** @@ -317,7 +290,6 @@ CompatibilityResponse checkCompatibilityForSubject(@PathVariable String subject, * @return The configuration for the specified subject */ @Get("/config/{subject}") - @SingleResult ConfigResponse getConfigForSubject(@PathVariable String subject); /** @@ -328,7 +300,6 @@ CompatibilityResponse checkCompatibilityForSubject(@PathVariable String subject, * @return The new configuration for the specified subject */ @Put("/config/{subject}") - @SingleResult ConfigResponse setConfigForSubject(@PathVariable String subject, @Body ConfigResponse config); /** @@ -338,6 +309,5 @@ CompatibilityResponse checkCompatibilityForSubject(@PathVariable String subject, * @return The configuration that was deleted */ @Delete("/config/{subject}") - @SingleResult ConfigResponse deleteConfigForSubject(@PathVariable String subject); } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java index 80df598f..98e43459 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java @@ -17,6 +17,8 @@ import io.micronaut.context.annotation.Context; import io.micronaut.context.annotation.Requires; +import io.micronaut.core.annotation.NonNull; +import io.micronaut.core.annotation.Nullable; import io.micronaut.core.beans.BeanIntrospector; import io.micronaut.core.io.ResourceLoader; import io.micronaut.jsonschema.GeneratedFromSchema; @@ -25,8 +27,9 @@ import jakarta.inject.Inject; import java.io.InputStream; -import java.util.HashSet; +import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; /** * A manager for the Confluent SchemaJson Registry Client. @@ -51,31 +54,20 @@ public SchemaRegistryManager(SchemaRegistryClient client, SchemaRegistryConfig c private void pushToRegistry() { // push all schemas to registry - Set uniqueFileNames = new HashSet<>(); - BeanIntrospector.SHARED.findIntrospections(GeneratedFromSchema.class).forEach(beanIntrospection -> { - beanIntrospection.getAnnotation(GeneratedFromSchema.class) - .stringValue("fileName") - .ifPresent(uniqueFileNames::add); - }); + Set uniqueFileNames = BeanIntrospector.SHARED.findIntrospections(GeneratedFromSchema.class) + .stream() + .map(i -> i.getAnnotation(GeneratedFromSchema.class).stringValue("fileName").orElse(null)) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); // for each unique filename, get schema from file - uniqueFileNames.forEach(filename -> { - String schemaString = null; - try (InputStream inputStream = getClass().getResourceAsStream("/" + filename)) { - // get local schema file - if (inputStream == null) { - System.err.println("Resource not found: " + filename); - return; - } - schemaString = new String(inputStream.readAllBytes()) - .replaceAll("\"", "\\\\\""); - } catch (Exception e) { - throw new RuntimeException("Error loading resource " + filename, e); + for (String filename: uniqueFileNames) { + String schemaString = readSchemaFromFile(filename); + if (schemaString == null) { + continue; } - // get schema from registry - var subjectName = filename.substring( - filename.contains("/") ? filename.lastIndexOf('/') : 0, - filename.contains(".") ? filename.indexOf('.') : filename.length()); + + var subjectName = getSubjectName(filename); String responseSchemaString = client.getSchemaWithSubjectAndVersion(subjectName, "latest"); // compare local vs registry, if different, push to registry if (!schemaString.equals(responseSchemaString)) { @@ -86,6 +78,25 @@ private void pushToRegistry() { System.err.println("Error pushing schema to registry: " + filename); } } - }); + } + } + + private @NonNull String getSubjectName(@NonNull String filename) { + return filename.substring( + filename.contains("/") ? filename.lastIndexOf('/') : 0, + filename.contains(".") ? filename.indexOf('.') : filename.length()); + } + + private @Nullable String readSchemaFromFile(@NonNull String filename) { + try (InputStream inputStream = getClass().getResourceAsStream("/" + filename)) { + // get local schema file + if (inputStream == null) { + System.err.println("Resource not found: " + filename); + return null; + } + return new String(inputStream.readAllBytes()); + } catch (Exception e) { + throw new RuntimeException("Error loading resource " + filename, e); + } } } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectRequestBody.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectRequestBody.java index 7ee74421..1cef5331 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectRequestBody.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectRequestBody.java @@ -15,7 +15,6 @@ */ package io.micronaut.jsonschema.registry.model; -import io.micronaut.core.annotation.Introspected; import io.micronaut.serde.annotation.Serdeable; import java.util.List; @@ -32,7 +31,6 @@ * @param ruleSet The rule set. */ @Serdeable -@Introspected public record SubjectRequestBody( String schema, SchemaType schemaType, @@ -47,7 +45,7 @@ public record SubjectRequestBody( * @param subject The subject name. * @param version The subject version. */ - @Introspected + @Serdeable public record ReferenceType( String name, String subject, diff --git a/json-schema-registry/src/test/resources/animal.schema.json b/json-schema-registry/src/test/resources/animal.schema.json index 3cfa07e3..adaebca8 100644 --- a/json-schema-registry/src/test/resources/animal.schema.json +++ b/json-schema-registry/src/test/resources/animal.schema.json @@ -1,6 +1,6 @@ { "$schema":"https://json-schema.org/draft/2020-12/schema", - "$id":"https://example.com/schemas/llama.schema.json", + "$id":"https://example.com/schemas/animal.schema.json", "title":"Animal", "description":"An animal.", "type":["object"], @@ -52,7 +52,7 @@ } } }], - "$defs": { + "definitions": { "id": { "pattern": "^[A-Za-z0-9\\-\\.]{1,64}$", "type": "string", From ccf8bd7baac8897955f60a555fe71cc9595f64a9 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Thu, 6 Mar 2025 15:18:40 +0100 Subject: [PATCH 21/24] remove confluent test --- .../registry/ConfluentClientTest.java | 106 ------------------ 1 file changed, 106 deletions(-) delete mode 100644 json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java deleted file mode 100644 index 63bfb4d6..00000000 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ConfluentClientTest.java +++ /dev/null @@ -1,106 +0,0 @@ -package io.micronaut.jsonschema.registry; - -import com.fasterxml.jackson.databind.json.JsonMapper; -import io.micronaut.context.annotation.Property; -import io.micronaut.core.io.ResourceLoader; -import io.micronaut.jsonschema.registry.model.CompatibilityLevel; -import io.micronaut.jsonschema.registry.model.ConfigResponse; -import io.micronaut.jsonschema.registry.model.ModeResponse; -import io.micronaut.jsonschema.registry.model.SchemaResponse; -import io.micronaut.jsonschema.registry.model.SchemaType; -import io.micronaut.jsonschema.registry.model.SubjectResponse; -import io.micronaut.jsonschema.registry.model.SubjectVersionResponse; -import io.micronaut.test.extensions.junit5.annotation.MicronautTest; -import org.junit.jupiter.api.Test; - -import jakarta.inject.Inject; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -/** - * Tests for the ConfluentClient for Schema Registry. - * Checking the response types from the client. - */ -@MicronautTest -@Property(name = SchemaRegistryConfig.HOST_URL, value = "http://144.24.55.159:8081/") -@Property(name = SchemaRegistryConfig.PREFIX + ".username", value = "micronaut") -@Property(name = SchemaRegistryConfig.PREFIX + ".password", value = "test") -@Property(name = SchemaRegistryConfig.BASIC_AUTH_ENABLED, value = "true") -public class ConfluentClientTest { - - @Inject - ResourceLoader resourceLoader; - @Inject - SchemaRegistryClient client; - - JsonMapper jsonMapper = new JsonMapper(); - - @Test - void testGetWithSchemas() { - var response = client.getSchemaWithId(1); - assertEquals(new SchemaResponse("\"string\""), response); - - var response2 = client.getSchemaStringWithId(1); - assertEquals("\"string\"", response2); - - var response3 = client.getSchemaVersionsWithId(1); - assertEquals(List.of(new SubjectVersionResponse("my_subject", 1)), response3); - - var response4 = client.getSchemaTypes(); - assertEquals(List.of(SchemaType.JSON, SchemaType.PROTOBUF, SchemaType.AVRO), response4); - } - - @Test - void testConfigGetters() { - var response1 = client.getConfig(); - assertEquals(new ConfigResponse(null, false, CompatibilityLevel.BACKWARD, - null, null, null, null, null), response1); - } - - @Test - void testModeGetters() { - var response1 = client.getMode(); - assertEquals(new ModeResponse(ModeResponse.ModeType.READWRITE), response1); - assertNull(client.getModeForSubject("human")); - } - - @Test - void testGetSubject() throws IOException { - var response1 = client.getSubjects(); - assertEquals(List.of("human", "my_subject"), response1); - - List response2 = client.getSubjectVersions("human"); - assertEquals(List.of(1), response2); - - // prepare expected response - String expected = getExpectedResponse("human.json"); - SubjectResponse subjectExpected = jsonMapper.readValue(expected, SubjectResponse.class); - - SubjectResponse response3 = client.getSubjectWithVersion("human", "latest"); - assertEquals(subjectExpected, response3); - - String response4 = client.getSchemaWithSubjectAndVersion("human", "latest"); - assertEquals(subjectExpected.schema(), response4); - - var response5 = client.getSubjectVersionReferencedBy("human", "latest"); - assertEquals(List.of(), response5); - - SubjectResponse response6 = client.getSubjectMetadata("human"); - assertNull(response6); - } - - private String getExpectedResponse(String filename) throws IOException { - Optional expectedOptional = resourceLoader.getResourceAsStream(filename); - assertTrue(expectedOptional.isPresent()); - String expected = new String(expectedOptional.get().readAllBytes(), StandardCharsets.UTF_8); - return expected.replaceAll("\\s+", "").trim(); - } -} From 8d3e6756db47cbea1e7e5fc8b885a75b2bfaa98c Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Wed, 12 Mar 2025 16:00:57 +0100 Subject: [PATCH 22/24] small cr changes --- json-schema-registry/build.gradle | 6 ++---- .../jsonschema/registry/SchemaRegistryClient.java | 4 ++-- .../jsonschema/registry/SchemaRegistryConfig.java | 3 +-- .../jsonschema/registry/SchemaRegistryManager.java | 7 +++++++ .../auth/{BasicAuth.java => SchemaRegistryAuth.java} | 2 +- .../registry/auth/SchemaRegistryClientBasicAuthFilter.java | 2 +- .../jsonschema/registry/model/CompatibilityResponse.java | 2 -- .../jsonschema/registry/model/ConfigResponse.java | 2 -- .../io/micronaut/jsonschema/registry/model/IdResponse.java | 2 -- .../micronaut/jsonschema/registry/model/ModeResponse.java | 6 ++---- .../jsonschema/registry/model/SchemaResponse.java | 2 -- .../jsonschema/registry/model/SubjectRequestBody.java | 4 ++-- .../jsonschema/registry/model/SubjectResponse.java | 2 -- .../jsonschema/registry/model/SubjectVersionResponse.java | 2 -- 14 files changed, 18 insertions(+), 28 deletions(-) rename json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/{BasicAuth.java => SchemaRegistryAuth.java} (96%) diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle index 946644e8..fc3aa87a 100644 --- a/json-schema-registry/build.gradle +++ b/json-schema-registry/build.gradle @@ -43,14 +43,12 @@ tasks.named("generateAnimals") { } sourceSets { - main { + test { + java.srcDir('src/test/java') resources { srcDirs(java.srcDir(animalGenerator.map(BeanGeneratorTask::getGeneratedSourcesDirectory))) } } - test { - java.srcDir('src/test/java') - } } tasks.withType(Checkstyle).configureEach { diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java index 2c1b7359..b3f95a25 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryClient.java @@ -23,7 +23,7 @@ import io.micronaut.http.annotation.Post; import io.micronaut.http.annotation.Put; import io.micronaut.http.client.annotation.Client; -import io.micronaut.jsonschema.registry.auth.BasicAuth; +import io.micronaut.jsonschema.registry.auth.SchemaRegistryAuth; import io.micronaut.jsonschema.registry.model.*; import jakarta.inject.Singleton; @@ -44,7 +44,7 @@ @Requires(beans = SchemaRegistryConfig.class) @Requires(property = SchemaRegistryConfig.HOST_URL) @Client(value = "${" + SchemaRegistryConfig.HOST_URL + "}") -@BasicAuth +@SchemaRegistryAuth @Singleton public interface SchemaRegistryClient { diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index d96d803f..4198ae5f 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -27,9 +27,8 @@ * @since 1.5.0 * @author Elif Kurtay */ -@Serdeable @ConfigurationProperties(PREFIX) -public class SchemaRegistryConfig { +public final class SchemaRegistryConfig { public static final String PREFIX = "schema.registry"; public static final String HOST_URL = PREFIX + ".url"; public static final String BASIC_AUTH_ENABLED = PREFIX + ".basicAuthEnabled"; diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java index 98e43459..2c687650 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryManager.java @@ -34,6 +34,13 @@ /** * A manager for the Confluent SchemaJson Registry Client. * + * This class is responsible for keeping the registry updated. + * When the application starts, + * - it will check for generated files from a local schema, + * - check if the local schema is different from the one in the registry + * (schema filename and registry subject name needs to be the same), + * - if yes, will push the new local schemas to the registry. + * * @author Elif Kurtay * @since 1.5.0 */ diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/BasicAuth.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryAuth.java similarity index 96% rename from json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/BasicAuth.java rename to json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryAuth.java index f43a5a6d..7c87782c 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/BasicAuth.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryAuth.java @@ -32,5 +32,5 @@ @Documented @Retention(RUNTIME) @Target({TYPE, PARAMETER}) -public @interface BasicAuth { +public @interface SchemaRegistryAuth { } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryClientBasicAuthFilter.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryClientBasicAuthFilter.java index 5990f91d..40d15773 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryClientBasicAuthFilter.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/auth/SchemaRegistryClientBasicAuthFilter.java @@ -30,7 +30,7 @@ */ @Requires(beans = SchemaRegistryConfig.class) @Requires(property = SchemaRegistryConfig.BASIC_AUTH_ENABLED) -@BasicAuth +@SchemaRegistryAuth @Singleton @ClientFilter("/**") public class SchemaRegistryClientBasicAuthFilter { diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/CompatibilityResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/CompatibilityResponse.java index e1d5ccc1..01dca729 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/CompatibilityResponse.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/CompatibilityResponse.java @@ -15,7 +15,6 @@ */ package io.micronaut.jsonschema.registry.model; -import io.micronaut.core.annotation.Introspected; import io.micronaut.serde.annotation.Serdeable; /** @@ -23,7 +22,6 @@ * * @param is_compatible Whether the two schemas are compatible */ -@Introspected @Serdeable public record CompatibilityResponse( boolean is_compatible diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ConfigResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ConfigResponse.java index d2a990cd..cfcade6d 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ConfigResponse.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ConfigResponse.java @@ -16,7 +16,6 @@ package io.micronaut.jsonschema.registry.model; import com.fasterxml.jackson.annotation.JsonAlias; -import io.micronaut.core.annotation.Introspected; import io.micronaut.serde.annotation.Serdeable; /** @@ -32,7 +31,6 @@ * @param defaultRuleSet The default rule set * @param overrideRuleSet The override rule set */ -@Introspected @Serdeable public record ConfigResponse( String alias, diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/IdResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/IdResponse.java index a2a0c4b9..63ad9eb4 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/IdResponse.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/IdResponse.java @@ -15,7 +15,6 @@ */ package io.micronaut.jsonschema.registry.model; -import io.micronaut.core.annotation.Introspected; import io.micronaut.serde.annotation.Serdeable; /** @@ -23,7 +22,6 @@ * * @param id The ID */ -@Introspected @Serdeable public record IdResponse(int id) { } diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ModeResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ModeResponse.java index 522355f2..e0ff87f1 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ModeResponse.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/ModeResponse.java @@ -15,7 +15,6 @@ */ package io.micronaut.jsonschema.registry.model; -import io.micronaut.core.annotation.Introspected; import io.micronaut.serde.annotation.Serdeable; /** @@ -23,15 +22,14 @@ * * @param mode The mode type */ -@Introspected @Serdeable public record ModeResponse( - ModeType mode + Mode mode ) { /** * The mode type. */ - public enum ModeType { + public enum Mode { IMPORT, READONLY, READWRITE diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaResponse.java index 90897793..a6a60955 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaResponse.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SchemaResponse.java @@ -15,7 +15,6 @@ */ package io.micronaut.jsonschema.registry.model; -import io.micronaut.core.annotation.Introspected; import io.micronaut.serde.annotation.Serdeable; /** @@ -23,7 +22,6 @@ * * @param schema The schema string */ -@Introspected @Serdeable public record SchemaResponse( String schema diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectRequestBody.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectRequestBody.java index 1cef5331..fdcf8445 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectRequestBody.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectRequestBody.java @@ -34,7 +34,7 @@ public record SubjectRequestBody( String schema, SchemaType schemaType, - List references, + List references, Map metadata, Set ruleSet ) { @@ -46,7 +46,7 @@ public record SubjectRequestBody( * @param version The subject version. */ @Serdeable - public record ReferenceType( + public record Reference( String name, String subject, String version) { diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectResponse.java index ba5868f9..8ee18b89 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectResponse.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectResponse.java @@ -15,7 +15,6 @@ */ package io.micronaut.jsonschema.registry.model; -import io.micronaut.core.annotation.Introspected; import io.micronaut.serde.annotation.Serdeable; /** @@ -27,7 +26,6 @@ * @param schemaType The type of the schema * @param schema The schema string */ -@Introspected @Serdeable public record SubjectResponse( String subject, diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectVersionResponse.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectVersionResponse.java index 93c6d358..cc0772e5 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectVersionResponse.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/model/SubjectVersionResponse.java @@ -15,7 +15,6 @@ */ package io.micronaut.jsonschema.registry.model; -import io.micronaut.core.annotation.Introspected; import io.micronaut.serde.annotation.Serdeable; /** @@ -24,7 +23,6 @@ * @param subject The subject name * @param version The version of the subject */ -@Introspected @Serdeable public record SubjectVersionResponse(String subject, int version) { } From acfe5c91426a79c5bdc3b76f806dab5e9d601fd8 Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Wed, 12 Mar 2025 18:30:10 +0100 Subject: [PATCH 23/24] manager test added --- json-schema-registry/build.gradle | 4 +--- .../micronaut/jsonschema/registry/ClientTest.java | 13 +++++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/json-schema-registry/build.gradle b/json-schema-registry/build.gradle index fc3aa87a..f9db4ccc 100644 --- a/json-schema-registry/build.gradle +++ b/json-schema-registry/build.gradle @@ -45,9 +45,7 @@ tasks.named("generateAnimals") { sourceSets { test { java.srcDir('src/test/java') - resources { - srcDirs(java.srcDir(animalGenerator.map(BeanGeneratorTask::getGeneratedSourcesDirectory))) - } + java.srcDir(animalGenerator.map(BeanGeneratorTask::getGeneratedSourcesDirectory)) } } diff --git a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java index aa43a235..5c1215ec 100644 --- a/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java +++ b/json-schema-registry/src/test/java/io/micronaut/jsonschema/registry/ClientTest.java @@ -19,6 +19,7 @@ import java.util.Set; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @MicronautTest @@ -33,6 +34,18 @@ public class ClientTest { SubjectResponse exampleSubject; + @Test + void testSchemaManager() { + SchemaRegistryConfig config = new SchemaRegistryConfig(); + config.setUrl("/test/"); + config.setPushToRegistryEnabled(true); + SchemaRegistryManager manager = new SchemaRegistryManager(client, config); + assertNotNull(manager); + + assertEquals(List.of("animal"), client.getSubjects()); + assertNotNull(client.getSubjectWithVersion("animal", "1")); + } + @Test void testAddNewSubject() throws IOException { prepareTestData(); From 4ee51d3344c2c6dff31bd52ac82c7c3cb0e1cbaa Mon Sep 17 00:00:00 2001 From: elifKurtay Date: Thu, 13 Mar 2025 16:51:09 +0100 Subject: [PATCH 24/24] add docs --- .../registry/SchemaRegistryConfig.java | 4 +-- src/main/docs/guide/generator/example.adoc | 7 +++++ src/main/docs/guide/introduction.adoc | 2 +- src/main/docs/guide/registry.adoc | 29 +++++++++++++++++++ src/main/docs/guide/toc.yml | 3 +- 5 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 src/main/docs/guide/registry.adoc diff --git a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java index 4198ae5f..24a6331e 100644 --- a/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java +++ b/json-schema-registry/src/main/java/io/micronaut/jsonschema/registry/SchemaRegistryConfig.java @@ -36,12 +36,10 @@ public final class SchemaRegistryConfig { @NotBlank private String url; - @NotBlank private String username; - @NotBlank private String password; private boolean pushToRegistryEnabled = false; - private boolean basicAuthEnabled = true; + private boolean basicAuthEnabled = false; public SchemaRegistryConfig() { } diff --git a/src/main/docs/guide/generator/example.adoc b/src/main/docs/guide/generator/example.adoc index 3a7201ab..05b53cb6 100644 --- a/src/main/docs/guide/generator/example.adoc +++ b/src/main/docs/guide/generator/example.adoc @@ -5,6 +5,13 @@ The following file is an example JSON schema describing an Animal interface whic include::test-suite-generator-java/src/test/resources/animal.schema.json[] ---- +And the following file shows the generated Java class for the Animal object: + +[source,java] +---- +include::test-suite-generator-java/build/generated/jsonSchema/src/main/java/io/micronaut/jsonschema/generator/animals/Animal.java[] +---- + The following example shows how the `JsonMapper` can map the JSON data to the best fitting/correct class in the inheritance relation even though only the interface is given to the function. snippet::io.micronaut.jsonschema.generator.animals.AnimalTest[project-base="test-suite-generator", tags=mapp, indent=0] diff --git a/src/main/docs/guide/introduction.adoc b/src/main/docs/guide/introduction.adoc index bc06fb06..b07856e5 100644 --- a/src/main/docs/guide/introduction.adoc +++ b/src/main/docs/guide/introduction.adoc @@ -1,4 +1,4 @@ link:https://json-schema.org/[JSON Schema] is a human-readable format for exchanging data that also enables JSON data consistency, validity and interoperability. -Micronaut JSON Schema assists transforming schemas to beans and beans to schemas in your applications. +Micronaut JSON Schema assists transforming schemas to beans and beans to schemas in your applications. In addition, it includes a convenient connection to https://docs.confluent.io/platform/current/schema-registry/index.html[Confluent Schema Registry] for schema management. diff --git a/src/main/docs/guide/registry.adoc b/src/main/docs/guide/registry.adoc new file mode 100644 index 00000000..c3b00689 --- /dev/null +++ b/src/main/docs/guide/registry.adoc @@ -0,0 +1,29 @@ +This section explain the connection to the https://docs.confluent.io/platform/current/schema-registry/index.html[Confluent Schema Registry] for schema management. + +The `SchemaRegistryConfig` class is used to configure the connection to the Confluent Schema Registry. The following properties are available: + +[cols="2,4", options="header"] +|=== +| Configuration Property | Explanation +| `SchemaRegistryConfig.HOST_URL` | This field is mandatory and specifies the URL of the Schema Registry. +| `SchemaRegistryConfig.BASIC_AUTH_ENABLED` | Whether the basic authentication is enabled. Default is `false`. +| `SchemaRegistryConfig.PUSH_TO_REGISTRY_ENABLED` | Whether new schemas should be automatically pushed to the registry. Default is `false`. +| `SchemaRegistryConfig.PREFIX + ".username"` | The username info needed if Basic Auth is enabled. +| `SchemaRegistryConfig.PREFIX + ".password"` | The password info needed if Basic Auth is enabled. +|=== + +The following example shows how to configure the connection to the Confluent Schema Registry: +[source,java] +---- +@Property(name = SchemaRegistryConfig.HOST_URL, value = "/test/") // The URL of your Schema Registry +public class ClientTest { + // Your code here +} +---- + +When the `SchemaRegistryConfig.PUSH_TO_REGISTRY_ENABLED` is set to `true`, the `SchemaRegistryManager` will automatically push new (or updated) schemas to the registry. If the schema already exists in the registry, the client will not push it again. However, there are some requirements: + +- The schema file must be available locally and in the `src/test/resources` directory. +- The schema file must be in the JSON Schema format. +- The schema file must have the same name as the subject name in the Confluent Schema Registry. For example, if the subject name is `test`, the schema file must be named `test.json` or `test.schema.json`. +- The schema must be used to generate sources from with the JSON Schema Generator module so that the generated files include the `@GeneratedFromSchema` annotation. diff --git a/src/main/docs/guide/toc.yml b/src/main/docs/guide/toc.yml index 708a414f..3f88e6f8 100644 --- a/src/main/docs/guide/toc.yml +++ b/src/main/docs/guide/toc.yml @@ -22,6 +22,7 @@ generator: registration: Build-time Generation Configuration usage: Run-time Generation Configuration support: Supported JSON Schema Keywords and Limitations - example: Example Output of Generation + example: Example Usage of Generation +registry: Schema Registry with Confluent repository: Repository releaseHistory: Release History