I have a project comprised of three java server apps. They need to run concurrently for me to use the application.
Gradle’s JavaExec waits for each java process to end (maybe that’s DefaultJavaExecAction:40) therefore only one JavaExec can run at a time.
I would like to customize JavaExec to build a different command line and instead of a myjava.exe -cp ... it would produce cmd /k start "myjava.exe -cp...". What would be the recommended approach to have such behavior ?
What we tried:
sneak in a change to commandLine but it’s read-only
use WorkerExecutor but it really doesn’t look right and seems to trigger multiple Gradle instances, eeeww
naively set executable to cmd /k start myjava.exe but javaexec seems to try to do a java -v first and is no longer to get its result
overriding JavaExec to leverage its classpath management…etc. work in progress but that proves to be trickier than I thought
Context:
Windows
Gradle 6.5.1
Java 8
can’t upload Gradle scan - company policy, sorry
Any pointer to a clean solution would be greatly appreciated.
The three app are defined in distinct subprojects and --parallel should be able to have them all run concurrently but that would be nice to not have to use a flag every time (and enabling it by default is not currently an acceptable option in our build).
Ended up doing something like that below but it doesn’t work with Gradle 6.6 (worked with 6.5.1). Any idea why it doesn’t work with 6.6 ? looks like commandLine only contains the executable now.
@CompileStatic
class ServerJavaExec extends JavaExec {
private final Property<ExecResult> serverJavaExecResult;
def serverName
ServerJavaExec() {
super()
serverJavaExecResult = objectFactory.property(ExecResult.class);
}
@Override
@TaskAction
public void exec() {
// drop the first item in commandLine, it is the executable (java.exe)
def javaCommandArgsLine = commandLine.drop(1).join(' ')
def javaCommand = "cmd /k start \"$serverName\" \"$executable\" $javaCommandArgsLine"
getLogger().info "Executing $javaCommand ..."
// >> Here I execute javaCommand, it eventually goes to process builder <<
// immediately return a success result
serverJavaExecResult.set([
exitValue: 0,
assertNormalExitValue: this,
rethrowFailure: this
] as ExecResult);
}
@Override
public Provider<ExecResult> getExecutionResult() {
return serverJavaExecResult;
}
}