Gradle 9 ReplaceToken Configuration Cache: Dynamic Properties Guide
Learn how to properly configure ReplaceToken-filter with dynamic properties in Gradle 9 using Configuration Cache. Avoid serialization errors with gradle.properties and providers.
How to properly configure ReplaceToken-filter with dynamic properties in Gradle 9 with Configuration Cache? The current approach using project.extra fails with the error ‘cannot serialize object of type org.gradle.api.internal.project.DefaultProject’. What is the recommended approach for property-based filtering that works with Gradle 9’s Configuration Cache?
Gradle 9’s Configuration Cache requires serializable property sources for ReplaceToken filtering, as using project.extra causes serialization errors. The recommended approach leverages gradle.properties, project.properties, or providers to dynamically supply values to the filter. This ensures compatibility with Gradle’s optimized serialization mechanism while maintaining dynamic token replacement functionality.
Contents
- Understanding the Configuration Cache Error
- Recommended Approaches for Dynamic Properties
- Using gradle.properties and project.properties
- Leveraging Providers for Dynamic Values
- Advanced Configuration with ReplaceToken
- Troubleshooting Common Issues
Understanding the Configuration Cache Error
The error “cannot serialize object of type org.gradle.api.internal.project.DefaultProject” occurs because Gradle’s Configuration Cache requires all configuration-time objects to be serializable. When using project.extra or other Project-level objects, Gradle cannot serialize these reference objects, causing cache failures. According to the official Gradle documentation, this cache improves build performance by storing configuration results, but requires all referenced objects to be serializable.
This serialization issue is particularly problematic when working with dynamic properties in resource filtering tasks. The Stack Overflow discussion highlights that any direct reference to project objects like project.extra will fail with this error in Gradle 9.
Recommended Approaches for Dynamic Properties
For ReplaceToken filtering in Gradle 9 with Configuration Cache enabled, there are three recommended approaches:
- Using gradle.properties or project.properties for simple key-value pairs
- Leveraging providers with project.provider for dynamic values
- Combining both approaches for complex scenarios
The Gradle Cookbook specifically recommends using Property
Using gradle.properties and project.properties
The simplest approach for serializable properties is using gradle.properties or project.properties files. Gradle automatically serializes these properties, making them cache-friendly. For example:
# gradle.properties
my_token=secret_value
app_version=1.0.0
In your build.gradle, you can then reference these properties directly:
tasks.register<Copy>("processResources") {
from("src/main/resources")
into("$buildDir/processed")
filtering {
properties(mapOf(
"TOKEN" to project.properties["my_token"],
"VERSION" to project.properties["app_version"]
))
}
}
This approach works well with ReplaceTokens filtering and is fully compatible with Gradle 9’s Configuration Cache. The properties files are automatically captured during configuration, making them ideal for static or rarely changing values.
Leveraging Providers for Dynamic Values
For dynamic values that need to be calculated at execution time, use providers. The official documentation emphasizes that Provider
val myToken = providers.provider {
System.getenv("MY_TOKEN") ?: "defaultToken"
}
val appVersion = providers.provider {
"v${project.properties["version"]}"
}
tasks.register<Copy>("processResources") {
from("src/main/resources")
into("$buildDir/processed")
filtering {
properties(mapOf(
"TOKEN" to myToken,
"VERSION" to appVersion
))
}
}
This approach allows for dynamic values while maintaining Configuration Cache compatibility, as noted in the Gradle requirements documentation. Providers evaluate lazily at execution time, making them perfect for environment variables, calculated values, or runtime information.
Advanced Configuration with ReplaceToken
For more complex scenarios with multiple tokens, you can combine approaches. Based on the Gradle Forums discussion, you can use a map with each token:
// Define tokens in gradle.properties or as providers
val buildTokens = mapOf(
"ENV" to providers.provider { System.getenv("ENV") ?: "dev" },
"VERSION" to providers.provider { project.version.toString() },
"BUILD_DATE" to providers.provider { java.time.LocalDate.now().toString() }
)
tasks.register<Copy>("processResources") {
from("src/main/resources")
into("$buildDir/processed")
// Apply ReplaceToken filter for each token
buildTokens.forEach { (key, value) ->
filter(ReplaceTokens, tokens = mapOf(key to value))
}
}
This approach provides maximum flexibility while maintaining Configuration Cache compatibility. You can mix static properties from files with dynamic providers to create comprehensive token replacement strategies.
Troubleshooting Common Issues
If you encounter serialization errors with Configuration Cache, consider these troubleshooting steps:
-
Check for non-serializable objects: Review your build scripts for any direct references to non-serializable objects like project.extra.
-
Use providers: Convert any dynamic values to use providers as shown above.
-
Temporarily disable cache: For debugging, you can temporarily disable the Configuration Cache with
--no-configuration-cache, but this is not a long-term solution. -
Update Gradle: Ensure you’re using the latest Gradle version, as Configuration Cache continues to evolve with each release.
-
Review project dependencies: Some plugins may not be fully compatible with Configuration Cache yet. Check plugin documentation for updates.
Sources
- How to use ReplaceToken-filter with properties and Gradle 9 Configuration Cache - Stack Overflow
- Configuration Cache - Gradle Documentation
- Configuration Cache Requirements for your Build Logic - Gradle Documentation
- Enabling and Configuring the Configuration Cache - Gradle Documentation
- Ensuring Configuration Cache compatibility - Gradle Cookbook
- Use replacetokens with map - Gradle Forums
- Gradle Configuration Cache Build Failure: How to Fix ‘Cannot Serialize Configuration’ Error - W3Tutorials
Conclusion
Successfully configuring ReplaceToken-filter with dynamic properties in Gradle 9 requires abandoning project.extra in favor of serializable property sources. By using gradle.properties files, project.properties, or providers, you can maintain dynamic token replacement functionality while ensuring Configuration Cache compatibility. This approach not only resolves the serialization error but also leverages Gradle’s optimized caching mechanism for improved build performance. The recommended patterns provide flexibility for both static and dynamic property scenarios, making your build scripts both robust and cache-friendly.