Running bootRun and use a different application.properties file - spring

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

Related

SpringBoot: dinamically set properties in application.yaml

application.yaml containts (for example) the settings:
spring.cloud.stream:
kafka.streams.binder.functions.filter:
applicationId: zk
I want "applicationId" to be set dinamically.
For this aim I tried to use SpEl. But turn out SpEl could not be applicable to apllication.yaml.
I read about 2 ways of dinamically settings of yaml:
Using pom.xml
Using environment variables
But this ways not applicable to my situation: its a gradle-project. All instances of application deployed from one container.
spring.cloud.stream:
kafka.streams.binder.functions.filter:
applicationId: ${zk_prop:zk}
Where zk_prop is the env variable and zk the default value.
To pass arguments while running your application using Gradle Plugin, you need to configure the bootRun task in build.gradle file like:
bootRun {
if (project.hasProperty('args')) {
args project.args.split(',')
}
}
Now, you can pass the command-line arguments as follows:
./gradlew bootRun -Pargs=--zk_prop=custom-zk,--other_props=...

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

How do you run micronaut from gradle with local properties

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

spring-boot - how to specify path of application.properties in envrionment or system properties?

If I want to run spring boot application, and want to use difference application.properties in difference path (other than using profile)
How can I specify path for application.properties?
If you want to use difference application.properties in difference path, use this command to start the jar file
nohup java -jar project.jar --spring.config.location=file://{file-path}/application.properties
environment variable SPRING_CONFIG_LOCATION can be also used.
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html
#PropertySource annotation is used to provide properties file into the environment and it is used with #Configuration classes.
#PropertySource({ "classpath:config.properties" })
use bellow code above main class:
#PropertySource(value = {"file:///${HOMEDIR}/application.properties"})

How to set active profile on Spring Boot while building bootJar?

how to set profile just for the executable (jar) built by calling bootJar task? Ideally, it would override (or add) a property in application.properties inside the jar or something like that.
I expect he is trying to do exactly what we are. In maven one can do something along these lines:
<profile>
<id>openshift</id>
<properties>
<activatedProperties>openshift</activatedProperties>
</properties>
</profile>
Which can be used to replace #activatedProperties# in application.properties to, e.g., openshift. If this is the case, we solved it by modifying build.gradle as follows:
import org.apache.tools.ant.filters.ReplaceTokens
# whatever you have here
def springProfile = project.hasProperty("profile") ? profile : ""
bootRun {
systemProperties["spring.profiles.active"] = springProfile
}
processResources {
with copySpec {
from "src/main/resources/"
filter(ReplaceTokens, tokens: ["activatedProperties": springProfile])
}
}
and in the application.properties have:
spring.profiles.active=#activatedProperties#
However, I would like to note that we consider this a temporary hack. Build scripts should not be modifying files, even if it's limited to resource files. A more correct approach would be to use templates in a separate location and output those to the resources. Or even better (which is what we will do in due time), fix the deployment setup, so it's part of the deployment configuration, as it should be.
You can provide spring.profiles.active=dev,mysql in your application/bootstrap.properties file of your spring boot application.
Or while running the jar you can provide the active profile as argument,
java -jar fatJar.jar --spring.profiles.active=dev,mysql

Resources