105

How to get the maven project.version property in a Spring Boot application with a @Value annotation?

Jack G.
  • 3,681
  • 4
  • 20
  • 24

5 Answers5

152

After some research and trials on how to get the Maven project version in a SpringBoot application I couldn't find anything working for me.

Using a manifest is definitively a rotten path due to class loaders issues, i.e. one gets the first manifest Spring finds, which in my case was not the one of my application.

One solution I have found is to use the maven resources plugin to "filter" (replace) properties in resource files. In this case the Spring application.properties.

Below are the steps to make this work.

In the pom file, activate resources filtering with the following definition:

<resources>
    <resource>
        <filtering>true</filtering>
        <directory>src/main/resources</directory>
        <includes>
            <include>application.properties</include>
        </includes>
    </resource>
</resources>

In the application.properties file:

application.name=@project.artifactId@
build.version=@project.version@
build.timestamp=@timestamp@

Notice the @property@ instead of ${property}. in the application.properties file.

The spring-boot-starter-parent pom redefines the standard ${} delimiter as @:

<resource.delimiter>@</resource.delimiter>
<!-- delimiter that doesn't clash with Spring ${} placeholders -->
<delimiters>
    <delimiter>${resource.delimiter}</delimiter>
</delimiters>

One can then access those properties in Spring using @Value like this:

@Value("${application.name}")
private String applicationName;

@Value("${build.version}")
private String buildVersion;

@Value("${build.timestamp}")
private String buildTimestamp;

A sample project is available here.

ℛɑƒæĿᴿᴹᴿ
  • 4,983
  • 4
  • 38
  • 58
Jack G.
  • 3,681
  • 4
  • 20
  • 24
  • 19
    You basically solved what Spring documentation describes for it: http://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html The one point in the docs is if you use the Spring Boot parent you don't need to explicitly define the resource filter. – Shawn Clark Aug 16 '16 at 23:57
  • We don't use spring-boot-starter-parent, but we didn't need to add the delimiters config like your answer and [section 72.1.1](http://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html) says. – pacoverflow Feb 10 '17 at 21:09
  • 8
    The timestamp should actually be something like `build.timestamp=@maven.build.timestamp@`. – wikier Mar 29 '17 at 13:05
  • 2
    Any suggestions on how to do this using yaml ? I'm trying to escape the '@' characters using quotes around the values (i.e "@project.artifactId@" but in Cent-OS the properties are not being resolved when I run the app as a jar – mariosk89 Jun 06 '17 at 14:10
  • I was still struggeling although I had this section in my pom. The problem was, that I had a separate `application.yml` in test/resources. When you want to enable filtering for that one, too, you'll need a `testResources` section similar to the one mentioned in http://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html – jaw Aug 28 '17 at 06:34
  • For newbies like me, I was trying to get the build number using JUnit test case which was not running the spring app. For you to get the build number run the app first. – Saurabh Gupta Dec 29 '17 at 16:50
  • Just define "info.app.version=@project.version@" and the information will be available at http://localhost:8080/actuator/info : nothing more to do! See https://www.baeldung.com/spring-boot-info-actuator-custom – Sebien Jan 15 '19 at 14:11
  • I used this solution and it works when I run my application on my computer but after deploying my application it doesn't work and it returns something like @project.artifactId@ that I added in application.properties. – majid_shoorabi May 07 '22 at 09:50
  • I have been using the `@project.name@` to get the name from pom.xml `myapi`. However, I find that it works most of the time but every once in a while it does not resolve project name but stays as `@project.name` causing my tests to fail. I have not been able to find solution to it. – pixel Jan 27 '23 at 17:05
79

To get access to Maven properties in Spring Boot application all we need is map them with delimiter @ in the application.properties like this:

app.version=@project.version@
app.name=@project.name@

Then use them in the app like ordinary properties, for example:

@Service
public class SomeService {

   @Value("${app.version}")
   private String appVersion;

   // other stuff
}

Source: Automatic Property Expansion Using Maven

But if you are using yaml to store application properties, you may need to replace delimiter @ with some other one, for example ^ in our pom.xml:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.7</version>
    <configuration>
        <delimiters>
            <delimiter>^</delimiter>
        </delimiters>
        <useDefaultDelimiters>false</useDefaultDelimiters>
    </configuration>
</plugin>

Or even simpler - just replace variable resource.delimiter in propeties block of your pom.xml:

<properties>
    <java.version>11</java.version>
    <resource.delimiter>^</resource.delimiter>
</properties>

Then use it in your property file, for example:

app:
  version: ^project.version^
  name: ^project.name^
Cepr0
  • 28,144
  • 8
  • 75
  • 101
  • 1
    Why we need to change the delimiter for the YML – Prabhat Yadav Mar 10 '21 at 12:07
  • @PrabhatYadav Often the default one doesn't work in YAML – Cepr0 Mar 10 '21 at 15:24
  • FYI for anyone looking for this, unless we replace `@` sign with `^`, Spring Cloud Config Server cannot serve YAML files with these delimiters properly. – emrekgn Aug 18 '21 at 12:24
  • @emrekgn those placeholders are suppose to be replaced at build time, they shouldn’t be there anymore when Spring Cloud Config Server serves the yaml files. – Didier L Apr 15 '22 at 12:33
  • Actually, when there is a native profile, the config server resolves YAML files when requested, not during build time. That's why Cepr0's suggestion to replace them with another char is the correct way to go because `@` sign is not a valid char. But, in all other use cases, you are correct. – emrekgn Apr 15 '22 at 14:16
68

There a easier way to do this, don't need to add application.properties or delimiter changes. Simply add plugin with goal build-info and Autowire start up class with bean BuildProperties.

<plugin>
<groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-maven-plugin</artifactId>
   <version>2.1.3.RELEASE</version>
   <executions>
     <execution>
       <goals>
         <goal>build-info</goal>
       </goals>
     </execution>
   </executions>
</plugin>

Startup class will have

@Autowired
  BuildProperties buildProperties;

later in @PostConstruct in start up class you can call multiple methods to retrieve build Timestamp, Version, Name of Artifact, Group etc.


private static final Logger LOGGER = LoggerFactory.getLogger(YourSpringApplication.class);

@Autowired
BuildProperties buildProperties;

public static void main(String[] args) {
    SpringApplication.run(YourSpringApplication.class, args);
  }

@PostConstruct
  private void logVersion() {
    LOGGER.info(buildProperties.getName());
    LOGGER.info(buildProperties.getVersion());
    LOGGER.info(buildProperties.get("time"));
    LOGGER.info(buildProperties.getGroup());
}

The info actuator will automatically use, and display this information if it detects it, as well as display git information if it finds any.

Milan Desai
  • 1,228
  • 8
  • 23
  • 9
    This is the most cleaner answer. @MilanDesai thank you very much! – falvojr Nov 29 '19 at 22:50
  • 2
    With SpringBoot 1.5.1 there us no such bean: `Consider revisiting the conditions above or defining a bean of type 'org.springframework.boot.info.BuildProperties' in your configuration.` – Oleksandr Yefymov Feb 02 '20 at 16:25
  • 1
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.info.BuildProperties' available: – ACV Aug 19 '20 at 09:32
  • 4
    For 'Failed Autowired of BuildProperties' just run a 'mvn clean package' and then restart the spring boot application from either Eclipse/IntelliJ. – danieltc07 Apr 06 '22 at 13:24
3

It works with @ charactor.

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

and...in your application.properties or appplication.yml file....

version: @project.version@
name: @project.name@
Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
2

It's probably because your main pom doesn't declare spring-boot-starter-parent as its parent pom. Because when so, the filtering is done by default, without needing to declare the filtering explicitly

For me changing from :

<parent>
    <groupId>com.mycompany</groupId>
    <artifactId>mycompany-parent</artifactId>
    <version>20</version>
</parent>

to :

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.6.RELEASE</version>
</parent>

In my application main pom.xml fixed the issue without having to declare the filtering.

TheBakker
  • 2,852
  • 2
  • 28
  • 49