Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring boot external configuration of property file

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
like image 499
turoni Avatar asked Mar 25 '17 18:03

turoni


People also ask

How do I put external properties in spring boot?

Load Using Profiles Additional to the default one, Spring Boot provides the way to use active profiles to load additional configurations via java command or java programmatically. Now, Add the new property file named application-error. properties in the classpath and add error codes into the file.

How do you externalize a constants from a Spring configuration file into a properties file?

You can use properties files, YAML files, environment variables and command-line arguments to externalize configuration. Property values can be injected directly into your beans using the @Value annotation, accessed via Spring's Environment abstraction or bound to structured objects.

How do you specify file path in application properties in spring boot?

Spring Boot loads the application. properties file automatically from the project classpath. All you have to do is to create a new file under the src/main/resources directory.

How do I set environment specific properties in spring boot?

Environment-Specific Properties File. If we need to target different environments, there's a built-in mechanism for that in Boot. We can simply define an application-environment. properties file in the src/main/resources directory, and then set a Spring profile with the same environment name.


2 Answers

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
like image 193
loïc Avatar answered Oct 19 '22 04:10

loïc


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);
    }
}
like image 8
developer Avatar answered Oct 19 '22 05:10

developer