Swagger Integration

When creating an application with REST API, good documentation is one of the mandatory non-functional requirement otherwise whoever is going to consume will have to go through lot of troubles to understand the API contract along with request and response model.

And another downside is that every time we update something in the API, it should be updated in the reference documentation. Accomplishing this manually is a tedious job and people tend to skip this portion upto 95% of time, so automation of this process is inevitable.

We will be using the swagger-springmvc implementation of the Swagger specification. In case, if you are not familiar with Swagger, please do visit swagger.io to learn more about it.

https://swagger.io

Image source – https://swagger.io

Here is the sample code base of spring REST web service application that has been built as an example with Swagger integrated. You can download the code from github.

Swagger Integrating Steps

Adding Maven Dependency

As you are aware to include any library into the project, you need to add a maven dependency into your project. Let’s go ahead and add the dependency of Springgox in our application pom.xml file.

<dependency>
      <groupId>com.mangofactory</groupId>
      <artifactId>swagger-springmvc</artifactId>
      <version>1.0.1</version>
</dependency>
New Property File

Create a new property file under src/main/resources folder and add the following properties and customize according to your project.

application.api.title=Title of the project you want to display in the Swagger UI
application.api.description=A short description about your project
application.api.email=Email address you want to use that will be provided as a link in the Swagger UI
application.api.licenseType=Application License V2
application.api.licenseLocation=http://www.apache.org/licenses/LICENSE-2.0.html
Swagger Configuration Class

Add a SwaggerConfiguration class to the project which basically to configure the SwaggerSpringMvcPlugin so that it can collect all API’s information. The configuration might look complicated, but is actually straight forward and SwaggerConfig will looks like this:

public class SwaggerConfig {

  private static final Logger LOGGER = LoggerFactory.getLogger(SwaggerConfig.class);

  @Autowired
  private SpringSwaggerConfig springSwaggerConfig;

  private ApiInfo apiInfo() {
    String appTitle = null;
    String appDescription = null;
    String appContactEmail = null;
    String appLicenseType = null;
    String appLicenseURL = null;
    Properties properties = new Properties();
    try {
      properties.load(this.getClass().getClassLoader().getResourceAsStream("swagger.properties"));
      appTitle = properties.getProperty("application.api.title");
      appContactEmail = properties.getProperty("application.api.email");
      appDescription = properties.getProperty("application.api.description");
      appLicenseType = properties.getProperty("application.api.licenseType");
      appLicenseURL = properties.getProperty("application.api.licenseLocation");
    } catch (IOException ioe) {
      LOGGER.error("Failed to load swagger.properties. ErrMessage: {}", ioe.getMessage(), ioe);
    }
    return new ApiInfo(appTitle, appDescription, null, appContactEmail, appLicenseType,
        appLicenseURL);
  }

  @Bean
  public SwaggerSpringMvcPlugin customImplementation() {
    SwaggerSpringMvcPlugin config = new SwaggerSpringMvcPlugin(this.springSwaggerConfig);
    config.apiInfo(apiInfo());
    config.ignoredParameterTypes(Principal.class);
    config.ignoredParameterTypes(HttpServletRequest.class);
    config.ignoredParameterTypes(HttpServletResponse.class);
    config.ignoredParameterTypes(Model.class);
    SwaggerPathProvider provider = new SwaggerPathProvider() {
      @Override
      protected String applicationPath() {
        return getAppRoot().build().toString();
      }

      private UriComponentsBuilder getAppRoot() {
        return UriComponentsBuilder.fromHttpUrl("http://localhost:9090/swagger-int");
      }

      @Override
      protected String getDocumentationPath() {
        return getAppRoot().path(DefaultSwaggerController.DOCUMENTATION_BASE_PATH).build()
            .toString();
      }
    };
    config.pathProvider(provider);
    return config;
  }

}
Swagger UI

Swagger UI is just a HTML/CSS/JavaScript interface that displays the JSON response in a nicer way. It is possible to just add a jar to your classpath and have the UI working, but that doesn’t enable you to make any changes to it. Hence we are going to add the static files to our project so that it can be customized as per the requirement.

To get the Swagger UI source and static files, use the following steps:

git clone https://github.com/wordnik/swagger-ui
git checkout v2.2.5
cp -r swagger-ui/dist /swagger-int/src/main/webapp/docs
Swagger Annotations

Your controllers and methods can be annotated with Swagger annotations to define the text of the API documentation. I have started off by only using two, namely @Api and @ApiOperation which are annotated at class level and method level respectively.

@RestController
@RequestMapping(value = "/api/systemProperty")
@Api(value = "SystemPropertyController", description = "System Property API")
public class SystemPropertyController {

  private static final Logger LOGGER = LoggerFactory.getLogger(SystemPropertyController.class);

  @ApiOperation(value = "Get System Property", notes = "Get System Property")
  @RequestMapping(value = {"/getValue"}, method = {RequestMethod.GET},
      produces = {MediaType.APPLICATION_JSON_VALUE})
  public SystemProperty getSystemProperty(@RequestParam String variable)
      throws ReflectiveOperationException {
    LOGGER.info("variable: {}", variable);
    return new SystemProperty(variable, UUID.randomUUID().toString());
  }

  @ApiOperation(value = "Set System Property", notes = "Set System Property")
  @RequestMapping(value = {"/setValue"}, method = {RequestMethod.POST},
      produces = {MediaType.APPLICATION_JSON_VALUE})
  public SystemProperty setSystemProperty(@RequestParam String variable, @RequestParam String value)
      throws ReflectiveOperationException {
    LOGGER.info("variable: {}, value: {}", variable, value);
    return new SystemProperty(variable, "Updated: " + value);
  }

}

After all above steps, compile your project and build the artifact. Once the artifact is built successfully, deploy it in your application/web server container like tomcat, jboss etc.

To validate that swagger integration is working fine with the application, you can type in the following URL in your browser:

http://localhost:8080/swagger-int/api-docs

The response what you get is a JSON with a set of key-value pairs. If you see the response, then swagger integration is working as expected.

To load the Swagger UI, you can type in the following URL in your browser:

http://localhost:8080/swagger-int/docs/index.html

Swagger UI is a built-in solution which makes user interaction with the Swagger-generated API documentation lot easier. Here you should see all the API’s of your application grouped based at each controller level. You can individual API details like HttpMethod, parameters, end point, request and response models and status code etc.

Each time you make the changes to any API signature, the documentation on the Swagger gets updated on each compilation. Hope it helps lot of us who are not interested in documentation or updating them whenever something gets changed or updated.

Engati – www.engati.com – A Coviam technologies platform
Coviam Technologies
www.coviam.com

Leave a Reply

Your email address will not be published.