question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Different artifact's content after registering an AsyncAPI definition

See original GitHub issue

I found that registering the same API schema, in my case an AsyncAPI sample, the results are not the same. The results depend of the method you used to register the API, somecases successfully and in others not.

To give a successful behaviour to the user, each case must work exactly and produce the same results, otherwise it could produce errors for third-party getting the artifact’s content.

Steps to reproduce it

Components, tools and versions used:

  • Apicurio Registry Version: 2.0.1 (using the apicurio-registry-mem:2.0.1.Final container image)
  • Apicurio Registry Maven Plugin 2.0.1.Final
  • Google Chrome 92.0.4515.159 (Official Build) (64-bit)
  • Firefox 91.0 (64-bit)

AsyncAPI Sample definition:

asyncapi: 2.1.0
info:
  title: Hello world application
  version: '0.1.0'
channels:
  hello:
    publish:
      message:
        payload:
          type: string
          pattern: '^hello .+$'

Case 1: Using Apicurio Registry Maven Plugin

This is the definition to upload the artifact:

                    <plugin>
                        <groupId>io.apicurio</groupId>
                        <artifactId>apicurio-registry-maven-plugin</artifactId>
                        <version>${apicurio.version}</version>
                        <executions>
                            <execution>
                                <phase>generate-sources</phase>
                                <goals>
                                    <goal>register</goal>
                                </goals>
                                <configuration>
                                    <registryUrl>${apicurio.registry.url}</registryUrl>
                                    <artifacts>
                                        <!-- AsyncAPI Spec -->
                                        <artifact>
                                            <groupId>asyncapi</groupId>
                                            <artifactId>hello-world</artifactId>
                                            <type>ASYNCAPI</type>
                                            <file>
                                                ${project.basedir}/src/main/asyncapi/hello-world.yml
                                            </file>
                                            <ifExists>RETURN_OR_UPDATE</ifExists>
                                            <canonicalize>true</canonicalize>
                                        </artifact>
                                    </artifacts>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>

Results: The artifact is registered successfully. If you review the content in the UI, the content is the same as the original one.

Case 2: Uploading by UI with Google Chrome

Registering with auto-detection and copying the content in the artifact section.

Results: It fails with the following exception in the UI:

io.apicurio.registry.storage.InvalidArtifactTypeException: Failed to discover artifact type from content.
	at io.apicurio.registry.util.ArtifactTypeUtil.discoverType(ArtifactTypeUtil.java:132)
	at io.apicurio.registry.rest.v2.GroupsResourceImpl.determineArtifactType(GroupsResourceImpl.java:639)
	at io.apicurio.registry.rest.v2.GroupsResourceImpl.createArtifact(GroupsResourceImpl.java:519)
	at io.apicurio.registry.rest.v2.GroupsResourceImpl_Subclass.createArtifact$$superaccessor31(GroupsResourceImpl_Subclass.zig:5963)
	at io.apicurio.registry.rest.v2.GroupsResourceImpl_Subclass$$function$$31.apply(GroupsResourceImpl_Subclass$$function$$31.zig:71)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
	at io.smallrye.metrics.interceptors.CountedInterceptor.countedCallable(CountedInterceptor.java:95)
	at io.smallrye.metrics.interceptors.CountedInterceptor.countedMethod(CountedInterceptor.java:70)
	at io.smallrye.metrics.interceptors.CountedInterceptor_Bean.intercept(CountedInterceptor_Bean.zig:366)
	at io.quarkus.arc.impl.InitializedInterceptor.intercept(InitializedInterceptor.java:79)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:50)
	at io.smallrye.metrics.interceptors.TimedInterceptor.timedCallable(TimedInterceptor.java:95)
	at io.smallrye.metrics.interceptors.TimedInterceptor.timedMethod(TimedInterceptor.java:70)
	at io.smallrye.metrics.interceptors.TimedInterceptor_Bean.intercept(TimedInterceptor_Bean.zig:366)
	at io.quarkus.arc.impl.InitializedInterceptor.intercept(InitializedInterceptor.java:79)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:50)
	at io.smallrye.metrics.interceptors.ConcurrentGaugeInterceptor.concurrentCallable(ConcurrentGaugeInterceptor.java:96)
	at io.smallrye.metrics.interceptors.ConcurrentGaugeInterceptor.countedMethod(ConcurrentGaugeInterceptor.java:69)
	at io.smallrye.metrics.interceptors.ConcurrentGaugeInterceptor_Bean.intercept(ConcurrentGaugeInterceptor_Bean.zig:366)
	at io.quarkus.arc.impl.InitializedInterceptor.intercept(InitializedInterceptor.java:79)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:50)
	at io.apicurio.registry.metrics.RestMetricsInterceptor.intercept(RestMetricsInterceptor.java:82)
	at io.apicurio.registry.metrics.RestMetricsInterceptor_Bean.intercept(RestMetricsInterceptor_Bean.zig:327)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:50)
	at io.apicurio.registry.logging.LoggingInterceptor.logMethodEntry(LoggingInterceptor.java:55)
	at io.apicurio.registry.logging.LoggingInterceptor_Bean.intercept(LoggingInterceptor_Bean.zig:275)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
	at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
	at io.apicurio.registry.rest.v2.GroupsResourceImpl_Subclass.createArtifact(GroupsResourceImpl_Subclass.zig:5908)
	at io.apicurio.registry.rest.v2.GroupsResourceImpl_ClientProxy.createArtifact(GroupsResourceImpl_ClientProxy.zig:819)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
	at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
	at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:408)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:69)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
	at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
	at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:249)
	at io.quarkus.resteasy.runtime.ResteasyFilter.doFilter(ResteasyFilter.java:35)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.apicurio.registry.ui.servlets.ResourceCacheControlFilter.doFilter(ResourceCacheControlFilter.java:83)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.apicurio.registry.rest.RegistryApplicationServletFilter.doFilter(RegistryApplicationServletFilter.java:113)
	at io.apicurio.registry.rest.RegistryApplicationServletFilter_ClientProxy.doFilter(RegistryApplicationServletFilter_ClientProxy.zig:225)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:63)
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:67)
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:133)
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:65)
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
	at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:247)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:56)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:111)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:108)
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$9$1.call(UndertowDeploymentRecorder.java:574)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:152)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$1.handleRequest(UndertowDeploymentRecorder.java:117)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:290)
	at io.undertow.server.DefaultExchangeHandler.handle(DefaultExchangeHandler.java:18)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$5$1.run(UndertowDeploymentRecorder.java:400)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2415)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1452)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
	at java.base/java.lang.Thread.run(Thread.java:829)
	at org.jboss.threads.JBossThread.run(JBossThread.java:501)

Case 3: Uploading by UI with Firefox

Registering with auto-detection and copying the content in the artifact section.

Results: It is registered successfully, however if you review the content in the UI, the content was reformatted as JSON:

{
  "asyncapi" : "2.1.0",
  "info" : {
    "title" : "Hello world application",
    "version" : "0.1.0"
  },
  "channels" : {
    "hello" : {
      "publish" : {
        "message" : {
          "payload" : {
            "type" : "string",
            "pattern" : "^hello .+$"
          }
        }
      }
    }
  }
}

Summary

To summarize the bug:

  • Case 1 ✔️ Artifact’s content in registry is the same as the original one.
  • Case 2: ✖️ Unable to register the artifact.
  • Case 3: ✖️ Artifact’s content in registry is different from the original one.

I did not check other specifications, but I guess that the results could be very similar.

It seems that #1651 issue fixed the Case 2 but I could reproduce again. At the same time the #1659 is related with auto-detection of AsyncAPI spec, so maybe this bug is related to that one.

WDTY?

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:11 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
SafarMirekcommented, Sep 10, 2021

@rmarting I have tested it with the current version of my PR and it looks it works, but you are free to test it out if you want.

1reaction
SafarMirekcommented, Aug 31, 2021

@rmarting Thanks for testing it. Yeah, it’s a bug in maven plugin and it needs to be fixed. Maven plugin should work same way as the UI.

I will look at it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

AsyncAPI and Apicurio for Asynchronous APIs
It supports registering different document formats, e.g., OpenAPI, AsyncAPI, GraphQL, Apache Avro, or Protobuf. Since AsyncAPI is developing ...
Read more >
Apicurio Registry REST API - Red Hat Customer Portal
Apache Avro schema; AsyncAPI specification; Google protocol buffers ... Gets the content for an artifact version in the registry using the unique content...
Read more >
Create a Streaming API from an AsyncAPI Definition
An API Creator can import an existing AsyncAPI definition to WSO2 API Manager to create a streaming API using any one of the...
Read more >
Registry | Apicurio
Storage/management of several types of artifacts ... and updating the following types of artifacts: OpenAPI, AsyncAPI, ... Configurable content rules.
Read more >
Model-driven development of asynchronous message-driven ...
On the other hand, artifacts at the M1 layer (the model layer) are ... to define the content of the messages to be...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found