10

I have this simple Java program:

package me.fornever.javaterminal;
public class Main {
    public static void main(String[] args) {
        System.out.println("Console: " + System.console());
    }
}

And this simple build.gradle:

apply plugin: 'java'
apply plugin: 'application'
mainClassName = 'me.fornever.javaterminal.Main'

When I'm executing it using gradle --no-daemon run, I get the following output:

Console: null

If I execute it from the terminal through gradle jar; java -cp '.\build\libs\java-terminal.jar' me.fornever.javaterminal.Main, I get the following:

Console: java.io.Console@3d4eac69

I am aware that System.console() may return null when the parent process uses stdout redirection. Is there some Gradle option to disable the redirection and make the console fully available for my program?

I am developing a terminal library for Java, so I want to run my tests and executables without Gradle intervention in stdin/stdout/stderr.

Please note that System.console() being null is not the only issue but the most obvious one. In reality I want to access WinAPI WriteConsoleW function from the program executed by gradle run, and I'm unable to use this function due to the same reasons System.console() being null. So I really need to disable output redirection in Gradle if this option is available.

Also please note that the question is different from Gradle build null console object because that question asks how to use System.console() inside of a Gradle script and not in the Java program invoked by gradle run; I believe they're working differently in that matter, because neither of the answers are working or applicable to my case.

Community
  • 1
  • 1
ForNeVeR
  • 6,726
  • 5
  • 24
  • 43
  • How can you *test* a program that uses `console()`? You can't send it test input and you can't verify the output, so what are you testing? – Andreas Sep 18 '16 at 05:10
  • @Andreas first of all I test if it's working at all and not throwing any exceptions. And the second option is to use some platform-dependent API like win32 `ReadConsoleOutput` or a wrapper such as `winpty`. I am writing a wrapper library for Windows console, so it's okay to use platform-dependent solutions. – ForNeVeR Sep 18 '16 at 06:01
  • So when you did a web search, what did you find? Did you find this duplicate question? – Andreas Sep 18 '16 at 06:03
  • Nope, the linked answer doesn't work for me. I specially mentioned that I'm running `gradle --no-daemon run` and it still doesn't work. – ForNeVeR Sep 18 '16 at 06:09
  • Also, the linked question is about getting `System.console()` inside of a Gradle script, and not in the Java program invoked by `gradle run`. So I still think that my question is different from the linked one. I've added this information to my question. – ForNeVeR Sep 18 '16 at 06:11
  • 3
    I have the same issue. I readed somewhere that including `standardInput = System.in` in run task will make it work, but it didn't work for me. Anyway, some reported that this worked for them. – Alireza Mohamadi Dec 04 '16 at 16:34

1 Answers1

4

In order for java.io.Console to be available, the child processes' stdin and stdout have to point to a Linux/macOS/Unix terminal or a Windows console. The easiest way to arrange that is to inherit the stdin and stdout from a parent process already set up that way. However, there is a known limitation of Gradle (GRADLE-3292) that the JavaExec task type does not support making the child process inherit the input/output streams of the parent process.

If the Gradle JavaExec task type was enhanced to support stdin/stdout inheritance, then this could be made to work for gradle --no-daemon run.

Getting it to work with the Gradle daemon would be far more complex, and likely involve platform-specific code to manipulate pseudoterminals or call the Windows console API.

Simon Kissane
  • 4,373
  • 3
  • 34
  • 59