This is an automated email from the ASF dual-hosted git repository.
davsclaus 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 d5d8c41a3caa CAMEL-24054: Add POST support to dev consoles and
variables to eval-language
d5d8c41a3caa is described below
commit d5d8c41a3caa349653c1d9123ae410f80157abe0
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Jul 13 21:43:52 2026 +0200
CAMEL-24054: Add POST support to dev consoles and variables to eval-language
Add HTTP POST support to all dev console endpoints (/q/dev/*) in
ManagementHttpServer, allowing parameters to be sent as a JSON request
body instead of query parameters to avoid URL length limits. Add exchange
variables support to EvalLanguageDevConsole and a --variable CLI option
to camel cmd expression. Pass variables through file-based IPC in
LocalCliConnector.
Closes #24667
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
.../camel/catalog/dev-consoles/eval-language.json | 14 +++
.../src/main/docs/platform-http-main.adoc | 2 +-
.../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 +++++++++++++++++++++
.../modules/ROOT/pages/camel-console.adoc | 23 +++++
.../modules/ROOT/pages/camel-jbang-managing.adoc | 13 ++-
.../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 ++++
12 files changed, 236 insertions(+), 11 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/eval-language.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/eval-language.json
index 35c058585559..efcadb3915cf 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/eval-language.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/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/components/camel-platform-http-main/src/main/docs/platform-http-main.adoc
b/components/camel-platform-http-main/src/main/docs/platform-http-main.adoc
index 141c11e4da03..00af28ba61c7 100644
--- a/components/camel-platform-http-main/src/main/docs/platform-http-main.adoc
+++ b/components/camel-platform-http-main/src/main/docs/platform-http-main.adoc
@@ -35,7 +35,7 @@ These features are as follows:
- `/observe/health` - Health checks
- `/observe/jolokia` - To use Jolokia to expose JMX over HTTP REST
- `/observe/metrics` - To provide OTEL metrics in prometheus format
-- `/q/dev` - Developer console that provides a lot of statistics and
information
+- `/q/dev` - Developer console that provides a lot of statistics and
information (supports both GET and POST; POST accepts a JSON body)
- `/q/upload` - Uploading source files, to allow hot reloading.
- `/q/download` - Downloading source files, to allow inspecting
- `/q/send` - Sending messages to the Camel application via HTTP
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..6d9dfe93629c 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) {
+ params.putAll(jo);
+ }
+ } 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/camel-console.adoc
b/docs/user-manual/modules/ROOT/pages/camel-console.adoc
index df4b6e23ca50..7c3f17d04467 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-console.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-console.adoc
@@ -85,6 +85,29 @@ and have the console started and accessible from
`http://localhost:8080/q/dev`
$ camel run foo.yaml myapp.properties --console
----
+=== HTTP Access
+
+The dev console endpoints accept both HTTP GET and POST requests.
+
+With GET, parameters are passed as query parameters:
+
+[source,bash]
+----
+$ curl
"http://localhost:8080/q/dev/eval-language?language=simple&template=\$\{body\}&body=hello"
+----
+
+With POST, parameters can be sent as a JSON request body, which avoids URL
length limits
+and is more natural for complex or large payloads:
+
+[source,bash]
+----
+$ curl -X POST -H "Accept: application/json" -H "Content-Type:
application/json" \
+ -d '{"language":"simple","template":"${body}","body":"hello"}' \
+ http://localhost:8080/q/dev/eval-language
+----
+
+To receive JSON output, set the `Accept` header to `application/json`.
Otherwise, the console returns plain text.
+
== Writing Custom Dev Consoles
To write a custom console, you need to add `camel-console` as dependency, as
it comes with the
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
b/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
index 82de1651af4a..9bb2551d7c22 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
@@ -285,13 +285,24 @@ camel run hello.java --console
----
The console is accessible at http://localhost:8080/q/dev and provides insights
into routes,
-performance, and EIP-level metrics. It also supports JSON output for tooling:
+performance, and EIP-level metrics. The endpoints support both HTTP GET and
POST.
+
+GET with query parameters:
[source,bash]
----
curl -s -H "Accept: application/json" http://0.0.0.0:8080/q/dev/top/ | jq
----
+POST with a JSON body (avoids URL length limits for large payloads):
+
+[source,bash]
+----
+curl -s -X POST -H "Accept: application/json" -H "Content-Type:
application/json" \
+ -d '{"language":"simple","template":"${body}","body":"hello"}' \
+ http://0.0.0.0:8080/q/dev/eval-language | jq
+----
+
== Message history
*Available since Camel 4.17*
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 4fe345bf8c0d..b8886fe3b73e 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
@@ -1081,16 +1081,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 aad2e662ac5d..d207910f993c 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);