Generate client code from Spring Boot using Springfox Swagger

One of Swagger’s strongest selling points is the ability to generate client code from an OpenAPI specification – this usually works well if you’re using the Design First approach. Unfortunately, there doesn’t seem to be much information on how to automate the process when using the Code First approach. Today we will learn how to easily generate Angular code from a Java Spring Boot project using Springfox Swagger and Swagger Codegen.

Prepare the project

Your project should be using Springfox Swagger for generating the documentation. I am assuming you are using Maven. If you are not, you should still be able to replicate this fairly easy using other build automation tools, as the use of Maven here is minimal.

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

https://github.com/daniel-frak/swagger-client-code-generation/tree/6ee4d65425ad1d1fe27cee69d35c03595172cf1f

Download Swagger Codegen CLI

There are several ways to use Swagger Codegen – as a Maven Dependency, via an online generator, using Swagger Hub or by simply downloading and running a jar file – that is Swagger Codegen CLI. The last option will be the most suitable for our purposes.

You need to decide which version of the CLI you are going to need. Versions 2.X support OpenAPI 2, while versions 3.X support OpenAPI 3. At this time Springfox Swagger only supports OpenAPI 2, so we should download the newest version of Swagger Codegen CLI 2.X:

https://mvnrepository.com/artifact/io.swagger/swagger-codegen-cli

Alternatively, the version for OpenAPI 3 can be found here:

https://mvnrepository.com/artifact/io.swagger.codegen.v3/swagger-codegen-cli

Make sure to download the jar file

Download the jar file manually from the website and put it into your project’s root directory.

Generate the OpenAPI specification file

Swagger Codegen works with OpenAPI specification files so we must generate one from our code. While Springfox Swagger doesn’t provide any tools for that, the specification we seek is already made available at the endpoint /v2/api-docs in our application. What is left to do is write some code to dump it into a file. We can do this in a Test class:

/**
 * Based on:
 * https://github.com/springfox/springfox/issues/1959
 */
@RunWith(SpringRunner.class)
@IfProfileValue(name = "test-profile", value = "GenerateSwagger")
@SpringBootTest
@TestPropertySource("classpath:application.properties")
public class GenerateSwagger {

    @Autowired
    WebApplicationContext context;

    /**
     * This test is intentionally skipped.
     * You can use it to generate a swagger.json file using the following command:
     * mvn -Dtest=GenerateSwagger -Dtest-profile=GenerateSwagger test
     */
    @Test
    public void generateSwagger() throws Exception {
        MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
        mockMvc.perform(MockMvcRequestBuilders.get("/v2/api-docs")
                .accept(MediaType.APPLICATION_JSON))
                .andDo(this::saveToFile);
    }

    private Path saveToFile(MvcResult r) throws IOException {
        return Files.write(Paths.get("swagger.json"),
                Collections.singletonList(r.getResponse().getContentAsString()), StandardCharsets.UTF_8);
    }
}

While the above solution is not ideal, there currently seems to be no other way to achieve the desired result. The addition of the @IfProfileValue annoation means that the test will not run during a normal mvn test routine. Now we can run the following command to generate a swagger.json file in our root project directory:

mvn -Dtest=GenerateSwagger -Dtest-profile=GenerateSwagger test

Generate the client code

With the swagger.json file now existing, we can finally generate the client code itself. The template for the command we need is:

java -jar swagger-codegen-file generate -i specification-file -l client-language -o output-directory

where:

  • swagger-codegen-file – the path to your Swagger Codegen jar file
  • specification-file – the path to the generated swagger.json file
  • client-language – the language in which we expect the generated code to be
    • To find out which languages are supported, you can run the following command:
      java -jar swagger-codegen-file langs
    • in our case the language is: typescript-angular
  • output-directory – a relative directory in which the generated code should be placed

In our case the full command needed to generate Angular client code from the swagger.json file is as follows:

java -jar swagger-codegen-cli-2.4.8.jar generate -i swagger.json -l typescript-angular -o angular

After running the command, you will find the generated client code in the /angular directory in your project root.

The generated client code, ready to be used

Automate the process

The last step is to create scripts to fully automate the client code generation. We want to be able to generate the swagger.json file, remove the angular folder and generate it again with a single command.

The following is a linux bash script which you should call generate-client-code.sh:

#!/bin/bash
mvn -Dtest=GenerateSwagger -Dtest-profile=GenerateSwagger test && rm -rf angular &&
java -jar swagger-codegen-cli-2.4.8.jar generate -i swagger.json -l typescript-angular -o angular

And here is a version of this script that will work on Windows machines. Call this one generate-client-code.bat:

mvn -Dtest=GenerateSwagger -Dtest-profile=GenerateSwagger test &&
java -jar swagger-codegen-cli-2.4.8.jar generate -i swagger.json -l typescript-angular -o angular

Both scripts should reside in the root directory. Running either of them will generate the Angular client code from the Springfox Swagger documentation.

Update your .gitignore

We don’t want to commit the generated files to our git repository, so make sure to add them to the .gitignore file:

/swagger.json
/angular

Conclusion

The work done in this post is contained in the commit b948fadce6bc0fd361003aee50d1367b073b6d72.

This is certainly not the only method of generating client code from backend code, but it is one that I found to work reasonably well – it reduces the sometimes complex process of code generation to a single command. You can even go further with the scripts, making it so that the client code gets copied straight to your frontend module after successful generation.

As there aren’t many resources detailing proper code generation techniques, I encourage you to let me know what you think about it and what could be improved.

Daniel Frąk Written by:

Be First to Comment

    Leave a Reply

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