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

davsclaus pushed a commit to branch fix/CAMEL-24054
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 5d7562bd8b350e90acd82bbe661264be6f8d6958
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Jul 13 19:43:49 2026 +0200

    CAMEL-24054: Add POST support to dev consoles and variables to eval-language
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../platform/http/main/ManagementHttpServer.java   |  21 +++-
 .../apache/camel/dev-console/eval-language.json    |  14 +++
 .../camel/impl/console/EvalLanguageDevConsole.java |  11 +++
 .../impl/console/EvalLanguageDevConsoleTest.java   | 106 +++++++++++++++++++++
 .../camel-jbang-eval-expression.adoc               |   1 +
 .../camel/cli/connector/LocalCliConnector.java     |  22 ++++-
 .../META-INF/camel-jbang-commands-metadata.json    |   2 +-
 .../commands/action/EvalExpressionCommand.java     |  18 ++++
 8 files changed, 186 insertions(+), 9 deletions(-)

diff --git 
a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java
 
b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java
index df77e4904c15..7fd07e9a0acf 100644
--- 
a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java
+++ 
b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java
@@ -995,13 +995,15 @@ public class ManagementHttpServer extends ServiceSupport 
implements CamelContext
 
     protected void setupDevConsole() {
         Route dev = router.route("/q/dev");
-        dev.method(HttpMethod.GET);
+        dev.method(HttpMethod.GET).method(HttpMethod.POST);
         dev.produces("text/plain");
         dev.produces("application/json");
+        dev.handler(BodyHandler.create(false));
         Route devSub = router.route("/q/dev/*");
-        devSub.method(HttpMethod.GET);
+        devSub.method(HttpMethod.GET).method(HttpMethod.POST);
         devSub.produces("text/plain");
         devSub.produces("application/json");
+        devSub.handler(BodyHandler.create(false));
 
         Handler<RoutingContext> handler = new Handler<RoutingContext>() {
             @Override
@@ -1083,6 +1085,19 @@ public class ManagementHttpServer extends ServiceSupport 
implements CamelContext
                 } else {
                     Map<String, Object> params = new HashMap<>();
                     ctx.queryParams().forEach(params::put);
+                    if (ctx.request().method() == HttpMethod.POST) {
+                        String jsonBody = ctx.body() != null ? 
ctx.body().asString() : null;
+                        if (jsonBody != null && !jsonBody.isBlank()) {
+                            try {
+                                Object parsed = Jsoner.deserialize(jsonBody);
+                                if (parsed instanceof JsonObject jo) {
+                                    jo.forEach((k, v) -> params.put(k, v));
+                                }
+                            } catch (Exception e) {
+                                // ignore invalid JSON
+                            }
+                        }
+                    }
                     params.put(Exchange.HTTP_PATH, path);
                     StringBuilder sb = new StringBuilder();
                     JsonObject root = new JsonObject();
@@ -1127,7 +1142,7 @@ public class ManagementHttpServer extends ServiceSupport 
implements CamelContext
         dev.blockingHandler(handler);
         devSub.blockingHandler(handler);
 
-        platformHttpComponent.addHttpManagementEndpoint("/q/dev", "GET", null,
+        platformHttpComponent.addHttpManagementEndpoint("/q/dev", "GET,POST", 
null,
                 "text/plain,application/json", null);
     }
 
diff --git 
a/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/eval-language.json
 
b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/eval-language.json
index 35c058585559..efcadb3915cf 100644
--- 
a/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/eval-language.json
+++ 
b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/eval-language.json
@@ -83,6 +83,20 @@
       "autowired": false,
       "secret": false,
       "description": "Template to use for executing simple language function"
+    },
+    "variables": {
+      "index": 5,
+      "kind": "option",
+      "displayName": "Variables",
+      "group": "query",
+      "label": "query",
+      "required": false,
+      "type": "string",
+      "javaType": "java.lang.String",
+      "deprecated": false,
+      "autowired": false,
+      "secret": false,
+      "description": "Optional exchange variables"
     }
   }
 }
diff --git 
a/core/camel-console/src/main/java/org/apache/camel/impl/console/EvalLanguageDevConsole.java
 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/EvalLanguageDevConsole.java
index f14d13bca504..2eeea51acd74 100644
--- 
a/core/camel-console/src/main/java/org/apache/camel/impl/console/EvalLanguageDevConsole.java
+++ 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/EvalLanguageDevConsole.java
@@ -48,6 +48,9 @@ public class EvalLanguageDevConsole extends 
AbstractDevConsole {
     @Metadata(label = "query", description = "Optional message headers", 
javaType = "java.lang.String")
     public static final String HEADERS = "headers";
 
+    @Metadata(label = "query", description = "Optional exchange variables", 
javaType = "java.lang.String")
+    public static final String VARIABLES = "variables";
+
     public EvalLanguageDevConsole() {
         super("camel", "eval-language", "Evaluate Language", "Evaluate 
Language and display result");
     }
@@ -68,6 +71,10 @@ public class EvalLanguageDevConsole extends 
AbstractDevConsole {
             if (headers instanceof Map map) {
                 dummy.getMessage().setHeaders(map);
             }
+            var variables = options.get(VARIABLES);
+            if (variables instanceof Map map2) {
+                map2.forEach((k, v) -> dummy.setVariable(k.toString(), v));
+            }
 
             String out;
             boolean predicate = optionBoolean(options, PREDICATE, false);
@@ -101,6 +108,10 @@ public class EvalLanguageDevConsole extends 
AbstractDevConsole {
             if (headers instanceof Map map) {
                 dummy.getMessage().setHeaders(map);
             }
+            var variables = options.get(VARIABLES);
+            if (variables instanceof Map map2) {
+                map2.forEach((k, v) -> dummy.setVariable(k.toString(), v));
+            }
 
             Exception cause = null;
             String out = null;
diff --git 
a/core/camel-console/src/test/java/org/apache/camel/impl/console/EvalLanguageDevConsoleTest.java
 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/EvalLanguageDevConsoleTest.java
new file mode 100644
index 000000000000..59e16c302000
--- /dev/null
+++ 
b/core/camel-console/src/test/java/org/apache/camel/impl/console/EvalLanguageDevConsoleTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.impl.console;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class EvalLanguageDevConsoleTest extends AbstractDevConsoleTest {
+
+    @Test
+    public void testEvalWithBody() {
+        DevConsole con = assertConsoleExists("eval-language", "camel");
+
+        JsonObject out = callJson(con, Map.of(
+                "language", "simple",
+                "template", "${body}",
+                "body", "Hello World"));
+
+        Assertions.assertEquals("success", out.getString("status"));
+        Assertions.assertEquals("Hello World", out.getString("result"));
+    }
+
+    @Test
+    public void testEvalWithHeaders() {
+        DevConsole con = assertConsoleExists("eval-language", "camel");
+
+        Map<String, String> headers = new LinkedHashMap<>();
+        headers.put("myKey", "myValue");
+
+        JsonObject out = callJson(con, Map.of(
+                "language", "simple",
+                "template", "${header.myKey}",
+                "body", "",
+                "headers", headers));
+
+        Assertions.assertEquals("success", out.getString("status"));
+        Assertions.assertEquals("myValue", out.getString("result"));
+    }
+
+    @Test
+    public void testEvalWithVariables() {
+        DevConsole con = assertConsoleExists("eval-language", "camel");
+
+        Map<String, String> variables = new LinkedHashMap<>();
+        variables.put("foo", "bar");
+
+        JsonObject out = callJson(con, Map.of(
+                "language", "simple",
+                "template", "${variable.foo}",
+                "body", "",
+                "variables", variables));
+
+        Assertions.assertEquals("success", out.getString("status"));
+        Assertions.assertEquals("bar", out.getString("result"));
+    }
+
+    @Test
+    public void testEvalPredicate() {
+        DevConsole con = assertConsoleExists("eval-language", "camel");
+
+        JsonObject out = callJson(con, Map.of(
+                "language", "simple",
+                "template", "${body} == 'Hello'",
+                "body", "Hello",
+                "predicate", true));
+
+        Assertions.assertEquals("success", out.getString("status"));
+        Assertions.assertEquals("true", out.getString("result"));
+    }
+
+    @Test
+    public void testEvalWithBodyAndVariables() {
+        DevConsole con = assertConsoleExists("eval-language", "camel");
+
+        Map<String, String> variables = new LinkedHashMap<>();
+        variables.put("greeting", "Hi");
+
+        JsonObject out = callJson(con, Map.of(
+                "language", "simple",
+                "template", "${variable.greeting} ${body}",
+                "body", "World",
+                "variables", variables));
+
+        Assertions.assertEquals("success", out.getString("status"));
+        Assertions.assertEquals("Hi World", out.getString("result"));
+    }
+}
diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-eval-expression.adoc
 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-eval-expression.adoc
index fad65d52ced2..258ebdad7dc5 100644
--- 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-eval-expression.adoc
+++ 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-eval-expression.adoc
@@ -30,6 +30,7 @@ camel eval expression [options]
 | `--repo,--repos` | Additional maven repositories for download on-demand (Use 
commas to separate multiple repositories) |  | String
 | `--template` | The template to use for evaluating (prefix with file: to 
refer to loading template from file) |  | String
 | `--timeout` | Timeout in millis waiting for evaluation to be done | 10000 | 
long
+| `--variable` | Exchange variable (key=value) |  | List
 | `--watch` | Execute periodically and showing output fullscreen |  | boolean
 | `-h,--help` | Display the help and sub-commands |  | boolean
 |===
diff --git 
a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
 
b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
index eee6b7a0c13d..3e6985b8c941 100644
--- 
a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
+++ 
b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
@@ -1058,16 +1058,28 @@ public class LocalCliConnector extends ServiceSupport 
implements CliConnector, C
             boolean predicate = root.getBooleanOrDefault("predicate", false);
             String template = root.getStringOrDefault("template", "");
             String body = root.getStringOrDefault("body", "");
-            Map<String, String> map = new LinkedHashMap<>();
+            Map<String, String> headerMap = new LinkedHashMap<>();
             Collection<JsonObject> headers = root.getCollection("headers");
             if (headers != null) {
-                map = new LinkedHashMap<>();
                 for (JsonObject jo : headers) {
-                    map.put(jo.getString("key"), jo.getString("value"));
+                    headerMap.put(jo.getString("key"), jo.getString("value"));
                 }
             }
-            JsonObject json = (JsonObject) dc.call(DevConsole.MediaType.JSON,
-                    Map.of("language", lan, "predicate", predicate, 
"template", template, "body", body, "headers", map));
+            Map<String, String> variableMap = new LinkedHashMap<>();
+            Collection<JsonObject> variables = root.getCollection("variables");
+            if (variables != null) {
+                for (JsonObject jo : variables) {
+                    variableMap.put(jo.getString("key"), 
jo.getString("value"));
+                }
+            }
+            Map<String, Object> params = new HashMap<>();
+            params.put("language", lan);
+            params.put("predicate", predicate);
+            params.put("template", template);
+            params.put("body", body);
+            params.put("headers", headerMap);
+            params.put("variables", variableMap);
+            JsonObject json = (JsonObject) dc.call(DevConsole.MediaType.JSON, 
params);
             LOG.trace("Updating output file: {}", outputFile);
             IOHelper.writeText(json.toJson(), outputFile);
         } else {
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 092515439667..c3463703d766 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
@@ -12,7 +12,7 @@
     { "name": "dirty", "fullName": "dirty", "description": "Check if there are 
dirty files from previous Camel runs that did not terminate gracefully", 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.Dirty", 
"options": [ { "names": "--clean", "description": "Clean dirty files which are 
no longer in use", "defaultValue": "false", "javaType": "boolean", "type": 
"boolean" }, { "names": "-h,--help", "description": "Display the help and 
sub-commands", "javaType": "boolean", " [...]
     { "name": "doc", "fullName": "doc", "description": "Shows documentation 
for kamelet, component, and other Camel resources", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.catalog.CatalogDoc", "options": [ { 
"names": "--camel-version", "description": "To use a different Camel version 
than the default version", "javaType": "java.lang.String", "type": "string" }, 
{ "names": "--download", "description": "Whether to allow automatic downloading 
JAR dependencies (over the internet [...]
     { "name": "doctor", "fullName": "doctor", "description": "Checks the 
environment and reports potential issues", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Doctor", "options": [ { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ] },
-    { "name": "eval", "fullName": "eval", "description": "Evaluate Camel 
expressions and scripts", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.EvalCommand", "options": [ { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ], "subcommands": [ { "name": "expression", 
"fullName": "eval expression", "description": "Evaluates Camel expression", 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.EvalEx [...]
+    { "name": "eval", "fullName": "eval", "description": "Evaluate Camel 
expressions and scripts", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.EvalCommand", "options": [ { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ], "subcommands": [ { "name": "expression", 
"fullName": "eval expression", "description": "Evaluates Camel expression", 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.EvalEx [...]
     { "name": "explain", "fullName": "explain", "description": "Explain what a 
Camel route does using AI\/LLM", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Explain", "options": [ { "names": 
"--api-key", "description": "API key for authentication. Also reads 
ANTHROPIC_API_KEY, OPENAI_API_KEY, or LLM_API_KEY env vars", "javaType": 
"java.lang.String", "type": "string" }, { "names": "--api-type", "description": 
"API type: 'ollama', 'openai' (OpenAI-compatible), or 'anthropic' (A [...]
     { "name": "export", "fullName": "export", "description": "Export to other 
runtimes (Camel Main, Spring Boot, or Quarkus)", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Export", "options": [ { "names": 
"--build-property", "description": "Maven build properties, ex. 
--build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, { 
"names": "--camel-spring-boot-version", "description": "Camel version to use 
with Spring Boot", "javaType": "java.lang.String", "ty [...]
     { "name": "get", "fullName": "get", "description": "Get status of Camel 
integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.CamelStatus", "options": [ { 
"names": "--watch", "description": "Execute periodically and showing output 
fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ], "subcommands": [ { "name": "activity", 
"fullName": " [...]
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/EvalExpressionCommand.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/EvalExpressionCommand.java
index dbbef4f163de..1501c278f966 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/EvalExpressionCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/EvalExpressionCommand.java
@@ -76,6 +76,10 @@ public class EvalExpressionCommand extends 
ActionWatchCommand {
                         description = "Message header (key=value)")
     List<String> headers;
 
+    @CommandLine.Option(names = { "--variable" },
+                        description = "Exchange variable (key=value)")
+    List<String> variables;
+
     @CommandLine.Option(names = { "--timeout" }, defaultValue = "10000",
                         description = "Timeout in millis waiting for 
evaluation to be done")
     long timeout = 10000;
@@ -165,6 +169,20 @@ public class EvalExpressionCommand extends 
ActionWatchCommand {
             }
             root.put("headers", arr);
         }
+        if (variables != null) {
+            JsonArray arr = new JsonArray();
+            for (String v : variables) {
+                JsonObject jo = new JsonObject();
+                if (!v.contains("=")) {
+                    printer().printErr("Variable must be in key=value format, 
was: " + v);
+                    return 1;
+                }
+                jo.put("key", StringHelper.before(v, "="));
+                jo.put("value", StringHelper.after(v, "="));
+                arr.add(jo);
+            }
+            root.put("variables", arr);
+        }
 
         Path outputFile = getOutputFile(Long.toString(pid));
         PathUtils.deleteFile(outputFile);

Reply via email to