How do Spotless and Error Prone fit into a Maven build, and how do they differ from check-only linters?
answer
- spotless:apply fixes, spotless:check fails
- Spotless = formatter, auto-fixable
- Error Prone = javac plugin, not Maven plugin
- annotationProcessorPaths + -Xplugin:ErrorProne
- -Xep:Name:ERROR/WARN/OFF
basics
~20 sSpotless is a formatter: spotless:apply rewrites files to a standard format, spotless:check fails the build if they aren't formatted. Error Prone isn't a plugin — it plugs into javac via maven-compiler-plugin and fails compilation on bug-pattern findings.
solid answer
~40 sSpotless enforces *formatting*: you pick a formatter (Google Java Format, Palantir, etc.) and run spotless:apply locally to auto-fix or spotless:check in CI to fail unformatted code. It's auto-fixable, unlike Checkstyle which only reports. Error Prone is a *compiler* plugin: you add it to maven-compiler-plugin's annotationProcessorPaths and compilerArgs (-XDcompilePolicy=simple -Xplugin:ErrorProne ...), so it runs inside javac and turns suspect patterns into compile errors/warnings at compile time. Because it's part of compilation, it's fast and catches bugs before tests, and you can promote/demote checks (-Xep:CheckName:ERROR/WARN/OFF) and even auto-patch. The combination: Spotless owns format, Error Prone owns compile-time correctness, Checkstyle/PMD/SpotBugs cover style and deeper analysis.
code
bash · 3 lines# locally auto-format, then CI verifies formatting
mvn spotless:apply
mvn verify # runs spotless:check + errorprone via compilergo deeper
Spotless formats code; spotless:apply fixes, spotless:check verifies.
Knows Error Prone runs in javac via the compiler plugin and that Spotless is auto-fixable.
Splits responsibilities cleanly (format vs correctness vs style) and tunes Error Prone severities per check.
Sets the org standard formatter and compile-time check policy, including auto-patch rollout and pre-commit integration.
## Spotless — a formatter, not just a linter Most linters *report* a problem and leave you to fix it. **Spotless** can *fix* it. Two goals: - `spotless:apply` — rewrites files to the configured format (run locally / pre-commit). - `spotless:check` — fails the build if any file isn't already formatted (run in CI). You choose an underlying formatter and Spotless also handles imports order, trailing whitespace, license headers, etc. ```xml <plugin> <groupId>com.diffplug.spotless</groupId> <artifactId>spotless-maven-plugin</artifactId> <version>2.43.0</version> <configuration> <java> <googleJavaFormat><version>1.22.0</version></googleJavaFormat> <removeUnusedImports/> </java> </configuration> <executions> <execution> <phase>verify</phase> <goals><goal>check</goal></goals> </execution> </executions> </plugin> ``` ## Error Prone — analysis inside the compiler **Error Prone** is a Google library that hooks into **javac** to flag bug patterns (e.g. == on boxed types, missing @Override, format-string mismatches). It is **not** a Maven plugin — you configure it on **maven-compiler-plugin**: ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.13.0</version> <configuration> <compilerArgs> <arg>-XDcompilePolicy=simple</arg> <arg>-Xplugin:ErrorProne -Xep:DeadException:ERROR -Xep:NullAway:WARN</arg> </compilerArgs> <annotationProcessorPaths> <path> <groupId>com.google.errorprone</groupId> <artifactId>error_prone_core</artifactId> <version>2.28.0</version> </path> </annotationProcessorPaths> </configuration> </plugin> ``` Because it's part of compilation it runs on every `mvn compile`, is fast, and fails early. You tune each check's severity with `-Xep:Name:ERROR|WARN|OFF` and can apply automated fixes with the patch mode. ## How they divide responsibility - **Spotless** → formatting (auto-fixable). - **Error Prone** → compile-time correctness. - **Checkstyle** → style rules beyond format. - **PMD** → source smells + duplication (CPD). - **SpotBugs/find-sec-bugs** → bytecode/security analysis. Keeping concerns separated avoids overlapping/conflicting rules (e.g. don't let Checkstyle fight Spotless over formatting — let Spotless own it).
- Why let Spotless own formatting instead of Checkstyle?Spotless can auto-fix formatting deterministically; Checkstyle only reports. Running both on format risks conflicting rules, so you assign format to Spotless and reserve Checkstyle for non-format style rules.
- Why is Error Prone configured on maven-compiler-plugin rather than added as its own plugin?It's a javac compiler plugin, so it runs during compilation; you wire it through the compiler's annotationProcessorPaths and compilerArgs, not a separate lifecycle binding.
saying these in an interview costs you the question
- Calling Error Prone a standalone Maven plugin with its own goals
- Thinking spotless:check auto-fixes (it only verifies; apply fixes)
- Running Checkstyle and Spotless with overlapping formatting rules so they fight each other