How to beautify java code reliably
Jérémie Chauvel4 min read
I recently had to set up code formatting on a spring boot java application. Auto code formatting is important to avoiding useless diffs in source files, reducing noise in code review, allowing reviewers to focus on what matters.
Ideally we want:
- Automatic formatting on file save in IDE’s (vscode, IntelliJ)
- Capacity to run in CI
I wanted to integrate well with vscode and after trying some solution like:
- java autoformat, which I couldn’t run in CI and that was not really portable between IDEs
- maven auto formatting plugin (didn’t run on save easily in IDEs)
I ended up, from a friend suggestion, looking into a java prettier plugin. Prettier allowed for an easy integration with most Web IDE, can be configured to format on save for vscode and is trivial to run in CI.
Installing prettier for java
Let’s start with the setup in command line:
- Install nodejs: (I highly recommend using a node version manager like fnm) and to install a recent node version (current long term support is 16+)
- Add a
package.json
file at the root of your project and add prettier and the java plugin:
{
"name": "api",
"version": "0.0.1",
"private": true,
"devDependencies": {
"prettier": "2.5.1",
"prettier-plugin-java": "1.6.1"
},
"engines": {
"node": "16.x"
},
"scripts": {
"format": "prettier --write \"{,**/}*.{java,yml,yaml,md,json}\"",
"check-format": "prettier --check \"{,**/}*.{java,yml,yaml,md,json}\"",
"lint": "npm run check-format"
}
}
- Install the required node_module:
npm install
💡 Don’t forget to add node_modules
to your .gitignore
.
💡 I highly recommend adding a .prettierignore
that list autogenerated files to avoid formatting those, eg:
node_modules
target
You can now format java code running npm run format
🚀
💡 Do not forget to add node as a dependency for your project installation and to run npm ci
in your project installation script for new developers.
We now want to improve developer experience by integrating with IDEs, running the formatter in CLI being impractical.
Monorepo
If you are using a monorepo, I highly recommend setting up prettier in the root of your monorepo instead of setting up prettier in each sub directory.
Integrating with IDEs
vscode
To set up prettier in vscode: add the prettier for java extension to recommended vscode extensions for the project, to do so, you can simply add the id of the extension to: .vscode/extensions.json
:
{
"recommendations": [
"pivotal.vscode-boot-dev-pack",
"vscjava.vscode-java-pack",
"redhat.vscode-xml",
"sonarsource.sonarlint-vscode",
"gabrielbb.vscode-lombok",
"dbaeumer.vscode-eslint",
+ "esbenp.prettier-vscode", // the classic prettier extension
"shengchen.vscode-checkstyle",
]
}
then set up this extension as the default linter for java file in .vscode/settings.json
:
{
// rest of your configuration
// automatic format on save, I recommend the save on focus lost option as well
+ "editor.formatOnSave": true,
+ "[java]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ }
}
Already we can easily format java code on save:
I highly recommend checking in the .vscode
folder in your versioning tool (most likely git) to share this configuration with all developers.
IntelliJ
To integrate with prettier java formatter:
-
First install the File Watchers IntelliJ plugin
-
Then configure the plugin
Tools/File Watchers
:
Name: Prettier-java
File type: Java
Program: full path to `.bin/prettier` eg: `node_modules/.bin/prettier`
Arguments: --write $FilePathRelativeToProjectRoot$
Output paths to refresh: $FilePathRelativeToProjectRoot
Auto-save edited files to trigger the watcher: check it
Trigger the watcher on external changes: check it
prettier documentation can be found here for IntelliJ integration
Integrate code formatting check in CI
Now we only need to integrate this check in CI, I’m using gitlab for this example, but the principles can be transposed to any other CI.
First we need to add a new job:
stages:
- build
- test
- deploy
# ... rest of the file
# beautify backend files with prettier
lint-back:
image: node:lts-alpine # We use a node image to run prettier
stage: test # must match an existing stage
needs: [] # none required optimization that explain to gitlab ci that this test has no dependency and can start as soon as possible
script:
- npm ci
- npm run lint
# ... rest of the file
now just push your change, and you are all set: