Hey community! I am creating a Gradle that has a ...
# community-support
i
Hey community! I am creating a Gradle that has a task that start a Java tool in an external JVM process. For that my tasks extends the JavaExec class provided by Gradle. Everything works as intended but I have some issue with log output: When I start the build with default logging level (lifecycle), the whole output from my external JVM process is shown. How can I control that? I want that output to be hidden unless the log level is at least INFO. Thanks!
c
Use ExecOperations to control the execution/output
v
logging.captureStandardOutput(<http://LogLevel.INFO|LogLevel.INFO>)
on the task
i
captureStandardOutput
does not look like a relevant solution:
v
Why not?
c
why not? It routes the output to the logger at the QUIET level.
v
It exactly answers the question you stated
i
My task has no field
logging
v
yes it has
Well, a method called
getLogging
So yes, no filed, but a property
logging
c
Copy code
@Override
    public org.gradle.api.logging.LoggingManager getLogging() {
        return super.getLogging();
    }
on DefaultTask.
i
This is my current solution (I am not satisfied that I have to redirect the stdout by myself):
Copy code
@TaskAction
public void execute() {
    var bufferOut = new ByteArrayOutputStream();

    var result = execOperations.javaexec(spec -> {
        spec.setClasspath(runtimeConfiguration);
        spec.getMainClass().set("jooqgenie.tool.JooqGenieTool");
        //...
        spec.setIgnoreExitValue(true);
        spec.setStandardOutput(bufferOut);

    });

    if (getLogger().isInfoEnabled()) {
        getLogger().info(bufferOut.toString());
    }

    if (result.getExitValue() != 0) {
        throw new GradleException("JooqGenieTool execution failed with exit code: " + result.getExitValue());
    }
}
v
Then just do what I told you 🙂
Of course translated to Java
i
image.png
v
logging, not logger
i
ups, let me try
new code:
Copy code
@TaskAction
public void execute() {
    getLogging().captureStandardOutput(LogLevel.INFO);

    execOperations.javaexec(spec -> {
        spec.setClasspath(runtimeConfiguration);
        spec.getMainClass().set("jooqgenie.tool.JooqGenieTool");
    });
}
and if i run:
Copy code
./gradlew clean build
and it outputs everything from the external process.
as if captureStandardOutput(LogLevel.INFO) would not affect anything
v
Hm, interesting. I have a task where I call an Xslt processor in-process, there it works fine. Maybe the
javaexec
already captures stdout and sends it to the logging making the option not work.
Or it is on stderr
🤷‍♂️
i
It is on stdout because my previous solution did work.
Just tried:
Copy code
getLogging().captureStandardOutput(LogLevel.QUIET);
System.out.println("!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?");
and it shown the output. For:
Copy code
getLogging().captureStandardOutput(<http://LogLevel.INFO|LogLevel.INFO>);
System.out.println("!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?!?");
it hides the output. So it indeed works in-process. Still, I am thankful for your help.
v
No it's not on stdout or the option would have helped. It is on whatever stream was set to the stdout field there. Maybe if you set the actual System.out to that field? 🤷‍♂️
No idea whether that will have other drawbacks though.
i
Copy code
getLogging().captureStandardOutput(<http://LogLevel.INFO|LogLevel.INFO>);
        System.out.println("####"); // !!!!!!!!!!

        execOperations.javaexec(spec -> {
            spec.setClasspath(runtimeConfiguration);
            spec.getMainClass().set("jooqgenie.tool.JooqGenieTool");
            spec.setStandardOutput(System.out); // !!!!!!!!!!!!
        });
It swallows only "####" but the child process output is still visible.
😔 1