Smooth and powerful Swagger integration via JaxRS Analyzer

TL;DR – watch this video: https://youtu.be/aKShM1AUbIU

This post is an update from “Some words on JavaEE, REST and Swagger” and will show the following:

  • Generating Swagger spec file via JaxRS Analyzer
  • Executable API documentation with Swagger UI
  • Automate everything with Swagger Addon

Generating Swagger 2.0 spec based on your REST endpoints

We will start with the most important (and easy) step shown in this post.

Let’s suppose that you have the following (JaxRS) REST endpoint which intends to update a given car:

@Path("/cars")
@Produces("application/json;charset=utf-8")
public class CarEndpoint {

    /**
     * @param id The identifier of the car to be updated
     * @param entity the changes to be applied
     */
    @PUT
    @Path("/{id:[0-9][0-9]*}")
    @Consumes("application/json")
    public Response update(@PathParam("id") Integer id, Car entity) {
        if (entity == null) {
            return Response.status(Status.BAD_REQUEST).build();
        }
        if (!id.equals(entity.getId())) {
            return Response.status(Status.CONFLICT).entity(entity).build();
        }
        if (carService.crud().eq("id", id).count() == 0) {
            return Response.status(Status.NOT_FOUND).build();
        }
        try {
            carService.update(entity);
        } catch (OptimisticLockException e) {
            return Response.status(Status.CONFLICT).entity(e.getEntity()).build();
        }

        return Response.noContent().build();
    }
}

 

Now to generate the swagger specification from this endpoint you can use the JaxRS Analyzer. JaxRS Analyzer will use byte code analysis to infer the endpoint payload, response status, response types and so on. It also reads javadoc tags to enrich endpoint and parameters descriptions.

We will use the analyzer maven plugin to generate swagger spec file at build time:

 

<plugin>
    <groupId>com.sebastian-daschner</groupId>
    <artifactId>jaxrs-analyzer-maven-plugin</artifactId>
    <version>0.14</version>
    <executions>
        <execution>
            <goals>
                <goal>analyze-jaxrs</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <backend>swagger</backend>
        <resourcesDir>cdi-crud/apidocs</resourcesDir>
    </configuration>
</plugin>

The minimal configuration for the plugin will require a backend which can be swagger, plain text (default) and asciidoc.

The resourcesDir, which defaults to jaxrs-analyzer, is a directory (relative to build directory) where swagger specification file will be generated. Other configuration attributes can be found here.

For our example, after maven build the swagger.json file will be generated at target/cdi-crud/apidocs, here is its content:

 

{
    "swagger":"2.0",
    "info":{
        "version":"4.0.0",
        "title":"cdi-crud"
    },
    "host":"",
    "basePath":"/cdi-crud/rest",
    "schemes":[
        "http"
    ],
    "tags":[
        {
            "name":"cars"
        }
    ],
    "paths":{
        "/cars/{id}":{
            "put":{
                "consumes":[
                    "application/json"
                ],
                "produces":[
                    "application/json;charset=utf-8"
                ],
                "parameters":[
                    {
                        "type":"integer",
                        "name":"id",
                        "in":"path",
                        "required":true,
                        "description":"The identifier of the car to be updated"
                    },
                    {
                        "name":"body",
                        "in":"body",
                        "required":true,
                        "schema":{
                            "$ref":"#/definitions/Car"
                        },
                        "description":"the changes to be applied"
                    }
                ],
                "responses":{
                    "204":{
                        "description":"No Content",
                        "headers":{
                        }
                    },
                    "400":{
                        "description":"Bad Request",
                        "headers":{
                        }
                    },
                    "404":{
                        "description":"Not Found",
                        "headers":{
                        }
                    },
                    "409":{
                        "description":"Conflict",
                        "headers":{
                        },
                        "schema":{
                            "$ref":"#/definitions/Car"
                        }
                    }
                },
                "tags":[
                    "cars"
                ]
            }
        }
    },
    "definitions":{
        "Car":{
            "properties":{
                "id":{
                    "type":"integer"
                },
                "model":{
                    "type":"string"
                },
                "name":{
                    "type":"string"
                },
                "price":{
                    "type":"number"
                },
                "version":{
                    "type":"integer"
                }
            }
        }
    }
}

As you can see the analyzer was able to infer all response codes from our endpoint as well as the payload. It also could read the javadoc and added parameters description.

You can paste the above json content into swagger editor to see how it looks like.

Executable API documentation with Swagger UI

A nice way to expose your API documentation is through Swagger UI. It is mainly a javascript library which will read your swagger.json spec file and turn it into a nice executable api documentation. As you are generating the swagger spec at build time it turns out that this documentation is always updated.

The steps to add swagger ui (as documented in the official site) is mainly copy the library to your project. I’ve done that and made a small change to make swagger ui read the swagger.json from within our application instead of a remote URL.

Here is how our sample endpoint is rendered in swagger ui:

cdi-crud-rest-api

 

You can also browse the API docs live on Openshift here (it may be unavailable on your first access because of my openshift free account [it shuts the app down when there is no access in a day], just wait a few minutes and try again).

Automating everything with JBoss Forge Swagger Addon

All the above steps described can be automated with Swagger Addon as showed in the video on the beginning of this post.

Conclusion

We saw that creating and maintaining an executable API documentation based on JaxRS endpoints is quite easy (thanks to JaxRS analyzer). You can even automate that with the Swagger Addon.

All code is available on github here.