How to debug a remote Scala app?


(Mark Petrovic) #1

Good day.

I am interested in learning how to debug a remote Scala app that is run via JavaExec in gradle.

I have this gradle.build file

apply plugin: 'scala'
  project.ext.scalaVersion = "2.9.2"
project.ext.mySqlVersion = "5.1.21"
project.ext.lambdaWorksVersion = "1.3.2"
project.ext.commonsCliVersion = "1.2"
  task slurp(type: JavaExec, dependsOn: classes) {
    main = 'slurper.App'
    args = System.getProperty("args", "").split().toList()
    classpath sourceSets.main.runtimeClasspath
}
  dependencies {
    // Libraries needed to run the scala tools
    scalaTools "org.scala-lang:scala-compiler:$project.scalaVersion"
    scalaTools "org.scala-lang:scala-library:$project.scalaVersion"
      // Libraries needed for scala api
    compile "org.scala-lang:scala-library:$project.scalaVersion"
      // MySQL
    compile "mysql:mysql-connector-java:${project.mySqlVersion}"
      // Scrypt
    compile "com.lambdaworks:scrypt:${project.lambdaWorksVersion}"
      // Commons CLI
    compile "commons-cli:commons-cli:${project.commonsCliVersion}"
}
  repositories {
    mavenCentral()
}

I then configure Java remote debugging like this:

export GRADLE_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=4000,server=y,suspend=y"

I then configure my IDE, set a breakpoint, start my app via “gradle slurp …” per my build file task, and connect the debugger to the remote JVM.

This much works, as I see the app suspend, then continue when the debugger attaches.

But the app does not stop at a breakpoint I know the code traverses.

I suspect I am missing something in the build file.

Can anyone help?

Thank you.


(Peter Niederwieser) #2

‘JavaExec’ forks its own JVM, so you’ll have to debug that instead of the Gradle JVM. You can pass the debug args to ‘JavaExec.args’.


(Mark Petrovic) #3

Thank you.

I believe this works, too: arrange to set the debug property on the task with a system property.

task slurp(type: JavaExec, dependsOn: classes) {
    main = 'slurper.App'
    args = System.getProperty("args", "").split().toList()
    debug = Boolean.valueOf(System.getProperty("debug", "false"))
    classpath sourceSets.main.runtimeClasspath
}

(Peter Niederwieser) #4

Sure, as long as you set the system property accordingly.


(Mark Petrovic) #5

Just curious: Is it possible to succinctly set a task property from the command line, like with this near-pseudocode?

gradle --JavaExec.debug=true slurp …

or

gradle --slurp.debug=true slurp …

where the token following the “–” is the task name.


(Peter Niederwieser) #6

No, there isn’t yet a generic way to do so. It’s a planned feature though.