Maven
Spring
@Value
project.version
Spring Boot

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

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

@Value("${project.version}") does not work automatically in a Spring application because project.version is a Maven build-time property, not a Spring runtime property source by default. To use the Maven version inside the running application, you have to copy that value into something Spring can actually read at runtime.

Why @Value Cannot See Maven Properties Directly

Maven resolves ${project.version} while building the project. Spring resolves ${...} placeholders at runtime from sources such as:

  • 'application.properties'
  • 'application.yml'
  • environment variables
  • system properties
  • explicitly registered property sources

Those are different phases. Unless the build writes the Maven value into a runtime-readable resource, Spring has nothing to inject.

That is why this does not work by itself:

java
@Value("${project.version}")
private String version;

The property is simply absent from Spring's environment.

Resource Filtering Is the Traditional Fix

A common solution is to let Maven filter application.properties during the build.

pom.xml:

xml
1<build>
2    <resources>
3        <resource>
4            <directory>src/main/resources</directory>
5            <filtering>true</filtering>
6        </resource>
7    </resources>
8</build>

src/main/resources/application.properties:

properties
app.version=@project.version@

Then inject the filtered property in Spring:

java
1import org.springframework.beans.factory.annotation.Value;
2import org.springframework.stereotype.Component;
3
4@Component
5public class VersionInfo {
6    @Value("${app.version}")
7    private String version;
8
9    public String getVersion() {
10        return version;
11    }
12}

Now Spring is not reading Maven directly. It is reading a normal runtime property that Maven wrote during packaging.

Spring Boot Has a Cleaner Option: Build Info

If you are using Spring Boot, BuildProperties is often a better answer than hand-rolled filtering.

Add the Spring Boot Maven plugin goal that generates build metadata.

xml
1<build>
2    <plugins>
3        <plugin>
4            <groupId>org.springframework.boot</groupId>
5            <artifactId>spring-boot-maven-plugin</artifactId>
6            <executions>
7                <execution>
8                    <goals>
9                        <goal>build-info</goal>
10                    </goals>
11                </execution>
12            </executions>
13        </plugin>
14    </plugins>
15</build>

Then inject BuildProperties:

java
1import org.springframework.boot.info.BuildProperties;
2import org.springframework.stereotype.Component;
3
4@Component
5public class VersionInfo {
6    private final BuildProperties buildProperties;
7
8    public VersionInfo(BuildProperties buildProperties) {
9        this.buildProperties = buildProperties;
10    }
11
12    public String getVersion() {
13        return buildProperties.getVersion();
14    }
15}

This is cleaner because it keeps version metadata in a dedicated build-info file rather than mixing it into general application properties.

Manifest Access Is Another Option

You can also write the version into the JAR manifest and read it from the package metadata.

java
String version = getClass().getPackage().getImplementationVersion();
System.out.println(version);

This works well for packaged applications, but it is often less convenient during local development and testing than filtered properties or BuildProperties.

Pick the Right Approach

A practical rule is:

  • use resource filtering if you already have a small simple property you want in application.properties
  • use Spring Boot BuildProperties when you want proper build metadata support
  • use manifest entries when version info belongs to packaged artifact metadata rather than Spring configuration

All three are valid. The important part is understanding that none of them happen automatically from @Value alone.

Keep Build-Time and Runtime Concerns Separate

The root confusion in this problem is mixing build metadata with runtime configuration. Maven knows the project version at build time. Spring knows runtime properties when the app starts. A build step or generated metadata file is the bridge between those worlds.

Once you view it that way, the behavior becomes predictable instead of surprising.

Common Pitfalls

A common mistake is expecting Spring to resolve raw Maven placeholders without resource filtering or generated metadata.

Another mistake is putting @project.version@ into application.properties but forgetting to enable Maven resource filtering.

Developers also sometimes use the wrong placeholder style. In filtered resources, the token depends on the chosen filtering syntax and plugin configuration.

Finally, if you use Spring Boot, do not ignore BuildProperties. It is often simpler and cleaner than custom workarounds.

Summary

  • 'project.version is a Maven build-time property, not a Spring runtime property by default.'
  • '@Value("${project.version}") fails unless the value is copied into a Spring-readable property source.'
  • Maven resource filtering can write the version into application.properties.
  • Spring Boot BuildProperties is often the cleanest solution.
  • Build-time metadata must be bridged intentionally into the runtime environment.

Course illustration
Course illustration

All Rights Reserved.