atiaomar1978-hub commented on code in PR #24844:
URL: https://github.com/apache/camel/pull/24844#discussion_r3741010058


##########
components/camel-apicurio-registry/src/main/java/org/apache/camel/component/apicurioregistry/ApicurioRegistryConfiguration.java:
##########
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.component.apicurioregistry;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+
+@UriParams
+public class ApicurioRegistryConfiguration implements Cloneable {
+
+    @UriParam(label = "common", description = "The Apicurio Registry base URL")
+    @Metadata(required = true)
+    private String registryUrl;
+
+    @UriParam(label = "producer",
+              enums = 
"createArtifact,updateArtifact,deleteArtifact,getArtifactContent,getArtifactMetadata,searchArtifacts,listVersions,createGroup,testCompatibility,validate",
+              description = "The operation to perform")
+    private String operation;
+
+    @UriParam(label = "producer", description = "The default artifact type", 
defaultValue = "JSON")
+    private String artifactType = "JSON";
+
+    @UriParam(label = "security", enums = "none,basic,oidc", defaultValue = 
"none",
+              description = "The authentication type to use")
+    private String authType = "none";
+
+    @UriParam(label = "security", security = "secret", description = "Username 
for basic authentication")
+    private String username;
+
+    @UriParam(label = "security", security = "secret", description = "Password 
for basic authentication")
+    private String password;
+
+    @UriParam(label = "security", description = "OAuth2 token endpoint URL")
+    private String tokenEndpoint;
+
+    @UriParam(label = "security", security = "secret", description = "OAuth2 
client ID")
+    private String clientId;
+
+    @UriParam(label = "security", security = "secret", description = "OAuth2 
client secret")
+    private String clientSecret;
+
+    @UriParam(label = "security", description = "OAuth2 scope")
+    private String scope;
+
+    @UriParam(label = "producer",
+              description = "Behavior when artifact already exists",
+              enums = "FAIL,CREATE_VERSION,FIND_OR_CREATE_VERSION",
+              defaultValue = "FAIL")
+    private String ifExists = "FAIL";
+
+    @UriParam(label = "consumer",
+              description = "Whether to fetch the content for each new version 
found by the consumer",
+              defaultValue = "false")
+    private boolean fetchContent;
+
+    @UriParam(label = "producer",
+              description = "Whether to throw an exception on validation 
failure (validate operation). When false, sets result headers instead.",
+              defaultValue = "true")
+    private boolean failOnValidation = true;
+
+    @UriParam(label = "producer",
+              description = "Schema cache TTL in milliseconds for the validate 
operation. 0 means no caching.",
+              defaultValue = "300000")
+    private long cacheTtl = 300000;

Review Comment:
   **Bugbot:** `cacheTtl` is documented and exposed as a URI option but is 
never read in `validate()` (or elsewhere). Either wire it into SDK/client 
caching or remove the option to avoid misleading users.
   
   _AI-generated Bugbot inline comment on behalf of atiaomar1978-hub._



##########
components/camel-apicurio-registry/src/main/java/org/apache/camel/component/apicurioregistry/ApicurioRegistryConsumer.java:
##########
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.component.apicurioregistry;
+
+import java.io.InputStream;
+import java.util.List;
+
+import io.apicurio.registry.rest.client.RegistryClient;
+import io.apicurio.registry.rest.client.models.SearchedVersion;
+import io.apicurio.registry.rest.client.models.VersionSearchResults;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.support.ScheduledPollConsumer;
+
+public class ApicurioRegistryConsumer extends ScheduledPollConsumer {
+
+    private final ApicurioRegistryEndpoint endpoint;
+    private final ApicurioRegistryConfiguration configuration;
+    private volatile Long lastSeenGlobalId;

Review Comment:
   **Bugbot:** `lastSeenGlobalId` is volatile in-memory state only. After a 
route/context restart the consumer will re-deliver every existing version. 
Consider documenting this clearly, seeding from a configurable initial 
globalId, or persisting the watermark (e.g. idempotent repository / header on 
first poll).
   
   _AI-generated Bugbot inline comment on behalf of atiaomar1978-hub._



##########
components/camel-apicurio-registry/src/main/java/org/apache/camel/component/apicurioregistry/ApicurioRegistryConsumer.java:
##########
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.component.apicurioregistry;
+
+import java.io.InputStream;
+import java.util.List;
+
+import io.apicurio.registry.rest.client.RegistryClient;
+import io.apicurio.registry.rest.client.models.SearchedVersion;
+import io.apicurio.registry.rest.client.models.VersionSearchResults;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.support.ScheduledPollConsumer;
+
+public class ApicurioRegistryConsumer extends ScheduledPollConsumer {
+
+    private final ApicurioRegistryEndpoint endpoint;
+    private final ApicurioRegistryConfiguration configuration;
+    private volatile Long lastSeenGlobalId;
+
+    public ApicurioRegistryConsumer(ApicurioRegistryEndpoint endpoint, 
Processor processor,
+                                    ApicurioRegistryConfiguration 
configuration) {
+        super(endpoint, processor);
+        this.endpoint = endpoint;
+        this.configuration = configuration;
+    }
+
+    @Override
+    protected int poll() throws Exception {
+        String groupId = endpoint.getGroupId();
+        String artifactId = endpoint.getArtifactId();
+
+        if (groupId == null || artifactId == null) {
+            throw new IllegalArgumentException(
+                    "Both groupId and artifactId are required for the 
consumer");
+        }
+
+        RegistryClient client = endpoint.getRegistryClient();
+        VersionSearchResults results = client.groups().byGroupId(groupId)
+                .artifacts().byArtifactId(artifactId).versions().get();
+
+        if (results == null || results.getVersions() == null) {
+            return 0;
+        }
+
+        List<SearchedVersion> versions = results.getVersions();
+        int count = 0;
+        for (SearchedVersion version : versions) {

Review Comment:
   **Bugbot:** Versions are processed in API list order. If `getVersions()` is 
not strictly ascending by `globalId`, a newer version processed first can cause 
older versions with lower IDs to be skipped forever (`globalId > 
lastSeenGlobalId`). Sort by `globalId` before the loop (or track a set of 
delivered IDs).
   
   _AI-generated Bugbot inline comment on behalf of atiaomar1978-hub._



##########
components/camel-apicurio-registry/src/main/java/org/apache/camel/component/apicurioregistry/ApicurioRegistryProducer.java:
##########
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.component.apicurioregistry;
+
+import java.io.InputStream;
+
+import io.apicurio.registry.rest.client.RegistryClient;
+import io.apicurio.registry.rest.client.models.ArtifactMetaData;
+import io.apicurio.registry.rest.client.models.CreateArtifact;
+import io.apicurio.registry.rest.client.models.CreateArtifactResponse;
+import io.apicurio.registry.rest.client.models.CreateGroup;
+import io.apicurio.registry.rest.client.models.CreateVersion;
+import io.apicurio.registry.rest.client.models.GroupMetaData;
+import io.apicurio.registry.rest.client.models.IfArtifactExists;
+import io.apicurio.registry.rest.client.models.VersionContent;
+import io.apicurio.registry.rest.client.models.VersionMetaData;
+import io.apicurio.registry.rest.client.models.VersionSearchResults;
+import org.apache.camel.Message;
+import org.apache.camel.spi.InvokeOnHeader;
+import org.apache.camel.support.HeaderSelectorProducer;
+
+public class ApicurioRegistryProducer extends HeaderSelectorProducer {
+
+    private final ApicurioRegistryEndpoint endpoint;
+    private final ApicurioRegistryConfiguration configuration;
+
+    public ApicurioRegistryProducer(ApicurioRegistryEndpoint endpoint,
+                                    ApicurioRegistryConfiguration 
configuration) {
+        super(endpoint, ApicurioRegistryConstants.HEADER_OPERATION, 
configuration::getOperation);
+        this.endpoint = endpoint;
+        this.configuration = configuration;
+    }
+
+    private RegistryClient getClient() {
+        return endpoint.getRegistryClient();
+    }
+
+    private String resolveGroupId(Message message) {
+        String gid = 
message.getHeader(ApicurioRegistryConstants.HEADER_GROUP_ID, String.class);
+        return gid != null ? gid : endpoint.getGroupId();
+    }
+
+    private String resolveArtifactId(Message message) {
+        String aid = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_ID, String.class);
+        return aid != null ? aid : endpoint.getArtifactId();
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_CREATE_ARTIFACT)
+    public void createArtifact(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String artifactType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_ARTIFACT_TYPE, 
configuration.getArtifactType(), String.class);
+        String name = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_NAME, String.class);
+        String description = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_DESCRIPTION, 
String.class);
+        String content = message.getBody(String.class);

Review Comment:
   **Bugbot:** `message.getBody(String.class)` will not carry binary artifact 
payloads (AVRO/Protobuf bytes). Consider `InputStream` / `byte[]` conversion 
via Camel type converter, Base64, or explicit content encoding — especially 
since docs/examples mention AVRO.
   
   _AI-generated Bugbot inline comment on behalf of atiaomar1978-hub._



##########
components/camel-apicurio-registry/src/main/java/org/apache/camel/component/apicurioregistry/ApicurioRegistryProducer.java:
##########
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.component.apicurioregistry;
+
+import java.io.InputStream;
+
+import io.apicurio.registry.rest.client.RegistryClient;
+import io.apicurio.registry.rest.client.models.ArtifactMetaData;
+import io.apicurio.registry.rest.client.models.CreateArtifact;
+import io.apicurio.registry.rest.client.models.CreateArtifactResponse;
+import io.apicurio.registry.rest.client.models.CreateGroup;
+import io.apicurio.registry.rest.client.models.CreateVersion;
+import io.apicurio.registry.rest.client.models.GroupMetaData;
+import io.apicurio.registry.rest.client.models.IfArtifactExists;
+import io.apicurio.registry.rest.client.models.VersionContent;
+import io.apicurio.registry.rest.client.models.VersionMetaData;
+import io.apicurio.registry.rest.client.models.VersionSearchResults;
+import org.apache.camel.Message;
+import org.apache.camel.spi.InvokeOnHeader;
+import org.apache.camel.support.HeaderSelectorProducer;
+
+public class ApicurioRegistryProducer extends HeaderSelectorProducer {
+
+    private final ApicurioRegistryEndpoint endpoint;
+    private final ApicurioRegistryConfiguration configuration;
+
+    public ApicurioRegistryProducer(ApicurioRegistryEndpoint endpoint,
+                                    ApicurioRegistryConfiguration 
configuration) {
+        super(endpoint, ApicurioRegistryConstants.HEADER_OPERATION, 
configuration::getOperation);
+        this.endpoint = endpoint;
+        this.configuration = configuration;
+    }
+
+    private RegistryClient getClient() {
+        return endpoint.getRegistryClient();
+    }
+
+    private String resolveGroupId(Message message) {
+        String gid = 
message.getHeader(ApicurioRegistryConstants.HEADER_GROUP_ID, String.class);
+        return gid != null ? gid : endpoint.getGroupId();
+    }
+
+    private String resolveArtifactId(Message message) {
+        String aid = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_ID, String.class);
+        return aid != null ? aid : endpoint.getArtifactId();
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_CREATE_ARTIFACT)
+    public void createArtifact(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String artifactType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_ARTIFACT_TYPE, 
configuration.getArtifactType(), String.class);
+        String name = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_NAME, String.class);
+        String description = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_DESCRIPTION, 
String.class);
+        String content = message.getBody(String.class);
+        String contentType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_CONTENT_TYPE, 
"application/json", String.class);
+        String ifExistsVal = message.getHeader(
+                ApicurioRegistryConstants.HEADER_IF_EXISTS, 
configuration.getIfExists(), String.class);
+
+        CreateArtifact createArtifact = new CreateArtifact();
+        createArtifact.setArtifactId(artifactId);
+        createArtifact.setArtifactType(artifactType);
+        createArtifact.setName(name);
+        createArtifact.setDescription(description);
+
+        if (content != null) {
+            CreateVersion firstVersion = new CreateVersion();
+            VersionContent vc = new VersionContent();
+            vc.setContent(content);
+            vc.setContentType(contentType);
+            firstVersion.setContent(vc);
+            createArtifact.setFirstVersion(firstVersion);
+        }
+
+        CreateArtifactResponse result = 
getClient().groups().byGroupId(groupId).artifacts()
+                .post(createArtifact, config -> {
+                    if (ifExistsVal != null) {
+                        config.queryParameters.ifExists = 
IfArtifactExists.forValue(ifExistsVal);
+                    }
+                });
+        message.setBody(result);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_UPDATE_ARTIFACT)
+    public void updateArtifact(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String content = message.getBody(String.class);
+        String version = 
message.getHeader(ApicurioRegistryConstants.HEADER_VERSION, String.class);
+        String contentType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_CONTENT_TYPE, 
"application/json", String.class);
+
+        CreateVersion createVersion = new CreateVersion();
+        createVersion.setVersion(version);
+        VersionContent vc = new VersionContent();
+        vc.setContent(content);
+        vc.setContentType(contentType);
+        createVersion.setContent(vc);
+
+        VersionMetaData result = 
getClient().groups().byGroupId(groupId).artifacts()
+                .byArtifactId(artifactId).versions().post(createVersion);
+        message.setBody(result);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_DELETE_ARTIFACT)
+    public void deleteArtifact(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        
getClient().groups().byGroupId(groupId).artifacts().byArtifactId(artifactId).delete();
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_GET_ARTIFACT_CONTENT)
+    public void getArtifactContent(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String version = message.getHeader(
+                ApicurioRegistryConstants.HEADER_VERSION, "branch=latest", 
String.class);
+
+        InputStream content = 
getClient().groups().byGroupId(groupId).artifacts()
+                
.byArtifactId(artifactId).versions().byVersionExpression(version).content().get();
+        message.setBody(content);

Review Comment:
   **Bugbot:** `getArtifactContent` sets an `InputStream` on the message body 
without documenting lifecycle. Downstream routes must close the stream or Camel 
may leak connections. Prefer converting to `byte[]`/`String` when feasible, or 
document stream ownership in the component page.
   
   _AI-generated Bugbot inline comment on behalf of atiaomar1978-hub._



##########
components/camel-apicurio-registry/src/main/java/org/apache/camel/component/apicurioregistry/ApicurioRegistryProducer.java:
##########
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.component.apicurioregistry;
+
+import java.io.InputStream;
+
+import io.apicurio.registry.rest.client.RegistryClient;
+import io.apicurio.registry.rest.client.models.ArtifactMetaData;
+import io.apicurio.registry.rest.client.models.CreateArtifact;
+import io.apicurio.registry.rest.client.models.CreateArtifactResponse;
+import io.apicurio.registry.rest.client.models.CreateGroup;
+import io.apicurio.registry.rest.client.models.CreateVersion;
+import io.apicurio.registry.rest.client.models.GroupMetaData;
+import io.apicurio.registry.rest.client.models.IfArtifactExists;
+import io.apicurio.registry.rest.client.models.VersionContent;
+import io.apicurio.registry.rest.client.models.VersionMetaData;
+import io.apicurio.registry.rest.client.models.VersionSearchResults;
+import org.apache.camel.Message;
+import org.apache.camel.spi.InvokeOnHeader;
+import org.apache.camel.support.HeaderSelectorProducer;
+
+public class ApicurioRegistryProducer extends HeaderSelectorProducer {
+
+    private final ApicurioRegistryEndpoint endpoint;
+    private final ApicurioRegistryConfiguration configuration;
+
+    public ApicurioRegistryProducer(ApicurioRegistryEndpoint endpoint,
+                                    ApicurioRegistryConfiguration 
configuration) {
+        super(endpoint, ApicurioRegistryConstants.HEADER_OPERATION, 
configuration::getOperation);
+        this.endpoint = endpoint;
+        this.configuration = configuration;
+    }
+
+    private RegistryClient getClient() {
+        return endpoint.getRegistryClient();
+    }
+
+    private String resolveGroupId(Message message) {
+        String gid = 
message.getHeader(ApicurioRegistryConstants.HEADER_GROUP_ID, String.class);
+        return gid != null ? gid : endpoint.getGroupId();
+    }
+
+    private String resolveArtifactId(Message message) {
+        String aid = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_ID, String.class);
+        return aid != null ? aid : endpoint.getArtifactId();
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_CREATE_ARTIFACT)
+    public void createArtifact(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String artifactType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_ARTIFACT_TYPE, 
configuration.getArtifactType(), String.class);
+        String name = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_NAME, String.class);
+        String description = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_DESCRIPTION, 
String.class);
+        String content = message.getBody(String.class);
+        String contentType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_CONTENT_TYPE, 
"application/json", String.class);
+        String ifExistsVal = message.getHeader(
+                ApicurioRegistryConstants.HEADER_IF_EXISTS, 
configuration.getIfExists(), String.class);
+
+        CreateArtifact createArtifact = new CreateArtifact();
+        createArtifact.setArtifactId(artifactId);
+        createArtifact.setArtifactType(artifactType);
+        createArtifact.setName(name);
+        createArtifact.setDescription(description);
+
+        if (content != null) {
+            CreateVersion firstVersion = new CreateVersion();
+            VersionContent vc = new VersionContent();
+            vc.setContent(content);
+            vc.setContentType(contentType);
+            firstVersion.setContent(vc);
+            createArtifact.setFirstVersion(firstVersion);
+        }
+
+        CreateArtifactResponse result = 
getClient().groups().byGroupId(groupId).artifacts()
+                .post(createArtifact, config -> {
+                    if (ifExistsVal != null) {
+                        config.queryParameters.ifExists = 
IfArtifactExists.forValue(ifExistsVal);
+                    }
+                });
+        message.setBody(result);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_UPDATE_ARTIFACT)
+    public void updateArtifact(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String content = message.getBody(String.class);
+        String version = 
message.getHeader(ApicurioRegistryConstants.HEADER_VERSION, String.class);
+        String contentType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_CONTENT_TYPE, 
"application/json", String.class);
+
+        CreateVersion createVersion = new CreateVersion();
+        createVersion.setVersion(version);
+        VersionContent vc = new VersionContent();
+        vc.setContent(content);
+        vc.setContentType(contentType);
+        createVersion.setContent(vc);
+
+        VersionMetaData result = 
getClient().groups().byGroupId(groupId).artifacts()
+                .byArtifactId(artifactId).versions().post(createVersion);
+        message.setBody(result);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_DELETE_ARTIFACT)
+    public void deleteArtifact(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        
getClient().groups().byGroupId(groupId).artifacts().byArtifactId(artifactId).delete();
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_GET_ARTIFACT_CONTENT)
+    public void getArtifactContent(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String version = message.getHeader(
+                ApicurioRegistryConstants.HEADER_VERSION, "branch=latest", 
String.class);
+
+        InputStream content = 
getClient().groups().byGroupId(groupId).artifacts()
+                
.byArtifactId(artifactId).versions().byVersionExpression(version).content().get();
+        message.setBody(content);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_GET_ARTIFACT_METADATA)
+    public void getArtifactMetadata(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+
+        ArtifactMetaData metadata = 
getClient().groups().byGroupId(groupId).artifacts()
+                .byArtifactId(artifactId).get();
+        message.setBody(metadata);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_SEARCH_ARTIFACTS)
+    public void searchArtifacts(Message message) {
+        var results = getClient().search().artifacts().get(config -> {
+            String name = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_NAME, String.class);
+            String groupId = resolveGroupId(message);
+            String description = message.getHeader(
+                    ApicurioRegistryConstants.HEADER_ARTIFACT_DESCRIPTION, 
String.class);
+            if (name != null) {
+                config.queryParameters.name = name;
+            }
+            if (groupId != null) {
+                config.queryParameters.groupId = groupId;
+            }
+            if (description != null) {
+                config.queryParameters.description = description;
+            }
+        });
+        message.setBody(results);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_LIST_VERSIONS)
+    public void listVersions(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+
+        VersionSearchResults results = 
getClient().groups().byGroupId(groupId).artifacts()
+                .byArtifactId(artifactId).versions().get();
+        message.setBody(results);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_CREATE_GROUP)
+    public void createGroup(Message message) {
+        String groupId = resolveGroupId(message);
+        String description = message.getHeader(
+                ApicurioRegistryConstants.HEADER_ARTIFACT_DESCRIPTION, 
String.class);
+
+        CreateGroup createGroup = new CreateGroup();
+        createGroup.setGroupId(groupId);
+        createGroup.setDescription(description);
+
+        GroupMetaData result = getClient().groups().post(createGroup);
+        message.setBody(result);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_TEST_COMPATIBILITY)
+    public void testCompatibility(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String content = message.getBody(String.class);
+        String contentType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_CONTENT_TYPE, 
"application/json", String.class);
+
+        CreateVersion createVersion = new CreateVersion();
+        VersionContent vc = new VersionContent();
+        vc.setContent(content);
+        vc.setContentType(contentType);
+        createVersion.setContent(vc);
+
+        try {
+            getClient().groups().byGroupId(groupId).artifacts()
+                    .byArtifactId(artifactId).versions()
+                    .post(createVersion, config -> 
config.queryParameters.dryRun = true);
+            message.setBody(true);
+        } catch (Exception e) {

Review Comment:
   **Bugbot:** `testCompatibility` catches broad `Exception` and only exposes 
`e.getMessage()`. Network/auth failures are indistinguishable from schema 
incompatibility. Consider rethrowing non-validation failures or aligning with 
`validate()` + `ApicurioRegistryValidationException`.
   
   _AI-generated Bugbot inline comment on behalf of atiaomar1978-hub._



##########
components/camel-apicurio-registry/pom.xml:
##########
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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
+
+         http://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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>components</artifactId>
+        <groupId>org.apache.camel</groupId>
+        <version>4.22.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-apicurio-registry</artifactId>

Review Comment:
   **Bugbot:** `apicurio-registry-sdk-version` is local to this module. Camel 
convention is to declare third-party versions in `parent/pom.xml` 
dependencyManagement (and reference without version here) so all modules stay 
aligned.
   
   _AI-generated Bugbot inline comment on behalf of atiaomar1978-hub._



##########
test-infra/camel-test-infra-apicurio-registry/src/main/resources/org/apache/camel/test/infra/apicurio/registry/services/container.properties:
##########
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You 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
+##
+##      http://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.
+## ---------------------------------------------------------------------------
+apicurio.registry.container=quay.io/apicurio/apicurio-registry:3.3.0

Review Comment:
   **Bugbot:** PR description mentions Testcontainers image 
`quay.io/apicurio/apicurio-registry:3.0.6` but `container.properties` pins 
**3.3.0** (matching SDK 3.3.0). Please align docs/PR text with the actual image 
tag.
   
   _AI-generated Bugbot inline comment on behalf of atiaomar1978-hub._



##########
components/camel-apicurio-registry/src/main/java/org/apache/camel/component/apicurioregistry/ApicurioRegistryConstants.java:
##########
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.component.apicurioregistry;
+
+import org.apache.camel.spi.Metadata;
+
+public interface ApicurioRegistryConstants {
+
+    @Metadata(description = "The operation to perform", javaType = "String")
+    String HEADER_OPERATION = "CamelApicurioRegistryOperation";
+
+    @Metadata(description = "The artifact group ID", javaType = "String")
+    String HEADER_GROUP_ID = "CamelApicurioRegistryGroupId";
+
+    @Metadata(description = "The artifact ID", javaType = "String")
+    String HEADER_ARTIFACT_ID = "CamelApicurioRegistryArtifactId";
+
+    @Metadata(description = "The artifact type (e.g. AVRO, PROTOBUF, JSON, 
OPENAPI)", javaType = "String")
+    String HEADER_ARTIFACT_TYPE = "CamelApicurioRegistryArtifactType";
+
+    @Metadata(description = "The artifact version expression", javaType = 
"String")
+    String HEADER_VERSION = "CamelApicurioRegistryVersion";
+
+    @Metadata(description = "The artifact name", javaType = "String")
+    String HEADER_ARTIFACT_NAME = "CamelApicurioRegistryArtifactName";
+
+    @Metadata(description = "The artifact description", javaType = "String")
+    String HEADER_ARTIFACT_DESCRIPTION = 
"CamelApicurioRegistryArtifactDescription";
+
+    @Metadata(description = "Behavior when artifact already exists (FAIL, 
CREATE_VERSION, FIND_OR_CREATE_VERSION)",
+              javaType = "String")
+    String HEADER_IF_EXISTS = "CamelApicurioRegistryIfExists";
+
+    @Metadata(description = "The content type of the artifact", javaType = 
"String")
+    String HEADER_CONTENT_TYPE = "CamelApicurioRegistryContentType";
+
+    @Metadata(description = "Whether the operation is a dry run", javaType = 
"Boolean")
+    String HEADER_DRY_RUN = "CamelApicurioRegistryDryRun";

Review Comment:
   **Grok:** `HEADER_DRY_RUN` is declared but no producer operation reads it — 
dry run is hard-coded only in `testCompatibility`/`validate`. Either wire the 
header through or remove it from the public header contract.
   
   _AI-generated Grok inline comment on behalf of atiaomar1978-hub._



##########
components/camel-apicurio-registry/src/main/java/org/apache/camel/component/apicurioregistry/ApicurioRegistryEndpoint.java:
##########
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.component.apicurioregistry;
+
+import io.apicurio.registry.client.RegistryClientFactory;
+import io.apicurio.registry.client.common.RegistryClientOptions;
+import io.apicurio.registry.rest.client.RegistryClient;
+import org.apache.camel.Category;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.spi.EndpointServiceLocation;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriPath;
+import org.apache.camel.support.ScheduledPollEndpoint;
+
+/**
+ * Manage artifacts, versions, and groups in Apicurio Registry v3.
+ */
+@UriEndpoint(firstVersion = "4.22.0", scheme = "apicurio-registry", title = 
"Apicurio Registry",
+             syntax = "apicurio-registry:groupId/artifactId",
+             category = { Category.CLOUD, Category.API }, headersClass = 
ApicurioRegistryConstants.class)
+public class ApicurioRegistryEndpoint extends ScheduledPollEndpoint implements 
EndpointServiceLocation {
+
+    @UriPath(description = "The artifact group ID")
+    private String groupId;
+
+    @UriPath(description = "The artifact ID")
+    private String artifactId;
+
+    @UriParam
+    private ApicurioRegistryConfiguration configuration;
+
+    @UriParam(label = "advanced", description = "To use a pre-configured 
RegistryClient instance")
+    private RegistryClient registryClient;
+
+    ApicurioRegistryEndpoint(String uri, ApicurioRegistryComponent component,
+                             ApicurioRegistryConfiguration configuration,
+                             String groupId, String artifactId) {
+        super(uri, component);
+        this.configuration = configuration;
+        this.groupId = groupId;
+        this.artifactId = artifactId;
+    }
+
+    @Override
+    public Producer createProducer() throws Exception {
+        return new ApicurioRegistryProducer(this, configuration);
+    }
+
+    @Override
+    public Consumer createConsumer(Processor processor) throws Exception {
+        ApicurioRegistryConsumer consumer = new ApicurioRegistryConsumer(this, 
processor, configuration);
+        configureConsumer(consumer);
+        return consumer;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+        if (registryClient == null) {
+            registryClient = createRegistryClient();
+        }
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        super.doStop();
+        registryClient = null;

Review Comment:
   **Grok:** `doStop()` nulls `registryClient` but does not close underlying 
HTTP resources if the SDK exposes a close/shutdown hook. Worth checking 
`RegistryClientFactory` lifecycle to avoid connection leaks in long-running 
apps.
   
   _AI-generated Grok inline comment on behalf of atiaomar1978-hub._



##########
components/camel-apicurio-registry/src/main/java/org/apache/camel/component/apicurioregistry/ApicurioRegistryProducer.java:
##########
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.component.apicurioregistry;
+
+import java.io.InputStream;
+
+import io.apicurio.registry.rest.client.RegistryClient;
+import io.apicurio.registry.rest.client.models.ArtifactMetaData;
+import io.apicurio.registry.rest.client.models.CreateArtifact;
+import io.apicurio.registry.rest.client.models.CreateArtifactResponse;
+import io.apicurio.registry.rest.client.models.CreateGroup;
+import io.apicurio.registry.rest.client.models.CreateVersion;
+import io.apicurio.registry.rest.client.models.GroupMetaData;
+import io.apicurio.registry.rest.client.models.IfArtifactExists;
+import io.apicurio.registry.rest.client.models.VersionContent;
+import io.apicurio.registry.rest.client.models.VersionMetaData;
+import io.apicurio.registry.rest.client.models.VersionSearchResults;
+import org.apache.camel.Message;
+import org.apache.camel.spi.InvokeOnHeader;
+import org.apache.camel.support.HeaderSelectorProducer;
+
+public class ApicurioRegistryProducer extends HeaderSelectorProducer {
+
+    private final ApicurioRegistryEndpoint endpoint;
+    private final ApicurioRegistryConfiguration configuration;
+
+    public ApicurioRegistryProducer(ApicurioRegistryEndpoint endpoint,
+                                    ApicurioRegistryConfiguration 
configuration) {
+        super(endpoint, ApicurioRegistryConstants.HEADER_OPERATION, 
configuration::getOperation);
+        this.endpoint = endpoint;
+        this.configuration = configuration;
+    }
+
+    private RegistryClient getClient() {
+        return endpoint.getRegistryClient();
+    }
+
+    private String resolveGroupId(Message message) {
+        String gid = 
message.getHeader(ApicurioRegistryConstants.HEADER_GROUP_ID, String.class);
+        return gid != null ? gid : endpoint.getGroupId();
+    }
+
+    private String resolveArtifactId(Message message) {
+        String aid = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_ID, String.class);
+        return aid != null ? aid : endpoint.getArtifactId();
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_CREATE_ARTIFACT)
+    public void createArtifact(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String artifactType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_ARTIFACT_TYPE, 
configuration.getArtifactType(), String.class);
+        String name = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_NAME, String.class);
+        String description = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_DESCRIPTION, 
String.class);
+        String content = message.getBody(String.class);
+        String contentType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_CONTENT_TYPE, 
"application/json", String.class);
+        String ifExistsVal = message.getHeader(
+                ApicurioRegistryConstants.HEADER_IF_EXISTS, 
configuration.getIfExists(), String.class);
+
+        CreateArtifact createArtifact = new CreateArtifact();
+        createArtifact.setArtifactId(artifactId);
+        createArtifact.setArtifactType(artifactType);
+        createArtifact.setName(name);
+        createArtifact.setDescription(description);
+
+        if (content != null) {
+            CreateVersion firstVersion = new CreateVersion();
+            VersionContent vc = new VersionContent();
+            vc.setContent(content);
+            vc.setContentType(contentType);
+            firstVersion.setContent(vc);
+            createArtifact.setFirstVersion(firstVersion);
+        }
+
+        CreateArtifactResponse result = 
getClient().groups().byGroupId(groupId).artifacts()
+                .post(createArtifact, config -> {
+                    if (ifExistsVal != null) {
+                        config.queryParameters.ifExists = 
IfArtifactExists.forValue(ifExistsVal);
+                    }
+                });
+        message.setBody(result);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_UPDATE_ARTIFACT)
+    public void updateArtifact(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String content = message.getBody(String.class);
+        String version = 
message.getHeader(ApicurioRegistryConstants.HEADER_VERSION, String.class);
+        String contentType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_CONTENT_TYPE, 
"application/json", String.class);
+
+        CreateVersion createVersion = new CreateVersion();
+        createVersion.setVersion(version);
+        VersionContent vc = new VersionContent();
+        vc.setContent(content);
+        vc.setContentType(contentType);
+        createVersion.setContent(vc);
+
+        VersionMetaData result = 
getClient().groups().byGroupId(groupId).artifacts()
+                .byArtifactId(artifactId).versions().post(createVersion);
+        message.setBody(result);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_DELETE_ARTIFACT)
+    public void deleteArtifact(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        
getClient().groups().byGroupId(groupId).artifacts().byArtifactId(artifactId).delete();
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_GET_ARTIFACT_CONTENT)
+    public void getArtifactContent(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String version = message.getHeader(
+                ApicurioRegistryConstants.HEADER_VERSION, "branch=latest", 
String.class);
+
+        InputStream content = 
getClient().groups().byGroupId(groupId).artifacts()
+                
.byArtifactId(artifactId).versions().byVersionExpression(version).content().get();
+        message.setBody(content);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_GET_ARTIFACT_METADATA)
+    public void getArtifactMetadata(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+
+        ArtifactMetaData metadata = 
getClient().groups().byGroupId(groupId).artifacts()
+                .byArtifactId(artifactId).get();
+        message.setBody(metadata);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_SEARCH_ARTIFACTS)
+    public void searchArtifacts(Message message) {
+        var results = getClient().search().artifacts().get(config -> {
+            String name = 
message.getHeader(ApicurioRegistryConstants.HEADER_ARTIFACT_NAME, String.class);
+            String groupId = resolveGroupId(message);
+            String description = message.getHeader(
+                    ApicurioRegistryConstants.HEADER_ARTIFACT_DESCRIPTION, 
String.class);
+            if (name != null) {
+                config.queryParameters.name = name;
+            }
+            if (groupId != null) {
+                config.queryParameters.groupId = groupId;
+            }
+            if (description != null) {
+                config.queryParameters.description = description;
+            }
+        });
+        message.setBody(results);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_LIST_VERSIONS)
+    public void listVersions(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+
+        VersionSearchResults results = 
getClient().groups().byGroupId(groupId).artifacts()
+                .byArtifactId(artifactId).versions().get();
+        message.setBody(results);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_CREATE_GROUP)
+    public void createGroup(Message message) {
+        String groupId = resolveGroupId(message);
+        String description = message.getHeader(
+                ApicurioRegistryConstants.HEADER_ARTIFACT_DESCRIPTION, 
String.class);
+
+        CreateGroup createGroup = new CreateGroup();
+        createGroup.setGroupId(groupId);
+        createGroup.setDescription(description);
+
+        GroupMetaData result = getClient().groups().post(createGroup);
+        message.setBody(result);
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_TEST_COMPATIBILITY)
+    public void testCompatibility(Message message) {
+        String groupId = resolveGroupId(message);
+        String artifactId = resolveArtifactId(message);
+        String content = message.getBody(String.class);
+        String contentType = message.getHeader(
+                ApicurioRegistryConstants.HEADER_CONTENT_TYPE, 
"application/json", String.class);
+
+        CreateVersion createVersion = new CreateVersion();
+        VersionContent vc = new VersionContent();
+        vc.setContent(content);
+        vc.setContentType(contentType);
+        createVersion.setContent(vc);
+
+        try {
+            getClient().groups().byGroupId(groupId).artifacts()
+                    .byArtifactId(artifactId).versions()
+                    .post(createVersion, config -> 
config.queryParameters.dryRun = true);
+            message.setBody(true);
+        } catch (Exception e) {
+            message.setBody(false);
+            
message.setHeader(ApicurioRegistryConstants.HEADER_VALIDATION_ERRORS, 
e.getMessage());
+        }
+    }
+
+    @InvokeOnHeader(ApicurioRegistryConstants.OPERATION_VALIDATE)
+    public void validate(Message message) throws Exception {

Review Comment:
   **Grok:** `validate` and `testCompatibility` duplicate the same dry-run POST 
logic. Extracting a shared helper would reduce drift (today they differ in 
exception handling and response shape).
   
   _AI-generated Grok inline comment on behalf of atiaomar1978-hub._



##########
components/camel-apicurio-registry/src/test/java/org/apache/camel/component/apicurioregistry/ApicurioRegistryProducerTest.java:
##########
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.component.apicurioregistry;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import io.apicurio.registry.rest.client.RegistryClient;
+import io.apicurio.registry.rest.client.models.ArtifactMetaData;
+import io.apicurio.registry.rest.client.models.CreateArtifact;
+import io.apicurio.registry.rest.client.models.CreateArtifactResponse;
+import io.apicurio.registry.rest.client.models.CreateGroup;
+import io.apicurio.registry.rest.client.models.CreateVersion;
+import io.apicurio.registry.rest.client.models.GroupMetaData;
+import io.apicurio.registry.rest.client.models.VersionMetaData;
+import io.apicurio.registry.rest.client.models.VersionSearchResults;
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class ApicurioRegistryProducerTest extends CamelTestSupport {
+
+    private final RegistryClient mockClient = mock(RegistryClient.class, 
org.mockito.Mockito.RETURNS_DEEP_STUBS);

Review Comment:
   **Grok:** New tests use JUnit `assertEquals`/`assertNotNull`. Project 
convention prefers AssertJ (`assertThat(...)`) in new test code. Same applies 
to the private `assertEquals` helper in `ApicurioRegistryConsumerIT`.
   
   _AI-generated Grok inline comment on behalf of atiaomar1978-hub._



##########
components/camel-apicurio-registry/src/main/docs/apicurio-registry-component.adoc:
##########
@@ -0,0 +1,198 @@
+= Apicurio Registry Component
+:doctitle: Apicurio Registry
+:shortname: apicurio-registry
+:artifactid: camel-apicurio-registry
+:description: Manage artifacts, versions, and groups in Apicurio Registry v3.
+:since: 4.22
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Both producer and consumer are supported
+
+*Since Camel {since}*
+
+*{component-header}*
+
+The Apicurio Registry component provides integration with 
https://www.apicur.io/registry/[Apicurio Registry] v3
+using the https://github.com/Apicurio/apicurio-registry[Apicurio Registry Java 
SDK].
+
+It supports CRUD operations on artifacts, groups, and versions, as well as 
schema validation
+and polling for new artifact versions.
+
+Maven users will need to add the following dependency to their `pom.xml`
+for this component:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-apicurio-registry</artifactId>
+    <version>x.x.x</version>
+    <!-- use the same version as your Camel core version -->
+</dependency>
+----
+
+== URI format
+
+----
+apicurio-registry:groupId/artifactId[?options]
+----
+
+Where `groupId` and `artifactId` identify the registry artifact. Both are 
optional for
+operations that do not require them (e.g., `searchArtifacts`, `createGroup`).
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+include::partial$component-endpoint-headers.adoc[]
+// component options: END
+
+== Producer Operations
+
+The producer supports the following operations, set via the `operation` 
endpoint option or
+the `CamelApicurioRegistryOperation` header:
+
+[cols="1,3"]
+|===
+| Operation | Description
+
+| `createArtifact` | Create a new artifact. Body contains the artifact content.
+| `updateArtifact` | Create a new version of an existing artifact. Body 
contains the new content.
+| `deleteArtifact` | Delete an artifact.
+| `getArtifactContent` | Retrieve the content of an artifact version.
+| `getArtifactMetadata` | Retrieve artifact metadata.
+| `searchArtifacts` | Search for artifacts using filter headers.
+| `listVersions` | List all versions of an artifact.
+| `createGroup` | Create a new group.
+| `testCompatibility` | Test schema compatibility (dry run). Returns 
`true`/`false` in the body.
+| `validate` | Validate the message body against the artifact's rules (dry 
run). Throws `ApicurioRegistryValidationException` on failure when 
`failOnValidation=true`.
+|===

Review Comment:
   **Grok:** Consumer section should mention first-start replay behavior (all 
existing versions are emitted once) and that `delay` defaults via 
`ScheduledPollConsumer`. Helps operators avoid surprise duplicate processing.
   
   _AI-generated Grok inline comment on behalf of atiaomar1978-hub._



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to