The spring-boot-gradle-plugin now delegates configured project properties to the JavaExec of the runApp tasks. This fixes a issue that caused sytem properties that are provided to gradle via command line were not known to the spring boot application. For example, running 'gradle bootRun -Pspring.config.location=/some/custom/location/application.properties' did not work and the external config file was not loaded.
Comment From: dsyer
I'm not sure this is a great idea. As far as I can tell Project properties in Gradle (-P...) are not really supposed to be the same as System properties. Your patch, for example, would be useless to pass reserved property names to the app: try "gradle -Pname=Dave" and see what I mean. Also the Gradle guys seem to prefer that you propagate JVM arguments and System properties explicitly from the command line in your build.gradle
. Note that the Boot plugin only extends the functionality of the built-in application plugin, so you can use its features (like "applicationDefaultJvmArgs = ...") to do the propagation.
Comment From: holgerstolzenberg
Okay understood. But that does not solve my problem. The idea is that the location of the global configuration file of the system is not part of the build script, as it should be configured for each developer working on the project.
I somehow need to delegate the "spring.config.location" property to the apps when running bootRun task.
Comment From: dsyer
Then don't you need to add something to your build.gradle
? I'm not really a gradle user so I'm not going to be much help. Maybe something like this:
applicationDefaultJvmArgs =
[ "-Dspring.config.location=${properties['configLocation']?:'classpath:/application.properties'}" ]
Comment From: holgerstolzenberg
Okay, now I ended up doing the following:
run {
systemProperties = System.properties
}
Now the command
gradle bootRun -Dspring.config.location=/somewhere/application.properties"
works.
I am still not sure if this is the "correct" way. Maybe its more a gradle specific topic. I am going to ask the gradle forum for that.
Still, thanks for your help.
Comment From: dsyer
That seems like the right way to do it. Please come back and tell us if you find anything else out. I'm also thinking there needs to be a way to set command line arguments, but you can do pretty much everything in a regular Boot app with System properties, so maybe not urgent.
Comment From: tomaslin
I think the main problem here is that it is not immediately obvious that the bootRun extends the application plugin at all.
I would expect to be able to do something like:
bootRun {
systemProperties = System.properties
}
in my .gradle file. But the way the bootRun task extends the run task doesn't let me do that.
The Grails Gradle plugin allows for properties to be passed via the grailsArgs property:
gradle -PgrailsArgs='--inplace solr' grails-create-plugin
It would be great if boot had a similar mechanism for this.
Comment From: vasya10
@lando thanks for the solution, exactly what i was looking for.
Comment From: marcingrzejszczak
Hi Guys!
I don't see that this issue has ever been resolved. In fact I think it isn't.
I'm running a project on Spring boot 1.1.4 and couldn't have passed any params to my bootRun task. In other words:
gradle bootRun -Dspring.profiles.active=prod
failed completely. As a workaround I tried many things that were described in this PR but what worked for me was:
project.gradle.projectsEvaluated {
applicationDefaultJvmArgs = ["-Dspring.profiles.active=${project.gradle.startParameter.systemPropertiesArgs['spring.profiles.active']}"]
}
Why on earth does Spring boot take args from a project property called 'applicationDefaultJvmArgs' ? Simillar issue: https://github.com/4finance/boot-microservice/issues/5 Culprit code ;) : https://github.com/spring-projects/spring-boot/blob/master/spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/run/RunPluginFeatures.java
Comment From: dsyer
Isn't that code just mapping "jvmArgs" to something more obscure that is needed by the gradle code that we wrap? I assume "jvmArgs" or "allJvmArgs" or "systemProperties" would work just as well (see http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.JavaExec.html).
And there was never any indication that this issue was resolved. It may be resolved at some point and marked as "Won'tFix" because it seems to be a general problem with gradle, not specifically anything to do with Boot. Or maybe not.Tomas's point that the Grails plugin has taken the lead and exposed properties in a more friendly way is well made: we could have a stronger position here, but the pull request as it stands is not going to work, so it's waiting for someone to fix it.
Comment From: marcingrzejszczak
Hi @dsyer! Thanks for your immediate answer.
Maybe I did sth wrong but I've been trying to pass all the possible params to the JavaExec task and nothing worked for me (the passed props were always ignored).
Anyway this works for me as a workaround so I'll stick to that until there is some other way to fix it.
Comment From: tomaslin
@marcingrzejszczak - we end up doing something like this.
tasks.withType(org.springframework.boot.gradle.run.BootRunTask) {
systemProperty('netflix.environment', 'test')
}
You can use the -P project variable mechanism in gradle to externalize your variables, but it's not dynamic - http://mrhaki.blogspot.com/2010/10/gradle-goodness-pass-command-line.html
Comment From: marcingrzejszczak
@tomaslin thx for the info - it looks nicer than our hack ;)
Comment From: raindev
Any updates on the issue?
Comment From: Jannis87
I am working on a Spring Boot Project. We need different application.properties for every team member.
Nothing from this discussion worked for me so i found another way to get it work.
My solution: I added the following code to my build.gradle:
bootRun {
systemProperties['spring.profiles.active']=project.gradle.startParameter.systemPropertiesArgs['spring.profiles.active'];
}
In Eclipse i added the following to my Gradle launch config:
-Dspring.profiles.active=XXXXX
I Think this should work out of the box.
Comment From: robfletcher
I have this in my build.gradle
which sets default profiles for bootRun
and test
tasks.
bootRun {
environment SPRING_PROFILES_ACTIVE: environment.SPRING_PROFILES_ACTIVE ?: "local"
}
test {
environment SPRING_PROFILES_ACTIVE: environment.SPRING_PROFILES_ACTIVE ?: "test"
}
If there's an environment variable in existence it will take precedence. So I can do SPRING_PROFILES_ACTIVE=test gradle bootRun
to run the app in the test profile, for example. Otherwise it uses the default local.
Comment From: itonics-tbeauvais
Why is is this so complicated?! There are several times where you want to test passing in a JVM property to the actual runtime of your developer application rather than to the Gradle runtime. You shouldn't have to set this of every property you wish to pass. So, if this is a different commandline syntax or a plugin to accept -Gabc.xyz="foo" then that would be fine (like Grails does it).
Comment From: philwebb
Whilst it would be nice to offer an easier way to pass properties, we'd prefer to do it like Grails does
gradle -PgrailsArgs='--inplace solr' grails-create-plugin
Comment From: philwebb
@itonics-tbeauvais #1176 is open to add Grails like support.
Comment From: cyotee
So how do you pass JVM properties then? Where is the documentation covering how to do it, as recommended?
Comment From: philwebb
@cyotee We're still looking at adding first class support for arguments (see #1176). We have added some updated documentation for the 2.0 release, but it doesn't specifically document how to pass arguments. Instead it states:
The bootRun task is an instance of BootRun which is a JavaExec subclass. As such, all of the usual configuration options for executing a Java process in Gradle are available to you
I realize that's a little open ended, but since Gradle is so flexible I'm not sure there is a single recommended approach. So far this seems like the most reasonable solution.
If you're interested in contributing some additional documentation, this is the asciidoctor source file you should edit.
Comment From: cyc1ingsir
It seems to me, the "most reasonable solution" doesn't work any longer. Starting from 2.0.0-M5 I needed to change the bootRun closure to this:
bootRun {
execSpec {
systemProperties System.properties
}
}
This does enable us to use: ./gradlew bootRun -Dspring.profiles.active=test,dev
Would it be sensible to add this to
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/asciidoc/running.adoc
?
Comment From: wilkinsona
There's already an example for setting a system property:
For more advanced configuration the JavaExecSpec that is used can be customized:
bootRun {
execSpec {
systemProperty 'com.example.foo', 'bar'
}
}
That mechanism gives you access to anything that you configure on a JavaExecSpec
.
Comment From: szauner
Hi, @wilkinsona, the possibility and @cyc1ingsir mentioned seems to be gone in the 2.0.0 SNAPSHOT of 11/23/2017. The BootRun.class is now less than half the size of yesterday. Can you tell me, will it come back or was it / will it be replaced by another technique? Kind regards
Comment From: wilkinsona
Sorry for the churn. BootRun
is back to being a JavaExec
subclass in the 2.0 snapshots. That means that configuring system properties is back to being the same as it was in 1.x.
Comment From: szauner
Thank you very much for the info, @wilkinsona!
Comment From: shaziazamanrean
I have create a variable 'profiles' and configure gradle as following:
bootRun {
if (project.hasProperty('profiles')) {
environment SPRING_PROFILES_ACTIVE: profiles
} else {
def profiles = 'local'
environment SPRING_PROFILES_ACTIVE: profiles
}
}
Then at command line, give following arguments in order to pick up respective profiles
prompt> gradle :bootRun -Pprofiles=dev
In order to pickup local profile as default, no arguments required
prompt> gradle :bootRun
Comment From: marlonklc
I have create a variable 'profiles' and configure gradle as following:
groovy bootRun { if (project.hasProperty('profiles')) { environment SPRING_PROFILES_ACTIVE: profiles } else { def profiles = 'local' environment SPRING_PROFILES_ACTIVE: profiles } }
Then at command line, give following arguments in order to pick up respective profiles
prompt> gradle :bootRun -Pprofiles=dev
In order to pickup local profile as default, no arguments required
prompt> gradle :bootRun
The best way that a found was:
./gradlew bootRun --args='--spring.profiles.active=local'
just specificy what profile do you want and be happy. I believe thats its best way to do that.
I hope that it works to another person.
Cheers!
Comment From: abitgen
groovy environment SPRING_PROFILES_ACTIVE: profiles
What does this line mean environment SPRING_PROFILES_ACTIVE: profiles
. Can gradle able to decipher what "environment" string is? Can I get a link to source of this.