4

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.

user3105453
  • 1,881
  • 5
  • 32
  • 55

3 Answers3

10

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.

Raja Anbazhagan
  • 4,092
  • 1
  • 44
  • 64
  • Thanks Raja, I really like your solution and I think it's a very clean one. Unfortunately, this setup requires `META-INF/build-info.properties` to be present, otherwise the mentioned bean and logback will throw errors. It's no problem to compile an artifact like this but as soon as the project is imported in my IDE (IntelliJ), the respective buildInfo task isn't run. By default, Gradle compiles to `build/`, whereas IntelliJ compiles to `out/`. I'll accept your answer since I wasn't asking for local development options. – user3105453 May 07 '18 at 06:46
  • If that's your your problem you can always configure your compilation output directories to your need... – Raja Anbazhagan May 07 '18 at 06:48
2

You need to add the file META-INF/build-info.properties as @PropertSource to your Spring-Boot-Application:

@SpringBootApplication()
@PropertySource("classpath:META-INF/build-info.properties")
public class MyApp implements WebMvcConfigurer { 
  ...
}

After that you can access the property build.version via @Value in your Controller/Service/...

@Controller(...)
public MyController {
    @Value("${build.version}") String myVersion;
    ...
}
Tarator
  • 1,517
  • 1
  • 13
  • 30
1

As of Spring 2.4, you can use the spring.config.import property. For example, in application.yml:

spring.config.import: "classpath:META-INF/build-info.properties"
...
sentry.version: ${build.version}

Similarly @Value("${build.version}") also works, or accessing the property in logback-spring.xml.

Adrian Baker
  • 9,297
  • 1
  • 26
  • 22