This guide explains how to set up automated code formatting in a Java Maven project using Google's Java code formatter via the fmt-maven-plugin
.
The setup combines two key components:
- Google Java Format (google-java-format): Google's Java code formatter that enforces Google Java Style
- Spotify's fmt-maven-plugin: A Maven plugin that integrates google-java-format into the Maven build lifecycle
- Maven 3.8.0 or higher
- Java 8 or higher
- A Maven-based Java project
In your pom.xml
, define the versions for both the formatter and the Maven plugin:
<properties>
<google-java-format.version>1.17.0</google-java-format.version>
<fmt-maven-plugin.version>2.25</fmt-maven-plugin.version>
</properties>
Add the following plugin configuration to your pom.xml
in the <build><plugins>
section:
<plugin>
<groupId>com.spotify.fmt</groupId>
<artifactId>fmt-maven-plugin</artifactId>
<version>${fmt-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>format</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
<testSourceDirectory>${project.build.testSourceDirectory}</testSourceDirectory>
<verbose>true</verbose>
<filesNamePattern>.*\.java</filesNamePattern>
<skipSortingImports>false</skipSortingImports>
</configuration>
<dependencies>
<dependency>
<groupId>com.google.googlejavaformat</groupId>
<artifactId>google-java-format</artifactId>
<version>${google-java-format.version}</version>
</dependency>
</dependencies>
</plugin>
sourceDirectory
: Directory containing the main source filestestSourceDirectory
: Directory containing the test source filesverbose
: Enables detailed output during formattingfilesNamePattern
: Regular expression to match files for formattingskipSortingImports
: Controls whether import statements should be sorted
The plugin automatically runs during the Maven build process. To manually format your code:
mvn fmt:format
To verify if code is properly formatted without making changes:
mvn fmt:check
- Install the "google-java-format" plugin
- Enable the plugin in Settings → Other Settings → google-java-format Settings
- Configure the code style:
- Settings → Editor → Code Style → Java
- Import the Google Style scheme
- Install the "google-java-format" plugin from the Eclipse Marketplace
- Configure formatting preferences to use Google Style
-
Pre-commit Hooks: Set up git pre-commit hooks to ensure code is formatted before committing:
#!/bin/sh mvn fmt:format git add .
-
CI Integration: Add format checking to your CI pipeline:
- name: Check Code Format run: mvn fmt:check
-
Team Standards: Document the formatting setup in your project's README
- Include installation steps for IDE plugins
- Document any custom configurations
- Explain the enforcement process
-
Format Conflicts with IDE
- Solution: Disable IDE's built-in formatter
- Use only google-java-format plugin
-
Build Failures Due to Format
- Run
mvn fmt:format
before committing - Check IDE settings for conflicting formatters
- Run
-
Version Compatibility
- Ensure Java version compatibility
- Check for plugin version conflicts
- The formatter enforces Google Java Style Guide rules
- Formatting is non-negotiable and consistent across all environments
- Changes are automatically applied during the Maven build process
- The plugin supports both main and test source directories
- Import sorting is handled automatically unless explicitly disabled
When working with multi-module Maven projects or when you want to centralize plugin configurations, you can use the <pluginManagement>
section instead of directly declaring plugins. This approach is particularly useful for:
- Ensuring consistent plugin versions across modules
- Centralizing plugin configurations
- Making plugin management more maintainable
Add the following configuration in your parent pom.xml
:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.spotify.fmt</groupId>
<artifactId>fmt-maven-plugin</artifactId>
<version>${fmt-maven-plugin.version}</version>
<configuration>
<sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
<testSourceDirectory>${project.build.testSourceDirectory}</testSourceDirectory>
<verbose>true</verbose>
<filesNamePattern>.*\.java</filesNamePattern>
<skipSortingImports>false</skipSortingImports>
</configuration>
<dependencies>
<dependency>
<groupId>com.google.googlejavaformat</groupId>
<artifactId>google-java-format</artifactId>
<version>${google-java-format.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement>
</build>
In your child modules, you can then simply reference the plugin:
<build>
<plugins>
<plugin>
<groupId>com.spotify.fmt</groupId>
<artifactId>fmt-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>format</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
-
Version Control
- Define plugin versions once in the parent POM
- Child modules inherit the version automatically
- Easier version updates across all modules
-
Configuration Inheritance
- Child modules can inherit the complete configuration
- Override specific configuration elements when needed
- Maintain consistency while allowing flexibility
-
Execution Control
<!-- In child module --> <build> <plugins> <plugin> <groupId>com.spotify.fmt</groupId> <artifactId>fmt-maven-plugin</artifactId> <!-- Override specific configuration --> <configuration> <verbose>false</verbose> <skipSortingImports>true</skipSortingImports> </configuration> </plugin> </plugins> </build>
-
Version Properties
- Define all plugin versions as properties in the parent POM
- Use property references in pluginManagement
- Easier version management and updates
-
Documentation
- Comment complex configurations
- Explain why certain settings are used
- Document any module-specific overrides
-
Module Organization
parent-project/ ├── pom.xml (with pluginManagement) ├── module1/ │ └── pom.xml (minimal plugin config) ├── module2/ │ └── pom.xml (minimal plugin config) └── module3/ └── pom.xml (minimal plugin config)
While google-java-format is opinionated, you can still configure certain aspects:
<configuration>
<style>AOSP</style> <!-- Use Android Open Source Project style -->
<formatSplitStatements>false</formatSplitStatements>
<formatJavadoc>true</formatJavadoc>
<fixImports>true</fixImports>
</configuration>
You can skip formatting based on conditions:
<configuration>
<skip>${format.skip}</skip>
<skipSourceDirectory>${skip.sources}</skipSourceDirectory>
<skipTestSourceDirectory>${skip.tests}</skipTestSourceDirectory>
</configuration>
Create profiles for different formatting scenarios:
<profiles>
<profile>
<id>strict-format</id>
<build>
<plugins>
<plugin>
<groupId>com.spotify.fmt</groupId>
<artifactId>fmt-maven-plugin</artifactId>
<configuration>
<verbose>true</verbose>
<failOnError>true</failOnError>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>