Generate client code from Spring Boot using Springdoc OpenAPI and Maven

Generating client code from an OpenAPI specification can save a lot of development time and reduce risk of that code being outdated. This article shows an easy and efficient way to generate Angular code from a Java Spring Boot project using Springdoc OpenAPI and Maven.

Your project should be using Springdoc OpenAPI for generating the documentation and Maven as your build automation tool. If you are not using Springdoc OpenAPI, click here to read about generating client code from Spring Boot using Maven for a slightly less efficient approach that works with other OpenAPI libraries.

If you are not using Maven, however, you may find use in combining the GenerateSwagger test class from an older article with either the OpenAPI Generator CLI or the OpenAPI Generator Gradle Plugin, instead.

To follow along with this article, I encourage you to use the example project. The following commit provides the blank slate we need:

https://github.com/daniel-frak/client-code-generation-maven-springdoc/tree/212db72a9f0de9499535dc3960a57b9bbf65ebfa

Add POM configuration

To achieve our goal we will add two new plugins – springdoc-openapi-maven-plugin and openapi-generator-maven-plugin – as well as configure the existing spring-boot-maven-plugin.

Springdoc-openapi-maven-plugin will be used to generate an OpenAPI specification file from our Java code during build time, then openapi-generator-maven-plugin will use that file to generate the desired Angular code.

Both of these plugins’ goals will be made to execute during the integration-test phase in a custom profile, so that we can run the code generation by invoking Maven’s verify phase (note that invoking just integration-test will not work as we will also need the pre- and post- phases).

All that needs to be done to achieve this is adding a new profile to the POM with the necessary plugins configured for code generation:

    <!-- Client code generation -->
    <profiles>
        <profile>
            <id>angular</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springdoc</groupId>
                        <artifactId>springdoc-openapi-maven-plugin</artifactId>
                        <version>1.4</version>
                        <executions>
                            <execution>
                                <id>openapi-file-generation</id>
                                <goals>
                                    <goal>generate</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.openapitools</groupId>
                        <artifactId>openapi-generator-maven-plugin</artifactId>
                        <version>6.0.0</version>
                        <executions>
                            <execution>
                                <id>angular-client-code-generation</id>
                                <phase>post-integration-test</phase>
                                <goals>
                                    <goal>generate</goal>
                                </goals>
                                <configuration>
                                    <inputSpec>${project.basedir}/target/openapi.json</inputSpec>
                                    <output>${project.build.directory}/generated-sources/angular</output>

                                    <generatorName>typescript-angular</generatorName>
                                    <!--
                                        Use this option to dump the configuration help for the specified generator
                                        instead of generating sources:
                                        <configHelp>true</configHelp>
                                    -->

                                    <configOptions>
                                        <!--
                                            Put generator-specific parameters here, e.g. for typescript-angular:
                                            <apiModulePrefix>Backend</apiModulePrefix>
                                         -->
                                    </configOptions>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

The springdoc-openapi-maven-plugin configuration is fairly straightforward – its generate goal is executed in the plugin’s default phase, which is integration-test.

Setting up openapi-generator-maven-plugin, however, is a little bit more complicated. Firstly, this plugin’s default phase is generate-sources, which means that it will run before the specification file gets generated. That is why the phase is explicitly set as post-integration-test.

Inside the <configuration> tag, <inputSpec> is used to define the location of the specification file, with <output> representing the target folder of the generated client code.

<generatorName> indicates which generator to use for the code generation. In this case typescript-angular is used, as that will create the necessary Angular 2+ files.

Optionally, generator-specific parameters can be specified inside <configOptions>.

Generate client code

The client code can now be generated using a simple mvn command:

mvn clean verify -P angular

A file called openapi.json should have now been generated inside the /target folder, right next to the application’s .jar file. This file has been used to generate the Angular code found in /target/generated-sources/angular.

Conclusion

The work done in this post is contained in the commit 820a35a7cef29d346ae63374124ccd76a61d9037.

This is the easiest and most efficient way to generate client code from an existing Spring Boot application that I have found so far. If code must be generated for more clients, additional profiles can be created, each for a specific generator and configuration.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *