System.out from JavaExec task to Windows terminal mangled


(thomas.glaeser) #1

When running a Java application from Gradle via ‘cmd.exe’ or ‘console.exe’ terminal applications, some ‘System.out’ lines returned by the ‘JavaExec’ task will include additional white spaces making the output difficult to read. This is a Windows only problem. (Using terminal mintty instead doesn’t show the same problem but then all colored output and the prompt is gone.)

Nothing special to say about the task declaration …

task simulator(type: JavaExec, group: 'IS simulator') {
    description = "Runs simulator scripts directly or interactively. Use -D${name}.workingDir and/or -D${name}.script to configure task properties."
    classpath = project.sourceSets.test.runtimeClasspath
    main = 'com.wm.app.b2b.server.sim.Simulator'
    workingDir project.file( System.getProperty("${name}.workingDir", 'src/test/resources/scriptedSchemaTests/work'))
    systemProperties 'watt.core.schema.validateIncomingXSDUsingXerces':'false'
    args '-b', project.sag.is.rootDir
    args '-h', workingDir
    args System.getProperty("${name}.script", '')
    standardInput = System.in
}

This looks like an Gradle issue. Any clue? Currently using Gradle version 1.5.


(Perryn Fowler) #2

Hi Thomas,

Is the output from JavaExec or from the Simulator class?


(thomas.glaeser) #3

Hi Perryn - Sorry for not being precise enough. Yes, the Simulator class prints to ‘System.out’ which in turn is mapped to the ‘JavaExec.standardOuput’. We don’t do anything fancy though. One of our commands is simply doing an ‘ls’ on the current directory. Usually the first two items are mangled, with more return results more mangled output happens in between. Thanks for checking…/Thomas


(Perryn Fowler) #4

and just to be clear, this doesn’t happen if you run the simulator class directly on the command line using java?


(thomas.glaeser) #5

Correct, not when running the Java directly. Not when executing via Gradle from a Linux terminal. Not when executing via Gradle from the mintty terminal. Only when using native Windows terminal.


(Perryn Fowler) #6

hard to debug remotely :slight_smile:

perhaps redirect the Gradle JavaExec.standardOutput to a file and do the same for a normal ‘java’ invocation and see if there are any differences?


(thomas.glaeser) #7

Well, I was hoping you have a test case for this anyway that could be used verify this using the environment specified. If not, I guess I could write a simple program that shows the problem.


(thomas.glaeser) #8

OK, here is a simple sample representing the problem. I guess I should have provided this in the first place …

defaultTasks 'badconsole'
  task badconsole(type: ConsoleTask)
  class ConsoleTask extends DefaultTask {
    @TaskAction def foo() {
        String[] lines = ['one', 'two\nthree', 'four\nfive', 'six seven eight\n\nnine']
        for (String line : lines)
             System.out.print(line + '\n')
        for (String line : lines)
            System.out.println(line)
    }
}

And here comes the output …

$ gradle
:badconsole
one
two
three
four
five
six seven eight
  nine
one
two
three
four
five
six seven eight
  nine
  BUILD SUCCESSFUL
  Total time: 3.008 secs

The output looks actually a little worse which seems to be hard to render in the HTML. But anyway, seems like it has problems with ‘print()’ when the input has embedded ‘\n’; whereas ‘println()’ seems to be OK.


(thomas.glaeser) #9

Actually, while pasting in the sample code I noticed issues with it which I therefore edited. In the edited version it looks all correct. So let me get back to the original code and verify if this isn’t an issue with the usage of ‘print()’ statements there or come-up with a better sample.


(Perryn Fowler) #10

something to do with CR/LF? http://www.codinghorror.com/blog/2010/01/the-great-newline-schism.html


(thomas.glaeser) #11

I don’t think so. Here is a better sample.

The Java code …

package my.pkg;
  public class Console {
    static String[] lines = new String[11];
    public static void main(String[] args) {
        lines[0] = "Just 10 lines of output ...";
        for(int i=1; i<11; i++){
            lines[i] = "line " + i;
        }
        for (String line : lines)
             System.out.print(line + "\n");
        for (String line : lines)
            System.out.println(line);
    }
}

… task declaration …

defaultTasks 'badconsole'
  apply plugin: 'java'
  task badconsole(type: JavaExec) {
    description = "Demonstrate faulty console output under windows."
    classpath = project.sourceSets.main.runtimeClasspath
    main = 'my.pkg.Console'
    standardInput = System.in
}

… and the output …

$ gradle
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:badconsole
Just 10 lines of output ...
line 1
                                    line 2
line 3
line 4
line 5
line 6
line 7
line 8
line 9
line 10
Just 10 lines ouf output ...
line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8
line 9
line 10
  BUILD SUCCESSFUL
  Total time: 3.281 secs

(thomas.glaeser) #12

Actually, you have a good point here, replacing ‘\n’ by ‘\r\n’ makes the problem disappear. But why does this cause problems only for line 2 and not when executing the class directly from Java?


(thomas.glaeser) #13

And not surprisingly replacing ‘\n’ by ‘System.lineSeparator()’ makes the problem go away.


(thomas.glaeser) #14

Just a slightly change to the test case showing sporadically added white space characters …

package my.pkg;
  public class Console {
    static String[] lines = new String[10];
    public static void main(String[] args) {
        lines[0] = "Just 9 lines of output ...";
        for(int i=1; i<10; i++){
            lines[i] = "line " + i;
        }
        for (String line : lines)
             System.out.print(line + System.lineSeparator());
        for (String line : lines)
            System.out.println(line);
        for (int i = 0; i < 500; i++)
            System.out.println("hello world\ngoodbye yellow brick road");
    }
}