Indraneel Bende
Indraneel Bende

Reputation: 3486

How to externalize application.properties files in Spring Boot to e.g. external dependent JAR?

I have a simple Maven module (not a Spring Boot application) in which I have placed my application.properties file.

I have 6-7 Spring Boot applications and I don't want to have an application.properties file in each and every application directory. I prefer it, if it is at one single place (external Maven module).

I am adding the maven module as a dependency in each of those Spring Boot application poms.

But, when I run those applications, it is not able to auto-detect the application.properties file because it is coming from a dependent jar not present physically in each of their application directories.

Is there any way to make this possible? I would like to avoid having properties files in 6-7 different locations, because that becomes tough to manage and handle.

Thank you in advance!

Upvotes: 4

Views: 6086

Answers (2)

Mark Bramnik
Mark Bramnik

Reputation: 42541

While Szymon Stepniak's answer certainly is a "by-the-book" of Spring Boot answer, I understand your situation, and even tried to do what you try to do by myself. Indeed, you can't define application.properties in other "external modules".

Here is how I've solved it:

  1. Create a configuration in the "common" module
  2. Create a property file in src/main/resources. It shouldn't be named application properties, It's better to provide a unique name for it (at least this is how I've done it, so let's assume that the file is called application-common.properties)

  3. Use @PropertySources annotation to define a property file and load it with configuration.

Here is an example:

package com.myapp.common;
@Configuration
@PropertySources({
    @PropertySource("classpath:application-common.properties")
})
public class MyConfiguration {
    // you don't really have to define beans 
}

Now if you want this configuration to load automatically only because the dependency is defined in your spring boot module of your build system, I've found the best to utilize spring factories:

  1. Create the file src/main/resources/META-INF/spring.factories
  2. Place the following into this file:

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.myapp.common.MyConfiguration
    

Upvotes: 3

Szymon Stepniak
Szymon Stepniak

Reputation: 42272

Consider using Spring Cloud Config that provides server and client-side support for externalized configuration in a distributed system. It requires some small effort, but it is very useful in long term. Config server manages configuration files (.properties or .yml), you can still use different config per profile (e.g. application-test.properties, application-prod.properties etc.). Your application has a higher priority, so you can always override properties coming from config server if needed. Another cool feature is that config server can utilize Git repository, so you can easily version all your configuration files. It also supports encryption - any fragile data can be encrypted so only your application knows how to decrypt it.

Config server

Config server is nothing else than a simple Spring Boot application that can be implemented as:

@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
  public static void main(String[] args) {
    SpringApplication.run(ConfigServer.class, args);
  }
}

with simple application.properties file included:

server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo

with dependency in pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

Config client

On client side you add a dependency to your pom.xml (or its equivalent in build.gradle if you use Gradle):

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-client</artifactId>
</dependency>

and all you have to do is add a URL to config server to your application.properties (or application.yml if you use YAML insted):

spring.cloud.config.uri: http://myconfigserver.com

Config files structure

Now let's say you have set up Git repository for your configuration files. Let's assume that your applications are named like horus, venus, mercury etc. and you have 3 different profiles: dev, test and prod. You also have some configuration that is common for all applications. In this case your configuration files structure would look like this (I will use properties files here but it applies to YAML as well):

  • application.properties - common config for all apps no matter what profile they use
  • application-dev.properties - common config for all apps running with dev profile
  • application-test.properties - common config for all apps running with test profile
  • application-prod.properties - common config for all apps running with prod profile
  • horus.properties - horus app config for, common for all profiles
  • horus-dev.properties - horus app config for dev profile only
  • horus-test.properties - horus app config for test profile only
  • horus-prod.properties - horus app config for prod profile only
  • etc.

There are some additional options that can be set (like encryption, connection strategy (fail fast or ignore) etc.), everything is well described and documented in official documentation https://cloud.spring.io/spring-cloud-config/ Hope it helps you making a good choice for managing your configuration in distributed application environment. Config server is a solution that was invented to solve this problem.

Upvotes: 5

Related Questions