Skip to content

Delegate command line system properties to spring-boot-gradle-plugin runApp task #592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

holgerstolzenberg
Copy link

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.

…ties 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.
@dsyer
Copy link
Member

dsyer commented Mar 27, 2014

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.

@holgerstolzenberg
Copy link
Author

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.

@dsyer
Copy link
Member

dsyer commented Mar 27, 2014

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'}" ]

@holgerstolzenberg
Copy link
Author

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.

@dsyer
Copy link
Member

dsyer commented Mar 28, 2014

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.

@tomaslin
Copy link
Contributor

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.

@dsyer dsyer added this to the 1.0.1.RELEASE milestone Apr 3, 2014
@philwebb philwebb modified the milestones: 1.0.2, 1.0.1 Apr 3, 2014
@dsyer dsyer removed this from the 1.0.2 milestone Apr 15, 2014
@vasya10
Copy link

vasya10 commented May 8, 2014

@lando thanks for the solution, exactly what i was looking for.

@marcingrzejszczak
Copy link
Contributor

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: 4finance/boot-microservice#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

@dsyer
Copy link
Member

dsyer commented Aug 7, 2014

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.

@marcingrzejszczak
Copy link
Contributor

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.

@tomaslin
Copy link
Contributor

@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

@marcingrzejszczak
Copy link
Contributor

@tomaslin thx for the info - it looks nicer than our hack ;)

@raindev
Copy link

raindev commented Mar 29, 2016

Any updates on the issue?

@Jannis87
Copy link

Jannis87 commented Jul 19, 2016

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

image

I Think this should work out of the box.

@robfletcher
Copy link
Contributor

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.

@itonics-tbeauvais
Copy link

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).

@philwebb
Copy link
Member

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

@philwebb philwebb closed this Jan 11, 2017
@snicoll snicoll added the status: declined A suggestion or change that we don't feel we should currently apply label Jan 11, 2017
@philwebb
Copy link
Member

@itonics-tbeauvais #1176 is open to add Grails like support.

@cyotee
Copy link

cyotee commented Aug 15, 2017

So how do you pass JVM properties then? Where is the documentation covering how to do it, as recommended?

@philwebb
Copy link
Member

@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.

@cyc1ingsir
Copy link

cyc1ingsir commented Oct 13, 2017

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
?

@wilkinsona
Copy link
Member

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.

@szauner
Copy link

szauner commented Nov 23, 2017

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

@wilkinsona
Copy link
Member

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.

@szauner
Copy link

szauner commented Nov 23, 2017

Thank you very much for the info, @wilkinsona!

@shaziazamanrean
Copy link

shaziazamanrean commented Apr 17, 2018

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

@marlonklc
Copy link

marlonklc commented Jul 14, 2021

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

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!

@abitgen
Copy link

abitgen commented Dec 13, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

Successfully merging this pull request may close these issues.