Maven pom.xml references: Working with Git Example Code
Table of Contents
Introduction
The more we can automate away manual tasks, like formatting, the faster we can get back to the really interesting parts of programming. The com.diffplug.spotless:spotless-maven-plugin can help.
Besides just helping us get away from the boring stuff, without such an automation, we can easily accidentally dilute the diff/changes in a commit by forgetting to select a code block before applying auto-formatting in the IDE. For example, this earlier Java101 commit had just that issue. The changes were still in there, but they were mixed in with a bunch of unrelated formatting changes I didn’t realize were included until after I had already committed. This makes it more difficult on the PR reviewer or anyone else looking at your commit. That was the catalyst for injecting this build related post into the middle of the Java101 series.
In our earlier post that added the maven-checkstyle-plugin, we used the default style – sun_checks.xml. Now, since both plugins will be either updating or confirming the status of the formatting in the build, they should be in sync. The easiest way to do this using only built-in configurations is to swap the maven-checkstyle-plugin from the sun to the google formatting style, as both plugins support google-styling. Let’s setup our build with both of these plugins.
Adding the Spotless Maven Plugin
Let’s add the spotless-maven-plugin tot he build.
Plugin Basics
First, we can add a property that controls the plugin version to use. In the pom.xml’s properties section, let’s add a property:
<spotless.maven.plugin.version>2.35.0</spotless.maven.plugin.version>
Then, let's add the plugin itself to the pom.xml's build.plugins section - but we need to do so before the maven-checkstyle-plugin. Maven will run plugins tied to the same phase in the order in which they appear in the pom.xml's configuration:
<plugin>
<!-- https://github.com/diffplug/spotless/tree/main/plugin-maven -->
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>${spotless.maven.plugin.version}</version>
<inherited>true</inherited>
<configuration>
</configuration>
<executions>
<execution>
<id>auto-style</id>
<goals>
<goal>apply</goal>
</goals>
<!-- Using validate phase, so this happens before enforce-style -->
<phase>validate</phase>
</execution>
</executions>
</plugin>
Maven Build Success
If we run the Maven build now, we should see output that confirms that the plugins are run in the desired order:
[INFO] --- spotless:2.35.0:apply (auto-style) @ java101 --- [INFO] Index file does not exist. Fallback to an empty index [INFO] [INFO] --- checkstyle:3.3.0:check (validate) @ java101 --- [INFO] Starting audit... Audit done. [INFO] You have 0 Checkstyle violations.
Checkstyle Using Google Style
Let’s update the pom.xml’s maven-checkstyle-plugin’s configuration to indicate that we now want to use the built-in google_checks.xml.
<configuration>
<!--
TODO - Create our own configuration file and reference here
-->
<configLocation>google_checks.xml</configLocation>
...
Maven Build Success
Again, we should see Maven build success at this point.
Adding Markdown Formatting
We have one markdown file in the docs directory at present – a sample UML diagram from our earlier posts, so let’s update the pom.xml’s spotless-maven-plugin configuration to include formatting of markdown (md) files:
<configuration>
<markdown>
<includes> <!-- You have to set the target manually -->
<include>**/*.md</include>
</includes>
<flexmark/> <!-- has its own section below -->
</markdown>
</configuration>
Maven Build Success
We should see Maven build success at this point, too.
Adding Java Formatting
Let’s add some configuration to ask the pom.xml’s spotless-maven-plugin to reformat Java files, too. Let’s add this just below the markdown section, but still within the configuration section.
<java>
<!-- Cleanthat will refactor your code, but it may break your style: apply it before your formatter -->
<cleanthat />
<googleJavaFormat>
<!-- GOOGLE or AOSP (optional) -->
<!-- https://github.com/google/google-java-format -->
<style>GOOGLE</style>
<!-- optional (requires at least 1.8) -->
<reflowLongStrings>true</reflowLongStrings>
</googleJavaFormat>
<!-- standard import order -->
<importOrder/>
<!-- Removing unused imports at the top of each file. -->
<removeUnusedImports/>
<!-- Fixes formatting of type annotations that may have occurred earlier in the formatting process. -->
<formatAnnotations/>
</java>
Maven Build Success
We should see Maven build success at this point, too.
Adding Maven Pom Formatting
The last type of file we currently have in our Java101 project is the pom.xml itself. This, too can be formatted during the build. Let’s add this just below the java section, but still within the configuration section.
<pom>
<!-- These are the defaults, you can override if you want -->
<includes>
<include>pom.xml</include>
</includes>
<sortPom>
<!-- The encoding of the pom files -->
<encoding>UTF-8</encoding>
<!-- Should empty elements be expanded-->
<expandEmptyElements>false</expandEmptyElements>
<!-- Should a space be added inside self-closing elements-->
<spaceBeforeCloseEmptyElement>false</spaceBeforeCloseEmptyElement>
<!-- Keep empty lines -->
<keepBlankLines>true</keepBlankLines>
<!-- Indentation -->
<nrOfIndentSpace>4</nrOfIndentSpace>
<!-- Should empty lines be indented -->
<indentBlankLines>false</indentBlankLines>
<!-- Should schema locations be indented -->
<indentSchemaLocation>true</indentSchemaLocation>
<!--
Sort order of elements: https://github.com/Ekryd/sortpom/wiki/PredefinedSortOrderProfiles
recommended_2008_06 - The POM Code Convention that was chosen by Maven developers in 2008 (default for 3.0.0+)
-->
<predefinedSortOrder>recommended_2008_06</predefinedSortOrder>
<!-- Sort dependency exclusions: https://github.com/Ekryd/sortpom/wiki/SortDependencies-->
<sortDependencyExclusions/>
<!-- Sort properties -->
<sortProperties>true</sortProperties>
<!-- Sort plugin executions -->
<sortExecutions>false</sortExecutions>
</sortPom>
</pom>
Create a Git Stash of Current Changes (Optional)
The next time we run the Maven build, we will perform formatting changes that may make reviewing our change more difficult. However, we don’t want to commit untested changes.
Here, a feature like Git Stash with a later Git Unstash may be of help.
- Git Stash – Saves the files that are both 1) modified and 2) currently tracked by Git locally to a “stash” and then removes those in-flight changes from the files in your file system. When you do this, it may be helpful to include a message, so you can find that “stash” in the future. Especially if you do this multiple times for different efforts.
- Git Unstash – Takes the existing stash of modified, tracked files and re-applies those in-flight changes to your file system.
# Change to the directory where you are coding your java101 project
cd ~/java101
# Create a new entry in the Git stash with your uncommitted changes
git stash push -m "Pre-pom.xml formatting"
# Sample output looks like:
# -----------
# Saved working directory and index state On automatedStyling: Pre-pom.xml formatting
# Confirm that our new stash was created
git stash list
# Sample output looks like:
# ------------
# stash@{0}: On automatedStyling: Pre-pom.xml formatting
# Re-apply the stash, but do not remove it, so we can re-apply it again after we test the build.
# The index value of 0 comes from the command above, the stash@{0} -> index = 0
git stash apply --index 0
# If something goes wrong and you need to try again, you can run this command to restore your file system to the commit you have checked out.
# It will remove all uncommitted changes.
git reset --hard HEAD
# Then, you can retry the git stash apply command above.
Maven Build Success
Running the Maven build should again produce a build success.
Commit
If you look at the changed files, you should see that java, md and pom.xml files all have changes. This is one of the reasons that it is good to add such an auto-formatter as early in the project lifecycle as possible. Now that we have tested our changes, let’s re-apply the original stash
If adding this to a legacy project, the number of files could easily exceed that of what a Pull Request (PR) may allow for reviews…which could hinder the review and merge process. If you have this issue, talk to your team and see how they want to proceed. They may ask you to break the formatting updates up into multiple PRs, so they can still review the changes in each PR.
If you did not create a stash earlier, then commit as normal. If you did create a stash earlier, then these commands may help.
# Reset to the HEAD (latest commit) in order to remove all uncommitted changes.
git reset --hard HEAD
# Confirm that our new stash is still at the same index
git stash list
# Sample output looks like:
# ------------
# stash@{0}: On automatedStyling: Pre-pom.xml formatting
# Re-apply the stash, but do not remove it, so we can re-apply it again after we test the build.
# The index value of 0 comes from the command above, the stash@{0} -> index = 0
git stash apply --index 0
# Check what files have uncommitted changes
git status
# Example output:
# ----------
# git status
# On branch automatedStyling
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git restore <file>..." to discard changes in working directory)
# modified: pom.xml
#
# no changes added to commit (use "git add" and/or "git commit -a")
# Add the pom.xml file to what we plan to commit.
# Even if you have other files with modifications (from earlier maven build runs), the pom.xml is all that we want to commit for now.
git add pom.xml
# Confirm the status of the commit
git status
# Example output:
# -------
# On branch automatedStyling
# Changes to be committed:
# (use "git restore --staged <file>..." to unstage)
# modified: pom.xml
# Commit the pom.xml changes
git commit -m "Automate the Formatting! Maven Spotless Plugin"
# Rerun the Maven build to re-apply all auto-formatting changes
mvn clean install
# Commit all modified files locally
git commit -a -m "Automated Formatting"
# Push your local changes to the team/remote Git instance
# In this case, my branch name is automatedStyling
git push origin automatedStyling

Leave a comment