day0ops
day0ops

Reputation: 7482

Spring boot on Tomcat with external configuration

I can't find an answer to this question on stackoverflow hence im asking here so I could get some ideas.

I have a Spring Boot application that I have deployed as a war package on Tomcat 8. I followed this guide Create a deployable war file which seems to work just fine.

However the issue I am currently having is being able to externalize the configuration so I can manage the configuration as puppet templates.

In the project what I have is,

src/main/resources
                  -- config/application.yml
                  -- config/application.dev.yml
                  -- config/application.prod.yml
                  -- logback-spring.yml

So how can I possibly load config/application.dev.yml and config/application.prod.yml externally and still keep config/application.yml ? (contains default properties including spring.application.name)

I have read that the configuration is load in this order,

  1. A /config subdirectory of the current directory.
  2. The current directory
  3. A classpath /config package
  4. The classpath root

Hence I tried to load the configuration files from /opt/apache-tomcat/lib to no avail.

What worked so far

Loading via export CATALINA_OPTS="-Dspring.config.location=/opt/apache-tomcat/lib/application.dev.yml"

however what I would like to know is,

  1. Find out why loading via /opt/apache-tomcat/lib classpath doesn't work.
  2. And is there a better method to achieve this ?

Upvotes: 3

Views: 13032

Answers (2)

Nomad
Nomad

Reputation: 206

You are correct about load order. According to Spring boot documentation

SpringApplication will load properties from application.properties 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 classpath root

The list is ordered by precedence (properties defined in locations higher in the list override those defined in lower locations).

[Note]
You can also use YAML ('.yml') files as an alternative to '.properties'.

This means that if you place your application.yml file to /opt/apache-tomcat/lib or /opt/apache-tomcat/lib/config it will get loaded.

  1. Find out why loading via /opt/apache-tomcat/lib classpath doesn't work.

However, if you place application.dev.yml to that path, it will not be loaded because application.dev.yml is not filename Spring is looking for. If you want Spring to read that file as well, you need to give it as option
--spring.config.name=application.dev or -Dspring.config.name=application.dev.
But I do not suggest this method.

  1. And is there a better method to achieve this ?

Yes. Use Spring profile-specific properties. You can rename your files from application.dev.yml to application-dev.yml, and give -Dspring.profiles.active=dev option. Spring will read both application-dev.yml and application.yml files, and profile specific configuration will overwrite default configuration.

I would suggest adding -Dspring.profiles.active=dev (or prod) to CATALINA_OPTS on each corresponding server/tomcat instance.

Upvotes: 6

murali
murali

Reputation: 1

    I have finally simplified solution for reading custom properties from external location i.e outside of the spring boot project. Please refer to below steps.
Note: This Solution created and executed windows.Few commands and folders naming convention may vary if you are deploying application on other operating system like Linux..etc.

         1. Create a folder in suitable drive.
         eg: D:/boot-ext-config

         2. Create a .properties file in above created folder  with relevant property key/values and name it as you wish.I created dev.properties for testing purpose.
         eg :D:/boot-ext-config/dev.properties

            sample values:
            dev.hostname=www.example.com


        3. Create a java class in your application as below
        ------------------------------------------------------
        import org.springframework.boot.context.properties.ConfigurationProperties;
        import org.springframework.context.annotation.PropertySource;

        @PropertySource("classpath:dev.properties")
        @ConfigurationProperties("dev")
        public class ConfigProperties {
            private String hostname;

            //setters and getters
        }
        --------------------------------------------
         4. Add @EnableConfigurationProperties(ConfigProperties.class) to SpringBootApplication as below
        --------------------------------------------
        @SpringBootApplication
        @EnableConfigurationProperties(ConfigProperties.class)
        public class RestClientApplication {
            public static void main(String[] args)  {
                 SpringApplication.run(RestClientApplication.class, args);
        }
        }
        ---------------------------------------------------------
        5. In Controller classes we can inject the instance using @Autowired and fetch properties

        @Autowired
            private ConfigProperties configProperties;

        and access properties using getter method 
       System.out.println("**********hostName******+configProperties.getHostName());

Build your  spring boot maven project and run the below command to start application.

-> set SPRING_CONFIG_LOCATION=<path to your properties file>

->java -jar app-name.jar 

Upvotes: -1

Related Questions