Dropwizard: Swagger Integration

This entry is part 5 of 5 in the series Dropwizard
(Last Updated On: )

In this tutorial I will show you how to use Swagger in your Maven application. I will also show you how to configure it with Swagger UI so when you start your application you can see the Swagger UI from your generated JSON.

POM.xml

Dependencies

<dependency>
	<groupId>io.dropwizard</groupId>
	<artifactId>dropwizard-assets</artifactId>
	<version>1.3.2</version>
</dependency>

<dependency>
	<groupId>io.swagger</groupId>
	<artifactId>swagger-jaxrs</artifactId>
	<version>1.5.19</version>
</dependency>

Plugins

maven-jar-plugin

If you followed creating a basic Dropwizard app then you should have this already installed. If so then just add the following two configs under “manifest” section.

<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
maven-clean-plugin

Because we are pulling the latest Swagger-UI code on each build we must clean the old build.

<plugin>
	<artifactId>maven-clean-plugin</artifactId>
	<version>3.1.0</version>
	<configuration>
		<filesets>
			<fileset>
				<directory>${basedir}/src/main/resources/swagger-ui</directory>
				<followSymlinks>false</followSymlinks>
			</fileset>
		</filesets>
	</configuration>
</plugin>
download-maven-plugin

We are downloading the latest Swagger-UI code from github. Notice how lifecycle phase “generate-resources” is used. This is important due to build getting the proper code before beginning build.

<plugin>
	<groupId>com.googlecode.maven-download-plugin</groupId>
	<artifactId>download-maven-plugin</artifactId>
	<version>1.4.0</version>
	<executions>
		<execution>
			<id>swagger-ui</id>
			<phase>generate-resources</phase>
			<goals>
				<goal>wget</goal>
			</goals>
			<configuration>
				<url>
					https://github.com/swagger-api/swagger-ui/archive/master.tar.gz
				</url>
				<unpack>true</unpack>
				<outputDirectory>
					${project.build.directory}
				</outputDirectory>
			</configuration>
		</execution>
	</executions>
</plugin>
replacer

This updates the code downloaded from github to have your swagger.json content instead of the petstore swagger content. Notice how lifecycle phase “generate-resources” is used. This is important due to build getting the proper code before beginning build.

<plugin>
	<groupId>com.google.code.maven-replacer-plugin</groupId>
	<artifactId>replacer</artifactId>
	<version>1.5.3</version>
	<executions>
		<execution>
			<phase>generate-resources</phase>
			<goals>
				<goal>replace</goal>
			</goals>
		</execution>
	</executions>
	<configuration>
		<includes>
			<include>${project.build.directory}/swagger-ui-master/dist/index.html</include>
			<include>${project.build.directory}/swagger-ui-master/dist/swagger-ui-bundle.js</include>
			<include>${project.build.directory}/swagger-ui-master/dist/swagger-ui-bundle.js.map</include>
			<include>${project.build.directory}/swagger-ui-master/dist/swagger-ui-standalone-preset.js</include>
			<include>${project.build.directory}/swagger-ui-master/dist/swagger-ui-standalone-preset.js.map</include>
			<include>${project.build.directory}/swagger-ui-master/dist/swagger-ui.js</include>
			<include>${project.build.directory}/swagger-ui-master/dist/swagger-ui.js.map</include>
		</includes>
		<replacements>
			<replacement>
				<token>http://petstore.swagger.io/v2/swagger.json</token>
				<value>/swagger.json</value>
			</replacement>
		</replacements>
	</configuration>
</plugin>
maven-resources-plugin

This will copy the content that you just downloaded and modified into your resources folder. Notice how lifecycle phase “generate-resources” is used. This is important due to build getting the proper code before beginning build.

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-resources-plugin</artifactId>
	<version>3.1.0</version>
	<executions>
		<execution>
			<id>copy-resources</id>
			<phase>generate-resources</phase>
			<goals>
				<goal>copy-resources</goal>
			</goals>
			<configuration>
				<outputDirectory>
					${basedir}/src/main/resources/swagger-ui
				</outputDirectory>
				<resources>
					<resource>
						<directory>
							${project.build.directory}/swagger-ui-master/dist
						</directory>
					</resource>
				</resources>
			</configuration>
		</execution>
	</executions>
</plugin>

Now if you run the following command you will see that the swagger-ui copied to your resources folder.

mvn clean install

MyDropwizardAppApplication

initialize

Now we need to configure our Dropwizard app to host the swagger-ui that we recently downloaded and modified. In our “MyDropwizardAppApplication” class that we created in the initial Dropwizard tutorial we must add the AssetsBundle for our swagger-ui.

@Override
public void initialize(final Bootstrap bootstrap) {
	bootstrap.addBundle(GuiceBundle.builder().enableAutoConfig(this.getClass().getPackage().getName())
			.modules(new ServerModule()).build());

	// This allows you to host swagger ui on this dropwizard app's host
	final AssetsBundle assetsBundle = new AssetsBundle("/swagger-ui", "/swagger-ui", "index.html");
	bootstrap.addBundle(assetsBundle);
	bootstrap.addCommand(new MyCommand());
}
run

Now we need to setup our Swagger scanners for our api and our models.

@Override
public void run(final MyDropwizardAppConfiguration configuration, final Environment environment) {
	this.initSwagger(configuration, environment);
}

private void initSwagger(MyDropwizardAppConfiguration configuration, Environment environment) {
	// Swagger Resource
	// The ApiListingResource creates the swagger.json file at localhost:8080/swagger.json
	environment.jersey().register(new ApiListingResource());
	environment.jersey().register(SwaggerSerializers.class);

	Package objPackage = this.getClass().getPackage();
	String version = objPackage.getImplementationVersion();

	// Swagger Scanner, which finds all the resources for @Api Annotations
	ScannerFactory.setScanner(new DefaultJaxrsScanner());

	//This is what is shown when you do "http://localhost:8080/swagger-ui/"
	BeanConfig beanConfig = new BeanConfig();
	beanConfig.setVersion(version);
	beanConfig.setSchemes(new String[] { "http" });
	beanConfig.setHost("localhost:8080");
	beanConfig.setPrettyPrint(true);
	beanConfig.setDescription("The drpowizard apis");
	beanConfig.setResourcePackage("ca.gaudreault.mydropwizardapp");
	beanConfig.setScan(true);
}

Now if we were to run our app we would be able to go to http://localhost:8080/swagger-ui/ and we would see our content but since we didn’t update any model or api then we wouldn’t see much of anything. So remember the previous tutorials on Dropwizard Guice and Dropwizard Resource. We will update those now.

Model

If you compare this to the one we did in the guice tutorial there are only a few differences. Notice we import the swagger annotations. We then add “ApiModel” annotation to the class and “ApiModelProperty” to the variable “value” and set it to be “NotNull”.

package ca.gaudreault.mydropwizardapp.models;

import java.io.Serializable;

import javax.validation.constraints.NotNull;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(description = "My Example Model.")
public class MyModel implements Serializable {
	private static final long serialVersionUID = 1L;
	@NotNull
	@ApiModelProperty(required = true, notes = "My value")
	private Integer value;
	
	public Integer getValue() {
		return value;
	}
	public void setValue(Integer value) {
		this.value = value;
	}
}

Resource

If you compare this to the one we did in the guice tutorial there are only a few differences. Notice our class has “@SwaggerDefinition” and “@API” defined. This will help the Swagger-UI  group your end points together using the tags. Also notice how our “runTest” end point has “@Path”, “@ApiResponses” and “@ApiOperation” now.

package ca.gaudreault.mydropwizardapp.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.eclipse.jetty.http.HttpStatus;

import com.codahale.metrics.annotation.Timed;
import com.google.inject.Inject;

import ca.gaudreault.mydropwizardapp.models.MyModel;
import ca.gaudreault.mydropwizardapp.services.MyService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Tag;

@SwaggerDefinition(tags = { @Tag(name = "MyResource", description = "My Example Resource") })
@Api(value = "MyResource")
@Timed
@Path("/my-resource")
public class MyResource {
	private MyService myService;

	@Inject
	public MyResource(final MyService myService) {
		this.myService = myService;
	}

	@GET
	@Path("/runTest")
	@ApiOperation(value = "Run test and returns myModel", notes = "Run test and returns myModel", response = MyModel.class, tags = {
			"MyResource" })
	@ApiResponses(value = {
			@ApiResponse(code = HttpStatus.OK_200, message = "Successfully Tested", response = MyModel.class) })
	@Timed
	@Produces(MediaType.APPLICATION_JSON)
	public MyModel runTest() {
		return this.myService.runTest();
	}
}

Run our Project

If we run our project and we hit the following rest end point http://localhost:8080/my-resource/runTest we will get back the below. This shows us our rest end point is working as expected still.

{"value":123123}

Checking Swagger-UI

Now that we have started our project we can now check to see what was generated. Go to Swagger-UI. You will see the below. You are now well on your way in using Swagger.

Model Expanded

Resource Expanded

 

 

 

 

References

The following helped me build this tutorial.

  • https://robferguson.org/blog/2016/12/11/resteasy-embedded-jetty-fat-jars-swagger-and-swagger-ui/
  • https://itazuramono.com/2015/12/07/automatic-swagger-documentation-for-dropwizard-using-maven/
  • http://mikelynchgames.com/software-development/adding-swagger-to-your-dropwizard-application/
Series Navigation<< Dropwizard: Resource