javaspringspring-bootmavenspring-boot-starter

How to load Maven project properties in Spring Boot Starter and add to Environment?


Let's assume there are multiple Spring Boot applications having properties with @...@ placeholders referring to Maven project properties:

spring.application.name=@project.name@
version=@project.version@
...

Since it's common to all applications, it would be useful to create a custom Spring Boot starter, to prevent duplication, that would add those properties to the Environment with the lowest precedence.


In the custom starter, I added the properties to the custom.properties file and created CustomEnvironmentPostProcessor to load them:

public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor {

    private final PropertiesPropertySourceLoader loader = new PropertiesPropertySourceLoader();

    @Override
    public void postProcessEnvironment(
            ConfigurableEnvironment environment, SpringApplication application) {
        ClassPathResource path = new ClassPathResource("custom.properties");
        PropertySource<?> propertySource = loadProperties(path);
        environment.getPropertySources().addLast(propertySource);
    }

    private PropertySource<?> loadProperties(ClassPathResource path) {
        Assert.isTrue(path.exists(), () -> "Resource " + path + " does not exist");
        try {
            return this.loader.load("custom-properties", path).get(0);
        } catch (IOException ex) {
            throw new IllegalStateException("Failed to load properties configuration from " + path, ex);
        }
    }
}

Unfortunately, those properties are not covered by resource filtering. The build part in the applications' pom.xml is shown below:

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

The question is is it possible to cover the starter's properties file by resource filtering? Or is there any other or better way to load properties from pom.xml and add them to the Environment before it starts?


Solution

  • One possible solution to read Maven properties is to use MavenXpp3Reader from the maven-model dependency.

    <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-model</artifactId>
       <version>3.8.6</version>
    </dependency>
    

    The EnvironmentPostProcessor, which adds properties to the Spring Environment, should be defined as follows:

    public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor {
    
      private final MavenXpp3Reader reader = new MavenXpp3Reader();
    
      @Override
      public void postProcessEnvironment(
          ConfigurableEnvironment environment, SpringApplication application) {
        try (FileReader fileReader = new FileReader("pom.xml")) {
          Model model = reader.read(fileReader);
    
          Map<String, Object> properties = new HashMap<>();
          properties.put("spring.application.name", model.getName());
          properties.put("version", model.getVersion());
          environment
              .getPropertySources()
              .addLast(new MapPropertySource("custom-properties", properties));
        } catch (Exception e) {
          throw new IllegalStateException(e);
        }
      }
    }