I am trying to externalize my ignite configuration in my spring boot application so the configuration can be changed without rebuilding the jar.
Previously the file resided in src/main/resrouces and was loaded via annotations.
#ImportResource("IgniteConfig.xml") and
#Autowired
private IgniteConfiguration cfg;
When I moved the IgniteConfig.xml to the config folder that resides next to the excutable jar the above stopped working and I have tried the following without success:
use --spring.config.location argument. I can tell this is picked up during run time as other configurations work but the above ImportResource annotation says the file IgniteConfig.xml cannot be found.
use a relative path to (e.g. ./config.IgniteConfig.xml) to Ignition.start. I cause this relative path to print the file contents of the xml file in my logs but when I pass it to Ignition.start it says the file cannot be found. I have tried using relative and absolute paths to do this.
Manually create an ApplicationContext and get the configuration by bean name.
ApplicationContext context = new ClassPathXmlApplicationContext("./config/IgniteConfig.xml");
This again complains that the file does not exist even though I can see by opening the file directly:
File igniteConfigFile = new File("./config/IgniteConfig.xml");
The comment by konqi in this post answered my question:
"In case you want to import a resource that is outside the classpath the syntax would be:
#ImportResource( { "file:path/spring-context1.xml", "file:path/spring-context2.xml" } )
"
In my case I just needed to do:
#ImportResource( { "file:./config/IgniteConfig.xml" } )
I have a config folder of xml files that my spring boot app needs , its located on the same level of src folder ... Now i now to locate it in Resources Folder on the same level of application.properties.. There is any way to be able to do that ?
There many way to read your file .properties:
You can read with plain java like this:
Properties properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName));
you can use the #PropertySource annotation in a Spring #Configuration class:
#Configuration
#PropertySource("db.properties")
public class ApplicationConfig {
// more config ...
}
//Or if you your config outside of your classpath, you can use the file: prefix:
#PropertySource("file:/path/to/application.properties")
Using Multiple file :
#PropertySources({
#PropertySource("classpath:foo.properties"),
#PropertySource("classpath:bar.properties")
})
public class PropertiesWithJavaConfig {
//...
}
And so on ...
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;
I have a property bean (example):
#Data
public class MyProperty {
private String name;
private String address;
}
and I have a custom yml file in classpath named: my_property.yml
my.property:
name: testName
address: testAddress
How to load this file to my property bean?
Not using #PropertyResource, because I want to use the yml file.
Thanks.
#PropertySource is the way to include external/custom properties but unfortunately is doesn't work with yaml files due to this issue.
You need to load these yaml files on your own by simply writing EnvironmentPostProcessor and adding it META-INF/spring.factories.
This is described in below Spring documentation (slight difference among versions).
Spring boot 1.5.x
Spring boot 2.x
There are two properties you can look at -
spring.config.name - If you don't like application as your file name
for eg-
java -Dspring.config.name = my_property myjar.jar
spring.config.location - To tell where your files lie
More information is well-documented here
spring documentation
Follow: http://www.baeldung.com/spring-yaml
The relative path of application.yml file is /myApplication/src/main/resources/application.yml.
and access is:
#Autowired
private YAMLConfig myConfig;
I put my application.properties file at src/main/resources/
End my #SpringBootApplication read.
application.properties file
spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=***
spring.datasource.username=***
spring.datasource.password=***
This is how I have set up external configuration file:
/** for .yaml file
#Configuration
#PropertySource("classpath:waterlvl.yaml")
#ConfigurationProperties("Alerts")
public class WaterLvlAlertConfig {
/** for .properties file
#Component
#PropertySource("classpath:waterlvl.properties")
public class WaterLvlConfig {
Properties are not being picked up, and my files are inside the resources file. I think the path I'm providing is wrong. What am I doing wrong?
In spring boot #PropertySource cannot be used when using .yaml configuration. Refer to point 24.6.4 YAML shortcomings in externalized configuration documents. Also, a similar question is answered earlier, refer - Spring boot external configuration of property file