I have a SpringBoot application where I have application.properties file outside of project (it's not in usual place src/main/resources).
While building application with gradle clean build, it fails as code is not able to find properties files.
I have tried many command to pass vm args, gradle opts but its not working.
gradle clean build -Djvmargs="-Dspring.config.location=/users/home/dev/application.properties" //not working
It fails on test phase when it creates Spring application context and not able to substitute property placeholders. If I skip test as gradle clean build -x test it works.
Though I can run the app with java -jar api.jar --spring.config.location=file:/users/home/dev/application.properties
Please help how I can pass spring.config.location=/users/home/dev/application.properties in gradle build using command line so that build runs with all Junit tests
If I were you, I would not get involved the actual properties to junit test. So I would create a test properties for the project under src/test/resources/application-test.properties and in junit test I would load the test properties.
Example:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = MyProperties.class)
#TestPropertySource("classpath:application-test.properties")
public class MyTestExample{
#Test
public void myTest() throws Exception {
...
}
}
System properties for running Gradle are not automatically passed on to the testing framework. I presume this is to isolate the tests as much as possible so differences in the environment will not lead to differences in the outcome, unless explicitly configured that way.
If you look at the Gradle API for the Test task, you can see that you can configure system properties through through the systemProperty method on the task (Groovy DSL):
test {
systemProperty "spring.config.location", "/path/to/my/configuration/repository/application.properties"
}
If you also want to read a system property from the Gradle command line and then pass that the test, you have to read it from Gradle first, e.g. as a project property, and then pass that value to the test:
test {
if (project.hasProperty('testconfig')) {
systemProperty 'spring.config.location', project.getProperty('testconfig')
}
}
Run it with gradle -Ptestconfig="/path/to/my/configuration/repository/application.properties" build
However, I would discourage using system properties on the build command line if you can avoid it. At the very least, it will annoy you greatly in the long run. If the configuration file can be in different locations on different machines (depending on where you have checkout out the repository and if it is not in the same relative path to your Spring Boot repository), you may want to specify it in a personal gradle.properties file instead.
I think there is a misunderstanding.
spring.config.location is used at runtime
As you validated:
java -jar api.jar --spring.config.location=file:/users/home/dev/application.properties
spring.config.location is used or required at runtime, not at build time.
When your spring boot app is building, an application.properties is required. An approach could be use an src/main/resources/application.properties with template values, but at runtime you will ignore it spring.config.location=file...
For unit tests
In this case as #nikos-bob said, you must use another properties, commonly inside of your src/test/resources
Environment variables instead external properties
We don't want to have hardcoded values in our main git repository src/main/resources/application.properties so the first idea is use an external properties. But this file must be stored in another git repository (equal to main repository ) or manually created.
Spring and other frameworks give us an alternative: Use environment variables.
So instead of manually external creation of application.properties or store it in our git repository, your spring boot app always must have an application.properties but with environment variables:
spring.datasource.url=jdbc:oracle:thin:#${DATABASE_HOST}:${DATABASE_PORT}:${DATABASE_SID}
spring.datasource.username=${DATABASE_USER}
spring.datasource.password=${DATABASE_PASSWORD}
spring.mail.host = ${MAIL_HOST}
spring.mail.username =${MAIL_USERNAME}
spring.mail.password =${MAIL_PASSWORD}
Advantages:
No manually creation of application.properties allowing us a more easy devops automations
No spring.config.location=file.. is required
I want to run Micronaut server from Gradle command line with "local" environment variables.
The regular command
.\gradlew.bat run
will use default variables defined in application.yml file.
I want to override some of them with values for my local environment and therefore need to specify system property micronaut.environments=local to use overriding values from application-local.yml file.
.\gradlew.bat run -Dmicronaut.environments=local
The command above won't work as Gradle will take only -Dmicronaut for the system property and the rest ".environments=local" will be considered as another task name:
Task '.environments=local' not found in root project 'abc'
What would be the correct way to pass such system property to the java process?
Command below works for unix, probably it should work also for windows:
MICRONAUT_ENVIRONMENTS=local gradle run
or use gradle wrapper
MICRONAUT_ENVIRONMENTS=local .\gradlew.bat run
P.S. also, you can find the same approach for Spring Boot
My approach is to add a gradle task.
task runLocal(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = "dontdrive.Application"
jvmArgs '-Dmicronaut.environments=local'
}
then start with:
./gradlew runLocal
I'd like to be able to run bootRun for spring boot, but use a different application.properties file besides the one in src/main/resources/. Is that possible? I'd prefer to not overwrite the file in src/main/resources/, as it would dirty the file.
Is this possible?
You can use profile based configuration selection.
Just set a system environment property:
spring.profiles.active=dev
And now provide application-dev.properties in application resources(src/main/resources/)
By this way you can use different properties for different environment.
If you want to provide files at a different location the use this environment property
spring.config.location=<path>
If you wish to use different name then application in property file name the use this environment property:
spring.config.name=<new_name>
For more info check this link:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html
Here is what my bootRun task looks like that does this
bootRun {
systemProperty "spring.config.location", "file:$projectDir/spring-config/"
main = springBootAppClass
}
Which specifies to use the spring-config directory in the project's root folder.
If using in conjunction with #PropertySource it looks like this
#PropertySource("${spring.config.location}/persistence.properties")
Try this command,
./gradlew bootRun --args='--spring.profiles.active=dev'
I too was looking for the solution, found it in official documentation
https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/#running-your-application
I got it to work like this:
tasks.named("bootRun") {
systemProperty "spring.config.location", "file:$projectDir/myConfigFolder"
mainClass = "my.project.MyMainClass"
}
I'm having a application.yml file that holds some placeholders e.g.
security:
user:
password: ${ADMIN_PASSWORD}
I've tried running e..g
./gradlew :project:bootRun -DADMIN_PASSWORD=admin
./gradlew :project:bootRun -PADMIN_PASSWORD=admin
./gradlew :project:bootRun --ADMIN_PASSWORD=admin
but the placeholder is not replaced. What is the proper way for passing command-line value to placeholder templated variables in YAML file?
The parameters are not automatically passed in via the bootRun task (see https://github.com/spring-projects/spring-boot/pull/592).
I add this to my build.gradle to get the behavior you are asking for:
bootRun {
// allows ./gradlew bootRun -Dspring.profiles.active=dev
systemProperties System.properties
}
I'm using Gradle spring-boot plugin and I need to select a spring active profile for the test run.
How do I pass spring.profiles.active system property to the bootRun plugin's task?
What has already failed:
task bootRunLocal {
systemProperty "spring.profiles.active", "local"
System.setProperty("spring.profiles.active", "local")
tasks.bootRun.execute() // I suspect that this task is executed in a separate JVM
}
and some command line magic also fails:
./gradle -Dspring.profiles.active=local bootRun
Could someone kindly help me solve my troubles?
Update from the answers and comments:
I'm able to set the systemProperty and pass it to the spring container by doing :
run {
systemProperty "spring.profiles.active", "local"
}
However, when I do this, the local profile is being set for both bootRun task and bootRunLocal task. I need a way to set this property for bootRunLocal task and call booRun task from bootRunLocal.
That might sound very simple, but I come with peace from the structured world of Maven.
I know I'm late here... but I recently faced this exact issue. I was trying to launch bootRun with spring.profiles.active and spring.config.location set as system properties on the command line.
So, to get your command line "magic" to work, simply add this to your build.gradle
bootRun {
systemProperties System.properties
}
Then running from the command line...
gradle -Dspring.profiles.active=local bootRun
Will set local as the active profile, without needing to define a separate task simply to add the env variable.
task local {
run { systemProperty "spring.profiles.active", "local" }
}
bootRun.mustRunAfter local
Then run gradle command as:
gradle bootRun local
There is no generic way to pass system properties to a task. In a nutshell, it's only supported for tasks that fork a separate JVM.
The bootRunLocal task (as defined above) will not execute in a separate JVM, and calling execute() on a task isn't supported (and would have to happen in the execution phase in any case). Tests, on the other hand, are always executed in a separate JVM (if executed by a Test task). To set system properties for test execution, you need to configure the corresponding Test task(s). For example:
test {
systemProperty "spring.profiles.active", "local"
}
For more information, see Test in the Gradle Build Language Reference.
SPRING_PROFILES_ACTIVE=local gradle clean bootRun
This is according to this and this and it works.
According to the spring-boot-gradle-plugin documentation you should be able to pass arguments like this
./gradlew bootRun --args='--spring.profiles.active=dev'
Seems like this is a new gradle feature since 4.9. I used it in my project and it worked out of the box.
For gradle 2.14 below example works.
I have added as below.
When System.properties['spring.profiles.active'] is null then default profile is set.
bootRun {
systemProperty 'spring.profiles.active', System.properties['spring.profiles.active']
}
command line example
gradle bootRun -Dspring.profiles.active=dev
Just for reference if anyone will have this issue:
Vlad answer didn't quite worked for me but this one works great with 2.4,
task local <<{
bootRun { systemProperty "spring.profiles.active", "local" }
}
local.finalizedBy bootRun
then gradle local
Responding to OP's exact request here ...
How do I pass spring.profiles.active system property to the bootRun plugin's task?
And assuming by "pass" the OP meant "pass from commandline" or "pass from IDE invocation" ... This is how I like to do it.
Add this to build.gradle:
/**
* Task from spring-boot-gradle-plugin, configured for easier development
*/
bootRun {
/* Lets you pick Spring Boot profile by system properties, e.g. gradle bootRun -Dspring.profiles.active=dev */
systemProperties = System.properties
}
Then when you invoke it, use the familiar Java flag for setting a system property
gradle bootRun -Dspring.profiles.active=local
There is one main advantage of sticking to system properties, over the environment variables option (SPRING_PROFILES_ACTIVE=local gradle bootRun) ... and that's easy portability between Linux/OS X (bash, etc.) and Windows (cmd.exe anyway).
I learned this way from this blog post.
(UPDATE: Ah somehow I had missed #Erich's response with same recommendation. Oops! I'm leaving my answer, because of the additional details about portability, etc.)
You can create a new task (in discussed case with name bootRunLocal), that would extend org.springframework.boot.gradle.run.BootRunTask and setup properties before task execution. You can create such a task with following code:
task bootRunLocal(type: org.springframework.boot.gradle.run.BootRunTask) {
doFirst() {
main = project.mainClassName
classpath = sourceSets.main.runtimeClasspath
systemProperty "spring.profiles.active", "local"
}
}
More details can be found here:
https://karolkalinski.github.io/gradle-task-that-runs-spring-boot-aplication-with-profile-activated/
Starting from SpringBoot 2.0.0-M5 setSystemProperties() is no longer a method of the task bootRun.
The build.gradle needs to be updated to
bootRun {
execSpec {
// System.properties["spring.profiles.active"]
systemProperties System.properties
}
}
This is as springBoot's run task uses org.gradle.process.JavaExecSpec
This works for me using Gradle 4.2
This works:
SPRING_PROFILES_ACTIVE=production ./gradlew app-service:bootRun
with run command you can add to build file run { systemProperties = System.properties } and start with gradle run -Dspring.profiles.active=local
Another way which doesn't require any support from the gradle task: Set the JAVA_TOOL_OPTIONS environment variable:
JAVA_TOOL_OPTIONS='-Dfoo=bar' gradle ...
Or if the variable might already contain anything useful:
JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -Dfoo=bar" gradle ...
// defualt value
def profiles = 'dev'
bootRun {
args = ["--spring.profiles.active=" + profiles]
}
Then you can simply pick a specific version when starting a gradle task, like
./gradlew bootRun -P dev
"dev" is gonna to take place "prod"