Apicurio / apicurio-registry

An API/Schema registry - stores APIs and Schemas.
https://www.apicur.io/registry/
Apache License 2.0
609 stars 269 forks source link

Deferencing $ref in json schema is not working after upgrade to v3 #5296

Closed mmmmillar closed 1 month ago

mmmmillar commented 1 month ago

Deferencing $ref in json schema is not working after upgrade to v3. The error I'm getting is "Unknown/unsupported data model type or version"

The referenced artifact shows correctly in the parent artifacts references in the registry

Version: 3.0.0 Persistence type: sql

/groups/GROUP/artifacts/ARTIFACT/versions/VERSION/content?references=DEREFERENCE

Parent schema:

{
  "$id": "https://x.com/night_time/front_door_open_detected.json",
  "$schema": "http://json-schema.org/draft-07/schema",
  "description": "xxx.",
  "type": "object",
  "properties": {
    "hub_id": {
      "type": "string"
    },
    "hub_timezone": {
      "$ref": "https://x.com/_common/timezone.json"
    },
    "detected_at_utc": {
      "type": "string",
      "format": "date-time"
    }
  },
  "required": [
    "hub_id",
    "hub_timezone",
    "detected_at_utc"
  ]
}

Referenced schema:

{
  "$id": "https://x.com/_common/timezone.json",
  "$schema": "https://json-schema.org/draft-07/schema",
  "name": "Timezone",
  "description": "An enum field that must be a valid timezone identifier string.",
  "enum": [
    "Africa/Abidjan",
    "Africa/Accra"
  ]
}
ERROR [io.apicurio.registry.services.http.CoreRegistryExceptionMapperService] (executor-thread-5) [500 ERROR DETECTED] : Unknown/unsupported data model type or version.: java.lang.RuntimeException: Unknown/unsupported data model type or version.
at io.apicurio.datamodels.ModelTypeDetector.discoverModelType(ModelTypeDetector.java:67)
at io.apicurio.datamodels.Library.readDocument(Library.java:89)
at io.apicurio.registry.content.dereference.ApicurioDataModelsContentDereferencer.dereference(ApicurioDataModelsContentDereferencer.java:23)
at io.apicurio.registry.rest.v3.AbstractResourceImpl.handleContentReferences(AbstractResourceImpl.java:59)
at io.apicurio.registry.rest.v3.GroupsResourceImpl_Subclass.handleContentReferences$$superforward(Unknown Source)
at io.apicurio.registry.rest.v3.GroupsResourceImpl_Subclass$$function$$1.apply(Unknown Source)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:73)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:62)
at io.apicurio.common.apps.logging.LoggingInterceptor.logMethodEntry(LoggingInterceptor.java:53)
at io.apicurio.common.apps.logging.LoggingInterceptor_Bean.intercept(Unknown Source)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:30)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:27)
at io.apicurio.registry.rest.v3.GroupsResourceImpl_Subclass.handleContentReferences(Unknown Source)
at io.apicurio.registry.rest.v3.GroupsResourceImpl.getArtifactVersionContent(GroupsResourceImpl.java:521)
at io.apicurio.registry.rest.v3.GroupsResourceImpl_Subclass.getArtifactVersionContent$$superforward(Unknown Source)
at io.apicurio.registry.rest.v3.GroupsResourceImpl_Subclass$$function$$20.apply(Unknown Source)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:73)
at io.quarkus.arc.impl.AroundInvokeInvocationContext$NextAroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:97)
at io.apicurio.common.apps.logging.LoggingInterceptor.logMethodEntry(LoggingInterceptor.java:53)
at io.apicurio.common.apps.logging.LoggingInterceptor_Bean.intercept(Unknown Source)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:70)
at io.quarkus.arc.impl.AroundInvokeInvocationContext$NextAroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:97)
at io.apicurio.registry.auth.AuthorizedInterceptor.authorizeMethod(AuthorizedInterceptor.java:64)
at io.apicurio.registry.auth.AuthorizedInterceptor_Bean.intercept(Unknown Source)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:70)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:62)
at io.quarkus.resteasy.runtime.QuarkusRestPathTemplateInterceptor.restMethodInvoke(QuarkusRestPathTemplateInterceptor.java:39)
at io.quarkus.resteasy.runtime.QuarkusRestPathTemplateInterceptor_Bean.intercept(Unknown Source)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:30)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:27)
at io.apicurio.registry.rest.v3.GroupsResourceImpl_Subclass.getArtifactVersionContent(Unknown Source)
at io.apicurio.registry.rest.v3.GroupsResourceImpl_ClientProxy.getArtifactVersionContent(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:569)
...
EricWittmann commented 1 month ago

The stack trace indicates that the wrong dereferencer is being used. Your content indicates the schemas are both JSON Schema, but the code is trying to dereference as though it's OpenAPI or AsyncAPI. Can you query the meta-data of your two artifacts and see what they say?

Either use the UI or something like this in curl:

curl http://registry.example.org/apis/registry/v3/groups/GROUP/artifacts/ARTIFACT

The result should include an artifactType that will tell us what the system thinks it is.

mmmmillar commented 1 month ago

Parent:

{
    "name": "https://x.com/night_time/front_door_open_detected.json",
    "owner": "",
    "createdOn": "2024-09-30T14:20:49Z",
    "modifiedBy": "",
    "modifiedOn": "2024-09-30T14:20:49Z",
    "artifactType": "JSON",
    "groupId": "night_time",
    "artifactId": "63e116dc-8e7e-6722-d47f-a67d14baf899"
}

Child:

{
    "name": "https://x.com/_common/timezone.json",
    "owner": "",
    "createdOn": "2024-09-30T14:20:47Z",
    "modifiedBy": "",
    "modifiedOn": "2024-09-30T14:20:47Z",
    "artifactType": "JSON",
    "groupId": "_common",
    "artifactId": "3350d0bf-ef9e-9d0a-7320-2924b3b9919f"
}
EricWittmann commented 1 month ago

Okay thank you for the information. The server obviously knows that the content is json schema. So I'm not sure why it is trying to use the wrong code to provide the dereferencing. You will have to try and reproduce this locally in a test and then fix.

carlesarnal commented 1 month ago

So this has been a mistake on our side. We never ported the json schema dereferencing work to 3.0. I fixed that in the PR I attached. We'll do a new release (likely this week) with that fixed. Sorry for the inconvenience.