spring-boot application.properties are not overwriten - spring-boot

I have one class:
package com.example.propertyorder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
#SpringBootApplication
#PropertySource(value="file:C:\\TEMP\\property-order.properties", ignoreResourceNotFound = true)
public class PropertyOrderApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(PropertyOrderApplication.class, args);
Environment env = (Environment) run.getBean("environment");
System.out.println(env.getProperty("my.value"));
System.out.println(env.getProperty("my.value2"));
}
}
and I have one application.properties file:
my.value=application.properties
and I have my external properties file C:\\TEMP\\property-order.properties:
my.value=property-order.properties
my.value2=gotcha
but the result is always:
application.properties
gotcha
instead of:
property-order.properties
gotcha
So it looks like, that spring-boot's application.properties overrules all.
Is there a way to fix it.
The only solution that i found is to not use the application.properties, but a my-app.properties instead and place that one before my external file in the ProperySource-tree:
#PropertySource(value="classpath:my-app.properties")
#PropertySource(value="file:C:\\TEMP\\property-order.properties", ignoreResourceNotFound = true)
Is there a better way, so that I can stay with the application.properties ?
edit:
added missing value2 to the property file

The actual behavior is conform to the Spring Boot documentation :
Spring Boot uses a very particular PropertySource order that is
designed to allow sensible overriding of values. Properties are
considered in the following order:
....
14.Application properties outside of your packaged jar (application.properties and YAML variants).
15.Application properties packaged inside your jar (application.properties and YAML variants).
16.#PropertySource annotations on your #Configuration classes.
The application.properties (inside or outside the jar) have a higher priority (14 and 15 respectively) than any #PropertySource annotations added in #Configuration class (16).
Is there a better way, so that I can stay with the
application.properties ?
Of course you can use any of the 13 higher priority ways :
1.Devtools global settings properties on your home directory
(~/.spring-boot-devtools.properties when devtools is active).
2.#TestPropertySource annotations on your tests.
3.#SpringBootTest#properties annotation attribute on your tests. Command
line arguments.
4.Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an
environment variable or system property).
5.ServletConfig init parameters.
6.ServletContext init parameters.
7.JNDI attributes from java:comp/env.
8.Java System properties (System.getProperties()).
9.OS environment variables.
10.A RandomValuePropertySource that has properties only in random.*.
11.Profile-specific application properties outside of your packaged jar
(application-{profile}.properties and YAML variants).
12.Profile-specific application properties packaged inside your jar
(application-{profile}.properties and YAML variants).
13.Application properties outside of your packaged jar
(application.properties and YAML variants).
For example renaming property-order.properties to application-order.properties to make it a Spring Boot profile properties and run your application with order as active profile would give it a higher priority and so it should be enough :
#SpringBootApplication
public class PropertyOrderApplication {...}

If you want to override the property defined int the application.properties, you can use the below approach.
#PropertySources({
#PropertySource(value = "classpath:application.properties"),
#PropertySource(value = "file:/user/home/external.properties", ignoreResourceNotFound = true)
})
public class Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
}
}

Related

How to use #Value in Junit tests

I'm trying to get a property value from my application-test.yml file like that :
#SpringBootTest()
#ActiveProfiles("test")
#ExtendWith(MockitoExtension.class)
public class GoogleServiceUtilsTest {
#Value("${google.service.account.user}")
private String serviceAccountUser;
#Value("${google.service.account.path}")
private String pathFile;
Set<String> scopesSet = DirectoryScopes.all();
List<String> scopesList = new ArrayList<String>(scopesSet);
#Test
void getCredentialTest() throws GoogleCredentialException {
// Given
GoogleCredentials credentials;
// When
credentials = GoogleServiceUtils.getCredential(serviceAccountUser, scopesList, pathFile);
// Then
assertThat(credentials != null);
assertThat(new HttpCredentialsAdapter(credentials));
}
}
but when I use it in my test method, serviceAccountUser and pathFile variables are always null.
My application-test.yml file is located in 'src/test/resources', and tests are in 'src/test/java/' and content :
google:
service:
account:
user: ...
path: ...
# FED credentials
fed:
url: ...
token: ...
grantType: ...
# Logging
logging:
level:
root: ...
org.springframework: ...
When I use the #Value tag in my app code, all is working. Variables are getting good values from 'src/main/resources/application.yml' file.
After reading comments, I add that the profiles are not useful in my case, but as when I don't use them, it doesn't work, I thought that maybe it came from there and that it is necessary to use them.
I also tried to write the value of the variables hard in the file, and then there is no problem, tests are passing well.
Is someone understanding this problem? Many people seem to have had the same, but I can't find an answer working for me.
Thank you for your answer!
Sorry, cannot reproduce!
Having:
Simplest starter
src/main/resources/application.yml
foo:
bar:
baz: normal
...and
src/test/resources/application-test.yml
foo:
bar:
baz: test
This test passes:
#SpringBootTest
#ActiveProfiles("test") // !
class SomeTest {
#Value("${foo.bar.baz}")
String foo;
#Test
void testProp() {
Assertions.assertEquals("test", foo); //!#
}
}
Either #ExtendWith(MockitoExtension.class) has no effect/does no harm.
Whenever you wonder, where your properties come from
Consult:https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config
And check (current version):
...considered in the following order:
Default properties (specified by setting SpringApplication.setDefaultProperties).
#PropertySource annotations on your #Configuration classes. Please note ...
Config data (such as application.properties files).
A RandomValuePropertySource that has properties only in random.*.
OS environment variables.
Java System properties (System.getProperties()).
JNDI attributes from java:comp/env.
ServletContext init parameters.
ServletConfig init parameters.
Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).
Command line arguments.
properties attribute on your tests. Available on #SpringBootTest and the test annotations for testing a particular slice of your application.
#TestPropertySource annotations on your tests.
Devtools global settings properties in the $HOME/.config/spring-boot directory when devtools is active.
Config data files (3.) are considered in the following order:
Application properties packaged inside your jar (application.properties and YAML variants).
Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
Application properties outside of your packaged jar (application.properties and YAML variants).
Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).

Spring boot application properties are all read as null

In my application class I have
#SpringBootApplication(scanBasePackages = {"com.binance.bot.timeandsales", <some other packages>})
#Configuration
#EnableScheduling
public class BinanceTimeAndSalesApplication implements CommandLineRunner {
#Autowired
AggTradeEventSubscriptionListener aggTradeEventSubscriptionListener;
And in the bean class which is a non-public class in the same file I have
#Component
class AggTradeEventSubscriptionListener implements SubscriptionListener<AggregateTradeEvent> {
#Value("${binance.api}")
private String apiUrl;
which is coming as null.
In my application.properties I have
binance.api=https://fapi.binance.com
The application.properties in src/main/resources directory which is also appearing as the resources directory in the Intellij module configuration.
In my pom.xml I have
<properties>
<start-class>com.binance.bot.timeandsales.BinanceTimeAndSalesApplication</start-class>
</properties>
What am I doing wrong that the application properties are read as null?
Another weirdity is that in some other class in a different package, the properties are getting read. But not in the newer classes that I'm writing in the com.binance.bot.timeandsales package, which is specified as one of the packages to scan in the Configuration.
Try adding #Configuration to AggTradeEventSubscriptionListener.

Load multiple external configuration file in spring boot

How to load multiple external configuration properties file in spring boot. Please find the below command to load external properties file when run the jar file.
"java -jar -Dspring.config.location= myBootProject.jar"
Like we add one or two configuration path, but when we add more than two configuration then how would we configure?
In spring you can do like below:
#Configuration
#PropertySource({
"classpath:app-config.properties",
"classpath:dtabase.properties"
})
public class AppConfig {
#Autowired
Environment env;
}
If you are using spring4 and Java8 or Greater:
#Configuration
#PropertySources({
#PropertySource("classpath:app-config.properties"),
#PropertySource("classpath:database.properties")
})
public class AppConfig {
//configuration classes
}
If a property key is duplicated, the last declared file will ‘win’ and override.
Read this for more information and complete samples
https://www.mkyong.com/spring/spring-propertysources-example/
Hope it helps!

How to replace properties in application.properties in src/main/resources in spring boot

I am using Spring boot application and having application.properties property file in src/main/resources. It has some properties which needs to replaced by external property file. I will pass the external file location in command line.
Need solution how to replace the properties inside application with external properties.
public static void main(String[] args) throws JMSException, MQException, IOException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("Application.properties");
Properties properties = new Properties();
properties.load(input);
properties.load(new FileReader(args[0]));
SpringApplication springApplication = new SpringApplication(new Object[]{ChapsSchemeFeed.class});
springApplication.setDefaultProperties(properties);
springApplication.run(args);
}
In this code, I am reading properties from command line and loading them with application.properties residing in application. But when I start, its loading properties from Application.properties. But I want to replace it with property from command line properties file.
From the Spring Boot manual:
Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values. Properties are considered in the following order:
Devtools global settings properties in the $HOME/.config/spring-boot folder when devtools is active.
#TestPropertySource annotations on your tests.
properties attribute on your tests. Available on #SpringBootTest and the test annotations for testing a particular slice of your application.
Command line arguments.
Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).
ServletConfig init parameters.
ServletContext init parameters.
JNDI attributes from java:comp/env.
Java System properties (System.getProperties()).
OS environment variables.
A RandomValuePropertySource that has properties only in random.*.
Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).
Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
Application properties outside of your packaged jar (application.properties and YAML variants).
Application properties packaged inside your jar (application.properties and YAML variants).
References:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Change search location in Spring boot 1.3.0

I would like externalize the configuration of my aplication, I use Spring Boot 1.3.0, and I kwnow that the class ConfigFileApplicationListener has a default value DEFAULT_SEARCH_LOCATIONS. How can I change the source of my configuration, before this class load the default properties source?
You can use #PropertySource annotation on your configuration class (which is annotated #SpringBootApplication or #Configuration).
Like this:
#SpringBootApplication
#PropertySource(value = { "classpath:other.properties", "file:./other-external.properties" }, ignoreResourceNotFound = true)
public class MyApplication {
It will search first other.properties in your classpath and then looks the external file other-external.properties right outside of your jar or war file. Latest files overwrites values of other files (if they exists)
See https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html for more details.

Resources