1. Overview
In this article, we'll explore the property expansion mechanism provided by Spring through Maven and Gradle build methods.
2. Maven
2.1. Default Configuration
For Maven projects using the spring-boot-starter-parent, there is no need for extra configurations to make use of property expansions:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
</parent>
Now we can expand our project's properties using @…@ placeholders. Here is an example of how we may save the project's version taken from Maven, into our properties:
[email protected]@
[email protected]@
We can only use these expansions within configuration files matching these patterns:
- **/application*.yml
- **/application*.yaml
- **/application*.properties
2.2. Manual Configuration
In the absence of the spring-boot-starter-parent parent, we'll need to configure this filtering and expansion manually. We'll need to include resources element into the <build> section of our pom.xml file:
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/application*.yml</include>
<include>**/application*.yaml</include>
<include>**/application*.properties</include>
</includes>
</resource>
</resources>
And in the <plugins>:
<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>
In cases where it's required to use the standard placeholders of type ${variable.name} we'll need to set useDefaultDelimeters to true, and your application.properties will look like this:
expanded.project.version=${project.version}
expanded.project.property=${custom.property}
3. Gradle
3.1. Standard Gradle Solution
The Gradle solution from the Spring Boot documentation is not 100% compatible with the Maven property filtering and expansion.
To allow us to use the property expansion mechanism, we'll need to include the following code into build.gradle:
processResources {
expand(project.properties)
}
This is a limited solution with the following differences from the Maven default configuration:
- Does not support properties with dots (e.g. user.name). Gradle understands dots as object property delimiters
- Filters all the resource files and not just a specific set of configuration files
- Uses the default dollar-sign placeholders ${…} thus conflicting with the standard Spring placeholders
3.2. Maven Compatible Solution
For us to replicate the standard Maven solution and make use of the @…@ style placeholders, we need to add the following code to our build.gradle:
import org.apache.tools.ant.filters.ReplaceTokens
processResources {
with copySpec {
from 'src/main/resources'
include '**/application*.yml'
include '**/application*.yaml'
include '**/application*.properties'
project.properties.findAll().each {
prop ->
if (prop.value != null) {
filter(ReplaceTokens, tokens: [ (prop.key): prop.value])
filter(ReplaceTokens, tokens: [ ('project.' + prop.key): prop.value])
}
}
}
}
This will resolve all the project's properties. We still cannot define properties with dots (e.g. user.name) in the build.gradle, but now we can use gradle.properties file to define properties in the standard Java properties format, and it also supports properties with dots (e.g database.url).
This build filters only the project configuration files and not all the resources, and it's 100% compatible with the Maven solution.
4. Conclusion
In this quick tutorial, we saw how to automatically expand Spring Boot properties using both Maven and Gradle build methods and how we can easily migrate from one to the other.
The complete source example can be found over on GitHub.