How to beautify java code reliably
Tags: java, productivity, tutorial, webdev
Published: 2024-02-07 13:50:00

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](https://github.com/jhipster/prettier-java). 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](https://github.com/Schniz/fnm)) and to install a recent node version ([current long term support is 16+](https://nodejs.org/en/about/releases/))
- Add a `package.json` file at the root of your project and add prettier and the java plugin:

```json
{
  "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](https://prettier.io/docs/en/ignore.html) to avoid formatting those, eg:

```txt
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`:

```diff
{
  "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` :

```diff
{
// 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:
![Formatting java code on save](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lvsxnqkgfr1l5z6mphgj.gif)

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](https://www.jetbrains.com/help/idea/using-file-watchers.html#ws_file_watchers_bedore_you_start)

- Then configure the plugin `Tools/File Watchers`:

```txt
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](https://prettier.io/docs/en/webstorm.html#running-prettier-on-save-using-file-watcher)

## 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:

```yaml
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:

![CI running lint successfully](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w43qmbm2l97s0jq1rjyw.png)