This is an automated email from the ASF dual-hosted git repository.

fmariani pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new cb315d5e2289 CAMEL-22292: Add --infra option to camel cmd send for 
infrastructure services (#20767)
cb315d5e2289 is described below

commit cb315d5e22893983153c2f3ca0cf7759b8975748
Author: Pranjul Kalsi <[email protected]>
AuthorDate: Fri Jan 23 15:51:23 2026 +0530

    CAMEL-22292: Add --infra option to camel cmd send for infrastructure 
services (#20767)
    
    * CAMEL-22292: Add --infra option to camel cmd send for infrastructure 
services
    
    * CAMEL-22292: camel send --infra refinements and add unit test
    
    * CAMEL-22292: Refactor and add tests for camel send --infra option
    
    * CAMEL-22292: Include credentials in InfraService endpointUri, remove 
workarounds
    
    * CAMEL-22292: Minor cleanup
    
    * update correct version
---
 .../modules/ROOT/pages/camel-jbang.adoc            |  54 ++
 .../pages/jbang-commands/camel-jbang-cmd-send.adoc |   1 +
 .../META-INF/camel-jbang-commands-metadata.json    |   2 +-
 .../core/commands/action/CamelSendAction.java      | 264 ++++++++-
 .../commands/action/CamelSendActionInfraTest.java  | 620 +++++++++++++++++++++
 .../arangodb/services/ArangoDBInfraService.java    |   8 +
 .../artemis/services/ArtemisInfraService.java      |  17 +
 .../infra/aws/common/services/AWSInfraService.java |   8 +
 .../azure/common/services/AzureInfraService.java   |  12 +
 .../cassandra/services/CassandraInfraService.java  |  24 +
 .../services/ChatScriptInfraService.java           |  12 +
 .../couchbase/services/CouchbaseInfraService.java  |   9 +
 .../couchdb/services/CouchDbInfraService.java      |  13 +
 .../docling/services/DoclingInfraService.java      |   4 +
 .../services/ElasticSearchInfraService.java        |  15 +
 .../test/infra/fhir/services/FhirInfraService.java |   7 +
 .../test/infra/ftp/services/FtpInfraService.java   |   9 +
 .../pubsub/services/GooglePubSubInfraService.java  |   9 +
 .../vault/services/HashicorpVaultInfraService.java |   4 +
 .../hazelcast/services/HazelcastInfraService.java  |   8 +
 .../infra/hivemq/services/HiveMQInfraService.java  |  17 +
 .../infra/ibmmq/services/IbmMQInfraService.java    |  20 +
 .../services/InfinispanInfraService.java           |   5 +
 .../keycloak/services/KeycloakInfraService.java    |  20 +
 .../lra/services/MicroprofileLRAInfraService.java  |   8 +
 .../infra/milvus/services/MilvusInfraService.java  |   8 +
 .../infra/minio/services/MinioInfraService.java    |   4 +
 .../mongodb/services/MongoDBInfraService.java      |   6 +
 .../mosquitto/services/MosquittoInfraService.java  |  13 +
 .../test/infra/nats/services/NatsInfraService.java |   5 +
 .../infra/ollama/services/OllamaInfraService.java  |  35 ++
 .../openldap/services/OpenldapInfraService.java    |  38 ++
 .../postgres/services/PostgresInfraService.java    |  32 ++
 .../infra/pulsar/services/PulsarInfraService.java  |  10 +
 .../infra/qdrant/services/QdrantInfraService.java  |   8 +
 .../rabbitmq/services/RabbitMQInfraService.java    |  24 +
 .../infra/redis/services/RedisInfraService.java    |   5 +
 .../rocketmq/services/RocketMQInfraService.java    |   4 +
 .../test/infra/smb/services/SmbInfraService.java   |  30 +
 .../test/infra/solr/services/SolrInfraService.java |  10 +
 .../services/TorchServeInfraService.java           |  12 +
 .../TorchServeLocalContainerInfraService.java      |   5 +
 .../test/infra/xmpp/services/XmppInfraService.java |   5 +
 .../zookeeper/services/ZooKeeperInfraService.java  |  13 +
 44 files changed, 1434 insertions(+), 3 deletions(-)

diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
index 87ac3bd6a046..1421e00c100d 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
@@ -1550,6 +1550,60 @@ for components like Kafka or AWS. So for these you may 
want to use a kamelet ins
 $ camel cmd send --body=file:payload.json 
--uri='kamelet:mqtt-sink?brokerUrl=tcp://mybroker:1883&topic=temperature'
 ----
 
+==== Sending messages to infrastructure services
+
+*Available since Camel 4.18*
+
+In Camel 4.17, you can use `camel cmd send` to send messages directly to 
infrastructure services that are started with `camel infra run`.
+This eliminates the need to manually specify server connection details, as the 
command automatically reads connection information from JSON files created by 
infrastructure services.
+
+This is done by using the `--infra` option to specify which infrastructure 
service to send to:
+
+[source,bash]
+----
+$ camel infra run nats
+$ camel cmd send --body=file:payload.json --infra=nats
+----
+
+The command automatically discovers the running infrastructure service, reads 
its connection details from the JSON file (stored in `~/.camel/`), and 
constructs the appropriate endpoint URI with the server information using the 
Camel Catalog.
+
+===== Specifying a custom endpoint
+
+If you don't specify an `--endpoint`, the command automatically creates a 
default endpoint based on the infrastructure service type (e.g., 
`kafka:default`, `nats:default`).
+
+You can also combine the `--infra` option with a specific endpoint to 
customize the destination:
+
+[source,bash]
+----
+$ camel cmd send --endpoint='kafka:myTopic' --body=file:payload.json 
--infra=kafka
+$ camel cmd send --endpoint='nats:mySubject' --body=file:payload.json 
--infra=nats
+----
+
+NOTE: If your endpoint already contains query parameters (e.g., 
`kafka:myTopic?groupId=myGroup`), the connection details from the 
infrastructure service will not override them.
+
+===== Automatic credential handling
+
+For services that support authentication (such as artemis, ftp, sftp), the 
command automatically appends credentials from the connection details to the 
endpoint URI if the Camel component supports them:
+
+[source,bash]
+----
+$ camel infra run artemis
+$ camel cmd send --endpoint='jms:myQueue' --body='Hello' --infra=artemis
+----
+
+The resulting endpoint will automatically include authentication parameters 
like `username` and `password=RAW(...)`.
+
+===== Multiple service detection
+
+If multiple instances of the same infrastructure service are running, the 
command will display an error and ask you to be more specific:
+
+[source,bash]
+----
+Multiple running infrastructure services found for: kafka. Found 2 services.
+----
+
+In this case, stop the unwanted service or specify the exact PID.
+
 ==== Poll messages via Camel
 
 *Available since Camel 4.8*
diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-cmd-send.adoc 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-cmd-send.adoc
index 1a011d2ebaa5..a525a9003d2e 100644
--- 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-cmd-send.adoc
+++ 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-cmd-send.adoc
@@ -22,6 +22,7 @@ camel cmd send [options]
 | `--body` | Message body to send (prefix with file: to refer to loading 
message body from file) |  | String
 | `--endpoint,--uri` | Endpoint where to send the message (can be uri, 
pattern, or refer to a route id) |  | String
 | `--header` | Message header (key=value) |  | List
+| `--infra` | Send to infrastructure service (e.g., nats, kafka) |  | String
 | `--logging-color` | Use colored logging | true | boolean
 | `--poll` | Poll instead of sending a message. This can be used to receive 
latest message from a Kafka topic or JMS queue. |  | boolean
 | `--pretty` | Pretty print response message body (InOut) when using JSon or 
XML format |  | boolean
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
index 65955e46ff1a..bc094d14443a 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
@@ -2,7 +2,7 @@
   "commands": [
     { "name": "bind", "fullName": "bind", "description": "Bind source and sink 
Kamelets as a new Camel integration", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.bind.Bind", "options": [ { "names": 
"--error-handler", "description": "Add error handler 
(none|log|sink:<endpoint>). Sink endpoints are expected in the format 
[[apigroup\/]version:]kind:[namespace\/]name, plain Camel URIs or Kamelet 
name.", "javaType": "java.lang.String", "type": "string" }, { "names": 
"--output", "d [...]
     { "name": "catalog", "fullName": "catalog", "description": "List artifacts 
from Camel Catalog", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.catalog.CatalogCommand", "options": [ 
{ "names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"component", "fullName": "catalog component", "description": "List components 
from the Camel Catalog", "sourceClass": "org.apache.camel.dsl.jbang.co [...]
-    { "name": "cmd", "fullName": "cmd", "description": "Performs commands in 
the running Camel integrations, such as start\/stop route, or change logging 
levels.", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.action.CamelAction", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"browse", "fullName": "cmd browse", "description": "Browse pending messages on 
endpoints [...]
+    { "name": "cmd", "fullName": "cmd", "description": "Performs commands in 
the running Camel integrations, such as start\/stop route, or change logging 
levels.", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.action.CamelAction", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"browse", "fullName": "cmd browse", "description": "Browse pending messages on 
endpoints [...]
     { "name": "completion", "fullName": "completion", "description": "Generate 
completion script for bash\/zsh", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Complete", "options": [ { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ] },
     { "name": "config", "fullName": "config", "description": "Get and set user 
configuration values", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.config.ConfigCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "get", 
"fullName": "config get", "description": "Display user configuration value", 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.config. [...]
     { "name": "debug", "fullName": "debug", "description": "Debug local Camel 
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Debug", 
"options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd 
HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background", "description": "Run in the background", "defaultValue": 
"false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "To  [...]
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSendAction.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSendAction.java
index 2ddbeae59a23..747b8a6be403 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSendAction.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSendAction.java
@@ -18,17 +18,26 @@ package org.apache.camel.dsl.jbang.core.commands.action;
 
 import java.io.File;
 import java.io.IOException;
+import java.net.URISyntaxException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
+import org.apache.camel.catalog.CamelCatalog;
+import org.apache.camel.catalog.DefaultCamelCatalog;
 import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
 import org.apache.camel.dsl.jbang.core.commands.Run;
+import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
 import org.apache.camel.dsl.jbang.core.common.PathUtils;
 import org.apache.camel.main.KameletMain;
 import org.apache.camel.util.StringHelper;
@@ -115,10 +124,16 @@ public class CamelSendAction extends ActionBaseCommand {
     @CommandLine.Option(names = { "--logging-color" }, defaultValue = "true", 
description = "Use colored logging")
     boolean loggingColor = true;
 
+    @CommandLine.Option(names = { "--infra" },
+                        description = "Send to infrastructure service (e.g., 
nats, kafka)")
+    String infra;
+
     private volatile long pid;
 
     private MessageTableHelper tableHelper;
 
+    private final CamelCatalog catalog = new DefaultCamelCatalog();
+
     public CamelSendAction(CamelJBangMain main) {
         super(main);
     }
@@ -134,7 +149,9 @@ public class CamelSendAction extends ActionBaseCommand {
             }
         }
 
-        if (name != null) {
+        if (infra != null) {
+            return doCallInfra(infra);
+        } else if (name != null) {
             return doCall(name);
         } else {
             return doCallLocal();
@@ -361,7 +378,7 @@ public class CamelSendAction extends ActionBaseCommand {
             c = Ansi.Color.RED;
         } else if (replyFile != null) {
             if (poll) {
-                status = "Poll save to fill (success)";
+                status = "Poll save to file (success)";
             } else {
                 status = "Reply save to file (success)";
             }
@@ -386,4 +403,247 @@ public class CamelSendAction extends ActionBaseCommand {
         }
     }
 
+    private Integer doCallInfra(String infraService) throws Exception {
+        Map<Long, Path> infraPids = findInfraPids(infraService);
+
+        if (infraPids.isEmpty()) {
+            printer().println("No running infrastructure service found for: " 
+ infraService);
+            return 1;
+        }
+
+        if (infraPids.size() > 1) {
+            printer().println("Multiple running infrastructure services found 
for: " + infraService +
+                              ". Found " + infraPids.size() + " services.");
+            return 1;
+        }
+
+        Map.Entry<Long, Path> entry = infraPids.entrySet().iterator().next();
+        Path jsonFile = entry.getValue();
+
+        JsonObject connectionDetails = readConnectionDetails(jsonFile);
+
+        if (connectionDetails == null) {
+            printer().println("Could not read connection details from: " + 
jsonFile);
+            return 1;
+        }
+
+        String scheme = extractScheme(endpoint, infraService);
+
+        this.endpoint = updateEndpointWithConnectionDetails(endpoint, 
infraService, connectionDetails);
+
+        Map<String, String> componentProps = buildComponentProperties(scheme, 
connectionDetails);
+
+        Map<String, String> beanProps = buildBeanProperties(connectionDetails);
+
+        int additionalCount = componentProps.size() + beanProps.size();
+        if (additionalCount > 0) {
+            int existingCount = (property != null) ? property.length : 0;
+            String[] merged = new String[existingCount + additionalCount];
+            if (property != null) {
+                System.arraycopy(property, 0, merged, 0, existingCount);
+            }
+            int i = existingCount;
+            for (Map.Entry<String, String> compEntry : 
componentProps.entrySet()) {
+                merged[i++] = "camel.component." + scheme + "." + 
compEntry.getKey() + "=" + compEntry.getValue();
+            }
+            for (Map.Entry<String, String> beanEntry : beanProps.entrySet()) {
+                merged[i++] = beanEntry.getKey() + "=" + beanEntry.getValue();
+            }
+            property = merged;
+        }
+
+        return doCallLocal();
+    }
+
+    private String extractScheme(String endpoint, String infraService) {
+        if (endpoint != null && endpoint.contains(":")) {
+            return StringHelper.before(endpoint, ":");
+        }
+        return infraService;
+    }
+
+    private Map<Long, Path> findInfraPids(String serviceName) throws Exception 
{
+        Map<Long, Path> pids = new HashMap<>();
+
+        Path camelDir = CommandLineHelper.getCamelDir();
+
+        try (Stream<Path> files = Files.list(camelDir)) {
+            List<Path> pidFiles = files
+                    .filter(p -> {
+                        String fileName = p.getFileName().toString();
+                        return fileName.startsWith("infra-") && 
fileName.endsWith(".json");
+                    })
+                    .collect(Collectors.toList());
+
+            for (Path pidFile : pidFiles) {
+                String fileName = pidFile.getFileName().toString();
+                // Format: infra-{service}-{pid}.json
+                String withoutPrefix = fileName.substring("infra-".length());
+                String withoutExtension = withoutPrefix.substring(0, 
withoutPrefix.lastIndexOf(".json"));
+
+                int lastDashIndex = withoutExtension.lastIndexOf('-');
+                if (lastDashIndex > 0) {
+                    String service = withoutExtension.substring(0, 
lastDashIndex);
+                    String pidStr = withoutExtension.substring(lastDashIndex + 
1);
+
+                    if (service.equals(serviceName)) {
+                        try {
+                            long pid = Long.parseLong(pidStr);
+                            pids.put(pid, pidFile);
+                        } catch (NumberFormatException e) {
+                            // Skip invalid PID
+                        }
+                    }
+                }
+            }
+        }
+
+        return pids;
+    }
+
+    private JsonObject readConnectionDetails(Path jsonFile) throws Exception {
+        String content = Files.readString(jsonFile);
+        return (JsonObject) Jsoner.deserialize(content);
+    }
+
+    String updateEndpointWithConnectionDetails(
+            String originalEndpoint, String infraService, JsonObject 
connectionDetails) {
+
+        if (originalEndpoint == null) {
+            originalEndpoint = infraService + ":default";
+        }
+
+        if (originalEndpoint.contains("?")) {
+            return originalEndpoint;
+        }
+
+        String scheme;
+        String path;
+        if (originalEndpoint.contains(":")) {
+            scheme = StringHelper.before(originalEndpoint, ":");
+            path = StringHelper.after(originalEndpoint, ":");
+        } else {
+            scheme = originalEndpoint;
+            path = null;
+        }
+
+        String pathBasedEndpoint = buildPathBasedEndpoint(path, 
connectionDetails);
+        if (pathBasedEndpoint != null) {
+            return pathBasedEndpoint;
+        }
+
+        Map<String, String> properties = buildPropertiesMap(scheme, 
connectionDetails);
+
+        try {
+            String uri = catalog.asEndpointUri(scheme, properties, true);
+            if (uri != null && !uri.isEmpty()) {
+                String queryPart = "";
+                if (uri.contains("?")) {
+                    queryPart = "?" + StringHelper.after(uri, "?");
+                }
+
+                if (path != null && !path.isEmpty()) {
+                    return scheme + ":" + path + queryPart;
+                } else {
+                    return uri;
+                }
+            }
+        } catch (URISyntaxException e) {
+            // Fall back to manual construction if catalog fails
+        }
+
+        return buildEndpointManually(originalEndpoint, properties);
+    }
+
+    private Map<String, String> buildBeanProperties(JsonObject 
connectionDetails) {
+        Map<String, String> properties = new LinkedHashMap<>();
+
+        Object beanProps = connectionDetails.get("beanProperties");
+        if (beanProps instanceof Map<?, ?> beanMap) {
+            for (Map.Entry<?, ?> entry : beanMap.entrySet()) {
+                if (entry.getKey() != null && entry.getValue() != null) {
+                    properties.put(String.valueOf(entry.getKey()), 
String.valueOf(entry.getValue()));
+                }
+            }
+        }
+
+        return properties;
+    }
+
+    private Map<String, String> buildComponentProperties(String scheme, 
JsonObject connectionDetails) {
+        Map<String, String> properties = new LinkedHashMap<>();
+
+        var componentModel = catalog.componentModel(scheme);
+        if (componentModel != null) {
+            componentModel.getComponentOptions().stream()
+                    .map(opt -> opt.getName())
+                    .filter(name -> isValidConnectionProperty(name, 
connectionDetails))
+                    .forEach(name -> properties.put(name, 
String.valueOf(connectionDetails.get(name))));
+        }
+
+        return properties;
+    }
+
+    private Map<String, String> buildPropertiesMap(String scheme, JsonObject 
connectionDetails) {
+        Map<String, String> properties = new LinkedHashMap<>();
+
+        var componentModel = catalog.componentModel(scheme);
+        if (componentModel != null) {
+            componentModel.getEndpointOptions().stream()
+                    .map(opt -> opt.getName())
+                    .filter(name -> isValidConnectionProperty(name, 
connectionDetails))
+                    .forEach(name -> properties.put(name, 
String.valueOf(connectionDetails.get(name))));
+        }
+
+        return properties;
+    }
+
+    private boolean isValidConnectionProperty(String name, JsonObject 
connectionDetails) {
+        if (!connectionDetails.containsKey(name)) {
+            return false;
+        }
+        Object value = connectionDetails.get(name);
+        return value != null && !(value instanceof Map);
+    }
+
+    private String buildPathBasedEndpoint(String path, JsonObject 
connectionDetails) {
+        String uri = connectionDetails.getString("endpointUri");
+        if (uri == null) {
+            return null;
+        }
+
+        if (path != null && !path.isEmpty()) {
+            String connectionBase = 
connectionDetails.getString("connectionBase");
+            if (connectionBase != null) {
+                String queryPart = StringHelper.after(uri, "?");
+                if (queryPart != null) {
+                    queryPart = "?" + queryPart;
+                } else {
+                    queryPart = "";
+                }
+
+                String newPath = path.startsWith("/") ? path : "/" + path;
+                return connectionBase + newPath + queryPart;
+            }
+        }
+
+        // fallback to original URI
+        return uri;
+    }
+
+    private String buildEndpointManually(String endpoint, Map<String, String> 
properties) {
+        if (properties.isEmpty()) {
+            return endpoint;
+        }
+
+        StringBuilder queryParams = new StringBuilder();
+        for (Map.Entry<String, String> entry : properties.entrySet()) {
+            if (queryParams.length() > 0) {
+                queryParams.append("&");
+            }
+            
queryParams.append(entry.getKey()).append("=").append(entry.getValue());
+        }
+
+        return endpoint + "?" + queryParams;
+    }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSendActionInfraTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSendActionInfraTest.java
new file mode 100644
index 000000000000..dad8c8c01375
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSendActionInfraTest.java
@@ -0,0 +1,620 @@
+/*
+ * 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.dsl.jbang.core.commands.action;
+
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.apache.camel.catalog.CamelCatalog;
+import org.apache.camel.catalog.DefaultCamelCatalog;
+import org.apache.camel.catalog.EndpointValidationResult;
+import org.apache.camel.dsl.jbang.core.commands.CamelCommandBaseTestSupport;
+import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+// CamelSendAction's --infra option.
+public class CamelSendActionInfraTest extends CamelCommandBaseTestSupport {
+
+    private CamelSendAction sendAction;
+    private CamelCatalog catalog;
+
+    private static final Set<String> SKIP_CATALOG_VALIDATION = Set.of(
+            "openldap",
+            "docling",
+            "torch-serve",
+            "microprofile",
+            "artemis",
+            "ibmmq",
+            "rabbitmq",
+            "postgres",
+            "ollama");
+
+    @BeforeEach
+    public void setup() throws Exception {
+        super.setup();
+        sendAction = new CamelSendAction(new 
CamelJBangMain().withPrinter(printer));
+        catalog = new DefaultCamelCatalog();
+    }
+
+    private String buildAndDecode(String endpoint, String service, JsonObject 
json) {
+        String result = 
sendAction.updateEndpointWithConnectionDetails(endpoint, service, json);
+        return URLDecoder.decode(result, StandardCharsets.UTF_8);
+    }
+
+    private void validateEndpointWithCatalog(String serviceName, String 
decodedUri) {
+        if (SKIP_CATALOG_VALIDATION.contains(serviceName)) {
+            return;
+        }
+
+        EndpointValidationResult result = 
catalog.validateEndpointProperties(decodedUri);
+
+        assertThat(result.getUnknown())
+                .describedAs("URI '%s' for service '%s' contains unknown 
properties: %s",
+                        decodedUri, serviceName, result.getUnknown())
+                .isNullOrEmpty();
+    }
+
+    static Stream<Arguments> infraServiceTestCases() {
+        List<Arguments> testCases = new ArrayList<>();
+
+        testCases.add(Arguments.of(
+                "nats",
+                createJson("servers", "localhost:4222"),
+                "nats:myTopic",
+                "servers", "localhost:4222"));
+
+        testCases.add(Arguments.of(
+                "kafka",
+                createJson("brokers", "localhost:9092"),
+                "kafka:myTopic",
+                "brokers", "localhost:9092"));
+
+        testCases.add(Arguments.of(
+                "mosquitto",
+                createJson("brokerUrl", "tcp://localhost:1883"),
+                "paho-mqtt5:myTopic",
+                "brokerUrl", "tcp://localhost:1883"));
+
+        testCases.add(Arguments.of(
+                "hive-mq",
+                createJson("brokerUrl", "tcp://localhost:1883"),
+                "paho-mqtt5:myTopic",
+                "brokerUrl", "tcp://localhost:1883"));
+
+        testCases.add(Arguments.of(
+                "artemis",
+                createJson("serviceAddress", "tcp://localhost:61616", 
"userName", "admin", "password", "secret"),
+                "jms:myQueue",
+                "password", "RAW(secret)"));
+
+        testCases.add(Arguments.of(
+                "rabbitmq",
+                createJson("uri", "amqp://localhost:5672", "username", 
"guest", "password", "guest"),
+                "spring-rabbitmq:myExchange",
+                "spring-rabbitmq", "myExchange"));
+
+        testCases.add(Arguments.of(
+                "mongodb",
+                createJson("hosts", "localhost:27017"),
+                "mongodb:myDatabase",
+                "hosts", "localhost:27017"));
+
+        testCases.add(Arguments.of(
+                "minio",
+                createJson("accessKey", "minioadmin", "secretKey", 
"minioadmin", "endpoint", "http://localhost:9000";),
+                "minio:myBucket",
+                "endpoint", "http://localhost:9000";));
+
+        testCases.add(Arguments.of(
+                "infinispan",
+                createJson("hosts", "localhost:11222", "username", "admin", 
"password", "secret"),
+                "infinispan:myCache",
+                "hosts", "localhost:11222"));
+
+        testCases.add(Arguments.of(
+                "zookeeper",
+                createJson("serverUrls", "localhost:2181",
+                        "endpointUri", "zookeeper:localhost:2181/camel",
+                        "connectionBase", "zookeeper:localhost:2181"),
+                "zookeeper:/myPath",
+                "localhost:2181", "/myPath"));
+
+        testCases.add(Arguments.of(
+                "couchdb",
+                createJson("host", "localhost", "port", 5984, "database", 
"mydb",
+                        "endpointUri", "couchdb:http:localhost:5984/mydb",
+                        "connectionBase", "couchdb:http:localhost:5984"),
+                "couchdb:myDatabase",
+                "localhost", "myDatabase"));
+
+        testCases.add(Arguments.of(
+                "arangodb",
+                createJson("host", "localhost", "port", 8529),
+                "arangodb:myDatabase",
+                "host", "localhost"));
+
+        testCases.add(Arguments.of(
+                "hashicorp",
+                createJson("host", "localhost", "port", 8200, "token", 
"mytoken"),
+                "hashicorp-vault:mySecret",
+                "host", "localhost"));
+
+        testCases.add(Arguments.of(
+                "keycloak",
+                createJson("serverUrl", "http://localhost:8080";, "realm", 
"myrealm"),
+                "http:localhost:8080/auth",
+                "http", "localhost"));
+
+        testCases.add(Arguments.of(
+                "smb",
+                createJson("address", "localhost:445", "shareName", "myShare",
+                        "userName", "user", "password", "pass",
+                        "endpointUri", 
"smb:localhost:445/myShare?username=user&password=RAW(pass)",
+                        "connectionBase", "smb:localhost:445"),
+                "smb:myShare",
+                "localhost", "myShare"));
+
+        testCases.add(Arguments.of(
+                "openldap",
+                createJson("host", "localhost", "port", 389,
+                        "ldapUrl", "ldap://localhost:389";,
+                        "ldapContextFactory", 
"com.sun.jndi.ldap.LdapCtxFactory",
+                        "endpointUri", "ldap:ldapEnv"),
+                "ldap:ou=users",
+                "ldap", "ldapEnv"));
+
+        testCases.add(Arguments.of(
+                "ollama",
+                createJson("baseUrl", "http://localhost:11434";, "modelName", 
"llama2"),
+                "langchain4j-chat:myModel",
+                "langchain4j-chat", "myModel"));
+
+        testCases.add(Arguments.of(
+                "couchbase",
+                createJson("hostname", "localhost", "port", 8091, "bucket", 
"myBucket",
+                        "protocol", "http",
+                        "endpointUri", 
"couchbase:http://localhost:8091/myBucket";,
+                        "connectionBase", "couchbase:http://localhost:8091";),
+                "couchbase:myBucket",
+                "localhost", "myBucket"));
+
+        testCases.add(Arguments.of(
+                "postgres",
+                createJson("host", "localhost", "port", 5432, "userName", 
"postgres", "password", "secret",
+                        "jdbcUrl", "jdbc:postgresql://localhost:5432/postgres",
+                        "endpointUri", "sql:SELECT 1?dataSource=#postgresDS"),
+                "sql:SELECT 1",
+                "sql", "SELECT"));
+
+        testCases.add(Arguments.of(
+                "ibmmq",
+                createJson("channel", "DEV.APP.SVRCONN", "queueManager", 
"QM1", "listenerPort", 1414),
+                "jms:myQueue",
+                "jms", "myQueue"));
+
+        testCases.add(Arguments.of(
+                "rocketmq",
+                createJson("namesrvAddr", "localhost:9876"),
+                "rocketmq:myTopic",
+                "namesrvAddr", "localhost:9876"));
+
+        testCases.add(Arguments.of(
+                "milvus",
+                createJson("host", "localhost", "port", 19530),
+                "milvus:myCollection",
+                "host", "localhost"));
+
+        testCases.add(Arguments.of(
+                "qdrant",
+                createJson("host", "localhost", "port", 6333),
+                "qdrant:myCollection",
+                "host", "localhost"));
+
+        testCases.add(Arguments.of(
+                "ftp",
+                createJson("host", "localhost", "port", 21,
+                        "username", "admin", "password", "admin",
+                        "endpointUri", 
"ftp:localhost:21/defaultdir?username=admin&password=RAW(admin)",
+                        "connectionBase", "ftp:localhost:21"),
+                "ftp:mydir",
+                "username", "admin"));
+
+        testCases.add(Arguments.of(
+                "ftps",
+                createJson("host", "localhost", "port", 21,
+                        "username", "admin", "password", "admin",
+                        "endpointUri", 
"ftps:localhost:21/defaultdir?username=admin&password=RAW(admin)",
+                        "connectionBase", "ftps:localhost:21"),
+                "ftps:mydir",
+                "username", "admin"));
+
+        testCases.add(Arguments.of(
+                "sftp",
+                createJson("host", "localhost", "port", 22,
+                        "username", "admin", "password", "admin",
+                        "endpointUri", 
"sftp:localhost:22/defaultdir?username=admin&password=RAW(admin)",
+                        "connectionBase", "sftp:localhost:22"),
+                "sftp:mydir",
+                "username", "admin"));
+
+        testCases.add(Arguments.of(
+                "docling",
+                createJson("doclingServerUrl", "http://localhost:5000";),
+                "rest:post:/convert",
+                "rest", "post"));
+
+        testCases.add(Arguments.of(
+                "torch-serve",
+                createJson("inferencePort", 8080, "managementPort", 8081, 
"metricsPort", 8082),
+                "rest:post:/predictions/model",
+                "rest", "post"));
+
+        testCases.add(Arguments.of(
+                "fhir",
+                createJson("serverUrl", "http://localhost:8080/fhir";),
+                "fhir:Patient/search",
+                "serverUrl", "http://localhost:8080/fhir";));
+
+        testCases.add(Arguments.of(
+                "pulsar",
+                createJson("serviceUrl", "pulsar://localhost:6650"),
+                "pulsar:persistent://public/default/myTopic",
+                "serviceUrl", "pulsar://localhost:6650"));
+
+        testCases.add(Arguments.of(
+                "aws",
+                createJson("amazonAWSHost", "localhost:4566", "region", 
"us-east-1",
+                        "accessKey", "test", "secretKey", "test"),
+                "aws2-s3:myBucket",
+                "region", "us-east-1"));
+
+        testCases.add(Arguments.of(
+                "azure",
+                createJson("host", "localhost", "port", 10000,
+                        "accountName", "devstoreaccount1", "accessKey", 
"testkey",
+                        "containerName", "testcontainer",
+                        "endpointUri", 
"azure-storage-blob:devstoreaccount1/testcontainer",
+                        "connectionBase", 
"azure-storage-blob:devstoreaccount1"),
+                "azure-storage-blob:myContainer",
+                "devstoreaccount1", "myContainer"));
+
+        testCases.add(Arguments.of(
+                "google",
+                createJson("endpoint", "localhost:8085"),
+                "google-pubsub:myTopic",
+                "google-pubsub", "myTopic"));
+
+        testCases.add(Arguments.of(
+                "microprofile",
+                createJson("host", "localhost", "port", 8080),
+                "http:localhost:8080/lra-coordinator",
+                "host", "localhost"));
+
+        return testCases.stream();
+    }
+
+    @ParameterizedTest(name = "{0}: {2}")
+    @MethodSource("infraServiceTestCases")
+    @DisplayName("Test endpoint building for infra service")
+    void testEndpointBuilding(
+            String serviceName, JsonObject mockJson, String baseEndpoint,
+            String expectedKey, String expectedValue) {
+
+        String decoded = buildAndDecode(baseEndpoint, serviceName, mockJson);
+
+        boolean hasQueryParam = decoded.contains(expectedKey + "=" + 
expectedValue);
+        boolean hasPathParts = decoded.contains(expectedKey) && 
decoded.contains(expectedValue);
+
+        assertThat(hasQueryParam || hasPathParts)
+                .describedAs("Endpoint for %s should contain '%s' and '%s' 
(got: %s)",
+                        serviceName, expectedKey, expectedValue, decoded)
+                .isTrue();
+
+        String expectedScheme = baseEndpoint.split(":")[0];
+        assertThat(decoded).startsWith(expectedScheme + ":");
+
+        validateEndpointWithCatalog(serviceName, decoded);
+    }
+
+    @Test
+    void testKafkaWithBrokersProperty() {
+        JsonObject json = new JsonObject();
+        json.put("brokers", "localhost:9092");
+        json.put("getBootstrapServers", "localhost:9092");
+
+        String decoded = buildAndDecode("kafka:myTopic", "kafka", json);
+
+        assertThat(decoded).contains("brokers=localhost:9092");
+        assertThat(decoded).doesNotContain("getBootstrapServers");
+    }
+
+    @Test
+    void testNatsWithCorrectProperty() {
+        JsonObject json = new JsonObject();
+        json.put("servers", "localhost:4222");
+
+        String decoded = buildAndDecode("nats:mySubject", "nats", json);
+
+        assertThat(decoded).contains("servers=localhost:4222");
+    }
+
+    @Test
+    void testMosquittoBrokerUrl() {
+        JsonObject json = new JsonObject();
+        json.put("brokerUrl", "tcp://localhost:1883");
+
+        String decoded = buildAndDecode("paho-mqtt5:myTopic", "mosquitto", 
json);
+
+        assertThat(decoded).contains("brokerUrl=tcp://localhost:1883");
+    }
+
+    @Test
+    void testHiveMqBrokerUrl() {
+        JsonObject json = new JsonObject();
+        json.put("brokerUrl", "tcp://localhost:1883");
+
+        String decoded = buildAndDecode("paho-mqtt5:myTopic", "hive-mq", json);
+
+        assertThat(decoded).contains("brokerUrl=tcp://localhost:1883");
+    }
+
+    @Test
+    void testArtemisWithCredentials() {
+        JsonObject json = new JsonObject();
+        json.put("serviceAddress", "tcp://localhost:61616");
+        json.put("userName", "admin");
+        json.put("password", "secret");
+
+        String decoded = buildAndDecode("jms:myQueue", "artemis", json);
+
+        assertThat(decoded).contains("password=RAW(secret)");
+    }
+
+    @Test
+    void testEndpointWithExistingQueryParams() {
+        JsonObject json = new JsonObject();
+        json.put("brokers", "localhost:9092");
+
+        String result = sendAction.updateEndpointWithConnectionDetails(
+                "kafka:myTopic?groupId=myGroup", "kafka", json);
+
+        assertThat(result).isEqualTo("kafka:myTopic?groupId=myGroup");
+    }
+
+    @Test
+    void testHazelcastEmptyJson() {
+        JsonObject json = new JsonObject();
+
+        String result = sendAction.updateEndpointWithConnectionDetails(
+                "hazelcast-map:myMap", "hazelcast", json);
+
+        assertThat(result).isEqualTo("hazelcast-map:myMap");
+    }
+
+    @Test
+    void testNullEndpointCreatesDefault() {
+        JsonObject json = new JsonObject();
+        json.put("brokers", "localhost:9092");
+
+        String decoded = buildAndDecode(null, "kafka", json);
+
+        assertThat(decoded).startsWith("kafka:default");
+        assertThat(decoded).contains("brokers=localhost:9092");
+    }
+
+    @Test
+    void testEmptyJsonHandledGracefully() {
+        JsonObject json = new JsonObject();
+
+        String result = sendAction.updateEndpointWithConnectionDetails(
+                "kafka:myTopic", "kafka", json);
+
+        assertThat(result).isEqualTo("kafka:myTopic");
+    }
+
+    @Test
+    void testRedisPathBasedEndpoint() {
+        JsonObject json = new JsonObject();
+        json.put("host", "localhost");
+        json.put("port", 6379);
+        json.put("endpointUri", "spring-redis:localhost:6379");
+
+        String result = sendAction.updateEndpointWithConnectionDetails(
+                "spring-redis:COMMAND", "redis", json);
+
+        assertThat(result).contains("localhost");
+        assertThat(result).contains("6379");
+        assertThat(result).startsWith("spring-redis:");
+    }
+
+    @Test
+    void testXmppPathBasedEndpoint() {
+        JsonObject json = new JsonObject();
+        json.put("host", "localhost");
+        json.put("port", 5222);
+        json.put("endpointUri", "xmpp:localhost:5222");
+
+        String result = sendAction.updateEndpointWithConnectionDetails(
+                "xmpp:room", "xmpp", json);
+
+        assertThat(result).contains("localhost");
+        assertThat(result).contains("5222");
+        assertThat(result).startsWith("xmpp:");
+    }
+
+    @Test
+    void testChatScriptPathBasedEndpoint() {
+        JsonObject json = new JsonObject();
+        json.put("serviceAddress", "localhost:1024");
+        json.put("botName", "Harry");
+        json.put("endpointUri", "chatscript:localhost:1024/Harry");
+
+        String result = sendAction.updateEndpointWithConnectionDetails(
+                "chatscript:Harry", "chat-script", json);
+
+        assertThat(result).isEqualTo("chatscript:localhost:1024/Harry");
+    }
+
+    @Test
+    void testPulsarWithServiceUrl() {
+        JsonObject json = new JsonObject();
+        json.put("serviceUrl", "pulsar://localhost:6650");
+
+        String decoded = 
buildAndDecode("pulsar:persistent://public/default/myTopic", "pulsar", json);
+
+        assertThat(decoded).contains("serviceUrl=pulsar://localhost:6650");
+    }
+
+    @Test
+    void testCassandraPathBasedEndpoint() {
+        JsonObject json = new JsonObject();
+        json.put("hosts", "localhost:9042");
+        json.put("port", 9042);
+
+        String result = sendAction.updateEndpointWithConnectionDetails(
+                "cql:cassandra-session:localhost:9042/mykeyspace", 
"cassandra", json);
+
+        assertThat(result).contains("localhost");
+        assertThat(result).startsWith("cql:");
+    }
+
+    @Test
+    void testFtpPathBasedEndpoint() {
+        JsonObject json = new JsonObject();
+        json.put("host", "localhost");
+        json.put("port", 21);
+        json.put("username", "admin");
+        json.put("password", "secret");
+        json.put("endpointUri", 
"ftp:localhost:21/mydir?username=admin&password=RAW(secret)");
+
+        String result = sendAction.updateEndpointWithConnectionDetails(
+                "ftp:mydir", "ftp", json);
+
+        assertThat(result).contains("localhost");
+        assertThat(result).contains("21");
+        assertThat(result).contains("username=admin");
+        assertThat(result).startsWith("ftp:");
+    }
+
+    @Test
+    void testElasticsearchWithHostAddresses() {
+        JsonObject json = new JsonObject();
+        json.put("hostAddresses", "localhost:9200");
+
+        String decoded = buildAndDecode("elasticsearch:myCluster", 
"elasticsearch", json);
+
+        assertThat(decoded).contains("hostAddresses=localhost:9200");
+    }
+
+    @Test
+    void testSolrPathBasedEndpoint() {
+        JsonObject json = new JsonObject();
+        json.put("host", "localhost");
+        json.put("port", 8983);
+
+        String result = sendAction.updateEndpointWithConnectionDetails(
+                "solr:localhost:8983/solr", "solr", json);
+
+        assertThat(result).contains("localhost");
+        assertThat(result).startsWith("solr:");
+    }
+
+    @Test
+    void testOpenLdapWithBeanProperties() {
+        JsonObject json = new JsonObject();
+        json.put("host", "localhost");
+        json.put("port", 389);
+        json.put("ldapUrl", "ldap://localhost:389";);
+        json.put("ldapContextFactory", "com.sun.jndi.ldap.LdapCtxFactory");
+        json.put("endpointUri", "ldap:ldapEnv");
+
+        JsonObject beanProps = new JsonObject();
+        beanProps.put("camel.beans.ldapEnv", "#class:java.util.Hashtable");
+        beanProps.put("camel.beans.ldapEnv[java.naming.factory.initial]", 
"com.sun.jndi.ldap.LdapCtxFactory");
+        beanProps.put("camel.beans.ldapEnv[java.naming.provider.url]", 
"ldap://localhost:389";);
+        json.put("beanProperties", beanProps);
+
+        String result = sendAction.updateEndpointWithConnectionDetails(
+                "ldap:ou=users", "openldap", json);
+
+        assertThat(result).isEqualTo("ldap:ldapEnv");
+    }
+
+    @Test
+    void testPostgresWithBeanProperties() {
+        JsonObject json = new JsonObject();
+        json.put("host", "localhost");
+        json.put("port", 5432);
+        json.put("jdbcUrl", "jdbc:postgresql://localhost:5432/postgres");
+        json.put("endpointUri", "sql:SELECT 1?dataSource=#postgresDS");
+
+        JsonObject beanProps = new JsonObject();
+        beanProps.put("camel.beans.postgresDS", 
"#class:org.postgresql.ds.PGSimpleDataSource");
+        beanProps.put("camel.beans.postgresDS.url", 
"jdbc:postgresql://localhost:5432/postgres");
+        beanProps.put("camel.beans.postgresDS.user", "postgres");
+        beanProps.put("camel.beans.postgresDS.password", "secret");
+        json.put("beanProperties", beanProps);
+
+        String result = sendAction.updateEndpointWithConnectionDetails(
+                "sql:SELECT 1", "postgres", json);
+
+        assertThat(result).isEqualTo("sql:SELECT 1?dataSource=#postgresDS");
+    }
+
+    @Test
+    void testCatalogValidationCatchesInvalidProperties() {
+        String invalidUri = 
"kafka:myTopic?brokers=localhost:9092&invalidFakeProperty=badvalue";
+
+        EndpointValidationResult result = 
catalog.validateEndpointProperties(invalidUri);
+
+        assertThat(result.getUnknown())
+                .describedAs("Catalog should detect 'invalidFakeProperty' as 
unknown")
+                .isNotNull()
+                .contains("invalidFakeProperty");
+    }
+
+    @Test
+    void testCatalogValidationPassesForValidProperties() {
+        String validUri = "kafka:myTopic?brokers=localhost:9092";
+
+        EndpointValidationResult result = 
catalog.validateEndpointProperties(validUri);
+
+        assertThat(result.getUnknown())
+                .describedAs("Valid URI should have no unknown properties")
+                .isNullOrEmpty();
+    }
+
+    private static JsonObject createJson(Object... keyValues) {
+        JsonObject json = new JsonObject();
+        for (int i = 0; i < keyValues.length; i += 2) {
+            json.put((String) keyValues[i], keyValues[i + 1]);
+        }
+        return json;
+    }
+}
diff --git 
a/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBInfraService.java
 
b/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBInfraService.java
index d7533dff4356..357f4439c463 100644
--- 
a/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBInfraService.java
+++ 
b/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBInfraService.java
@@ -50,4 +50,12 @@ public interface ArangoDBInfraService extends 
InfrastructureService {
     default String documentCollection() {
         return "myCollection";
     }
+
+    default String user() {
+        return "root";
+    }
+
+    default String password() {
+        return "";
+    }
 }
diff --git 
a/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisInfraService.java
 
b/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisInfraService.java
index efb2199bded9..105fcefff66d 100644
--- 
a/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisInfraService.java
+++ 
b/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisInfraService.java
@@ -24,12 +24,29 @@ public interface ArtemisInfraService extends 
InfrastructureService {
 
     String serviceAddress();
 
+    @Deprecated
     String userName();
 
     String password();
 
+    default String username() {
+        return userName();
+    }
+
     int brokerPort();
 
+    default String host() {
+        return "localhost";
+    }
+
+    default int port() {
+        return brokerPort();
+    }
+
+    default String brokerUrl() {
+        return String.format("amqp://%s:%d", host(), port());
+    }
+
     default String remoteURI() {
         throw new IllegalArgumentException("Remote URI is not supported");
     }
diff --git 
a/test-infra/camel-test-infra-aws-common/src/main/java/org/apache/camel/test/infra/aws/common/services/AWSInfraService.java
 
b/test-infra/camel-test-infra-aws-common/src/main/java/org/apache/camel/test/infra/aws/common/services/AWSInfraService.java
index ddd88cf9d2b0..4f0d049db658 100644
--- 
a/test-infra/camel-test-infra-aws-common/src/main/java/org/apache/camel/test/infra/aws/common/services/AWSInfraService.java
+++ 
b/test-infra/camel-test-infra-aws-common/src/main/java/org/apache/camel/test/infra/aws/common/services/AWSInfraService.java
@@ -34,4 +34,12 @@ public interface AWSInfraService extends 
InfrastructureService {
     String accessKey();
 
     String secretKey();
+
+    default String uriEndpointOverride() {
+        return String.format("%s://%s", protocol(), amazonAWSHost());
+    }
+
+    default boolean overrideEndpoint() {
+        return true;
+    }
 }
diff --git 
a/test-infra/camel-test-infra-azure-common/src/main/java/org/apache/camel/test/infra/azure/common/services/AzureInfraService.java
 
b/test-infra/camel-test-infra-azure-common/src/main/java/org/apache/camel/test/infra/azure/common/services/AzureInfraService.java
index 0f4e7fae3bcc..b1a22a039ead 100644
--- 
a/test-infra/camel-test-infra-azure-common/src/main/java/org/apache/camel/test/infra/azure/common/services/AzureInfraService.java
+++ 
b/test-infra/camel-test-infra-azure-common/src/main/java/org/apache/camel/test/infra/azure/common/services/AzureInfraService.java
@@ -40,4 +40,16 @@ public interface AzureInfraService extends 
InfrastructureService {
     default String credentialType() {
         return "SHARED_KEY_CREDENTIAL";
     }
+
+    default String containerName() {
+        return "testcontainer";
+    }
+
+    default String endpointUri() {
+        return String.format("azure-storage-blob:%s/%s", accountName(), 
containerName());
+    }
+
+    default String connectionBase() {
+        return String.format("azure-storage-blob:%s", accountName());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-cassandra/src/main/java/org/apache/camel/test/infra/cassandra/services/CassandraInfraService.java
 
b/test-infra/camel-test-infra-cassandra/src/main/java/org/apache/camel/test/infra/cassandra/services/CassandraInfraService.java
index e9c8efc3e7de..bcc47855dcba 100644
--- 
a/test-infra/camel-test-infra-cassandra/src/main/java/org/apache/camel/test/infra/cassandra/services/CassandraInfraService.java
+++ 
b/test-infra/camel-test-infra-cassandra/src/main/java/org/apache/camel/test/infra/cassandra/services/CassandraInfraService.java
@@ -35,4 +35,28 @@ public interface CassandraInfraService extends 
InfrastructureService {
     String hosts();
 
     int port();
+
+    default String keyspace() {
+        return "camel";
+    }
+
+    default String datacenter() {
+        return "datacenter1";
+    }
+
+    default String username() {
+        return "cassandra";
+    }
+
+    default String password() {
+        return "cassandra";
+    }
+
+    default String endpointUri() {
+        return String.format("cql:%s:%d/%s?username=%s&password=RAW(%s)", 
hosts(), port(), keyspace(), username(), password());
+    }
+
+    default String connectionBase() {
+        return String.format("cql:%s:%d", hosts(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-chatscript/src/main/java/org/apache/camel/test/infra/chatscript/services/ChatScriptInfraService.java
 
b/test-infra/camel-test-infra-chatscript/src/main/java/org/apache/camel/test/infra/chatscript/services/ChatScriptInfraService.java
index 26da3316c7b2..ba8e2e1bc50d 100644
--- 
a/test-infra/camel-test-infra-chatscript/src/main/java/org/apache/camel/test/infra/chatscript/services/ChatScriptInfraService.java
+++ 
b/test-infra/camel-test-infra-chatscript/src/main/java/org/apache/camel/test/infra/chatscript/services/ChatScriptInfraService.java
@@ -24,4 +24,16 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
 public interface ChatScriptInfraService extends InfrastructureService {
 
     String serviceAddress();
+
+    default String botName() {
+        return "Harry";
+    }
+
+    default String endpointUri() {
+        return String.format("chatscript:%s/%s", serviceAddress(), botName());
+    }
+
+    default String connectionBase() {
+        return String.format("chatscript:%s", serviceAddress());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseInfraService.java
 
b/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseInfraService.java
index bb734e333def..b09cd51b5ba0 100644
--- 
a/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseInfraService.java
+++ 
b/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseInfraService.java
@@ -54,4 +54,13 @@ public interface CouchbaseInfraService extends 
InfrastructureService {
     String viewName();
 
     String designDocumentName();
+
+    default String endpointUri() {
+        return 
String.format("couchbase:%s://%s:%d/%s?username=%s&password=RAW(%s)", 
protocol(), hostname(), port(), bucket(),
+                username(), password());
+    }
+
+    default String connectionBase() {
+        return String.format("couchbase:%s://%s:%d", protocol(), hostname(), 
port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbInfraService.java
 
b/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbInfraService.java
index ee8ae667dbce..f9de00a66b59 100644
--- 
a/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbInfraService.java
+++ 
b/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbInfraService.java
@@ -27,7 +27,20 @@ public interface CouchDbInfraService extends 
InfrastructureService {
 
     int port();
 
+    @Deprecated
     default String getServiceAddress() {
         return String.format("%s:%d", host(), port());
     }
+
+    default String database() {
+        return "testdb";
+    }
+
+    default String endpointUri() {
+        return String.format("couchdb:http:%s:%d/%s", host(), port(), 
database());
+    }
+
+    default String connectionBase() {
+        return String.format("couchdb:http:%s:%d", host(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-docling/src/main/java/org/apache/camel/test/infra/docling/services/DoclingInfraService.java
 
b/test-infra/camel-test-infra-docling/src/main/java/org/apache/camel/test/infra/docling/services/DoclingInfraService.java
index 45b03ec8b3ea..f1aac5c02add 100644
--- 
a/test-infra/camel-test-infra-docling/src/main/java/org/apache/camel/test/infra/docling/services/DoclingInfraService.java
+++ 
b/test-infra/camel-test-infra-docling/src/main/java/org/apache/camel/test/infra/docling/services/DoclingInfraService.java
@@ -24,4 +24,8 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
 public interface DoclingInfraService extends InfrastructureService {
 
     String doclingServerUrl();
+
+    default String doclingServeUrl() {
+        return doclingServerUrl();
+    }
 }
diff --git 
a/test-infra/camel-test-infra-elasticsearch/src/main/java/org/apache/camel/test/infra/elasticsearch/services/ElasticSearchInfraService.java
 
b/test-infra/camel-test-infra-elasticsearch/src/main/java/org/apache/camel/test/infra/elasticsearch/services/ElasticSearchInfraService.java
index afcee5a9e1e1..8e04d75b273a 100644
--- 
a/test-infra/camel-test-infra-elasticsearch/src/main/java/org/apache/camel/test/infra/elasticsearch/services/ElasticSearchInfraService.java
+++ 
b/test-infra/camel-test-infra-elasticsearch/src/main/java/org/apache/camel/test/infra/elasticsearch/services/ElasticSearchInfraService.java
@@ -25,10 +25,13 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
 
 public interface ElasticSearchInfraService extends InfrastructureService {
 
+    @Deprecated
     int getPort();
 
+    @Deprecated
     String getElasticSearchHost();
 
+    @Deprecated
     default String getHttpHostAddress() {
         return String.format("%s:%d", getElasticSearchHost(), getPort());
     }
@@ -40,4 +43,16 @@ public interface ElasticSearchInfraService extends 
InfrastructureService {
     String getUsername();
 
     String getPassword();
+
+    default String hostAddresses() {
+        return getHttpHostAddress();
+    }
+
+    default String user() {
+        return getUsername();
+    }
+
+    default String password() {
+        return getPassword();
+    }
 }
diff --git 
a/test-infra/camel-test-infra-fhir/src/main/java/org/apache/camel/test/infra/fhir/services/FhirInfraService.java
 
b/test-infra/camel-test-infra-fhir/src/main/java/org/apache/camel/test/infra/fhir/services/FhirInfraService.java
index 8f62b4245e2a..d8230016834b 100644
--- 
a/test-infra/camel-test-infra-fhir/src/main/java/org/apache/camel/test/infra/fhir/services/FhirInfraService.java
+++ 
b/test-infra/camel-test-infra-fhir/src/main/java/org/apache/camel/test/infra/fhir/services/FhirInfraService.java
@@ -23,9 +23,16 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
  */
 public interface FhirInfraService extends InfrastructureService {
 
+    @Deprecated
     String getServiceBaseURL();
 
+    @Deprecated
     String getHost();
 
+    @Deprecated
     Integer getPort();
+
+    default String serverUrl() {
+        return getServiceBaseURL();
+    }
 }
diff --git 
a/test-infra/camel-test-infra-ftp/src/main/java/org/apache/camel/test/infra/ftp/services/FtpInfraService.java
 
b/test-infra/camel-test-infra-ftp/src/main/java/org/apache/camel/test/infra/ftp/services/FtpInfraService.java
index 9b1a505c8e1b..95470f466c9b 100644
--- 
a/test-infra/camel-test-infra-ftp/src/main/java/org/apache/camel/test/infra/ftp/services/FtpInfraService.java
+++ 
b/test-infra/camel-test-infra-ftp/src/main/java/org/apache/camel/test/infra/ftp/services/FtpInfraService.java
@@ -71,4 +71,13 @@ public interface FtpInfraService extends 
InfrastructureService {
     default String knownHostsEntry() {
         return null;
     }
+
+    default String endpointUri() {
+        return String.format("ftp:%s:%d/%s?username=%s&password=RAW(%s)", 
host(), port(), directoryName(), username(),
+                password());
+    }
+
+    default String connectionBase() {
+        return String.format("ftp:%s:%d", host(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-google-pubsub/src/main/java/org/apache/camel/test/infra/google/pubsub/services/GooglePubSubInfraService.java
 
b/test-infra/camel-test-infra-google-pubsub/src/main/java/org/apache/camel/test/infra/google/pubsub/services/GooglePubSubInfraService.java
index a978569aeefb..ce61df3e2db9 100644
--- 
a/test-infra/camel-test-infra-google-pubsub/src/main/java/org/apache/camel/test/infra/google/pubsub/services/GooglePubSubInfraService.java
+++ 
b/test-infra/camel-test-infra-google-pubsub/src/main/java/org/apache/camel/test/infra/google/pubsub/services/GooglePubSubInfraService.java
@@ -23,5 +23,14 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
  */
 public interface GooglePubSubInfraService extends InfrastructureService {
 
+    @Deprecated
     String getServiceAddress();
+
+    default String endpoint() {
+        return getServiceAddress();
+    }
+
+    default boolean authenticate() {
+        return false;
+    }
 }
diff --git 
a/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultInfraService.java
 
b/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultInfraService.java
index 5dbb39e3f8f6..bb83f4db7f3b 100644
--- 
a/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultInfraService.java
+++ 
b/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultInfraService.java
@@ -28,4 +28,8 @@ public interface HashicorpVaultInfraService extends 
InfrastructureService {
     int port();
 
     String host();
+
+    default String scheme() {
+        return "http";
+    }
 }
diff --git 
a/test-infra/camel-test-infra-hazelcast/src/main/java/org/apache/camel/test/infra/hazelcast/services/HazelcastInfraService.java
 
b/test-infra/camel-test-infra-hazelcast/src/main/java/org/apache/camel/test/infra/hazelcast/services/HazelcastInfraService.java
index b575e26909ca..dd9798dad144 100644
--- 
a/test-infra/camel-test-infra-hazelcast/src/main/java/org/apache/camel/test/infra/hazelcast/services/HazelcastInfraService.java
+++ 
b/test-infra/camel-test-infra-hazelcast/src/main/java/org/apache/camel/test/infra/hazelcast/services/HazelcastInfraService.java
@@ -25,4 +25,12 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
 public interface HazelcastInfraService extends InfrastructureService {
 
     Config createConfiguration(String name, int port, String instanceName, 
String componentName);
+
+    default String endpointUri() {
+        return "hazelcast-map:default";
+    }
+
+    default String hazelcastInstanceName() {
+        return "camel-hazelcast";
+    }
 }
diff --git 
a/test-infra/camel-test-infra-hivemq/src/main/java/org/apache/camel/test/infra/hivemq/services/HiveMQInfraService.java
 
b/test-infra/camel-test-infra-hivemq/src/main/java/org/apache/camel/test/infra/hivemq/services/HiveMQInfraService.java
index e03c106ce5f5..9d98485ecbc7 100644
--- 
a/test-infra/camel-test-infra-hivemq/src/main/java/org/apache/camel/test/infra/hivemq/services/HiveMQInfraService.java
+++ 
b/test-infra/camel-test-infra-hivemq/src/main/java/org/apache/camel/test/infra/hivemq/services/HiveMQInfraService.java
@@ -20,17 +20,34 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
 
 public interface HiveMQInfraService extends InfrastructureService {
 
+    @Deprecated
     int getMqttPort();
 
+    @Deprecated
     String getMqttHost();
 
     boolean isRunning();
 
+    @Deprecated
     String getUserName();
 
+    @Deprecated
     char[] getUserPassword();
 
+    @Deprecated
     default String getMqttHostAddress() {
         return String.format("tcp://%s:%d", getMqttHost(), getMqttPort());
     }
+
+    default String brokerUrl() {
+        return getMqttHostAddress();
+    }
+
+    default String userName() {
+        return getUserName();
+    }
+
+    default String password() {
+        return getUserPassword() != null ? new String(getUserPassword()) : 
null;
+    }
 }
diff --git 
a/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQInfraService.java
 
b/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQInfraService.java
index 82472f2f83a9..0d668c697ee6 100644
--- 
a/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQInfraService.java
+++ 
b/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQInfraService.java
@@ -28,4 +28,24 @@ public interface IbmMQInfraService extends 
InfrastructureService {
     String queueManager();
 
     int listenerPort();
+
+    default String host() {
+        return "localhost";
+    }
+
+    default int port() {
+        return listenerPort();
+    }
+
+    default String username() {
+        return "app";
+    }
+
+    default String password() {
+        return "";
+    }
+
+    default String brokerUrl() {
+        return String.format("amqp://%s:%d", host(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanInfraService.java
 
b/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanInfraService.java
index 711cc160b6e6..87124267fe75 100644
--- 
a/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanInfraService.java
+++ 
b/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanInfraService.java
@@ -31,5 +31,10 @@ public interface InfinispanInfraService extends 
InfrastructureService {
 
     String host();
 
+    @Deprecated
     String getServiceAddress();
+
+    default String hosts() {
+        return String.format("%s:%d", host(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakInfraService.java
 
b/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakInfraService.java
index 3dc8d05e41d7..3108955e5fd6 100644
--- 
a/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakInfraService.java
+++ 
b/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakInfraService.java
@@ -24,12 +24,16 @@ import org.keycloak.admin.client.Keycloak;
  */
 public interface KeycloakInfraService extends InfrastructureService {
 
+    @Deprecated
     String getKeycloakServerUrl();
 
+    @Deprecated
     String getKeycloakRealm();
 
+    @Deprecated
     String getKeycloakUsername();
 
+    @Deprecated
     String getKeycloakPassword();
 
     /**
@@ -38,4 +42,20 @@ public interface KeycloakInfraService extends 
InfrastructureService {
      * @return Keycloak admin client instance
      */
     Keycloak getKeycloakAdminClient();
+
+    default String serverUrl() {
+        return getKeycloakServerUrl();
+    }
+
+    default String realm() {
+        return getKeycloakRealm();
+    }
+
+    default String username() {
+        return getKeycloakUsername();
+    }
+
+    default String password() {
+        return getKeycloakPassword();
+    }
 }
diff --git 
a/test-infra/camel-test-infra-microprofile-lra/src/main/java/org/apache/camel/test/infra/microprofile/lra/services/MicroprofileLRAInfraService.java
 
b/test-infra/camel-test-infra-microprofile-lra/src/main/java/org/apache/camel/test/infra/microprofile/lra/services/MicroprofileLRAInfraService.java
index 70a748d4f4ed..10d6670bcc6f 100644
--- 
a/test-infra/camel-test-infra-microprofile-lra/src/main/java/org/apache/camel/test/infra/microprofile/lra/services/MicroprofileLRAInfraService.java
+++ 
b/test-infra/camel-test-infra-microprofile-lra/src/main/java/org/apache/camel/test/infra/microprofile/lra/services/MicroprofileLRAInfraService.java
@@ -32,4 +32,12 @@ public interface MicroprofileLRAInfraService extends 
InfrastructureService {
     default String getServiceAddress() {
         return String.format("http://%s:%d";, host(), port());
     }
+
+    default String endpointUri() {
+        return String.format("http:%s:%d/lra-coordinator/start", host(), 
port());
+    }
+
+    default String coordinatorUrl() {
+        return String.format("http://%s:%d/lra-coordinator";, host(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-milvus/src/main/java/org/apache/camel/test/infra/milvus/services/MilvusInfraService.java
 
b/test-infra/camel-test-infra-milvus/src/main/java/org/apache/camel/test/infra/milvus/services/MilvusInfraService.java
index 3b375ee8280d..a248df86070e 100644
--- 
a/test-infra/camel-test-infra-milvus/src/main/java/org/apache/camel/test/infra/milvus/services/MilvusInfraService.java
+++ 
b/test-infra/camel-test-infra-milvus/src/main/java/org/apache/camel/test/infra/milvus/services/MilvusInfraService.java
@@ -38,4 +38,12 @@ public interface MilvusInfraService extends 
InfrastructureService {
     String host();
 
     int port();
+
+    default String collection() {
+        return "testcollection";
+    }
+
+    default String token() {
+        return "";
+    }
 }
diff --git 
a/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioInfraService.java
 
b/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioInfraService.java
index 751f991edea4..2594ae1c475d 100644
--- 
a/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioInfraService.java
+++ 
b/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioInfraService.java
@@ -36,4 +36,8 @@ public interface MinioInfraService extends 
InfrastructureService {
     String consoleUsername();
 
     String consolePassword();
+
+    default String endpoint() {
+        return String.format("http://%s:%d";, host(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBInfraService.java
 
b/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBInfraService.java
index 2317e486cfa5..392eaa2784aa 100644
--- 
a/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBInfraService.java
+++ 
b/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBInfraService.java
@@ -26,6 +26,7 @@ public interface MongoDBInfraService extends 
InfrastructureService {
      *
      * @return the replica set URL
      */
+    @Deprecated
     String getReplicaSetUrl();
 
     /**
@@ -33,5 +34,10 @@ public interface MongoDBInfraService extends 
InfrastructureService {
      *
      * @return the connection address
      */
+    @Deprecated
     String getConnectionAddress();
+
+    default String hosts() {
+        return getConnectionAddress();
+    }
 }
diff --git 
a/test-infra/camel-test-infra-mosquitto/src/main/java/org/apache/camel/test/infra/mosquitto/services/MosquittoInfraService.java
 
b/test-infra/camel-test-infra-mosquitto/src/main/java/org/apache/camel/test/infra/mosquitto/services/MosquittoInfraService.java
index e160abfbdde0..c6051e00e5fa 100644
--- 
a/test-infra/camel-test-infra-mosquitto/src/main/java/org/apache/camel/test/infra/mosquitto/services/MosquittoInfraService.java
+++ 
b/test-infra/camel-test-infra-mosquitto/src/main/java/org/apache/camel/test/infra/mosquitto/services/MosquittoInfraService.java
@@ -23,5 +23,18 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
  */
 public interface MosquittoInfraService extends InfrastructureService {
 
+    @Deprecated
     Integer getPort();
+
+    default String host() {
+        return "localhost";
+    }
+
+    default int port() {
+        return getPort();
+    }
+
+    default String brokerUrl() {
+        return String.format("tcp://%s:%d", host(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-nats/src/main/java/org/apache/camel/test/infra/nats/services/NatsInfraService.java
 
b/test-infra/camel-test-infra-nats/src/main/java/org/apache/camel/test/infra/nats/services/NatsInfraService.java
index 5fbea42615c5..e6a70c650c8e 100644
--- 
a/test-infra/camel-test-infra-nats/src/main/java/org/apache/camel/test/infra/nats/services/NatsInfraService.java
+++ 
b/test-infra/camel-test-infra-nats/src/main/java/org/apache/camel/test/infra/nats/services/NatsInfraService.java
@@ -23,5 +23,10 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
  */
 public interface NatsInfraService extends InfrastructureService {
 
+    @Deprecated
     String getServiceAddress();
+
+    default String servers() {
+        return getServiceAddress();
+    }
 }
diff --git 
a/test-infra/camel-test-infra-ollama/src/main/java/org/apache/camel/test/infra/ollama/services/OllamaInfraService.java
 
b/test-infra/camel-test-infra-ollama/src/main/java/org/apache/camel/test/infra/ollama/services/OllamaInfraService.java
index 707149879e82..d3933b2bd1e2 100644
--- 
a/test-infra/camel-test-infra-ollama/src/main/java/org/apache/camel/test/infra/ollama/services/OllamaInfraService.java
+++ 
b/test-infra/camel-test-infra-ollama/src/main/java/org/apache/camel/test/infra/ollama/services/OllamaInfraService.java
@@ -33,4 +33,39 @@ public interface OllamaInfraService extends 
InfrastructureService {
     String baseUrlV1();
 
     String apiKey();
+
+    default String host() {
+        // Extract host from baseUrl (e.g., "http://localhost:11434"; -> 
"localhost")
+        String url = baseUrl();
+        if (url != null) {
+            url = url.replace("http://";, "").replace("https://";, "");
+            int colonIdx = url.indexOf(':');
+            if (colonIdx > 0) {
+                return url.substring(0, colonIdx);
+            }
+            return url;
+        }
+        return "localhost";
+    }
+
+    default int port() {
+        // Extract port from baseUrl (e.g., "http://localhost:11434"; -> 11434)
+        String url = baseUrl();
+        if (url != null) {
+            url = url.replace("http://";, "").replace("https://";, "");
+            int colonIdx = url.indexOf(':');
+            if (colonIdx > 0) {
+                try {
+                    return Integer.parseInt(url.substring(colonIdx + 1));
+                } catch (NumberFormatException e) {
+                    // Fall through to default
+                }
+            }
+        }
+        return 11434;
+    }
+
+    default String endpointUri() {
+        return String.format("http:%s:%d/api/generate", host(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-openldap/src/main/java/org/apache/camel/test/infra/openldap/services/OpenldapInfraService.java
 
b/test-infra/camel-test-infra-openldap/src/main/java/org/apache/camel/test/infra/openldap/services/OpenldapInfraService.java
index aa0314e2b1ef..aa0ac6ea44be 100644
--- 
a/test-infra/camel-test-infra-openldap/src/main/java/org/apache/camel/test/infra/openldap/services/OpenldapInfraService.java
+++ 
b/test-infra/camel-test-infra-openldap/src/main/java/org/apache/camel/test/infra/openldap/services/OpenldapInfraService.java
@@ -16,6 +16,9 @@
  */
 package org.apache.camel.test.infra.openldap.services;
 
+import java.util.LinkedHashMap;
+import java.util.Map;
+
 import org.apache.camel.test.infra.common.services.InfrastructureService;
 
 /**
@@ -23,9 +26,44 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
  */
 public interface OpenldapInfraService extends InfrastructureService {
 
+    @Deprecated
     Integer getPort();
 
+    @Deprecated
     Integer getSslPort();
 
+    @Deprecated
     String getHost();
+
+    default String host() {
+        return getHost();
+    }
+
+    default int port() {
+        return getPort();
+    }
+
+    default int sslPort() {
+        return getSslPort();
+    }
+
+    default String ldapUrl() {
+        return String.format("ldap://%s:%d";, host(), port());
+    }
+
+    default String ldapContextFactory() {
+        return "com.sun.jndi.ldap.LdapCtxFactory";
+    }
+
+    default String endpointUri() {
+        return "ldap:ldapEnv";
+    }
+
+    default Map<String, String> beanProperties() {
+        Map<String, String> properties = new LinkedHashMap<>();
+        properties.put("camel.beans.ldapEnv", "#class:java.util.Hashtable");
+        properties.put("camel.beans.ldapEnv[java.naming.factory.initial]", 
ldapContextFactory());
+        properties.put("camel.beans.ldapEnv[java.naming.provider.url]", 
ldapUrl());
+        return properties;
+    }
 }
diff --git 
a/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresInfraService.java
 
b/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresInfraService.java
index 01ef149e98f1..4d6b5a313874 100644
--- 
a/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresInfraService.java
+++ 
b/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresInfraService.java
@@ -16,6 +16,9 @@
  */
 package org.apache.camel.test.infra.postgres.services;
 
+import java.util.LinkedHashMap;
+import java.util.Map;
+
 import org.apache.camel.test.infra.common.services.InfrastructureService;
 
 /**
@@ -32,4 +35,33 @@ public interface PostgresInfraService extends 
InfrastructureService {
     String password();
 
     String getServiceAddress();
+
+    default String database() {
+        return "postgres";
+    }
+
+    default String jdbcUrl() {
+        return String.format("jdbc:postgresql://%s:%d/%s", host(), port(), 
database());
+    }
+
+    default String jdbcDriver() {
+        return "org.postgresql.Driver";
+    }
+
+    default String username() {
+        return userName();
+    }
+
+    default String endpointUri() {
+        return "sql:SELECT 1?dataSource=#postgresDS";
+    }
+
+    default Map<String, String> beanProperties() {
+        Map<String, String> properties = new LinkedHashMap<>();
+        properties.put("camel.beans.postgresDS", 
"#class:org.postgresql.ds.PGSimpleDataSource");
+        properties.put("camel.beans.postgresDS.url", jdbcUrl());
+        properties.put("camel.beans.postgresDS.user", username());
+        properties.put("camel.beans.postgresDS.password", password());
+        return properties;
+    }
 }
diff --git 
a/test-infra/camel-test-infra-pulsar/src/main/java/org/apache/camel/test/infra/pulsar/services/PulsarInfraService.java
 
b/test-infra/camel-test-infra-pulsar/src/main/java/org/apache/camel/test/infra/pulsar/services/PulsarInfraService.java
index b5d54886a2bb..34ced80cb28e 100644
--- 
a/test-infra/camel-test-infra-pulsar/src/main/java/org/apache/camel/test/infra/pulsar/services/PulsarInfraService.java
+++ 
b/test-infra/camel-test-infra-pulsar/src/main/java/org/apache/camel/test/infra/pulsar/services/PulsarInfraService.java
@@ -23,7 +23,17 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
  */
 public interface PulsarInfraService extends InfrastructureService {
 
+    @Deprecated
     String getPulsarAdminUrl();
 
+    @Deprecated
     String getPulsarBrokerUrl();
+
+    default String serviceUrl() {
+        return getPulsarBrokerUrl();
+    }
+
+    default String adminUrl() {
+        return getPulsarAdminUrl();
+    }
 }
diff --git 
a/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantInfraService.java
 
b/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantInfraService.java
index 4bb872b371d4..4bfe745236bc 100644
--- 
a/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantInfraService.java
+++ 
b/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantInfraService.java
@@ -44,6 +44,14 @@ public interface QdrantInfraService extends 
InfrastructureService {
 
     int port();
 
+    default String collection() {
+        return "testcollection";
+    }
+
+    default String apiKey() {
+        return "";
+    }
+
     default HttpResponse<byte[]> put(String path, Map<Object, Object> body) 
throws Exception {
         final String reqPath = !path.startsWith("/") ? "/" + path : path;
         final String reqUrl = String.format("http://%s:%d%s";, getHttpHost(), 
getHttpPort(), reqPath);
diff --git 
a/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQInfraService.java
 
b/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQInfraService.java
index 43783f50634b..8c3682211964 100644
--- 
a/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQInfraService.java
+++ 
b/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQInfraService.java
@@ -65,4 +65,28 @@ public interface RabbitMQInfraService extends 
InfrastructureService {
     String managementPassword();
 
     String managementUri();
+
+    default String hostname() {
+        return connectionProperties().hostname();
+    }
+
+    default int port() {
+        return connectionProperties().port();
+    }
+
+    default String username() {
+        return connectionProperties().username();
+    }
+
+    default String password() {
+        return connectionProperties().password();
+    }
+
+    default String host() {
+        return connectionProperties().hostname();
+    }
+
+    default String brokerUrl() {
+        return String.format("amqp://%s:%d", hostname(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisInfraService.java
 
b/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisInfraService.java
index 196320b0f680..0d7635248d90 100644
--- 
a/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisInfraService.java
+++ 
b/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisInfraService.java
@@ -27,7 +27,12 @@ public interface RedisInfraService extends 
InfrastructureService {
 
     int port();
 
+    @Deprecated
     default String getServiceAddress() {
         return String.format("%s:%d", host(), port());
     }
+
+    default String endpointUri() {
+        return String.format("spring-redis:%s:%d", host(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-rocketmq/src/main/java/org/apache/camel/test/infra/rocketmq/services/RocketMQInfraService.java
 
b/test-infra/camel-test-infra-rocketmq/src/main/java/org/apache/camel/test/infra/rocketmq/services/RocketMQInfraService.java
index 87a1b584ba95..198efd15e518 100644
--- 
a/test-infra/camel-test-infra-rocketmq/src/main/java/org/apache/camel/test/infra/rocketmq/services/RocketMQInfraService.java
+++ 
b/test-infra/camel-test-infra-rocketmq/src/main/java/org/apache/camel/test/infra/rocketmq/services/RocketMQInfraService.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 import org.apache.camel.test.infra.common.services.InfrastructureService;
 
 public interface RocketMQInfraService extends InfrastructureService {
+    @Deprecated
     String nameserverAddress();
 
     default String defaultCluster() {
@@ -31,4 +32,7 @@ public interface RocketMQInfraService extends 
InfrastructureService {
 
     void deleteTopic(String topic) throws IOException, InterruptedException;
 
+    default String namesrvAddr() {
+        return nameserverAddress();
+    }
 }
diff --git 
a/test-infra/camel-test-infra-smb/src/main/java/org/apache/camel/test/infra/smb/services/SmbInfraService.java
 
b/test-infra/camel-test-infra-smb/src/main/java/org/apache/camel/test/infra/smb/services/SmbInfraService.java
index 899c0a21adeb..bd8f752ca1cc 100644
--- 
a/test-infra/camel-test-infra-smb/src/main/java/org/apache/camel/test/infra/smb/services/SmbInfraService.java
+++ 
b/test-infra/camel-test-infra-smb/src/main/java/org/apache/camel/test/infra/smb/services/SmbInfraService.java
@@ -24,9 +24,39 @@ public interface SmbInfraService extends 
InfrastructureService {
 
     String shareName();
 
+    @Deprecated
     String userName();
 
     String password();
 
     String smbFile(String file);
+
+    default String hostname() {
+        String addr = address();
+        if (addr != null && addr.contains(":")) {
+            return addr.substring(0, addr.indexOf(':'));
+        }
+        return addr;
+    }
+
+    default int port() {
+        String addr = address();
+        if (addr != null && addr.contains(":")) {
+            return Integer.parseInt(addr.substring(addr.indexOf(':') + 1));
+        }
+        return 445; // default SMB port
+    }
+
+    default String username() {
+        return userName();
+    }
+
+    default String endpointUri() {
+        return String.format("smb:%s:%d/%s?username=%s&password=RAW(%s)", 
hostname(), port(), shareName(), username(),
+                password());
+    }
+
+    default String connectionBase() {
+        return String.format("smb:%s:%d", hostname(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrInfraService.java
 
b/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrInfraService.java
index 6f8f4d7e69af..5f5d8c79b42c 100644
--- 
a/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrInfraService.java
+++ 
b/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrInfraService.java
@@ -21,12 +21,22 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
 
 public interface SolrInfraService extends InfrastructureService {
 
+    @Deprecated
     int getPort();
 
+    @Deprecated
     String getSolrHost();
 
+    @Deprecated
     default String getHttpHostAddress() {
         return String.format("%s:%d", getSolrHost(), getPort());
     }
 
+    default String host() {
+        return getSolrHost();
+    }
+
+    default int port() {
+        return getPort();
+    }
 }
diff --git 
a/test-infra/camel-test-infra-torchserve/src/main/java/org/apache/camel/test/infra/torchserve/services/TorchServeInfraService.java
 
b/test-infra/camel-test-infra-torchserve/src/main/java/org/apache/camel/test/infra/torchserve/services/TorchServeInfraService.java
index 6ab7640fab5d..ca7b2a77e603 100644
--- 
a/test-infra/camel-test-infra-torchserve/src/main/java/org/apache/camel/test/infra/torchserve/services/TorchServeInfraService.java
+++ 
b/test-infra/camel-test-infra-torchserve/src/main/java/org/apache/camel/test/infra/torchserve/services/TorchServeInfraService.java
@@ -25,4 +25,16 @@ public interface TorchServeInfraService extends 
InfrastructureService {
     int managementPort();
 
     int metricsPort();
+
+    default String host() {
+        return "localhost";
+    }
+
+    default String inferenceAddress() {
+        return host();
+    }
+
+    default String managementAddress() {
+        return host();
+    }
 }
diff --git 
a/test-infra/camel-test-infra-torchserve/src/main/java/org/apache/camel/test/infra/torchserve/services/TorchServeLocalContainerInfraService.java
 
b/test-infra/camel-test-infra-torchserve/src/main/java/org/apache/camel/test/infra/torchserve/services/TorchServeLocalContainerInfraService.java
index 9996916d00f0..7c9b9c738f43 100644
--- 
a/test-infra/camel-test-infra-torchserve/src/main/java/org/apache/camel/test/infra/torchserve/services/TorchServeLocalContainerInfraService.java
+++ 
b/test-infra/camel-test-infra-torchserve/src/main/java/org/apache/camel/test/infra/torchserve/services/TorchServeLocalContainerInfraService.java
@@ -125,4 +125,9 @@ public class TorchServeLocalContainerInfraService 
implements TorchServeInfraServ
     public int metricsPort() {
         return container.getMappedPort(METRICS_PORT);
     }
+
+    @Override
+    public String host() {
+        return container.getHost();
+    }
 }
diff --git 
a/test-infra/camel-test-infra-xmpp/src/main/java/org/apache/camel/test/infra/xmpp/services/XmppInfraService.java
 
b/test-infra/camel-test-infra-xmpp/src/main/java/org/apache/camel/test/infra/xmpp/services/XmppInfraService.java
index e50863c742ec..f5eedc2e24bd 100644
--- 
a/test-infra/camel-test-infra-xmpp/src/main/java/org/apache/camel/test/infra/xmpp/services/XmppInfraService.java
+++ 
b/test-infra/camel-test-infra-xmpp/src/main/java/org/apache/camel/test/infra/xmpp/services/XmppInfraService.java
@@ -26,5 +26,10 @@ public interface XmppInfraService extends 
InfrastructureService {
 
     int port();
 
+    @Deprecated
     String getUrl();
+
+    default String endpointUri() {
+        return String.format("xmpp:%s:%d", host(), port());
+    }
 }
diff --git 
a/test-infra/camel-test-infra-zookeeper/src/main/java/org/apache/camel/test/infra/zookeeper/services/ZooKeeperInfraService.java
 
b/test-infra/camel-test-infra-zookeeper/src/main/java/org/apache/camel/test/infra/zookeeper/services/ZooKeeperInfraService.java
index e2b6a87ebff0..994d3f0ff5b6 100644
--- 
a/test-infra/camel-test-infra-zookeeper/src/main/java/org/apache/camel/test/infra/zookeeper/services/ZooKeeperInfraService.java
+++ 
b/test-infra/camel-test-infra-zookeeper/src/main/java/org/apache/camel/test/infra/zookeeper/services/ZooKeeperInfraService.java
@@ -22,5 +22,18 @@ import 
org.apache.camel.test.infra.common.services.InfrastructureService;
  * Test infra service for ZooKeeper
  */
 public interface ZooKeeperInfraService extends InfrastructureService {
+    @Deprecated
     String getConnectionString();
+
+    default String serverUrls() {
+        return getConnectionString();
+    }
+
+    default String endpointUri() {
+        return String.format("zookeeper:%s/camel", serverUrls());
+    }
+
+    default String connectionBase() {
+        return String.format("zookeeper:%s", serverUrls());
+    }
 }


Reply via email to