Documenting Spring Boot Microservices with Swagger

It’s a fairly well known fact that many developers don’t like to write documentation, often muttering things like “the code is the documentation” in a half hearted manner suggesting even they don’t believe themselves. Recently I was looking to write a Microservice, so I wanted to also look at ways in which we could make nice easy to use documentation in a consistent manner.

Swagger

This led me to look at Swagger. It’s a way to produce elegant and powerful interactive documentation on your REST API without having to write pages of documentation. And when used with annotations and Spring Boot, truly the code *is* the documentation.

Spring Boot Example

I’m completely taken with Spring Boot already. It takes a lot of the complexity out of getting an initial application up and running, and allows you to add in features easily. In my application, I produced a REST API for getting identities out of LDAP, to support both a lookup on the logged in persons identity, and also other identities.

The POM file

We still use Maven (although it’s getting more and more tempting to switch to Gradle). My pom file contains the following dependencies:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-rest</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency> 
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.jayway.jsonpath</groupId>
        <artifactId>json-path</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.ldap</groupId>
        <artifactId>spring-ldap</artifactId>
        <version>1.2.1</version>
        <type>jar</type>
    </dependency>
    <dependency>
        <groupId>com.mangofactory</groupId>
        <artifactId>swagger-springmvc</artifactId>
        <version>1.0.2</version>
        <type>jar</type>
    </dependency>
</dependencies>

Most of the dependencies are covering the Spring Boot side of things, REST support, web application and LDAP/JSON support. Note though the bottom dependency, which is including support for Swagger Spring MVC.

The Controller

The controller is fairly simple, it maps two URLs. The key thing of note is the @ApiOperation annotation, where we describe what the method does.

@RestController
public class UserLookupController {
    
    @Autowired
    LdapService ldapService;
    
    @ApiOperation(value="Get the currently logged in users details",notes="Uses the remote user logged in")
    @RequestMapping(value="/my",method=RequestMethod.GET)
    public @ResponseBody Person getMyDetails(HttpServletRequest request) throws ServletException
    {
        if (request.getRemoteUser()==null)
        {
            throw new ServletException("Remote user is null.");
        }
        return ldapService.getPerson(request.getRemoteUser());
    }

    @ApiOperation(value="Get a specific users details",notes="Requires uid of user to look up")
    @RequestMapping(value="/id/{uid}",method=RequestMethod.GET)
    public @ResponseBody Person getUserDetails(@PathVariable("uid") String uid)
    {
        return ldapService.getPerson(uid);
    }
    
}

Swagger Config

We also need a config class to tell Swagger what to do, and also provide high level documentation about what the Service is providing.

@Configuration
@EnableSwagger
@EnableAutoConfiguration
public class SwaggerConfig {
    
    private SpringSwaggerConfig springSwaggerConfig;
 
    @Autowired
    public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {
        this.springSwaggerConfig = springSwaggerConfig;
    }
    
    @Bean
    public SwaggerSpringMvcPlugin customImplementation() {
        return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
                //Root level documentation
                .apiInfo(new ApiInfo(
                        "Central Authorisation Service JSON API",
                        "This service provides a JSON representation of the LDAP identity data held in the Central Authorisation Service",
                        null,
                        null,
                        null,
                        null
                ))
                .useDefaultResponseMessages(false)
                //Map the specific URL patterns into Swagger
                .includePatterns("/id/.*","/my");
    }
    
}

The Application Class

The Application class is simple, and just hooks into our LDAP config:

@Configuration
@ComponentScan("uk.ac.ed.ca")
@EnableAutoConfiguration
public class Application {
    
    public static void main(String[] args)
    {
        SpringApplication.run(Application.class, args);
    }
    
    @Bean
    @ConfigurationProperties(prefix="ldap.contextSource")
    public LdapContextSource contextSource() {
        LdapContextSource contextSource = new LdapContextSource();
        return contextSource;
    }

    @Bean
    public LdapTemplate ldapTemplate(ContextSource contextSource) {
        return new LdapTemplate(contextSource);
    }
    
}


HTML UI

Finally, we add in a static set of HTML/CSS/JS to cover the API. You can get the static pages from https://github.com/swagger-api/swagger-ui. Put them in your project under (src/main/)resources/static and they’ll automatically get mapped into the application.

The end result

Swagger UI screenshot

The end result is a service which also provides the following documentation. As the documentation is interactive you can also try to call the id service and see what kind of response it gives. Very neat, very powerful, and a very easy way for us to provide API documentation!