spring-bootspring-boot-gradle-plugin

access buildInfo in Spring Boot 2.0 with @Value


Previously in Spring Boot 1.x, I wrote a Gradle task to copy the jar's build version to the application's application.yml and replaced a given property by regex, e.g. info.build.version: 0.0.1

Migrating to Spring Boot 2.0, I realise there's the io.spring.dependency-management plugin allowing me to define the buildInfo task:

springBoot {
    buildInfo()
}

This works and successfully displays the same information when accessing the /info actuator.

Now I would like to use the generated build.version in META-INF/build-info.properties in two use-cases:

  1. Display the version in SwaggerUI
  2. Include the version in each log line

Previously, it was enough to access the property like this: @Value("${info.build.version:undefined}") String buildVersion or in logback-spring.xml:

<springProperty scope="context" name="applicationVersion" source="info.build.version"/>

Unfortunately, both accessors don't work anymore, even if I replace info.build.version with build.version (as I would expect it to work).

I believe including the version in logback is just a small step away from accessing the property through the @Value annotation, so that's the core of my question:

How can I access the generated build.version in META-INF/build-info.properties through @Value?

I also tried adding the task

processResources {
    filesMatching('build-info.properties') {
        expand(project.properties)
    }    
}

as suggested in https://stackoverflow.com/a/42051412/3105453 but that doesn't seem to have any effect.


Solution

  • When it comes to spring-boot, Almost every information that spring handles is most likely is accessible as a spring managed bean.

    For build information, spring-boot has a bean exposed for autowiring called buildProperties. This happens via ProjectInfoAutoConfiguration module.

    Along with Spring Expression language (SpEL) support for @Value annotations, You can get the expected results as mentioned below.

    @Value("#{buildProperties.get('version')}")           // not 'build.version'
    private String myAppBuildVersion;
    

    Or better, Autowire the buildProperties bean directly to your components so you can play with it as you want.

    @Autowired
    private BuildProperties buildProperties;
    

    NOTE: The autoconfiguration strips off the build. prefix. So your SpEL expressions should use version as key. Not build.version.


    UPDATE:

    I was confused by your question first because the question was more over towards how to work with @Value annotation. So I will leave the above answer as is.

    To help you with the logback-spring.xml, import the build-info.properties into logback-spring.xml as shown below. This allows each key in build-info.properties to be accessed using logback place-holders. (DO NOT CONFUSE THIS WITH SPRING PROPERTY PLACEHOLDERS OR SPRING-EXPRESSIONS)

    <?xml version="1.0" encoding="UTF-8" ?>
    <configuration>
      <springProperty scope="context" name="appLogTarget" source="app.log.target"
        defaultValue="CONSOLE"/>
      <property resource="META-INF/build-info.properties" />
    
    
      <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
          <Pattern>[${build.version}] %d{ISO8601}" %-5p [%c{3}"] \(%t:%X{}"\) %m%n</Pattern>
        </layout>
      </appender>
     <root>
        <level value="DEBUG"/>
        <appender-ref ref="CONSOLE"/>
      </root>
    </xml>
    

    the "resource" property of <properties/> tag will look through the classpath resources and find the one which is appropriate.