2016/09/24

Generate PDF documentation from swagger annotations

TL DR;: Check this working example github.com/nacho4d/rest_to_pdf_example

Overview

I have a REST (JAX-RS) Java Web App and I use Maven (pom.xml) to build it.
  1. Annotate: Use swagger-annotations to annotate my endpoints.
  2. Generate swagger file: Use the swagger-maven-plugin to generate swagger file from sources
  3. Generate asciidoc file: Use the swagger2markup-maven-plugin to generate asciidoc from swagger file
  4. Generate pdf file: Use asciidoctor-maven-plugin to generate PDF from asciidoc file

0. Preparation

I use a couple of variables: swagger.directory and asciidoctor.directory.
<properties>
    <swagger.directory>${project.build.directory}/generated-docs/swagger</swagger.directory>
    <asciidoctor.directory>${project.build.directory}/generated-docs/asciidoc</asciidoctor.directory>
</properties>
One of the dependencies (markdown_to_asciidoc) of swagger2markup-maven-plugin need below repository:
<pluginRepositories>
    <pluginRepository>
        <id>jcenter-snapshots</id>
        <name>jcenter</name>
        <url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
    </pluginRepository>
    <pluginRepository>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
        <id>jcenter-releases</id>
        <name>jcenter</name>
        <url>http://jcenter.bintray.com</url>
    </pluginRepository>
</pluginRepositories>

1. Annotate

Add io.swagger dependency inside dependenciesand start annotating. Basically just add @ApiOperation(value = "Description of endpoint") to each endpoint (or swagger file will contain 0 endpoints). Near @POST, @GET, @DELETE, etc should be fine. See a more detailed example.
<dependency>
    <groupId>io.swagger</groupId>
    <artifactId>swagger-annotations</artifactId>
    <version>1.5.10</version>
</dependency>

2. Generate swagger file

This looks a bit lengthy. but IMO should work for most people. Please adjust locations to have a list of all packages where your endpoints classes are (or swagger file will contain 0 endpoints). This should be inside build/plugins
<plugin>
    <groupId>com.github.kongchen</groupId>
    <artifactId>swagger-maven-plugin</artifactId>
    <version>3.1.4</version>
    <configuration>
        <apiSources>
            <apiSource>
                <springmvc>false</springmvc>
                <locations>
                    <location>com.company.com.support.service</location>  <!-- Modify for your project -->
                </locations>
                <schemes>http,https</schemes>
                <host>my.host.net</host>
                <basePath>/api</basePath>
                <info>
                    <title>Some System - API Reference</title>
                    <version>v1</version>
                    <description>API Reference Description.</description>
                    <termsOfService>TOS</termsOfService>
                    <contact>
                        <email>me@email.com</email>
                        <name>Me</name>
                        <url>www.company.com</url>
                    </contact>
                    <license>
                        <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
                        <name>Apache 2.0</name>
                    </license>
                </info>
                <outputPath>${swagger.directory}/document.html</outputPath>
                <swaggerDirectory>${swagger.directory}</swaggerDirectory>
                <outputFormats>yaml</outputFormats>
            </apiSource>
        </apiSources>
    </configuration>
    <executions>
        <execution>
            <?m2e execute onConfiguration?>
            <phase>compile</phase>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
</plugin>
I have attached generate goal of this plugin to the compile phase. Hence we should be able to generate target/generated-docs/swagger/swagger.yaml file with:
mvn compile

2. Generate asciidoc file

I set the input to be the output of the previous plugin. Also set the output file (not output directory) so everything is concatenated in a single file. Place this inside build/plugins after swagger-maven-plugin.
<plugin>
    <groupId>io.github.swagger2markup</groupId>
    <artifactId>swagger2markup-maven-plugin</artifactId>
    <version>1.0.1</version>
    <configuration>
        <swaggerInput>${swagger.directory}/swagger.yaml</swaggerInput>
        <outputFile>${asciidoctor.directory}/ApiDocumentation</outputFile>
        <config>
            <swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
        </config>
    </configuration>
    <executions>
        <execution>
            <phase>prepare-package</phase>
            <goals>
                <goal>convertSwagger2markup</goal>
            </goals>
        </execution>
    </executions>
</plugin>
I have attached convertSwagger2markup goal of this plugin to the prepare-package phase. Hence we should be able to generate target/generated-docs/asciidocs/ApiDocumentation.adoc file with:
mvn package

3. Generate pdf file

Again, I set the input to be the output of the previous plugin. Place this inside build/plugins after swagger2markup-maven-plugin.
<plugin>
    <groupId>org.asciidoctor</groupId>
    <artifactId>asciidoctor-maven-plugin</artifactId>
    <version>1.5.3</version>
    <dependencies>
        <dependency>
            <groupId>org.asciidoctor</groupId>
            <artifactId>asciidoctorj-pdf</artifactId>
            <version>1.5.0-alpha.11</version>
        </dependency>
    </dependencies>
    <configuration>
        <sourceDirectory>${asciidoctor.directory}</sourceDirectory>
        <attributes>
            <sourcedir>${project.build.sourceDirectory}</sourcedir>
        </attributes>
    </configuration>
    <executions>
        <execution>
            <id>generate-pdf-doc</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>process-asciidoc</goal>
            </goals>
            <configuration>
                <backend>pdf</backend>
                <sourceHighlighter>rouge</sourceHighlighter>
                <attributes>
                    <icons>font</icons>
                    <pagenums/>
                    <toc/>
                    <idprefix/>
                    <idseparator>-</idseparator>
                    <sectnums>true</sectnums>
                </attributes>
            </configuration>
        </execution>
    </executions>
</plugin>
Similarly process-asciidoc goal of this plugin to the prepare-package phase. Hence we should be able to generate target/generated-docs/ApiDocumentation.pdf file with:
mvn package
That is all folks :)
PDF自動生成できた!APIリファレンスと頼まれて「えええええーーーーー」と言わなくなったはず、(笑)

Links

0 comments :