From 925b09703846845f9c7948811d01661bb697bbf9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 10:11:13 +0000 Subject: [PATCH 1/5] Initial plan From 77559df9075b808f88a5ff58fcda79d25cff1ced Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 10:15:13 +0000 Subject: [PATCH 2/5] Add windowsHide configuration support with tests Co-authored-by: nvuillam <17500430+nvuillam@users.noreply.github.com> --- lib/cli.js | 11 +++++++++- lib/index.d.ts | 7 ++++++ lib/java-caller.js | 2 +- test/java-caller.test.js | 47 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/lib/cli.js b/lib/cli.js index 36ba000..1bdbd9d 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -26,7 +26,16 @@ class JavaCallerCli { const java = new JavaCaller(this.javaCallerOptions); const args = [...process.argv]; args.splice(0, 2); - const { status } = await java.run(args); + + // Parse --no-windows-hide flag + const runOptions = {}; + const noWindowsHideIndex = args.indexOf('--no-windows-hide'); + if (noWindowsHideIndex !== -1) { + runOptions.windowsHide = false; + args.splice(noWindowsHideIndex, 1); + } + + const { status } = await java.run(args, runOptions); process.exitCode = status; } } diff --git a/lib/index.d.ts b/lib/index.d.ts index 5d7714c..b57ee59 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -131,6 +131,13 @@ export interface JavaCallerRunOptions { * @default "SIGTERM" */ killSignal?: number | NodeJS.Signals; + + /** + * On Windows, hide the subprocess console window that would normally be created. + * This option is ignored on Unix. + * @default true + */ + windowsHide?: boolean; } /** diff --git a/lib/java-caller.js b/lib/java-caller.js index 1545ee6..97f79eb 100644 --- a/lib/java-caller.js +++ b/lib/java-caller.js @@ -115,7 +115,7 @@ class JavaCaller { cwd: javaExeToUse === "java" || javaExeToUse === "javaw" ? runOptions.cwd : undefined, env: Object.assign({}, process.env), stdio: this.output === "console" ? "inherit" : runOptions.detached ? "ignore" : "pipe", - windowsHide: true, + windowsHide: runOptions.windowsHide !== undefined ? runOptions.windowsHide : true, windowsVerbatimArguments: runOptions.windowsVerbatimArguments, }; if (javaExeToUse.includes(" ")) { diff --git a/test/java-caller.test.js b/test/java-caller.test.js index a1229a0..55199c2 100644 --- a/test/java-caller.test.js +++ b/test/java-caller.test.js @@ -58,6 +58,36 @@ describe("Call with classes", () => { checkStatus(0, status, stdout, stderr); }); + it("should call JavaCallerTester.class with windowsHide set to false", async () => { + const java = new JavaCaller({ + classPath: 'test/java/dist', + mainClass: 'com.nvuillam.javacaller.JavaCallerTester' + }); + const { status, stdout, stderr } = await java.run([], { windowsHide: false }); + checkStatus(0, status, stdout, stderr); + checkStdOutIncludes(`JavaCallerTester is called !`, stdout, stderr); + }); + + it("should call JavaCallerTester.class with windowsHide set to true (default)", async () => { + const java = new JavaCaller({ + classPath: 'test/java/dist', + mainClass: 'com.nvuillam.javacaller.JavaCallerTester' + }); + const { status, stdout, stderr } = await java.run([], { windowsHide: true }); + checkStatus(0, status, stdout, stderr); + checkStdOutIncludes(`JavaCallerTester is called !`, stdout, stderr); + }); + + it("should call JavaCallerTester.class with default windowsHide (should be true)", async () => { + const java = new JavaCaller({ + classPath: 'test/java/dist', + mainClass: 'com.nvuillam.javacaller.JavaCallerTester' + }); + const { status, stdout, stderr } = await java.run([]); + checkStatus(0, status, stdout, stderr); + checkStdOutIncludes(`JavaCallerTester is called !`, stdout, stderr); + }); + it("should call JavaCallerTester.class with proper stdout encoding", async () => { const java = new JavaCaller({ @@ -188,6 +218,23 @@ describe("Call with classes", () => { await javaCli.process(); }); + it("should use JavaCallerCli with --no-windows-hide flag", async () => { + // Save original argv + const originalArgv = process.argv; + + // Mock process.argv to include --no-windows-hide + process.argv = ['node', 'script.js', '--no-windows-hide']; + + try { + const javaCli = new JavaCallerCli("examples/cli_app/lib"); + await javaCli.process(); + checkStatus(0, process.exitCode); + } finally { + // Restore original argv + process.argv = originalArgv; + } + }); + it("Should work with an absolute path", async () => { const absolutePath = path.join(process.cwd(), "test/java/jar/JavaCallerTesterRunnable.jar"); From 9df3719e3f3ad86e2d1b4f146596cdaa201a6d96 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 10:16:09 +0000 Subject: [PATCH 3/5] Update README with windowsHide documentation and examples Co-authored-by: nvuillam <17500430+nvuillam@users.noreply.github.com> --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 9aa8c8c..f42d95f 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ Example: `["-Xms256m", "--someflagwithvalue myVal", "-c"]` | javaArgs | List of arguments for JVM only, not the JAR or the class | `[]` | `['--add-opens=java.base/java.lang=ALL-UNNAMED']` | | [windowsVerbatimArguments](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | No quoting or escaping of arguments is done on Windows. Ignored on Unix. This is set to true automatically when shell is specified and is CMD. | `true` | `false` | | [windowless](https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html#:~:text=main()%20method.-,javaw,information%20if%20a%20launch%20fails.) | If windowless is true, JavaCaller calls javaw instead of java to not create any windows, useful when using detached on Windows. Ignored on Unix. | false | true +| [windowsHide](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | On Windows, hide the subprocess console window that would normally be created. Set to `false` if you need Java UI dialogs to be visible (e.g., print dialogs). Ignored on Unix. | `true` | `false` | [timeout](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | In milliseconds the maximum amount of time the process is allowed to run. | `undefined` | `1000` | [killSignal](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | The signal value to be used when the spawned process will be killed by timeout or abort signal. | `SIGTERM` | `SIGINT` @@ -149,6 +150,23 @@ const java = new JavaCaller({ const { status, stdout, stderr } = await java.run(['--sleep'], { windowless: true }); ``` +Call java process with visible windows (e.g., for print dialogs) + +```javascript +const java = new JavaCaller({ + classPath: 'test/java/dist', + mainClass: 'com.nvuillam.javacaller.JavaCallerTester' +}); +// Set windowsHide to false to allow Java UI dialogs to be visible +const { status, stdout, stderr } = await java.run([], { windowsHide: false }); +``` + +When using CLI mode with `--no-windows-hide` flag: + +```bash +node index.js --no-windows-hide +``` + You can see **more examples in** [**test methods**](https://github.com/nvuillam/node-java-caller/blob/master/test/java-caller.test.js) ## TROUBLESHOOTING From db5808fca7a1990db78fde9ee43a20dddf23a1ce Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 10:17:14 +0000 Subject: [PATCH 4/5] Address code review feedback: improve test names and CLI flag parsing Co-authored-by: nvuillam <17500430+nvuillam@users.noreply.github.com> --- lib/cli.js | 16 +++++++++------- test/java-caller.test.js | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/cli.js b/lib/cli.js index 1bdbd9d..6e85230 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -27,15 +27,17 @@ class JavaCallerCli { const args = [...process.argv]; args.splice(0, 2); - // Parse --no-windows-hide flag + // Parse --no-windows-hide flag (remove all occurrences) const runOptions = {}; - const noWindowsHideIndex = args.indexOf('--no-windows-hide'); - if (noWindowsHideIndex !== -1) { - runOptions.windowsHide = false; - args.splice(noWindowsHideIndex, 1); - } + const filteredArgs = args.filter(arg => { + if (arg === '--no-windows-hide') { + runOptions.windowsHide = false; + return false; // Remove from args + } + return true; // Keep in args + }); - const { status } = await java.run(args, runOptions); + const { status } = await java.run(filteredArgs, runOptions); process.exitCode = status; } } diff --git a/test/java-caller.test.js b/test/java-caller.test.js index 55199c2..6a90e49 100644 --- a/test/java-caller.test.js +++ b/test/java-caller.test.js @@ -68,7 +68,7 @@ describe("Call with classes", () => { checkStdOutIncludes(`JavaCallerTester is called !`, stdout, stderr); }); - it("should call JavaCallerTester.class with windowsHide set to true (default)", async () => { + it("should call JavaCallerTester.class with windowsHide explicitly set to true", async () => { const java = new JavaCaller({ classPath: 'test/java/dist', mainClass: 'com.nvuillam.javacaller.JavaCallerTester' From d9ada8d2e704f71cb22671430fa7151cc4f9b2ab Mon Sep 17 00:00:00 2001 From: Nicolas Vuillamy Date: Sat, 7 Feb 2026 11:22:36 +0100 Subject: [PATCH 5/5] changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d215aa2..8c598b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,10 @@ ## Unreleased +## [4.4.0] 2025-02-07 + - Add `timeout` and `killSignal` run options +- Add `windowsHide` (default: true) to allow to show window if `windowHide: true` is sent ## [4.3.3] 2025-02-03