Gradle Property Expansion w/ Spring Boot


Setup Gradle

In order to have gradle substitute properties in your application.[properties|yaml|yml], you will need to include:

processResources {
	expand(project.properties)
}

This will process all file located in /src/main/resources/ and replace all ${..} tokens with gradle's project properties.

Its important to note: this will not process test resources. i.e. /src/test/resources.

If you want to limit the files it will process you can filter expand(project.properties) by wrapping it with filesMatching('file|**/wildcard.*').

processResources {
    filesMatching('application.yml') {
        expand(project.properties)
    }
}

Setup Spring Boot

As an example, let's say we are using spring actuator in our project, and we want to configure the /actuator/info endpoint. Our appplication.yml would look something like this:

info:
	application:
		name: MyApplication
		version: 1.0.1

Since gradle already has a project name and version defined, we could use that instead of dupicating the data. Having a single point of truth for things like a version number can save a lot of time and confusion. Changing it instead to this:

info:
	application:
		name: ${rootProject.name}
		version: ${version}

Gradle will process those placeholders and replace them with the resolved values from the build script. The resolved application.yml is then copied into the build directory and packaged with the artifact, and will look that same as our hardcoded version above.

Caveats

If one of those properties are unable to be resolved, the build will fail. Sometimes this could be a good reason for failure. However, for the cases where a default value would suffice, we can provide a default value like this:

version: ${version?:SNAPSHOT}
# version != null ? version : 'SNAPSHOT'

Spring Boot also provides property expansion of its own as runtime. Unfortunately, it shares the same syntax that Gradle uses. In order to use Spring Boot's property expansion in conjunction with Gradle's, you will have to escape \$ in order for Gradle to ignore it. Reusing our above yml, we could add:

info:
	application:
		name: ${rootProject.name} # Gradle will resolve this.
		version: ${version} # Gradle will resolve this.
		springProperty: \${springProperty} # Spring will resolve this.

Conclusion

Gradle can easily expand your Spring Boot property files at build time with a quick configuration and adding placeholders in your application.* files. Just remember, if you are using Spring Boot property expansion as well, you will need to escape the placeholders so Gradle will not attempt to expand them. More information on property expansion can be found here: Spring Boot: Properties and Configuration

tristanfarmer.dev by Tristan Farmer