Home » Integration » Customize Swagger and use annotations in Spring Boot

Customize Swagger and use annotations in Spring Boot

In this article let us see how to customize swagger in Spring Boot Applications. The customization includes

  • Avoid documenting the APIs and Model objects from Spring configuration.
  • Change the application metadata with our own information.
  • Use annotations to provide more information to the documented APIs and Model objects.

Before continuing the customization part we need to know how to add Swagger and Swagger UI in the Spring Boot application. I have already explained this in the last article. Please take a look at Integrate Swagger in Spring Boot Application.

Here let us use the same project from the last article. So if you didn't read the last article then please go through that first through the above-attached link then only you can understand it clearly.

Avoid documenting the APIs and Model objects from Spring configuration

Generally, swagger documents the APIs and Model objects created by us and the APIs and Model objects from the spring configuration. Actually, we don't need to document the APIs and Model objects from the spring out of box configuration.

In the last article, we have already seen how the swagger documents the APIs right. By default, the swagger documents the REST APIs from ProfileController and some other APIs from the spring configuration like basic-error-controller, operation-handler, and web-mvc-links-handler.

Now let us customize swagger to avoid documenting the APIs and model objects from spring configuration. The below are the controller and the model objects used in the last article.

ProfileController

package com.tipstocode.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.tipstocode.manager.ProfileManager;
import com.tipstocode.model.ProfileVO;

@RestController
@RequestMapping("/api")
public class ProfileController {	
	
@Autowired
ProfileManager userManager;
	
@RequestMapping(value = "/saveprofile", method = RequestMethod.POST )
public ResponseEntity<ProfileVO> saveUser(@RequestBody ProfileVO userVO) {		
	userVO = userManager.saveUser(userVO);		
	return new ResponseEntity<ProfileVO>(userVO, HttpStatus.OK);		
}	
@RequestMapping(value = "/getprofilebyid", method = RequestMethod.GET )	
public ResponseEntity<ProfileVO> getUserById(@RequestParam("id") String id) {		
	ProfileVO userVO = userManager.getUserById(id);		
	return new ResponseEntity<ProfileVO>(userVO, HttpStatus.OK);		
}	
@RequestMapping(value = "/updateprofile", method = RequestMethod.POST )
public ResponseEntity<ProfileVO> updateUser(@RequestBody ProfileVO userVO) {		
	userVO = userManager.updateUser(userVO);		
	return new ResponseEntity<ProfileVO>(userVO, HttpStatus.OK);		
}	
@RequestMapping(value = "/deleteprofilebyid", method = RequestMethod.GET )
public ResponseEntity<Long> deleteUserById(@RequestParam("id") String id) {		
	long count = userManager.deleteUserById(id);		
	return ResponseEntity.ok(count);			
}		
}

Model Object - ProfileVO

package com.tipstocode.model;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection  = "user_profile")
public class ProfileVO {	
@Id	
private ObjectId _id;	
private String firstName;	
private String lastName;	
private String mobile;	
private String emailId;	
public ObjectId get_id() {
	return _id;
}
public void set_id(ObjectId _id) {
	this._id = _id;
}
public String getFirstName() {
	return firstName;
}
public void setFirstName(String firstName) {
	this.firstName = firstName;
}
public String getLastName() {
	return lastName;
}
public void setLastName(String lastName) {
	this.lastName = lastName;
}
public String getMobile() {
	return mobile;
}
public void setMobile(String mobile) {
	this.mobile = mobile;
}
public String getEmailId() {
	return emailId;
}
public void setEmailId(String emailId) {
	this.emailId = emailId;
}
}

To avoid documenting spring configuration stuff we have to create a docket instance. A docket is an object that contains all the customization properties of a swagger.

We have to configure the docket with @Bean annotation in the Swagger configuration file. The docket has its own builder pattern to define the customization properties. Those customization properties are

  • We can choose the REST APIs that we want to document by using the PathSelectors.
  • Select the packages that we want to document by using the RequestHandlerSelectors.
  • We can specify the application metadata with our information through the ApiInfo method.

The below swagger configuration file uses all the above configuration properties except the application metadata.

package com.tipstocode.SpringMongo;
import java.util.Collections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SpringSwaggerConfig {
    @Bean
    public Docket apiDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
        .select()
        .apis(RequestHandlerSelectors.basePackage("com.tipstocode"))                
        .paths(PathSelectors.ant("/api/*"))
        .build();                
    }
}

The above swagger configuration avoids the APIs and Model objects to be documented from the spring configuration. It documents all the APIs that match the URL pattern /api/* and the APIs within the package com.tipstocode.

Let us run the application and check the below Swagger UI URL in the browser.

http://localhost:8080/swagger-ui.html

Swagger-Customization-with-Docket

The above URL displays only the documented APIs from the path /api/*. It removes all other APIs and model objects from the spring configuration.

Change the Swagger application metadata with our own information

We can change the title, description, version, terms and conditions, and contact information displayed on the top of the Swagger UI by providing our own information.

For that, we have to configure the method called ApiInfo within that we have to set all the metadata properties like below.

package com.tipstocode.SpringMongo;
import java.util.Collections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SpringSwaggerConfig {
    @Bean
    public Docket apiDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
        .select()
        .apis(RequestHandlerSelectors.basePackage("com.tipstocode"))          
        .paths(PathSelectors.ant("/api/*"))
        .build()
        .apiInfo(apiData());
    }   
    private ApiInfo apiData() {
        return new ApiInfo(
        "User Profile API", 
        "All the API's of User Profile from tipstocode", 
        "1.0", 
        "Open Source", 
        new springfox.documentation.service.Contact("Sikkandar", "https://www.tipstocode.com", "[email protected]"), 
        "API Licence", 
        "https://www.tipstocode.com",
        Collections.EMPTY_LIST);
 }    
}

The above configuration changes the swagger application metadata with our own title, description, and all. Now let us run the application and check the below URL in the browser.

http://localhost:8080/swagger-ui.html

Swagger-Metadata-Configuration
Swagger-Metadata-Configuration

The above URL displays the documented APIs and the application metadata based on the swagger docket configuration.

Use annotations to provide more information to the documented APIs and Model objects

Here let us use some of the annotations from the Swagger to provide more information to the documented APIs and the Model objects. Those annotations are

  • @ApiOpertaion
  • @ApiParam
  • @ApiModel
  • @ApiModelProperty

The annotations @ApiOperation and @ApiParam used in the REST APIs and the annotations @ApiModel and @ApiModelProperty used in the Model Object.

@ApiOperation - This annotation describes the purpose of the REST APIs. It is always used at the top of the REST APIs.

@ApiParam - This annotation provides extra information on the request parameters in the APIs.

@ApiModel - This annotation describes the purpose of the Model object. It is always used at the top of the Model Object.

@ApiModelProperty - It describes each member variable of the model object.

Now let us use all the above annotations in the REST APIs and the Model objects in our project. The below controller used these annotations @ApiOperation and @ApiParam.

package com.tipstocode.controller;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.tipstocode.manager.ProfileManager;
import com.tipstocode.model.ProfileVO;

@RestController
@RequestMapping("/api")
public class ProfileController {	
@Autowired
ProfileManager userManager;	
@RequestMapping(value = "/saveprofile", method = RequestMethod.POST )
public ResponseEntity<ProfileVO> saveUser(@RequestBody ProfileVO userVO) {		
	userVO = userManager.saveUser(userVO);		
	return new ResponseEntity<ProfileVO>(userVO, HttpStatus.OK);		
}

@RequestMapping(value = "/getprofilebyid", method = RequestMethod.GET )
@ApiOperation(value = "Get User Profile by their Id", notes="Please provide valid id to get the user profile info", response=ProfileVO.class)
public ResponseEntity<ProfileVO> getUserById(@ApiParam(value="Id for the User Profile which you need to get", required=true) @RequestParam("id")       String id) {		
	ProfileVO userVO = userManager.getUserById(id);		
	return new ResponseEntity<ProfileVO>(userVO, HttpStatus.OK);		
}
	
@RequestMapping(value = "/updateprofile", method = RequestMethod.POST )
public ResponseEntity<ProfileVO> updateUser(@RequestBody ProfileVO userVO) {		
	userVO = userManager.updateUser(userVO);		
	return new ResponseEntity<ProfileVO>(userVO, HttpStatus.OK);
}
	
@RequestMapping(value = "/deleteprofilebyid", method = RequestMethod.GET )
public ResponseEntity<Long> deleteUserById(@RequestParam("id") String id		
        long count = userManager.deleteUserById(id);		
	return ResponseEntity.ok(count);			
}
}

The below model object ProfileVO used these annotations @ApiModel and @ApiModelProperty.

package com.tipstocode.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection  = "user_profile")
@ApiModel(description = "This object hold the information of User Profile")
public class ProfileVO {		
@Id	
private ObjectId _id;	
private String firstName;	
private String lastName;	
private String mobile;
@ApiModelProperty(notes = "Email Id of the User")	
private String emailId;	
public ObjectId get_id() {
	return _id;
}
public void set_id(ObjectId _id) {
	this._id = _id;
}
public String getFirstName() {
	return firstName;
}
public void setFirstName(String firstName) {
	this.firstName = firstName;
}
public String getLastName() {
	return lastName;
}
public void setLastName(String lastName) {
	this.lastName = lastName;
}
public String getMobile() {
	return mobile;
}
public void setMobile(String mobile) {
	this.mobile = mobile;
}
public String getEmailId() {
	return emailId;
}
public void setEmailId(String emailId) {
	this.emailId = emailId;
}
}

Now, let's run the application and check this URL 'http://localhost:8080/swagger-ui.html' in the browser. You can see the below-documented APIs and Model objects with more information.

Swagger-With-Annotations

The above image shows the information from the annotations @ApiOpertaion and @ApiParam.

Swagger-with-model-object-annotations

The above image shows the information from the annotations @ApiModel and @ApiModelProperty.

Here we have used only some annotations from the swagger. But there are a lot more annotations available in the Swagger. Please see their documentation website for more annotations by using this link Swagger Annotations.

The one thing about the swagger is if you want to provide more information to the documented APIs then we need to use more and more annotations from the Swagger.

If our code needs annotations free then we have to use another technology called REST Docs from the Spring to document the REST APIs. Let us see that in the upcoming article.

I hope you understood how to configure and customize Swagger with Spring Boot applications. If you need any clarification please keep me updated in the comment section. Thanks!. Keep Reading!.

Leave a Reply

Your email address will not be published. Required fields are marked *