Documenting your Rest API is very important because providing rich information to the consumer of your Rest API in the document is very effective.
Have you ever wonder about creating documentation for your Rest API?
If yes, then you have visited the right site. In this tutorial, I'll walk you through how to document your rest API using the Swagger.
For this tutorial, I'll use my latest Spring Data JPA tutorial code. You can find the source code from (getButton) #text=(GitHub) #icon=(download) #color=(#000000)
Prerequisite
1. Building Rest API using the Spring Data JPA
2. Java 8 or later, I'll use Amazon Corretto 11
3. Maven
What is Swagger?
Swagger is a tool build by SmartBear Software.
Swagger is often use to describe the Rest API Structure. In other words, The Swager is used to build the documentation of the Rest APIs.
But what makes swagger so attractive when it comes to API documentation?
Swagger provides documentation in both JSON and YAML formats. Swagger also implements the UI documentation, which we shall cover later. Isn't it fantastic?
Including a Maven dependency
We will use the SpringFox swagger implementations in our project to implement the swagger.
If you're using the Maven build tool, include the following dependency in the pom.xml file.The latest dependency can be found springfox-swagger2 and springfox-swagger-ui.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
Gradle
implementation group: 'io.springfox', name: 'springfox-swagger2', version: '3.0.0'(code-box)
implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '3.0.0'(code-box)
Spring boot dependency
If you are using the spring boot then, add the following Maven-dependency in the pom.xml
file. The latest version can be found from (getButton) #text=(MVN Repository) #icon=(link) #color=(#2339bd)
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
How to configure swagger in spring boot?
The spring boot mostly provides an auto-configure swagger functionality. You need to return the bean of the Docket
object and then see the spring boot magic.
package in.learnjavaskills.springdataJPAtutorila.swagger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfiguration
{
@Bean
public Docket swaggerSpringfoxDocket()
{
return new Docket(DocumentationType.SWAGGER_2);
}
}
Explanation of the above code
To configure the springfox implementations swagger in the spring boot, here we have created a SwaggerConfiguration
java class.
The class is annotated with @Configuration
because it is the instruction to the spring boot that this java class is the configuration, and it contains the beans. So next time, when you will restart the spring boot project, spring boot
will inject the docket beans at the startup.
The @EnableSwagger2
annotation indicates to the spring boot to allow the swagger configuration. If you miss this annotation, then you will fail to configure the swagger in the spring boot.
And Finally, we are returning the Docket object, and in the parameter, we have instructed the document type must be Swagger 2. That's it for the swagger configuration.
How to access the JSON documentation of the swagger
Till now, we have successfully configured the swagger in our project but we have not yet tested.
To test our swagger documentation, we will try to access the JSON format document. The endpoint for swagger Json documentation is as follows.
http://localhost:8080/v2/api-docs(code-box)
Note: Here, we are using the port 8080
, you can replace the port number which you are using in your project and localhost as well.
If you have added the JSON viewer extension in your favorite browser then, you can see the following JSON document in well-formatted like below.
You can even use version 3.0 as well because we have used swagger version 3.0.0 in our pom.xml.
http://localhost:8080/v3/api-docs(code-box)
Swagger UI
Isn't it reading the JSON document quite convenient? To access the user interface of the swagger document, you just need to hit the following URL in your favourite browser.
http://localhost:8080/swagger-ui/(code-box)
You will get the following screen.
Swagger UI Rest API documentation details
Let's add meta-data in the swagger UI. In our current swagger UI documentation, we don't have enough details about our Rest APIs.
Let's Modify the above default Rest API documentation to the desire documentation details as shown in the below images.
Swagger UI Rest API documentation details java code
@Configuration
@EnableSwagger2
public class SwaggerConfiguration
{
public static final Contact CONTACT = new Contact("LearnJavaSkills.in", "https://www.learnjavaskills.in/", "contact@LearnJavaSkills.in");
public static final ApiInfo APIINFO = new ApiInfo("LearnJavaSkills Documentation", "Swagger documentation of the LearnJavaSkills.in", "1.0 version", "urn:tos",
CONTACT, "Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0", new ArrayList<>());
@Bean
public Docket swaggerSpringfoxDocket()
{
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(APIINFO);
}
}
Isn't it amazing overriding default documentation details to appropriate rest API details?
How to solve some swagger problem documents?
Can you spot some problems in the generated swagger documentation?
There are some out of the box spring MVC related stuff reside on the document because swagger doesn't know, It watches you Rest API and then documents it.
This includes your Rest API and Spring boot MVC API that comes along with that you are using the spring framework.
Why you should remove this? what the harm?
Well if you include this in your swagger documentation, then it's likely that the reader of this swagger document will use it, and in the future, if you change the framework then they may get an error and surely they will blame you.
Let's control this by configuring the swagger.
@Configuration
@EnableSwagger2
public class SwaggerConfiguration
{
public static final Contact CONTACT = new Contact("LearnJavaSkills.in", "https://www.learnjavaskills.in/", "contact@LearnJavaSkills.in");
public static final ApiInfo APIINFO = new ApiInfo("LearnJavaSkills Documentation", "Swagger documentation of the LearnJavaSkills.in", "1.0 version", "urn:tos",
CONTACT, "Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0", new ArrayList<>());
@Bean
public Docket swaggerSpringfoxDocket()
{
return new Docket(DocumentationType.SWAGGER_2)
.select()
.paths(PathSelectors.any())
.apis(RequestHandlerSelectors.basePackage("in.learnjavaskills"))
.build()
.apiInfo(APIINFO);
}
}
Now, swagger documentation looks more cleaner and shows accurate information which the reader really needs.
Let's Mofidy the Model
If you expand the Model section in the swagger documentation UI, then you will not get rich and appropriate data.
Let's customize the Swager Model to show more information in the Model. In our example, we have only one model i.e Book.
package in.learnjavaskills.springdataJPAtutorila.dto;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import com.sun.istack.NotNull;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import net.bytebuddy.implementation.auxiliary.AuxiliaryType.SignatureRelevant;
@Entity
@ApiModel(description = "The Book entity, to store the book's information")
public class Books
{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@ApiModelProperty(notes = "Book Id is a primary key. The Book Id will auto-generate and it will increment by 1.)
private Long id;
@NotNull
@ApiModelProperty(notes = "The title of the Book")
@Column(name = "title")
private String title;
@NotNull
@ApiModelProperty(notes = "Author value should name should not null")
@Column(name = "author")
private String author;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "Books [id=" + id + ","
+ " title="
+ title
+ ", author="
+ author + "]";
}
}
Once you update your model like above you will get the model in more detail and rich information which is required by the consumers of our Rest APIs. Now the reader can easily understand the Book model.
Annotations required for swagger configure Model and explanation
We have used two annotations such as @ApiModel
and @ApiModelProperty
.
The @ApiModel
annotation is used on the entity class level. With this annotation, you can describe your entity very well. The format to use this annotation is as follows.
@ApiModel(description = "Description here")(code-box)
The @ApiModelProperty
annotation is used on the java field level. With this annotation, you instruct the reader what these fields are expectation by providing simple notes. The Following is the way of using @ApiModelProperty annotation in the java spring boot framework.
@ApiModelProperty(notes = "Your note come here")(code-box)
Customizing controller
If you expand the book-controller node, here you will find all your controller, But you will also notice that it doesn't provide the information which the reader needed
From the above image, The reader of this Swagger document can't get them enough information, and surely he will get back to you to know more.
Just imagine, if the consumer of your rest API doesn't get whats your Rest API controller is used for then what's the use of your API?
let's configure swagger to describe our rest API controller.
Controller code
package in.learnjavaskills.springdataJPAtutorila.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import in.learnjavaskills.springdataJPAtutorila.dto.Books;
import in.learnjavaskills.springdataJPAtutorila.service.BooksService;
import io.swagger.annotations.ApiOperation;
@RestController
public class BooksController
{
@Autowired
private BooksService bookService;
@GetMapping(path = "getAllBooks")
@ApiOperation(value = "Fetch All the books from the database", notes = "Return list of books", response = Books.class)
private List getAllBooks()
{
return bookService.getAllBooks();
}
@DeleteMapping(path = "deleteBookById/{id}")
@ApiOperation(value = "Deleting the book by id", notes = "Provide the id in the param, for e.g deleteBooksById/101", response = Books.class)
private void deleteBookById(@PathVariable Long id)
{
bookService.deleteBookByID(id);
}
@PostMapping(path = "addBook")
@ApiOperation(value = "Adding the book", notes = "Once book is added successfully, you will get the added book object", response = Books.class)
private Books addBook(@RequestBody Books book)
{
return bookService.addBook(book);
}
@PutMapping(path = "updateBookById/{id}")
@ApiOperation(value = "Updating the books using the book id", notes = "To update the book, please veify the book id is available in the database", response = Books.class)
private Books updateBookById(@PathVariable Long id, @RequestBody Books book)
{
return bookService.updateBookById(id, book);
}
}
Annotation for the swagger used in controller code
The @ApiOperation
annotation is used on the method level of the controller to describe the controller.
This annotation is used in the following format.
@ApiOperation(value = "Little information of your controller", notes = "Notes for your controller", response = EntityName.class)(code-box)
Swagger UI after adding the @ApiOperation annotation in each controller.
Conclusion
In this tutorial, we have seen what is swagger, how to use swagger in spring boot?
We have also seen some default configure swagger problem and how to resolve it. We have discussed why Rest API documentation is so important.
If you have enjoyed this article and found useful, then please subscribe to the LearnJavaSkills, so in the future, if I publish new tutorials, you don't miss it.
Thanks for reading and keep learning and keep growing
(getButton) #text=(Next: Spring Data JPA) #icon=(link) #color=(#2339bd)