Espinosa Espinosa - 3 years ago 148
Groovy Question

Gradle doesn't collect strings starting with -D

Is that a Gradle or Groovy bug?

I want to pass JVM parameters from Gradle to forked JVM, which is unfortunately not done automatically. This is supposed to work,

build.gradle
:

...
bootRun {
jvmArgs = System.properties.iterator().findAll{it.key.startsWith('myapp')}.collect {
"-D${it.key}=${it.value}"}
}
...


It is executed as:

gradle bootRun -Dmyapp.port=34501 -Dmyapp.member.name=server1


The method
collect
always return empty collecting if string starts with
-D
. If it starts with anything else it returns expected two element String collection. If I put space before
-D
it also works however it breaks the build further downstream on
:findMainClass
misinterpreting
-Dmyapp.port=...
with main class name. It simply has to start with
-D
.

I also tried different string concatenation but as far as the result is a string starting with -D it doesn't work.

Is it a bug or I'm missing something. This is my first Gradle project and I'm not a Groovy developer.
Should I report is bug? Where, Groovy or Gradle?

Notes:
I'm running Gradle from IntelliJ IDE 2016.1.2

Using Gradle 3.5

Forked JVM runs Spring Boot application

UPDATE

Big apologies, my bad! The truth is, the JVM parameters are passed down using the formula above; the problem is with how I measured it that the weren't. I simply put printouts:

println "jvmArgs: ${jvmArgs}"
println "jvmArgs.size: ${jvmArgs.size}"
println "jvmArgs.class: ${jvmArgs.class}"


..and aborting bootRun if
jvmArgs.size == 0
, to avoid slow application start; that is I wasn't really checking if parameters were passed or not in the application itself. And it turned out they were.

FYI the outputs were:

jvmArgs: []
jvmArgs.size: 0
jvmArgs.class: java.lang.ArrayList


The class of jvmArgs is reported as a standard ArrayList, but behaves more like a input stream consumer, whatever array is jvmArgs assigned to, that array is scanned for all strings starting with "-D", those are consumed (by what?), passed to some ProcessBuilder (??) and jvmArgs is left only with remaining elements.

Take this example:

jvmArgs = ["-Daaa=bbb", "foo", "bar"]
jvmArgs = ["stuff", "-Dccc=ddd", "morestuff"]
jvmArgs = ["-Deee=fff"]
println "jvmArgs: ${jvmArgs}"


..it prints
jvmArgs: []
and Spring Boot application is launched with
-Daaa=bbb -Dccc=ddd -Deee=fff
.

Can someone explain what causes this magic stream like property of jvmArgs, which otherwise claims to be a simple ListArray?

Answer Source

This works for me, but I don't have an explanation for the observed behavior. Hope it helps anyway.

def array = System.properties.iterator().findAll{
   it.key.startsWith('myapp')
}.collect {
   "-D${it.key}=${it.value}"
}
jvmArgs.addAll(array)

EDIT

jvmArgs = ["value"] calls setJvmArgs which, if I haven't missed something, goes from JavaExec to JavaExecHandleBuilder and later JvmOptions. Here, some parameters get removed. Entries beginning with -D gets added to systemproperties instead.

setJvmArgs( ["-Dtest=1", "xx"])
println getJvmArgs() //[xx]
println systemProperties //[test:1]

Does your Application does't have access to that properties?

https://github.com/gradle/gradle/blob/master/subprojects/core/src/main/java/org/gradle/process/internal/JvmOptions.java#L183

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download