Swagger

Add Swagger to Spring Boot app

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}
not(regex("/error.*"))
ant("/notes/*")
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(onlyNotes())
.build();
}
public ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("Example Notes API")
.description("Example API showing usege of Swagger for documenting Sprinv MVC RestControllers")
.contact(new Contact("Łukasz Monkiewicz", "https://lmonkiewicz.com", "lmonkiewicz@gmail.com"))
.version("1.0")
.build();
}

Add documentation to controllers

@RestController
@RequestMapping("/notes")
@Api(value = "Example of MVC controller with Swagger documentation",
description = "Note operation")
public class NotesController {
}
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@ApiOperation("Find Note by given Id")
@ApiResponses({
@ApiResponse(code = 200, message = "Note with given id has been found and returned",
response = Note.class),
@ApiResponse(code = 404, message = "Note with given id does not exist")
})
public ResponseEntity<Note> getNote(@ApiParam(value = "Id of a Note", required = true)
@PathVariable(name = "id") Integer id){
if (data.containsKey(id)){
return ResponseEntity.ok(data.get(id));
}
else {
return ResponseEntity.notFound().build();
}
}
@ApiModel("Note data")
public class Note {
@ApiModelProperty(value = "ID of a note", example = "1", readOnly = true)
private Integer id;
@ApiModelProperty(value = "Title of note", example = "My important note!")
private String title;
@ApiModelProperty(value = "Content of note", example = "Buy milk", required = true)
private String content;
@ApiModelProperty("Is note marked as done?")
private boolean done = false;
}

Generate physical docs

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-staticdocs</artifactId>
<version>2.6.1</version>
<scope>test</scope>
</dependency>
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringSwaggerDocApplication.class)
public class Swagger2MarkupTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc; @Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
@Test
public void saveSwaggerJson() throws Exception {
this.mockMvc.perform(get("/v2/api-docs")
.accept(MediaType.APPLICATION_JSON))
.andDo(result -> {
File outputDir = new File("src/docs/swagger");
if (!outputDir.exists()){
outputDir.mkdirs();
}
try (FileOutputStream fos = new FileOutputStream("src/docs/swagger/swagger.json")) {
fos.write(result.getResponse().getContentAsByteArray());
fos.flush();
}
})
.andExpect(status().isOk());
}
@Test
public void convertSwaggerToAsciiDoc() throws Exception {
this.mockMvc.perform(get("/v2/api-docs")
.accept(MediaType.APPLICATION_JSON))
.andDo(Swagger2MarkupResultHandler.outputDirectory("src/docs/asciidoc").build())
.andExpect(status().isOk());
}
@Test
public void convertSwaggerToMarkdown() throws Exception {
this.mockMvc.perform(get("/v2/api-docs")
.accept(MediaType.APPLICATION_JSON))
.andDo(Swagger2MarkupResultHandler.outputDirectory("src/docs/markdown")
.withMarkupLanguage(MarkupLanguage.MARKDOWN).build())
.andExpect(status().isOk());
}
}
<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>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>1.5.4.1</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>output-pdf</id>
<phase>test</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>pdf</backend>
<sourceHighlighter>rouge</sourceHighlighter>
<attributes>
<icons>font</icons>
<tabsize>4</tabsize>
<pagenums/>
<toc/>
<idprefix/>
<idseparator>-</idseparator>
</attributes>
<outputDirectory>src/docs/pdf</outputDirectory>
</configuration>
</execution>
</executions>
<configuration>
<sourceDirectory>src/docs/asciidoc</sourceDirectory>
<headerFooter>true</headerFooter>
</configuration>
</plugin>
<execution>
<id>output-html</id>
<phase>test</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<sourceHighlighter>coderay</sourceHighlighter>
<backend>html</backend>
<attributes>
<toc/>
<linkcss>false</linkcss>
</attributes>
<outputDirectory>src/docs/html</outputDirectory>
</configuration>
</execution>

Conclusion

Architect, Developer, Software Engineer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store