When working in a project with multiple contributors often times we see that code formatting in git repos is not consistent because every developer has their own style guide preferences.

It’s vital that a common style guide standard is set for a project. Spotless Maven Plugin automatically formats java code during maven build phases when configured with some specific style guide preferences.

Spotless is a general-purpose formatting plugin

It can be applied to multiple programming languages like Java, Groovy, Scala, C/C++, Python, SQL, Typescript etc., but this post is focused on Java code formatting.

For java formatting Spotless supports 3 style guides out of the box

  • Google Java Formatter - My preference for Java projects
  • Eclipse
  • Prettier

And, Google Java formatter supports 2 styles:

  • AOSP - Android Open Source Project
  • GOOGLE - Default Google Java Style - My preference for Java projects

Spotless Maven plugin has primarily 2 goals

  • check- Detects and prints the formatting violations
  • apply- silently applies the formatting.

By default, spotless maven plugin check goal is bound to maven verify phase. So when you do mvn verify all the spotless formatting violations are caught.


Integrating the spotless maven plugin

  • Add the below plugin snippet to your pom.xml

     <build>
       <plugins>
        <!-- Add spotless maven plugin here -->
       </plugins>
     </build>
    
  • Here is the sample spotless maven plugin configuration with my formatting preferences

     <plugin>
          <groupId>com.diffplug.spotless</groupId>
          <artifactId>spotless-maven-plugin</artifactId>
          <version>${spotless.version}</version>
          <executions>
            <execution>
              <goals>
                <goal>apply</goal><!-- Applies spotless formatting rules -->
              </goals>
              <phase>clean</phase><!-- spotless goal is bound to maven clean phase -->
            </execution>
          </executions>
          <configuration>
            <!-- define a language-specific format -->
            <java>
              <!-- no need to specify files, inferred automatically, but you can if you want -->
              <!-- These are the defaults, you can override if you want -->
              <includes>
                <include>src/main/java/**/*.java</include>
                <include>src/test/java/**/*.java</include>
              </includes>
    
              <!-- apply a specific flavor of google-java-format and reflow long strings -->
              <googleJavaFormat>
                <version>1.15.0</version>
                <style>GOOGLE</style>
                <reflowLongStrings>true</reflowLongStrings>
                <groupArtifact>com.google.googlejavaformat:google-java-format</groupArtifact>
              </googleJavaFormat>
    
              <formatAnnotations />
              <!-- To format annotations -->
    
              <importOrder>              <!-- or a custom ordering -->
                <wildcardsLast>false</wildcardsLast>
                <!-- Optional, default false. Sort wildcard import after specific imports -->
                <order>\\#,java,javax,org,com,io,lombok</order>
                <!-- or use <file>${project.basedir}/eclipse.importorder</file> -->
                <!-- you can use an empty string for all the imports you didn't specify explicitly,
                '|' to join group without blank line, and '\\#` prefix for static imports. -->
              </importOrder>
    
              <!-- make sure every file has the following copyright header.
                optionally, Spotless can set copyright years by digging
                through git history (see "license" section below) -->
              <licenseHeader>
                <content>/* (C) SaiRaghava Katepally  $YEAR */</content>
                <!-- or <file>${project.basedir}/license-header</file> -->
              </licenseHeader>
            </java>
          </configuration>
        </plugin>
    
  • From the above snippet it’s clear that apply goal is bound to clean phase so that every time we do mvn clean code is auto-formatted.

  • I also have Vscode on file-save event trigger enabled that formats code. So, it’s important that both file-save event and mvn clean formats code in a similar style. To enforce that, I ensured that the below imports order is in sync with spotless plugin configuration

    "java.completion.importOrder": [
      /*Ensure that these imports and aligned with your spotless maven plugin 
      configuration for a given project*/
      "#", // static imports at the top
      "java",
      "javax",
      "org",
      "com",
      "io",
      "lombok",
      "" // any other imports
    ],
    
  • Here is a sample java code snippet that’s auto formatted with spotless maven plugin

     /* (C) SaiRaghava Katepally  2023 */
    package spotless;
    
    import static java.io.File.pathSeparator;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.xml.crypto.URIReference;
    
    public class Demo {
    
      public static void main(String[] args) {
        List<String> fruits = new ArrayList<>(); // Just to add a java import
        URIReference uriReference = null; // Just to add javax import
        String pathSeparatorVal = pathSeparator; // Just to add static import
      }
    }
    
  • Additionally, If you’d like to indent it with tabs, you can configure it as shown below.

     <googleJavaFormat/>
     <indent>
         <tabs>true</tabs>
         <spacesPerTab>4</spacesPerTab>
     </indent>
    

Overall, the Spotless Maven Plugin is a useful tool for maintaining consistent code formatting in your Java projects. It can save your time and effort by automatically formatting your code for you, and help you to maintain high-quality, readable code.

References:

  1. Spotless maven plugin
  2. Refer Google Java Formatter styles
  3. Spotless Maven Plugin Goals
  4. Refer Quickstart section