We are using a spring boot application, where properties are loaded from application.yml file instead of application.properties, located at src/main/resources/ which looks like below:
config:
host: localhost:8080
server: 123
And they are being pulled in a .java file like this
#ConfigurationProperties( prefix="config")
public class ConnectionImpl implements Connection{
#Value("${config.host}")
private Stringhost;
}
I am able to retrieve properties this way.
But we are trying to move the config properties from application.yml to a different .yml file which is located at a different location. (src/main/resources/env-config).
Now I am not able to retrieve properties same way, i.e, using #Value annotation. Is there any other annotation I need to add ?
From the documentation:
SpringApplication will load properties from application.properties (or application.yml) files in the following locations and add them to the Spring Environment:
A /config subdirectory of the current directory.
The current directory
A classpath /config package
The class path root
If you don’t like application.properties as the configuration file name you can switch to another by specifying a spring.config.name environment property. You can also refer to an explicit location using the spring.config.location environment property (comma-separated list of directory locations, or file paths).
The default search path classpath:,classpath:/config,file:,file:config/ is always used, irrespective of the value of spring.config.location. This search path is ordered from lowest to highest precedence (file:config/ wins). If you do specify your own locations, they take precedence over all of the default locations and use the same lowest to highest precedence ordering. In that way you can set up default values for your application in application.properties (or whatever other basename you choose with spring.config.name) and override it at runtime with a different file, keeping the defaults.
You need to supply a command line argument that tells SpringApplication where specifically to look. If everything in resources/ is added to the classpath root, then your command line would look like:
java -jar myproject.jar --Dspring.config.location=classpath:/env-config/service-config.yml
If you have a general application.yml under resources/, the properties in there will still be loaded but will take a lower precedence to the properties file specified on the command line.
Your question doesn't really say what you intend to do, but if you want to have a different configuration for different environments (e.g. development, test, production), there is a simple solution for that.
Place your config files in a file hierarchy like this inside your project:
src/
main/
resources/
application.yml
application-development.yml
application-test.yml
application-production.yml
When you now start your application with
java -jar mySpringApplication.jar -Dspring.profiles.active=development
the configuration from application.yml will be taken as a "base layer", overridden by the configuration in application-development.yml. By this, you can have "default" settings for all environments in application.yml and environment-specific configuration in the application-ENV.yml files. The same works for test and production.
No.
You'll be in a much better position if you avoid hard-coding file path like that within your code base. #ConfigurationProperties used to have a locations attribute but it's deprecated and already removed in 1.5.
In Spring Boot, you configure the Environment which is a single source of truth for your configuration. Rather than having settings buried in code, you should configure Spring Boot to read the files that you want. Read the documentation for spring.config.location. If you want to do this in a more transparent manner, perhaps EnvironmentPostProcessor is what you need
Related
I am new to Springboot and I am having trouble with externalizing my properties files.
I have multiple ".properties" files that I have kept in a subdirectory "config/". I have removed context-placeholders from my project and have included the comma-separated properties files while executing the jar.
eg. java -jar myjar.jar --spring.config.location=file:////config/PROP1.properties, file:///config/PROP2.properties -debug
I have few questions
Why are the files in the config directory not being read even after explicitly mentioning where to look?
I have my own dependencies in the project that have same-named properties files packed in its jar. Is that creating any sort of problem when SpringBoot tries to read the files from the config folder while executing my project jar?
Update
Now I am keeping only a single properties file suppose ABC.properties outside the jar in the same directory . I am using the name "ABC" instead of "application". I am using the below command
java -Dserver.log.dir=/path/to/log/dir -jar myjar.jar --server.port=9090 --spring.config.name=ABC --prop1=val1
I have overriden a property in my external property file but I don't see the overriden value being used when I run the application. My new questions are
Is there anything wrong with the command-line?
I have the following line in xml bean configuration
<context:property-placeholder location="ABC.properties" />. Is this causing any sort of problems to detect and use the external properties?
If the above is true and I have to remove the line how will SpringBoot understand from where the property values are to be imported?
(Not related directly to the question) Is there a order that I need to follow while giving command line arguments?
Spring boot has explicit indicate how to write this external configuration. See doc ref here: https://docs.spring.io/spring-boot/docs/2.5.2/reference/htmlsingle/#features.external-config.files
Basically, you need to specify the location like this:
--spring.config.location=classpath:/somefolder/somefile.properties
--spring.config.location=file:./somefolder/somefile.properties
From your command line, it seems that you are missing one dash, and also using a wrong format of file schema.
Q1: Why are the files in the config directory not being read even after explicitly mentioning where to look?
A1: If your config folder is beside your jar file, your command should be like
java -jar myjar.jar --spring.config.location=file:./config/PROP1.properties
meanwhile, you can also use the full path to target your config file.
Q2: If I don't mention the properties files names explicitly as an argument then they won't be picked up even when they are in the config directory
A2: No. See this doc, Spring Boot will try to find config files from the four places:
A /config subdir of the current directory.
The current directory
A classpath /config package
The classpath root
If spring.config.location is not set, files in these folders named application.properties will be treated as valid config file. You can change the accepted file name by setting property spring.config.name.
Q3 About Config File Priority
A3 As described in the doc mentioned earlier, if same name properties appear in different config files, locations higher in the list override lower items.
Another tip, it will be better to remove config files inside the jar file, so you can get a full view of configuration just in one place (the externalized config folder);
I have a spring boot maven java application. I have the application.yml file and the properties specified here are used by a jar dependency of the project and I want to keep this file for them dependencies alone.
There is some additional config I want to use in the application. Is there a way to specify a second configuration file to be used within the project?
Thanks
You can use #PropertySource({"classpath:first.properties", "classpath:second.properties"}) like given below,
#Component
#PropertySource("classpath:config.properties")
public class MySeparateProperties
{
#Value( "${property.path.name}" )
private String prop;
}
Now use this bean to use the properties where ever you want in your application
The only issue is that, if the property path is same for application.yml and config.properties application.yml will have higher priority
Edit 1
If the file is located at resources/config/config.properties then you have to give classpath:config/config.properties
You can specify a different name using the property spring.config.name.
From the docs:
If you do not like application.properties as the configuration file name, you can switch to another file name by specifying a spring.config.name environment property.
Create property file as example x.properties and use #PropertySourse(“classpath:x.propeties”)
When need to use it
Configuration files can be set by spring properties, you can use:
spring.config.name to select the names of the configuration files (separated by comma)
spring.config.location to set the paths where the configuration files are located (separted by comma)
Try to look at springboot reference doc here for details.
I need two application.properties in my Spring Boot App.
I know that using the annotation #PropertySource I can specify more than 1 property files.
I tried to use: #PropertySource({"classpath:application.properties","classpath:external.properties"})
The idea of it is having application.properties with the machine independent properties and this file will be included inside the war file.
The other file (external.properties), will leave in the machine, and won't be included in the war file. Here I want to leave properties like the database connection and so on.
I've already changed catalina.properties for adding the external.properties location into the classpath, but unfortunately when running on Eclipse it doesn't work (complains about the missing database properties.).
If the external properties file will be available in a known location on the machine, then have an environment variable, system property, or command-line argument set up with the path to the file. Then, reference the file in you #PropertySource annotation using file: rather than classpath:
Example: #PropertySource("file:${CONF_DIR}/external.properties")
References:
Spring boot docs on external configuration
PropertySource documentation
Blog post regarding PropertySource
In my project I have seperate application.yml files for each environments, inside each folder for an environment.
NOTE: Below red color yml file made temporarily, to make the code work. But should remove this after fixing. So what I want is to use separate application.yml file according to environment. Specially I need to use local/application.yml for local development
Below has an example of getting env variables in my project
#Component
#Configuration
public class ApplicationProperties {
#Value("${ex.my.url}")
private String myServiceUrl;
// getters setters and nedded stuff
}
But it doesn't work, since could not find a way to mention the needed environment. Because it is in a seperate folder. All the other examples mention the way to get the yml file inside resource folder, without seperate folders.
Any fix for the issue?
in my projects, I specify a profile with the VM option :
-Dspring.profiles.active=local
Then I have a file named application-local.yml
in production :
-Dspring.profiles.active=prod , will use the file application-prod.yml
In the resources folder
Do make file of application.yml, application-local.yml, application-dev.yml etc.. what ever you want
and then in application.yml
spring.profile.active = ${ENV}
now during the run specify the ENV variables from run/debug configuration under Intellij or mention the profile for which you want to build the jar in application.yml.
Alternative, you can use the -D spring.profile.active=dev
at-first, from the documentation:
SpringApplication loads properties from application.properties files in the following locations and adds them to the Spring Environment:
A /config subdirectory of the current directory
The current directory
A classpath /config package
The classpath root
So, with passed directory hierarchy you'll get problems.
at-second, for file specification, you could use Profiles. This works as follows:
if no specified profiles - application.properties would be used
for any additional profile also would be used profile with name application-<name>.properties
Thus, if you specify dev and cool profiles, properties application.properties, application-dev.properties, `application-cool.properties, would be in use
UPDATE:
You could pass spring.config.location for property file path specify, but if you want directory hierarchy as you have - you need some customizations using context.initializers.classes and ApplicationContextInitializer
The classic solution is to setup one config file
(I prefer properties because I'm sane)
and allow for an overrides file to be placed on each installed host.
Spring supports this out-of-the-box.
Here is an example:
public static void main(final String[] argumentArray)
{
final StringApplicationBuilder springApplicationBuilder;
springApplicationBuilder = new SpringApplicationBuilder(YourSpringBootApplication.class)
springApplicationBuilder.properties(
"spring.config.location=classpath:/yourConfig.properties,/some/path/to/overrides/directory/yourConfig.properties");
springApplicationBuilder.build().run(argumentArray);
}
I am working with Java and spring boot. I was wondering how to add Property placeholders into .yml files. I've found some crisp examples but I am not sure where are the Property placeholders are being instantiated in. Is it in system env variables, a file, etc..?
Bootstrap.yml
spring:
cloud:
config:
username: ${my.stored.files.username}
password: ${my.stored.files.password}
label: ${spring.cloud.find.label}
uri: ${spring.cloud.config.uri}
enabled: false
failFast: true
User is using Property placeholders, but where did the user declared them?
Where is this .yml reading the values from? (same question as above)
Is there a document that explains the connection?
This web application will be pushed to cloud foundry using "cf push", Which will automatically pick manifest.yml file to configure. If possible a cloud foundry example would be great.
Understanding/ Sample Application.properties file
app.name=MyApp
app.description=${app.name}
User was able to use ${app.name} because it is defined. I am confused on the example above. How and where is the user getting "${my.stored.files.username}.
Where is that being defined? I assumed it would be in system.properties or environment variables. Can anyone confirm?
After intensive research, I was able to find that when I use placeholders in .yml files it reads that values from environment variables. Which was part of my theory in the beginning, but no one has confirmed.
Answer for local environment
spring:
cloud:
config:
username: ${my.stored.files.username}
password: ${my.stored.files.password}
label: ${spring.cloud.find.label}
uri: ${spring.cloud.config.uri}
enabled: false
failFast: true
*In environment variables *
set key as: my.stored.files.username
set value as: UsernameSample
Then
When you run application, yml will read like so.
config:
username: ${my.stored.files.username}
//gets replaced with UsernameSample
This is the link that solved my problem link
For Cloudfoundry
You would have to create cups or manually add these variables onto the service.
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files
SpringApplication loads properties from application.properties files in the following locations and adds them to the Spring Environment:
A /config subdirectory of the current directory
The current directory
A classpath /config package
The classpath root
The list is ordered by precedence (properties defined in locations higher in the list override those defined in lower locations).
You can also use YAML ('.yml') files as an alternative to '.properties'.
If you do not like application.properties as the configuration file name, you can switch to another file name by specifying a spring.config.name environment property. You can also refer to an explicit location by using the spring.config.location environment property (which is a comma-separated list of directory locations or file paths). The following example shows how to specify a different file name:
$ java -jar myproject.jar --spring.config.name=myproject
The following example shows how to specify two locations:
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
spring.config.name and spring.config.location are used very early to determine which files have to be loaded. They must be defined as an environment property (typically an OS environment variable, a system property, or a command-line argument).
If spring.config.location contains directories (as opposed to files), they should end in / (and, at runtime, be appended with the names generated from spring.config.name before being loaded, including profile-specific file names). Files specified in spring.config.location are used as-is, with no support for profile-specific variants, and are overridden by any profile-specific properties.
Config locations are searched in reverse order. By default, the configured locations are classpath:/,classpath:/config/,file:./,file:./config/. The resulting search order is the following:
file:./config/
file:./
classpath:/config/
classpath:/
When custom config locations are configured by using spring.config.location, they replace the default locations. For example, if spring.config.location is configured with the value classpath:/custom-config/,file:./custom-config/, the search order becomes the following:
file:./custom-config/
classpath:custom-config/
Alternatively, when custom config locations are configured by using spring.config.additional-location, they are used in addition to the default locations. Additional locations are searched before the default locations. For example, if additional locations of classpath:/custom-config/,file:./custom-config/ are configured, the search order becomes the following:
file:./custom-config/
classpath:custom-config/
file:./config/
file:./
classpath:/config/
classpath:/
This search ordering lets you specify default values in one configuration file and then selectively override those values in another. You can provide default values for your application in application.properties (or whatever other basename you choose with spring.config.name) in one of the default locations. These default values can then be overridden at runtime with a different file located in one of the custom locations.
After doing some research and experiments I found out placeholders can be both environment variables and command line arguments. The syntax for properties file worked in YAML file too. Environtment variable has already been explained by #Jesse. If you lets say pass command line argument:
--my.stored.files.username=UsernameSample or --username=UsernameSample, the configuration attribute would be filled as expected
my:
stored:
files:
username: ${username:defaultUsername}
I hope this might be helpful to someone having a similar issue.
ddsultan's answer works for me. just in case someone like me need to set placeholder value in idea. Edit run configuration, click Modify options, then check "Program options", in the newly added field, input the place holder value, for example "--section=4".
Please use {{your key}} as a place holder in case of .yml file