If you’re working with Java and want to generate immutable value types, immutables.org is a powerful and widely-used library. It provides annotation-based code generation to help you reduce boilerplate while keeping your code clean and safe.
However, while the official documentation offers a clear setup example for Maven, it falls short when it comes to Gradle. Worse, it recommends using a single value
artifact with the provided
scope, which doesn’t translate directly to Gradle — and isn’t ideal in terms of dependency hygiene either.
This post explains how to correctly and minimally configure immutables
for a Gradle-based project.
Annotation processors are tools that run at compile time and generate source code or other resources based on annotations in your code. In the case of immutables
, they scan for @Value.Immutable
and generate implementation classes like ImmutableMyType
.
In Java’s build ecosystem:
This separation is crucial for keeping your build fast and secure.
If you’re using the Kotlin DSL (build.gradle.kts
), here’s how you can configure your project with the minimal and correct setup:
dependencies {
// Only needed at compile time for annotations like @Value.Immutable
compileOnly("org.immutables:value-annotations:<latest-version>")
// Used by the compiler to generate immutable implementation classes
annotationProcessor("org.immutables:value-processor:<latest-version>")
}
Replace <latest-version>
with the latest release of org.immutables
(you can find it on Maven Central).
value-annotations
: Contains only the annotations (like @Value.Immutable
) — this is all your source code needs to see during compilation.value-processor
: This is the actual annotation processor that generates the code during compilation — it should never be part of your runtime classpath.Minimizing dependencies is about more than aesthetics — it’s about performance, maintainability, and security.
By properly scoping your dependencies, you ensure that your build is lean and your application is not bloated with unnecessary code or potential vulnerabilities.
Using immutables
with Gradle doesn’t have to be a guessing game. While the official docs lean Maven-first, a clean Gradle setup is simple and elegant when you understand the role of annotation processors.
To recap:
compileOnly
for annotations like @Value.Immutable
.annotationProcessor
for the code generator.A disciplined approach to build configuration pays dividends in speed, safety, and maintainability. Happy building — and stay immutable.
If you need help optimizing or troubleshooting your Gradle builds, I offer consulting services — feel free to reach out!