Cannot get maven project.version property in a Spring application with @Value

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

[email protected]@
[email protected]@

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^

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:

[email protected]@
[email protected]@
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.