Dev Gosain
Dev Gosain

Reputation: 740

How to pass spring.config.location="somepath" while building SpringBoot application with command-line Gradle (6.4) build

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

Upvotes: 0

Views: 11111

Answers (3)

Bjørn Vester
Bjørn Vester

Reputation: 7590

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.

Upvotes: 2

JRichardsz
JRichardsz

Reputation: 16495

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

Upvotes: 0

nikos-bob
nikos-bob

Reputation: 23

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 {
  ...
  }

}

Upvotes: 1

Related Questions