How To Generate Spring Properties Documentation
Are you struggling to keep the documentation of your Spring configuration properties in line with the code? Learn how to solve the issue in this article.
Join the DZone community and get the full member experience.
Join For FreeAre you struggling to keep the documentation of your Spring configuration properties in line with the code? In this blog, you will take a look at the Spring Configuration Property Documenter Maven plugin, which solves this issue for you. Enjoy!
Introduction
Almost every Spring (Boot) application makes use of configuration properties. These configuration properties ensure that certain items in your application can be configured by means of an application.properties (or YAML) file. However, there is also a need to document these properties in order for someone to know what these properties mean, how to use them, etc. This is often documented in a README file. This README file needs to be manually maintained while the properties are present in a Java class which also contains documentation and annotations.
Wouldn’t it be great when the documentation was present at one location (the Java class, close to the code) and the documentation could be generated out of the code? Good news! This is exactly what the Spring Configuration Property Documenter Maven plugin will do for you! In the remainder of this post, you will explore some of the features of this Maven plugin and how you can easily incorporate it into your project. The official documentation is more elaborate and can be found here.
The sources used in this blog can be found on GitHub.
Sample Application
First of all, you need to create a basic sample application. Navigate to Spring Initializr and select the dependencies Spring Web, Lombok, and Spring Configuration Processor.
Annotate the main Spring Boot application class with @ConfigurationPropertiesScan
.
@SpringBootApplication
@ConfigurationPropertiesScan("com.mydeveloperplanet.myspringconfigdocplanet.config")
public class MySpringConfigDocPlanetApplication {
public static void main(String[] args) {
SpringApplication.run(MySpringConfigDocPlanetApplication.class, args);
}
}
Create a configuration class MyFirstProperties
in the package config
. The configuration class makes use of constructor binding. See also a previous post, "Spring Boot Configuration Properties Explained," for more information about the different ways to create configuration properties.
@Getter
@ConfigurationProperties("my.first.properties")
public class MyFirstProperties {
private final String stringProperty;
private final boolean booleanProperty;
public MyFirstProperties(String stringProperty, boolean booleanProperty) {
this.stringProperty = stringProperty;
this.booleanProperty = booleanProperty;
}
}
Also, a ConfigurationController
is added to the package controller
which returns the properties. This controller is only added as an example of how to use the properties. It will not be of any relevance to this blog.
Build the application.
$ mvn clean verify
Run the application.
$ mvn spring-boot:run
Invoke the endpoint as configured in the ConfigurationController
.
$ curl http://localhost:8080/configuration
Take a look at the directory target/classes/META-INF
. A file spring-configuration-metadata.json
is present here, which contains metadata about the configuration classes. This information is used by the Spring Configuration Property Documenter Maven plugin in order to generate the documentation.
This metadata file is generated because you added the Spring Configuration Processor as a dependency.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
Generate Documentation
The plugin is able to generate the documentation in four different formats:
- ASCII Doctor
- Markdown
- HTML
- XML
In order to generate the documentation, you only have to add the plugin to the build section (next to adding the Spring Configuration Processor dependency). For each format type, an execution is added. If you only want documentation in markdown, just remove the other executions.
<build>
<plugins>
<plugin>
<groupId>org.rodnansol</groupId>
<artifactId>spring-configuration-property-documenter-maven-plugin</artifactId>
<version>0.6.1</version>
<executions>
<execution>
<id>generate-adoc</id>
<phase>process-classes</phase>
<goals>
<goal>generate-property-document</goal>
</goals>
<configuration>
<type>ADOC</type>
</configuration>
</execution>
<execution>
<id>generate-markdown</id>
<phase>process-classes</phase>
<goals>
<goal>generate-property-document</goal>
</goals>
<configuration>
<type>MARKDOWN</type>
</configuration>
</execution>
<execution>
<id>generate-html</id>
<phase>process-classes</phase>
<goals>
<goal>generate-property-document</goal>
</goals>
<configuration>
<type>HTML</type>
</configuration>
</execution>
<execution>
<id>generate-xml</id>
<phase>process-classes</phase>
<goals>
<goal>generate-property-document</goal>
</goals>
<configuration>
<type>XML</type>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The documentation will be generated when executing a build with Maven, but a quick way is to execute the process-classes
goal.
$ mvn process-classes
Or you can invoke a specific execution.
$ mvn spring-configuration-property-documenter:generate-property-document@generate-markdown
Take a look at the directory target/property-docs
. For each type, documentation for the configuration properties is added.
The ASCII Doctor format
The Markdown format
The HTML format
The XML format is a bit elaborate to display, but it contains an XML representation of the above.
In case you have a Maven multi-module project, you can combine all the properties of the different modules into one file. How to do so is described in the documentation.
Customize Output
In the remainder of the post, you will continue with the markdown format. In the above screenshots, you notice that an Unknown Group is added. This group is also empty. By default, this group is always added to the output, but it is possible to remove it by means of the markdownCustomization
parameter. There are many more customizations available which are listed in the documentation. In order to disable the Unknown Group in the output, you set the parameter includedUnknownGroup
to false
.
<execution>
<id>generate-markdown</id>
<phase>process-classes</phase>
<goals>
<goal>generate-property-document</goal>
</goals>
<configuration>
<type>MARKDOWN</type>
<markdownCustomization>
<includeUnknownGroup>false</includeUnknownGroup>
</markdownCustomization>
</configuration>
</execution>
Execute the markdown generation, and you will notice that the Unknown Group is not present anymore in the output.
Description and Default Value
In the above output, you notice that the description of the properties and the default value of stringProperty
is empty.
Create a new configuration class MySecondProperties
. Add a Javadoc above the fields representing the properties and add a @DefaultValue
annotation before stringProperty
in the constructor.
@Getter
@ConfigurationProperties("my.second.properties")
public class MySecondProperties {
/**
* This is the description for stringProperty
*/
private final String stringProperty;
/**
* This is the description for booleanProperty
*/
private final boolean booleanProperty;
public MySecondProperties(@DefaultValue("default value for stringProperty") String stringProperty,
boolean booleanProperty) {
this.stringProperty = stringProperty;
this.booleanProperty = booleanProperty;
}
}
Generate the documentation and you will notice that the description is present and the default value is filled for stringProperty
.
This is quite awesome, isn’t it? The documentation is right there together with the code and the documentation in markdown is generated from it.
Nested Properties
Does it also work for nested properties? Let’s find out. Create a configuration class MyThirdProperties
with a nested property nestedProperty
which also contains a stringProperty
and a booleanProperty
. The booleanProperty
is defaulted to true.
@Getter
@ConfigurationProperties("my.third.properties")
public class MyThirdProperties {
/**
* This is the description for stringProperty
*/
private final String stringProperty;
/**
* This is the description for booleanProperty
*/
private final boolean booleanProperty;
private final NestedProperty nestedProperty;
public MyThirdProperties(@DefaultValue("default value for stringProperty") String stringProperty,
boolean booleanProperty,
@DefaultValue NestedProperty nestedProperty) {
this.stringProperty = stringProperty;
this.booleanProperty = booleanProperty;
this.nestedProperty = nestedProperty;
}
@Getter
public static class NestedProperty {
/**
* This is the description for nested stringProperty
*/
private final String stringProperty;
/**
* This is the description for nested booleanProperty
*/
private final boolean booleanProperty;
public NestedProperty(@DefaultValue("default value for nested stringProperty") String stringProperty,
@DefaultValue("true") boolean booleanProperty) {
this.stringProperty = stringProperty;
this.booleanProperty = booleanProperty;
}
}
}
Generate the Markdown documentation and you will notice that the documentation also contains the nested property.
Records
Since the configuration properties are immutable, it is even better to use Java records instead of using Lombok. Create a configuration class MyFourthProperties
and use Java records. The question is where to add the description of the properties because there are no fields to which you can add Javadoc.
/**
* @param stringProperty This is the description for stringProperty
* @param booleanProperty This is the description for booleanProperty
*/
@ConfigurationProperties("my.fourth.properties")
public record MyFourthProperties (@DefaultValue("default value for stringProperty") String stringProperty,
@DefaultValue("true") boolean booleanProperty) {
}
Generate the Markdown documentation and notice that the description is empty.
This is not an issue with the plugin, however. The description is empty in the spring-configuration-metadata.json
file and the plugin just uses this information.
A question on Stack Overflow is asked about this. Hopefully, an answer will follow.
Conclusion
The Spring Configuration Property Documenter Maven plugin is a great initiative in order to keep documentation closer to the code and to generate it based on the code. It fills a gap in my opinion which benefits almost all Spring projects.
Published at DZone with permission of Gunter Rotsaert, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments