Version endpoint in Spring Boot

When generating your Spring Boot project using Spring Initializr, you already have the spring-boot-maven-plugin plugin in your Maven pom.xmlfile.

Generating build info is done by adding the build-info goal. This results in a /META-INF/build-info.properties file in your resulting package. By default this contains group id, artifact, buildtime and version of the project.

Off course you can add additional properties in the additionalProperties element. Just like you define properties in any Maven section.

Below is the relevant snippet from a Spring Boot application. It contains

  • the spring-boot-maven-plugindefinition
  • the build-infogoal
  • additional properties such as application name and application description. You can add as many as you like
<build>
   <plugins>
      <plugin>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-maven-plugin</artifactId>
         <executions>
            <execution>
               <goals>
                  <goal>build-info</goal>
               </goals>
               <configuration>
                  <additionalProperties>
                     <java.source>${maven.compiler.source}</java.source>
                     <java.version>${java.version}</java.version>
                     <application.name>${project.name}</application.name>
                     <application.description>${project.description}</application.description>
                  </additionalProperties>
               </configuration>
            </execution>
         </executions>
      </plugin>
   </plugins>
</build>

Next part is to read this properties file. Thank god for BuildProperties . Spring Boot also creates a Bean when starting an application, so you can just auto wire it to a field.

Only downside is that this class is not related to the default java.util.Propertiesclass. So you have to create an intermediate Propertiesobject and copy all (key,value) pairs from the buildProperties to the property object you want to return. This is required as the BuildPropertiesclass does not define getters for custom properties

The timeproperty had to be transformed to a String as the default Instantdoes not map properly to json.

If you put all things together, you get the following controller.

@RestController
@RequestMapping("/version")
public class BuildInfoController {
    @Autowired
    private BuildProperties buildProperties;

    @GetMapping
    public Properties getInfo() {
        Properties prop = new Properties();
        //need to explicitly loop over all entries, just returning the BuildProperties object only contains the specific fields (artificact, group, name, time and version)
        buildProperties.forEach(entry -> prop.put(entry.getKey(),entry.getValue()));
        //proper date formatting for time
        prop.put("time", Instant.ofEpochMilli(Long.parseLong(prop.getProperty("time"))).toString());
        return prop;
    }
}

Now you can run the application and do a request for localhost:8080/version, and this results in the following json:

{  
   "name":"ta",
   "java.version":"1.8",
   "time":"2019-02-05T13:13:48.282Z",
   "application.description":"Demo project for Spring Boot",
   "application.name":"ta",
   "version":"0.0.1-SNAPSHOT",
   "java.source":"1.8",
   "group":"com.example.edev.ott",
   "artifact":"ta"
}

Summary

To conclude: only two steps required for a version endpoint:

  1. configure Maven and add your custom properties if required
  2. create a RestController, auto-wire BuildProperties and transform it to java.util.properties , Map or whatever you want