A 'simple' way to implement Swagger in a Spring MVC application

wavicle picture wavicle · Nov 3, 2014 · Viewed 82.2k times · Source

I have a ReSTFul API written in simple Spring (no Spring Boot, no fancy stuff!). I need to implement Swagger into this. So far, EVERY page on the internet has only driven me crazy with confusing configurations and bloated code that I did not find portable at all.

Does anyone have a sample project (or a set of detailed steps) that can help me accomplish this? In particular, I am looking for a good sample that uses swagger-springmvc. I know it has 'samples', but at best, the esoteric code is discouraging.

I must clarify that I am not looking for "why Swagger is simply the best". I am not using (and for my current task will not use) Spring Boot or such.

Answer

woemler picture woemler · Nov 3, 2014

Springfox (Swagger spec 2.0, current)

Springfox has replaced Swagger-SpringMVC, and now supports both Swagger specs 1.2 and 2.0. The implementation classes have changed, allowing for some deeper customization, but with some work. The documentation has improved, but still needs some details added for advanced configuration. The old answer for the 1.2 implementation can still be found below.

Maven dependency

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.5.0</version>
</dependency> 

The bare-minimum implementation looks more-or-less the same, but now uses the Docket class instead of the SwaggerSpringMvcPlugin class:

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket api(){
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.any())
            .paths(PathSelectors.regex("/api/.*"))
            .build()
            .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
            .title("TITLE")
            .description("DESCRIPTION")
            .version("VERSION")
            .termsOfServiceUrl("http://terms-of-services.url")
            .license("LICENSE")
            .licenseUrl("http://url-to-license.com")
            .build();
    }

}

Your Swagger 2.0 API documentation will now be available at http://myapp/v2/api-docs.

Note : If you are not using Spring boot then you should add jackson-databind dependency. Since springfox uses jackson for databinding.

Adding Swagger UI support is even easier now. If you are using Maven, add the following dependency for the Swagger UI webjar:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.5.0</version>
</dependency>

If you are using Spring Boot, then your web app should automatically pick up the necessary files and show the UI at http://myapp/swagger-ui.html (formerly: http://myapp/springfox). If you are not using Spring Boot, then as yuriy-tumakha mentions in the answer below, you will need to register a resource handler for the files. The Java configuration looks like this:

@Configuration
@EnableWebMvc
public class WebAppConfig extends WebMvcConfigurerAdapter {

    @Override 
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

}

The new static documentation generation feature also looks quite nice, though I have not tried it out myself.

Swagger-SpringMVC (Swagger spec 1.2, older)

The documentation for Swagger-SpringMVC can be a little bit confusing, but it is actually incredibly easy to set up. The simplest configuration requires creating a SpringSwaggerConfig bean and enabling annotation-based configuration (which you probably already do in your Spring MVC project):

<mvc:annotation-driven/>
<bean class="com.mangofactory.swagger.configuration.SpringSwaggerConfig" />

However, I think it is well worth it to take the extra step of defining a custom Swagger configuration using the SwaggerSpringMvcPlugin, instead of the previous XML-defined bean:

@Configuration
@EnableSwagger
@EnableWebMvc
public class SwaggerConfig {

    private SpringSwaggerConfig springSwaggerConfig;

    @SuppressWarnings("SpringJavaAutowiringInspection")
    @Autowired
    public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {
        this.springSwaggerConfig = springSwaggerConfig;
    }

    @Bean
    public SwaggerSpringMvcPlugin customImplementation(){

        return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
                .apiInfo(apiInfo())
                .includePatterns(".*api.*"); // assuming the API lives at something like http://myapp/api
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
            .title("TITLE")
            .description("DESCRIPTION")
            .version("VERSION")
            .termsOfServiceUrl("http://terms-of-services.url")
            .license("LICENSE")
            .licenseUrl("http://url-to-license.com")
            .build();
    }

}

When you run your application, you should now see your API spec created at http://myapp/api-docs. To get the fancy Swagger UI set up, you need to clone the static files from the GitHub project and put them in your project. Make sure your project is configured to serve the static HTML files:

<mvc:resources mapping="*.html" location="/" />

Then edit the index.html file at the top level of the Swagger UI dist directory. Towards the top of the file, you'll see some JavaScript that refers to the api-docs URL of another project. Edit this to point to your project's Swagger documentation:

  if (url && url.length > 1) {
    url = url[1];
  } else {
    url = "http://myapp/api-docs";
  }

Now when you navigate to http://myapp/path/to/swagger/index.html, you should see the Swagger UI instance for your project.