One of my favorites low-key features of Spring Boot is the ability to map configuration properties from your application.{yml|properties} into Java Beans using @ConfigurationProperties annotation :

  • It allows type-safe configuration binding
  • It allows also easy validation using β€” with the standard JSR-380 specification.

Furthermore, using spring-boot-configuration-processor, you can generate a configuration metadata in a JSON file, which provides useful information on how to use the properties.

While this is mostly useful for your IDE to provide autocompletion and usage, in this post we are going to look at how to leverage this mechanism to document your custom properties in any format using jbang.

Creating a demo project

First let’s create a very simple Spring Boot application. I generated one using https://start.spring.io (πŸ”— example configuration).

First let’s start by defining our custom application properties.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21

@Component
@ConfigurationProperties("my-service")
public class MyProperties {

  /** enable a feature */
  private boolean enabled;

  private final Other other = new Other();

  // getters & setters omitted for brevity
  public static class Other {

    /** another documenter property */
    private String someProperty = "a default value";

    // getters & setters omitted for brevity
  }
}


Let’s note a few things:

  • our properties are included in a standard java bean class
  • documentation is provided via our usual javadoc
  • πŸ’‘tip: we define our custom properties in a given namespace. This is to ensure it does not clash with other properties from spring core or a starter-* dependency

Generating metadata file

To generate a metadata files, let’s follow the instructions for maven, by adding the needed dependency in our pom.xml (configuration is provided for gradle users too).

1
2
3
4
5
6

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

Now to generate the configuration metadata, a standard mvn compile command should generate our file in the build folder: META-INF/spring-configuration-metadata.json. It should look something like this :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
  "groups": [
    {
      "name": "my-service",
      "type": "com.example.demo.MyProperties",
      "sourceType": "com.example.demo.MyProperties"
    }
  ],
  "properties": [
    {
      "name": "my-service.enabled",
      "type": "java.lang.Boolean",
      "description": "enable a feature",
      "sourceType": "com.example.demo.MyProperties",
      "defaultValue": false
    }
  ]
}

The generated file contains our property name, value and description.

The configuration metadata format could also contain deprecation information, or even hints with possible values for a given property. You could even provide manual hints via an additional file. Be sure to check the official docs!.

Documenting our configuration properties

Now that we have a json file containing all the information we need, it would be nice to have a script that can:

  • parse the json data from one or many files
  • aggregate it (in case of multiple files)
  • export it to a file using a templating engine (to support any format: markdown, html, asciidoc)

This is exactly what I did using JBang, that I discovered not so long ago.

This time around I discovered that you can publish your scripts and easily share them with the world πŸŽ‰

Using the script

The source code is available on github.

Using jbang’s implicit alias catalog you can call the script as easily as a single shell command.

1
jbang springPropertyDocumenter@mikomatic -o generated-docs.md

This will download the script (you have to trust the source thought 😏), parse your current folder looking for META-INF/spring-configuration-metadata.json files and generates a markdown version using a default template. Then it outputs the result to generated-docs.md

Result should look like this (with your favorite markdown editor):

spring documenter result

Options

As any command line application, usage is provided via the -h options:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
❯ jbang springPropertyDocumenter@mikomatic -h        
Usage: springPropertyDocumenter [-hV] -o=<output> [-t=<templateFile>]
                                [-m=<metadataLocationFolders>]...
Document spring boot properties based on property metadata
  -h, --help              Show this help message and exit.
  -m, --metadata-location-folders=<metadataLocationFolders>
                          Folder(s) containing spring boot configuration
                            metadata files (defaults to current folder)
  -o, --output=<output>   Markdown file output filename
  -t, --template=<templateFile>
                          an optional mustache template
  -V, --version           Print version information and exit.
  • -m, --metadata-location-folders: provides folders containing spring boot configuration metadata files (defaults to current folder)
  • -t, --template: provides a mustache template file if you want to customize the output, instead of the default one. This could be useful if you want to export you documentation in another format (asciidoc, html …).
  • -o, --output: the exported filename

I should probably document what variables are available in case of providing a custom template, but hopefully the source code is a good starting point for the moment.

Conclusion

In conclusion, the article demonstrates the power of Spring Boot’s @ConfigurationProperties combined with the spring-boot-configuration-processor.

We explored how to leverage this mechanism to document custom properties using JBang.

This approach could greatly simplify the documentation process by automating the extraction of property information and generating documentation in a desired format. It enhances the developer experience by providing autocomplete and usage information in IDEs and ensures that custom properties are well-documented and easily accessible to other team members.

Hope you found this useful, until next time πŸ‘‹!

References