Spring Boot & Multi module projects – Adding module specific property files [Updated]

Hello!

In this post I will show you several ways how you can add module specific properties files in a Spring Boot project. It will cover a manual approach for making the property files profile aware and a semi automatic way that is profile aware. An example project is published on my Github account (https://github.com/coders-kitchen/spring-boot-multi-module-property-files).

Reasons for having dedicated property files per module in a multi-module project are multifold. One is that you would like be able easily cut out the module into a own service. Having own property files per module, will help here as it makes it clear to the user, that he just has to extract all files from the module to have it standalone. Or that you would like to specify defaults per module that can be overwritten by the main properties.

In general there are three options

  • Specifying the additional property files via active profiles
  • Setting up a configuration in the modules that uses @PropertySource annotation
  • Making the spring context aware of additional file patterns

Let’s discuss one after the other:

Property files specified via active profiles

This approach uses the active profiles mechanism of Spring to activate additional property files. For example the active profile local would read also settings from the file application-local.properties.

The benefit of this approach are, that you just use the standard mechanism for adding new property files per module. And they can be specified in the main application.properties or dedicated application-<profile>.properties files.

The drawbacks are that you have to remember every time to add the active profiles in the right order, for example the profile module1 must be come right before module1-production to allow the latter one to overwrite the default profile.

Additionally you must remember that the default profile needs to be applied in all environment aka profiles to have the default settings available.

Manual via @PropertySource

Spring itself ships an annotation for adding additional property files to the context. It’s called @PropertySource and can be used on class level (see the next example).

To make this approach aware of multiple profiles you can use it this way

The benefits are, that you must not use dedicated profiles per module in the main application, but you can rely on simple profiles. Additionally it is expressed in the configuration classes itself, which could make it easy to check which profiles are available.

Drawbacks are that this works only very well for a pre-defined set of profiles this approach, but when you would like to add a new profile you have to remember that you must add it also to the MyPropertyConfig class. Additionally when you change the name of the module you must not only change the file names, but also the references in the code.

Adding new property file pattern to the property sources

This way is the most generic one, as it will directly inject the new property file patterns into the context and make it automatically profile aware. To get it working you must use the extension mechanics via ApplicationListener interface.

This allows you to directly listen on the ApplicationEnvironmentPreparedEvent event which is fired after the runtime environment is prepared but before it is loaded. It enables you to add files to the property sources for example. The event provides access to the ConfigurableEnvironment which provides among other things information about the active profiles.

This is an example implementation if the listener, that will first add the profile specific properties files and than the default property file to the ConfigurableEnvironment.

 

To activate it you must add it as an ApplicationListener when loading the application context, like this

The drawbacks are, that you must add the listener to the main module for each sub module. And using the additional / different property files (or at least the default variant) in the tests aren’t straight forward. You can utilize the @PropertySource annotation for that, but there is even a better way.

The alternative is to use the spring.factories file for this, thanks to Filip Hrisafov as he contributed this to the example project.

For the spring factories file you have to add

to the file META-INF/spring.factories. This will advice spring to register this listener also.

This approach has the major benefit, that integration tests will recognize the spring.factories file and the property files are also available also in integration tests.

The general benefits of this variants are, that we are agnostic of the active profiles and can easily add new profile specific property files. It also kicks in very early in the boot process so that the application is from the beginning on aware of the properties specified here.

Hint Please keep in mind that making the listener aware of all the cases that the default Spring loader supports is more complex than the approach described above.

Summary

We’ve discussed in this post several ways of adding new property files to a Spring Boot application. All variants have the benefits and drawbacks.

Depending on the use case I would either go for @PropertySource or the usage of ApplicationListener interface. The former one is good enough if you just want to have a common set of properties that could be overwritten for specific profiles or by the main modules properties. The latter one is the most generic approach and should be used, when you absolutely need this flexibility.

 
5 Kudos
Don't
move!

Leave a Reply

Your email address will not be published. Required fields are marked *