Spring Boot + Swagger Codegen

Spring Boot + Swagger Codegen

2018, Apr 29    

Swagger Codegen

I’m sure you must have at least heard of swagger. Swagger is a documentation tool for your API which is widely used in the industry. Most of the developers out there, if they don’t have a purpose to put out custom documentation, they usually use swagger to inform their users about the API specification.

In swagger’s official website, it’s told that it can be used in all phases through API development lifecycle such as; design, documentation, testing and deployment. In this article, we are going to stay on using swagger for design purposes. I will describe how I define my API specification and models with swagger while working with spring boot.

An API is only as good as it’s documentation. Even if you serve some kickass, powerful business with your application, the person who is going to consume it will be successful as much as how well you provide them functionalities. So, it’s very important to provide them with a decent structure and describe the aspects of your interface completely. The reason why I prefer to use swagger codegen for implementing rest layers is that it reduces some overhead by providing a boilerplate and I can work more efficiently with keeping a single specification file and implementing my application around that.

Normally, I start developing a rest layer with designing. Firstly, I decide on the paths I’m going to serve. Then, I supply those paths with their corresponding request and response models, and I also think about exceptional cases and create error responses. After all that, I get my hands dirty and start to code. Reusability is the key thing for implementing a rest layer since all the models end up being similar in some way at the end of the day. So, it takes time for me to implement all the things and keep a nice structure during that.

However, while working with swagger codegen all I have to do is to just plan my interface in a yaml file. Then I can generate and use the corresponding mappings and models in my program. Swagger Editor is very handy for designing the interface. You can perfectly review the documentation output that resembles your specification and decide upon.

Swagger Editor

Swagger codegen uses a format called OpenAPI Specification. It is actually a cool format to keep your design well and formatted. Every time I check out for defining something new, I find ways to improve my patterns.

Using it in a spring boot project.

I am using maven in this example, so the first thing we need to configure is the swagger-codegen-maven-plugin. Generated classes will use swagger annotations, so we also add it as a dependency. I defined the path for definition.yml file under resources, which is going to be the single file codegen is going to use for generating the classes.

<properties>
    ...
    <swaggerSpec>src/main/resources/swagger/definition.yaml</swaggerSpec>
    <io.springfox.version>2.9.2</io.springfox.version>
    <io.swagger.version>1.5.21</io.swagger.version>
    <swagger-codegen-maven-plugin.version>2.3.1</swagger-codegen-maven-plugin.version>
    ...
</properties>
<dependencies>
    ...
    <dependency>
        <groupId>io.swagger</groupId>
        <artifactId>swagger-annotations</artifactId>
        <version>${io.swagger.version}</version>
        <scope>compile</scope>
    </dependency>
    ...
</dependencies>
<build>
    <plugins>
        ...
        <plugin>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-codegen-maven-plugin</artifactId>
            <version>${swagger-codegen-maven-plugin.version}</version>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    <configuration>
                        <inputSpec>${swaggerSpec}</inputSpec>
                        <apiPackage>swaggergen.controller</apiPackage>
                        <modelPackage>swaggergen.model</modelPackage>
                        <language>spring</language>
                        <configOptions>
                            <interfaceOnly>true</interfaceOnly>
                            <java8>true</java8>
                        </configOptions>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        ...
    </plugins>
</build>


For this example, we are going to define a simple hello path within our definition.yml.

paths:
  /hello:
    post:
      summary: Hello service.
      operationId: hello
      consumes:
        - application/json
      produces:
        - application/json
      parameters:
        - in: body
          name: helloRequest
          description: Credentials
          required: true
          schema:
            $ref: '#/definitions/HelloRequest'
      responses:
        "200":
          description: Successful operation
          schema:
            $ref: "#/definitions/HelloResponse"
definitions:
  HelloRequest:
    type: object
    properties:
      username:
        type: string
        description: name for the user
  HelloResponse:
    type: object
    properties:
      message:
        type: string
        description: Hello messsage


After a nice mvn clean compile, if nothing else is specified in properties, the package name will be derived from the API package name (in our case its swaggergen) and the codegen plugin will generate these resources.

Generated Classes

Alright now, codegen provided us with an interface “Hello.api” and two models to use. Hello.api basically includes our request mappings. So we can create a controller class and start implementing it. As you can see below, we are overriding the method “hello” which we defined as an operationId for our {post}/hello path. The method signature is ready as we defined in the definition.yml. We wind through the business implementation within the hello method and voila, we are done!

...
import swaggergen.controller.HelloApi;
import swaggergen.model.HelloRequest;
import swaggergen.model.HelloResponse;

@RestController
public class HelloController implements HelloApi {
    @Override
    public ResponseEntity<HelloResponse> hello(@RequestBody final HelloRequest helloRequest) {
        HelloResponse helloResponse = new HelloResponse();
        helloResponse.setMessage("Hello, " + helloRequest.getUsername() + "!");
        return ResponseEntity.status(HttpStatus.OK).body(helloResponse);
    }
}


You can also check this example from my github repository.