Cannot run gradlew.bat from project sub folder

I have below project struture

MyProject
    projA
    projB
        build.gradle
gradlew.bat
build.gradle
gradlew
settings.gradle

I have below task in MyProject/projB/build.gradle

def process;
task bootRunStartDaemon() {
    doFirst {

        println("Starting application it profile")

        ProcessBuilder builder = new ProcessBuilder("./gradlew.bat", "bootRun", "--args='--spring.profiles.active=it'")
        builder.redirectErrorStream(true)
        builder.directory(projectDir)
        process = builder.start()
        InputStream stdout = process.getInputStream()
        BufferedReader reader = new BufferedReader(new InputStreamReader(stdout))

        def line
        while ((line = reader.readLine()) != null) {
            println line
            if (line.contains('Started MyApplication ')) {
                println "App is ready to receive traffic"
                break;
            }
        }
    }
}

However when I run > gradlew bootRunStartDaemon from the root directory I get below error

Caused by: org.gradle.api.UncheckedIOException: java.io.IOException: Cannot run program "./gradlew.bat" (in directory "MyProject\projB"): CreateProcess error=2, The system cannot find the file specified
        at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:62)

I have below in settings.gradle

....
rootProject.name = "MyProject"
include "projA", "projB"

There are various issues like
why do you use ProcessBuilder instead of an Exec task, or a GradleBuild task, or the GradleRunner from the tooling API, or actually just invoke the bootRun task,
or that the executable is gradlew.bat, not ./gradlew.bat, the ./ syntax is a Bash-specific thing,
or that I’m not sure whether you can start a .bat file using ProcessBuilder.
The main problem though is, that you set the CWD for the process to the projectDir of the subproject instead of rootProject.projectDir and in the project dir of the subproject you don’t have a gradlew.bat as the error tells you.

1 Like

@Vampire The reason why I took this approach was, I wanted to start-up the app before running api integration tests in Jenkins. (e.g. task integrationTest(type: Test, dependsOn: bootRunStartDaemon)
I tried with bootRun and the issue I had was, it start-up the app and never move to the tests task.

So as you correctly mentioned my integration tests are in submodule ans gradlew.bat file is not accessible from there. That was the issues I wanted to solve.
The reason why I was using ./gradlew.bat to go to the root folder from sub module and access gradlew.bat

Somehow I manged to do this by adding the complete path as below.

ProcessBuilder builder = new ProcessBuilder(projectDir.toString().replace("projB","")  + gradleCommand, "bootRun", "--args='--spring.profiles.active=it'")

But not sure whther there is a better way.

./gradlew.bat to go to the root folder

Thast does not go to the root folder.
You set with builder.directory(projectDir) the project dir of the subproject as working directory.
And ./gradlew.bat is the gradlew.bat in the current working directory.
What you meant to do is ../gradlew.bat.
Or probably better and easier use builder.directory(rootProject.projectDir) to have the working directory in the root projects directory.

Btw. the idiomatic way to start such a server is to use a shared build service.
There you can properly start up a server and when it is no longer needed, shut it down orderly.
See here for more information: Shared Build Services