Java system properties, properties defined inside application.properties file and properties defined in pom.xml file, are they the same ?
What is different between all of these properties ?
Is it possible to reference one through the other (eg, pass system property from pom.xml file ...)
Are they all part of Java or JEE standard ? which one is ?
Not the same.
Java system properties are pure Java. They are part of Java. Values can be set from the command line and within code with System.getProperties.setProperty()
Maven properties are in pom.xml with ‘<properties’>’<property’> tag. Maven is a build tool so these properties are used at build time.
Spring framework properties (application.properties or application.yaml). These properties are read at runtime, mostly during startup. Standard properties are read by Spring classes, eg spring.data.source.url. They can also be accessed in code with #Value
You can get pom properties into application.properties with the following in the application.properties file:
foo.bar=#application.name#
You can get application.properties into system properties with the following in a class:
#Value(${foo.bar})
String applicationName;
System.getProperties.setProperty("application.name", applicationName)
Related
In a spring boot application, I have a property in application.properties
spring.datasource.url: jdbc:mysql://host1:3306/test?useSSL=false&autoReconnect=true
However when I start the application, it is connecting to a totally different database.
So when I checked the env values in /actuator/env it url, it shows that the value is getting overrided by an environment property
SPRING_DATASOURCE_URL": {
"value": "jdbc:mysql://host2:3306/test",
"origin": "System Environment Property \"SPRING_DATASOURCE_URL\""
}
I have no idea where this environment property is configured.
I just want it to pick from my property file and not the environment. Is there any way to do that?
there are 17 ways to set and override properties in spring boot and they are ordered,
for example- application.properties outside the jar comes before application.properties inside the jar.
you could search potential source that override your properties in all those ways-
(ordered from strongest to weakest ) - copied from spring boot reference -https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config
Devtools global settings properties in the $HOME/.config/spring-boot directory 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).
#PropertySource annotations on your #Configuration classes. Please note that such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging.* and spring.main.* which are read before refresh begins.
Default properties (specified by setting SpringApplication.setDefaultProperties).
I want to read Spring's boot active application.properties file a jar file that I add as Maven dependency.
We mange environment params via 3-4 files under publish folder, for example:
-publish
--some.project-application.properties.test
--some.project-application.properties.dev
in the project root so I cannot use PropertySources(different file name per env).
So is there is a way to read the active(in use) application.properties file?
Is using #Value annotation will work without any configuration?
I think you should use spring naming conventions(application.properties, application-dev.properties), so that spring will automatically take the correct property file from the class path.
Also, refer : How to resolve placeholder in properties file with values from another properties file in spring boot application
Spring has an explicit order for the loading of externalized configurations.
Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).
#TestPropertySource annotations on your tests.
#SpringBootTest#properties annotation attribute on your tests.
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).
#PropertySource annotations on your #Configuration classes.
Default properties (specified by setting SpringApplication.setDefaultProperties).
However, there seems to be a glaring omission for configurations coming from Spring Cloud Config. Does anyone know where Spring Cloud Config fit above
As others have stated, the config-server comes first. If you are trying to override the config-server's properties with local properties (i.e. application-local.yml), then you need to add two properties to the config-server**:
spring.cloud.config.allowOverride=true
spring.cloud.config.overrideNone=true
Per the documentation:
The property sources that are added to you application by the
bootstrap context are often "remote" (e.g. from a Config Server), and
by default they cannot be overridden locally. If you want to allow your applications to override the remote
properties with their own System properties or config files, the
remote property source has to grant it permission by setting
spring.cloud.config.allowOverride=true (it doesn’t work to set this
locally). Once that flag is set there are some finer grained settings
to control the location of the remote properties in relation to System
properties and the application’s local configuration:
spring.cloud.config.overrideNone=true to override with any local
property source, and
spring.cloud.config.overrideSystemProperties=false if only System
properties and env vars should override the remote settings, but not
the local config files.
Also see this, regarding using spring.cloud.config.override-system-properties=false to override via system / command line properties. The documentation quoted above had/has an inconsistency, which I removed from the quote.
Note, if you want the remote config server to override your local properties file sources but not your local system properties or environment properties, add the following in the config server:
spring.cloud.config.allowOverride=true
spring.cloud.config.overrideNone=false
spring.cloud.config.overrideSystemProperties=false
** In this case the overrideSystemProperties value is ignored. See org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration#insertPropertySources
Note: All the above applies to Spring Boot 2.3.x. Version 2.4.x uses an alternate loading priority. See https://github.com/spring-cloud/spring-cloud-config/issues/1856
The documentation states that:
The bootstrap properties show up in the /env endpoint as a high-priority property source, as shown in the following example
So it would be position #0
Points 12 and 14 cover Spring Cloud Config.
12.Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).
14.Application properties outside of your packaged jar (application.properties and YAML variants).
I need to use two *.properties file to determine config of Spring Boot application server. How can I set the second configuration path?
I use spring-boot-starter-parent version 1.5.10 and such *.properties file:
spring.datasource.url=url
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialec
spring.jpa.properties.hibernate.current_session_context_class=
org.springframewok.orm.hibernate4.SpringSessionContext
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.idle-timeout=30000
Now, I need to address database info from another properties file.
Edit: Note that I need to put second properties file outside of my WAR file in WEB-INF folder.
(1) This is best practices when switching between development mode and production environment.
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html#boot-features-profiles
Reference for version 1.5.10.RELEASE: https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#boot-features-external-config-profile-specific-properties
For more specific, you create 3 files
application.properties for common properties.
application-dev.properties for only own properties what used in profile dev
application-production.properties for only own properties what used in profile production
(Notice: Has convention over naming)
Point profile what used, in application.properties has line spring.profiles.active=dev (in development) or spring.profiles.active=production (in production)
(2)
Note that I need to put second properties file outside of my WAR file
in WEB-INF folder.
Assumption, your file is foo.properties. It is outside WAR file, it has not nature of Spring's properties file. Therefore, Spring Framework/Spring Boot can not read it automatically. You must write few lines of Java code to reading the content of foo.properties, then assign to configuration manually (see example configuration class)
You can access multiple of properties file using #PropertySource
Follow the following stackoverflow thread.
https://stackoverflow.com/a/47178674/7538821
I have a spring boot application that I can package in a war that I want to deploy to different environments. To automate this deployment it'd be easier to have the configuration file externalized.
Currently everything works fine with a application.properties file in src/main/resources. Then I use ´mvn install´ to build a war deployable to tomcat.
But I would like to use a .yml file that does not need to be present on mvn install but that would be read from during deployment of the war and is in the same or a directory relative to my war.
24. externalized configuration shows where spring boot will look for files and 72.3 Change the location of external properties of an application gives more detail on how to configure this but I just do not understand how to translate this to my code.
My application class looks like this:
package be.ugent.lca;
Updated below
Do I need to add a #PropertySource to this file? How would I refer to a certain relative path?
I feel like it's probably documented in there as most spring boot documentation but I just don't understand how they mean me to do this.
EDIT
Not sure if this should be a separate issue but I think it's still related.
Upon setting the os variable the error of yaml file not found went away. Yet I still get the same error again as when I had no application .properties or .yml file.
Application now looks like this:
#Configuration
**#PropertySource("file:${application_home}/application.yml")**
#ComponentScan({"be.ugent.lca","be.ugent.sherpa.configuration"})
#EnableAutoConfiguration
#EnableSpringDataWebSupport
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
The application_home OS variable
$ echo $application_home
C:\Masterproef\clones\la15-lca-web\rest-service\target
My application.yml file(part it complains about):
sherpa:
package:
base: be.ugent.lca
Error upon java -jar *.war
All variations upon:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'sherpa.package.base' in string value "${sherpa.package.base}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:172)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:808)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1027)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
... 142 more
Using external properties files
The answer lies in the Spring Boot Docs, I'll try to break it down for you.
First of all, no you should not use #PropertySource when working with Yaml configuration, as mentioned here under the Yaml shortcomings :
YAML files can’t be loaded via the #PropertySource annotation. So in the case that you need to load values that way, you need to use a properties file.
So, how to load propery files? That is explained here Application Property Files
One is loaded for you: application.yml , place it in one of the directories as mentioned in the link above. This is great for your general configuration.
Now for your environment specific configuration (and stuff like passwords) you want to use external property files, how to do that is also explained in that section :
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).
So you use the spring.config.location environment property.
Imagine you have an external config file: application-external.yml in the conf/ dir under your home directory, just add it like this:
-Dspring.config.location=file:${home}/conf/application-external.yml as a startup parameter of your JVM.
If you have multiple files, just seperate them with a comma. Note that you can easily use external properties like this to overwrite properties, not just add them.
I would advice to test this by getting your application to work with just your internal application.yml file , and then overwrite a (test) property in your external properties file and log the value of it somewhere.
Bind Yaml properties to objects
When working with Yaml properties I usually load them with #ConfigurationProperties, which is great when working with for example lists or a more complex property structure. (Which is why you should use Yaml properties, for straightforward properties you are maybe better of using regular property files). Read this for more information: Type-Safe Configuration properties
Extra: loading these properties in IntelliJ, Maven and JUnit tests
Sometimes you want to load these properties in your maven builds or when performing tests. Or just for local development with your IDE
If you use IntelliJ for development you can easily add this by adding it to your Tomcat Run Configuration : "Run" -> "Edit Configurations" , select your run configuration under "Tomcat Server" , check the Server tab and add it under "VM Options".
To use external configuration files in your Maven build : configure the maven surefire plugin like this in your pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dspring.config.location=file:${home}/conf/application-external.yml</argLine>
</configuration>
</plugin>
When running JUnit tests in IntelliJ:
Run → Edit Configurations
Defaults → JUnit
add VM Options -> -ea -Dspring.config.location=file:${home}/conf/application-external.yml
Yes, you need to use #PropertySource as shown below.
The important point here is that you need to provide the application_home property (or choose any other name) as OS environment variable or System property or you can pass as a command line argument while launching Spring boot. This property tells where the configuration file (.properties or .yaml) is exactly located (example: /usr/local/my_project/ etc..)
#Configuration
#PropertySource("file:${application_home}config.properties")//or specify yaml file
#ComponentScan({"be.ugent.lca","be.ugent.sherpa.configuration"})
#EnableAutoConfiguration
#EnableSpringDataWebSupport
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
There is a very simple way to achieve this.
Inside your original application.properties file you can just specify the following line:
spring.config.import=file:Directory_To_The_File/Property_Name.properties
It will automatically sync all the properties from the external property file.
Now lets say that you have a situation where you need to get properties from multiple property files. In that case, you can mention the same line in the external property file which in turn will take the remaining properties from the second property file and so on.
Consider the following example.
application.properties:
spring.config.import=file:Resources/Custom1.properties
Custom1.properties:
server.port=8090
.
.
.
spring.config.import=file:Resources/Custom2.properties
One of the easiest way to use externalized property file using system environment variable is, in application.properties file you can use following syntax:
spring.datasource.url = ${OPENSHIFT_MYSQL_DB_HOST}:${OPENSHIFT_MYSQL_DB_PORT}/"nameofDB"
spring.datasource.username = ${OPENSHIFT_MYSQL_DB_USERNAME}
spring.datasource.password = ${OPENSHIFT_MYSQL_DB_PORT}
Now, declare above used environment variables,
export OPENSHIFT_MYSQL_DB_HOST="jdbc:mysql://localhost"
export OPENSHIFT_MYSQL_DB_PORT="3306"
export OPENSHIFT_MYSQL_DB_USERNAME="root"
export OPENSHIFT_MYSQL_DB_PASSWORD="123asd"
This way you can use different value for same variable in different environments.
Use below code in your boot class:
#PropertySource({"classpath:omnicell-health.properties"})
use below code in your controller:
#Autowired
private Environment env;