33

I have a spring-boot application which I want to run with external configuration file. When I run it as jar (with embedded servlet container), everything is fine. But I want to run it under external servlet container (Tomcat) and here i have problem with external configuration. I have tried a @PropertySource, but in this case application gets only properties absent in war file configuration: external configuration doesn't override internal configuration. So the question: how can I configure external configuration which will override internal configuration?

Simulant
  • 19,190
  • 8
  • 63
  • 98
Aram Aslanyan
  • 745
  • 3
  • 11
  • 18

4 Answers4

32

You're probably using external configuration in the form of application.properties in the current directory when you're running your application as a jar. However, "current directory" isn't very useful when deploying as a war in an external tomcat. Even if you find out what the current directory is, it's most likely the same location for all applications running in that tomcat, so when you're running more than one application, that's not going to work very well.

What we do here is this declare two PropertySources on our application:

@PropertySources({@PropertySource(value={"classpath:internal.properties"}), @PropertySource(value={"file:${application.properties}"})})

internal.properties contains "built in" default values for propeties. The second PropertySource is a file containing external configuration. Note how the name of the file is itself a property.

We define this externally in the Context element of our application (in tomcat):

<Context docBase="/path/to/your/war/your.war">
    <Parameter name="application.properties" value="/path/to/your/properties/application.properties"/>
</Context>

This allows you to have multiple applications running in tomcat, each application using it's own external properties file. You can even have multiple instances of the same application running with different properties.

ci_
  • 8,594
  • 10
  • 39
  • 63
  • 2
    Thanks for your response. Yes, this configuration will work and as I mentioned in my question I tried this solution. the shortcoming of this solution is that external configuration doesn't override the internal configuration. My question is how can I set priority on external configuration? – Aram Aslanyan Mar 18 '15 at 20:23
  • 1
    It should work, it does for me. Note that I'm not using the default name application.properties, which would have a different priority. Are you sure you've tried exactly what's in my answer? – ci_ Mar 18 '15 at 21:40
  • Yes, it works!:) I have changed the internal configuration name to internal.properties and it's works perfectly. Is there a way to reload external configuration at runtime? – Aram Aslanyan Mar 18 '15 at 22:34
  • I'm not aware of any way to do that, maybe another question? – ci_ Mar 18 '15 at 22:39
  • Added! http://stackoverflow.com/questions/29134315/reload-external-configuration-runtime-on-spring-boot – Aram Aslanyan Mar 18 '15 at 23:03
23

Spring Boot offer many ways to specify the location of your properties, it´s not needed to modify your sources.

Yo can define the spring.config.location value for example:

  • In your tomcat/conf/Catalina/<host> context descriptors:

    <Context>
        <Parameter name="spring.config.location" value="/path/to/application.properties" />
    </Context>
    
  • As a JVM parameter in your tomcat setenv.sh file:

    -Dspring.config.location=/path/to/application.properties
    
  • As a SPRING_CONFIG_LOCATION environment variable.

Rafael Membrives
  • 614
  • 5
  • 14
21

To externalize the Spring Boot application.properties when deploying as a war file you can set spring.config.location at the beginning when Spring Boot application is configured:

public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder springApplicationBuilder) {
        return springApplicationBuilder
                .sources(Application.class)
                .properties(getProperties());
    }

    public static void main(String[] args) {

        SpringApplicationBuilder springApplicationBuilder = new SpringApplicationBuilder(Application.class)
                .sources(Application.class)
                .properties(getProperties())
                .run(args);
    }

   static Properties getProperties() {
      Properties props = new Properties();
      props.put("spring.config.location", "classpath:myapp1/");
      return props;
   }

For more details check this solution.

Community
  • 1
  • 1
Daniel Mora
  • 2,589
  • 1
  • 25
  • 21
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – Necreaux Jun 26 '15 at 13:54
  • Ok @Necreaux essential parts were added – Daniel Mora Jun 26 '15 at 14:01
  • @Necreaux I do not understand the downvote after adding the essential parts? Is there anything still missing? – Daniel Mora Jun 26 '15 at 14:48
  • `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.` – coderatchet Jun 06 '17 at 04:47
0

You can add configuration files folder to set Classpath line catalina.bat, catalina.sh(which one if you want to use.) or you can add to setenv.bat/sh file. Your config files will be added to war classpath.

For Example;

In Windows env.

set CLASSPATH=D:\app\conf
mertaksu
  • 535
  • 1
  • 9
  • 26