Jack G.
Jack G.

Reputation: 3941

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

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

Upvotes: 116

Views: 138744

Answers (7)

Heena Patidar
Heena Patidar

Reputation: 41

In my case, the error occurred because the dependent services (Config Server, Eureka Server, and Gateway Server) were not running before the Cards Service. The Cards Service relies on the Config Server for fetching configurations and on the Eureka Server for service discovery. Starting these services sequentially resolved the issue, and no changes were needed in the pom.xml or application.yml.

Upvotes: 0

Nexevis
Nexevis

Reputation: 4667

As I was using spring-boot-starter-parent I just had to use double quotes with @ as the delimiter in the my application.yml in order to grab the version:

app:
  version: "@project.version@"

I then get the value later with @Value:

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

The Spring docs use double quotes as the example here when using an application.yml instead of an application.properties.

I did not need to modify delimiters this way in the pom.

Upvotes: 1

Milan Desai
Milan Desai

Reputation: 1306

There a easier way to do this, don't need to add application.properties or delimiter changes.

for Spring Boot 2.X.X

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.

Upvotes: 73

Rashmin H Gadhavi
Rashmin H Gadhavi

Reputation: 221

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@

Upvotes: 5

Cepr0
Cepr0

Reputation: 30389

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^

Upvotes: 82

Jack G.
Jack G.

Reputation: 3941

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.

Upvotes: 165

TheBakker
TheBakker

Reputation: 3062

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.

Upvotes: 2

Related Questions