Win 10, Git Bash, gradlew, multiple debug-jvm, specify different ports

Hi,

I have opened five git bash cli windows.

I am in my gradle project, which contains a multitude of build.gradle files for the different subprojects, e.g.:

my-user@my-laptop MINGW64 ~/my-projects/some-project/some-folder (develop)
$ find ./ -name build.gradle
./build.gradle
./folder-a/service-a/build.gradle
./folder-a/service-b/build.gradle
./folder-a/service-c/build.gradle
./service-d/build.gradle
./service-e/build.gradle

I want to start all services with the debug-jvm option enabled, because I want to step through the execution with a remote debugger.

So I begin by starting the first service:

my-user@my-laptop MINGW64 ~/my-projects/some-project/some-folder (develop)
$ ./gradlew -b ./folder-a/service-a/build.gradle bootRun --debug-jvm

This works and my application is started, but starting the second service like so does not work and fails:

my-user@my-laptop MINGW64 ~/my-projects/some-project/some-folder (develop)
$ ./gradlew -b ./folder-a/service-b/build.gradle bootRun --debug-jvm

> Task :service-b:bootRun FAILED
ERROR: transport error 202: bind failed: Address already in use
ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [debugInit.c:750]

Of course I investigated the problem and tried specifying another JDWP port, but it does not give me any status output about the bootRun at all and just prints that its listening on the new port I specified, thus I conclude that the application is not started at all:

my-user@my-laptop MINGW64 ~/my-projects/some-project/some-folder (develop)
$ GRADLE_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=6543" ./gradlew -b cloud/service-b/build.gradle bootRun --debug-jvm
Listening for transport dt_socket at address: 6543

I also tried passing in the specific port in a different fashion like this, but it fails with the error that it does not know the arg parameter:

my-user@my-laptop MINGW64 ~/my-projects/some-project/some-folder (develop)
$ ./gradlew -b cloud/service-b/build.gradle bootRun --jvm-args="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=6543"

Problem configuring task :service-b:bootRun from command line.
> Unknown command-line option '--jvm-args'.

Then I tried switching --jvm-args to --jvmArgs, but that lead to the same error.

I am kind of stuck now and would like to ask the Gradle community for help.

If you want to run the services in parallel, I guess you have to specify a different port for each of your services, i.e.

  • 6543 - ./folder-a/service-a/build.gradle
  • 6544 - ./folder-a/service-b/build.gradle
  • 6545 - ./folder-a/service-c/build.gradle
  • 6546 - ./service-d/build.gradle
  • 6547 - ./service-e/build.gradle

Have you even read what I have written?

I tried different approaches specifiying the debug port for the JDWP connection, but gradle wont recognize any of them.

I thought I’ve read it. Maybe I wasn’t careful enough. Sorry for wasting your time.

1 Like

Maybe my text was not clear enough? Can you elaborate a bit on what was hard to read?

I would just add the following to your build.gradle:

bootRun {
    debugOptions {
        port = Integer.valueOf(findProperty('debugPort') ?: port.get())
        suspend = false // optional
    }
}

You can then run on the default port with no extra argument:

./gradlew -b ./folder-a/service-a/build.gradle bootRun --debug-jvm

or on another port with -PdebugPort={port}:

./gradlew -b ./folder-a/service-b/build.gradle bootRun --debug-jvm -PdebugPort=6543

This is what should happen until you attach the debugger on the specified port because in the command line args, suspend=y. I included an optional suspend = false line that you can include if you want the application to start up ready to debug, but not wait for you to attach the debugger.

1 Like

I would just add the following to your build.gradle :

Thanks, but no. I would rather not add anything to our already totally confusing and misleading build.gradle files. I am totally fine with a simple shell trick.

Thanks for pointing this out though:

So the suspend=y is responsible for ommitting the task output. Thank you for this clarification.

Your shell trick isn’t doing the same thing. It’s setting the debug options for the JVM running Gradle (same as -Dorg.gradle.debug=true), not the debug options for the JVM it forks to run your Spring Boot service (same as --debug-jvm).

1 Like

Ok, how would i set the latter within a simple command line without additional build.gradle foo? By the way your solution with the suspend=n worked!

Gradle attempts to make builds as reproducible as possible. As such, the behavior of JavaExec tasks like bootRun is to not propagate system, environments, args, etc. to the forked JVM unless you explicitly set them on the task. Those task properties can be hard-coded in the build.gradle or set with properties that can be controlled from the command line, but you can’t really avoid doing something in build.gradle if you want to impact the Spring Boot JVM.

The build.gradle files should be almost entirely declarative, just setting the values you need, but it sounds like this is not what you have. Having come from a web application that started with 10,000+ lines in build.gradle to now having only a few hundred declarative lines (mostly plugins and dependencies now), I’m always wary of attempts to circumvent the intended design. One workaround leads to another until you’re adding more to the confusion that you hoped to avoid (and you have 10,000+ lines to untangle).