Swagger documentation and OpenAPI

The microservice architecture will drive the enterprise architecture ecosystem to build a huge number of APIs, through which data can be exposed and communication can be implemented between the various microservices.

For this reason, it is essential to document the API, in order to facilitate its proper use by users. To standardize how REST APIs are described, a consortium of forward-looking industry experts created the OpenAPI Initiative (OAI).

The OAI purpose is to create and evolve a vendor-neutral / standard description format.

SmartBear company donated the Swagger specification to the OAI in order to set it as the starting point of this open specification. For that reason, Swagger can be considered the de facto standard for API documentation.

Spring does not have a built-in mechanism to generate API documentation, but, as usual, the open source community, through frameworks such as SpringFox, makes this operation very easy.

SpringFox enable developers to create, automatically, a readable specifications for JSON APIs that there written using the Spring framework.

As I mentioned earlier, SpringFox is not a component of the Spring framework—for this reason it's not approved by the Spring framework contributors.

We will configure our simple microservice implementation, in order to document our APIs and build an easy portal that not only shows the API documentation, but will also make it available to users for testing.

The first operation that's needed to integrate Swagger and SpringFox is setting the relative dependencies in the Maven pom.xml file, as follows:

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

Then we will create a Docket bean in a Spring Boot configuration, to integrate Swagger 2 inside our application.

This way, SpringFox provides primary API configurations, with sensible defaults and convenient methods for configuration.

The following code shows the implementation of the bean:

@Configuration
@EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.basePackage(
"com.packtpub.springboot.footballplayermicroservice.controller"))
.paths(PathSelectors.any())
.build();
}

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

We used the @EnableSwagger2 annotation to enable Swagger support in the class. The key point of the class is the api method, which filters the controllers and methods being documented, using string predicates.

The RequestHandlerSelectors.basePackage predicate matches the com.packtpub.springboot.footballplayermicroservice.controller base package, to filter the API that will be documented. For the API path, I didn't set a filter, so I decided to expose all APIs.

Now you can run the application with the following command:

$ mvn spring-boot:run

You should be able to test the configuration by starting the app and pointing your browser to http://localhost:8080/v2/api-docs.

This way, you can retrieve the JSON representations of the documentation of your APIs.

The following code snippet shows a portion of what you will see in your browser:

{
"swagger":"2.0",
"info":{
"description":"Api Documentation",
"version":"1.0",
"title":"Api Documentation",
"termsOfService":"urn:tos",
"contact":{
},
"license":{
"name":"Apache 2.0",
"url":"http://www.apache.org/licenses/LICENSE-2.0"
}
},
"host":"localhost:8080",
"basePath":"/",
"tags":[
{
"name":"football-player-rest-controller",
"description":"Football Player REST Controller"
}
],
"paths":{
"/footballplayer":{
"get":{
"tags":[
"football-player-rest-controller"
],
"summary":"findAll",
"operationId":"findAllUsingGET",
"produces":[
"application/json"
],
"responses":{
"200":{
"description":"OK",
"schema":{
"$ref":"#/definitions/Iterable«FootballPlayer»"
}
},
"401":{
"description":"Unauthorized"
},
"403":{
"description":"Forbidden"
},
"404":{
"description":"Not Found"
}
},
"deprecated":false
}
},
"/footballplayer/delete/{id}":{
"delete":{
"tags":[
"football-player-rest-controller"
],
"summary":"delete",
"operationId":"deleteUsingDELETE",
"produces":[
"application/json"
],
"parameters":[
{
"name":"id",
"in":"path",
"description":"id",
"required":true,
"type":"integer",
"format":"int32"
}
],
"responses":{
"200":{
"description":"OK"
},
"204":{
"description":"No Content"
},
"401":{
"description":"Unauthorized"
},
"403":{
"description":"Forbidden"
}
},
"deprecated":false
}
},
....

In order to get readable, structured documentation, we will use the Swagger UI, a portal in which the users can see the full documentation for our APIs, and also test them.

If you invoke the http://localhost:8080/swagger-ui.html URL, you will see the generated documentation rendered by the Swagger UI, as follows:

As you can see, Swagger 2 generated documentation related to the football-player-rest-controller, using the camel-case naming convention, to retrieve the words used in our class, and to get the Models used by our controller.

Before we start to use the newly constructed microservice, we will customize the header part of the console, in order to explain to our users what type of API documentation is described in the UI.

We will add the metadata API info to the SwaggerConfig class, as follows:

private ApiInfo metaData() {
return new ApiInfoBuilder()
.title("Spring Boot REST API")
.description(""Spring Boot REST API for Football Player Microservice"")
.version("1.0.0")
.license("Apache License Version 2.0")
.licenseUrl("https://www.apache.org/licenses/LICENSE-2.0"")
.contact(new Contact("Mauro Vocale",
"https://github.com/Hands-on-MSA-JakartaEE",
"[email protected]"))
.build();
}

Remember to also add the invocation of the metaData method to the pipeline builder, inside the api method of the SwaggerConfig class.

Now run the application again, as follows:

$ mvn spring-boot:run

You will now see more detailed information related to the organization that built and exposed the APIs:

Now it's time to customize our controller class. The goal is to describe the purpose of our operation endpoint. We will use the @ApiOperation annotation to describe the endpoint and its response type, as follows:

...
@ApiOperation(value = "View all available football players", response
= Iterable.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successfully retrieved list"),
@ApiResponse(code = 404, message = "The resource you were trying to reach is not found")
}
)
@RequestMapping(method = RequestMethod.GET, produces = "application/json")
public Iterable<FootballPlayer> findAll() {
return service.findAll();
}

@ApiOperation(value = "Add a football player")
@RequestMapping(value = "/save", method = RequestMethod.POST, produces = "application/json")
public FootballPlayer save(@RequestBody FootballPlayer entity) {
return service.save(entity);
}

@ApiOperation(value = "Update a football player")
@RequestMapping(value = "/update/{id}", method = RequestMethod.PUT, produces = "application/json")
public FootballPlayer edit(@PathVariable Integer id, @RequestBody FootballPlayer entity) {
return service.save(entity);
}

@ApiOperation(value = "Delete a football player")
@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE, produces = "application/json")
public void delete(@PathVariable Integer id) {
service.deleteById(id);
}

@ApiOperation(value = "Search a football player with an ID", response = FootballPlayer.class)
@RequestMapping(value = "/show/{id}", method = RequestMethod.GET, produces = "application/json")
public Optional<FootballPlayer> findById(@PathVariable Integer id) {
return service.findById(id);
}
...

In the browser, the output of the operation endpoints will look as follows:

Now the user has a good idea of which APIs are exposed by our microservice application, as well as the target of each one.

Now let's start to test one of these. We will expand the Search a football player with an ID API, which has the following path—/footballplayer/show/{id}:

As you can see, Swagger shows you the following:

  • The HTTP verb of the API, which is GET.
  • A brief description of the API.
  • The parameter needed to invoke the API (in our case, Id).
  • The different types of response:
    • A JSON object representation
    • HTTP error codes

Any user who would like to use our API will be able to start to develop the code to interact with it, since they have all of the elements needed to do so.

To test the API, the user only needs to do the following:

  1. Click on the Try it out button, as follows:

  1. Insert the ID parameter and click on the Execute button:

  1. Finally, the user will see the response of the API call:
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset