JAVA-21460 Upgrade spring-boot-swagger-jwt modules to use SpringDoc in place of SpringFox (#14296)

* JAVA-21460 Upgrade spring-boot-swagger-jwt modules to use SpringDoc in place of SpringFox

* JAVA-21460 Upgrade spring-boot-swagger-2 module to use SpringDoc in place of SpringFox

* JAVA-21460 Upgrade spring-boot-swagger module to use SpringDoc in place of SpringFox
This commit is contained in:
anuragkumawat 2023-06-25 17:00:13 +05:30 committed by GitHub
parent fee50e9b34
commit bac109cdc8
14 changed files with 115 additions and 154 deletions

View File

@ -4,35 +4,20 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.ApiInfoBuilder; import io.swagger.v3.oas.models.OpenAPI;
import springfox.documentation.builders.PathSelectors; import io.swagger.v3.oas.models.info.Info;
import springfox.documentation.builders.RequestHandlerSelectors; import io.swagger.v3.oas.models.info.License;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration @Configuration
@EnableWebMvc @EnableWebMvc
@EnableSwagger2
public class Swagger2Config { public class Swagger2Config {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.apiInfo(apiEndPointsInfo());
}
private ApiInfo apiEndPointsInfo() { @Bean
return new ApiInfoBuilder().title("Swagger Array") public OpenAPI openAPI() {
return new OpenAPI().info(new Info().title("Swagger Array")
.description("This is a sample Swagger description for an Array server") .description("This is a sample Swagger description for an Array server")
.license("Apache 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.version("1.0.0") .version("1.0.0")
.build(); .license(new License().name("Apache 2.0")
.url("http://www.apache.org/licenses/LICENSE-2.0.html")));
} }
} }

View File

@ -12,8 +12,8 @@ import org.springframework.web.bind.annotation.ResponseStatus;
import com.baeldung.swagger2bootmvc.model.Foo; import com.baeldung.swagger2bootmvc.model.Foo;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.v3.oas.annotations.Parameters;
@Controller @Controller
public class FooController { public class FooController {
@ -26,7 +26,7 @@ public class FooController {
@RequestMapping(method = RequestMethod.POST, value = "/foos") @RequestMapping(method = RequestMethod.POST, value = "/foos")
@ResponseStatus(HttpStatus.CREATED) @ResponseStatus(HttpStatus.CREATED)
@ResponseBody @ResponseBody
@ApiImplicitParams({ @ApiImplicitParam(name = "foo", value = "List of strings", paramType = "body", dataType = "Foo") }) @Parameters({ @Parameter(name = "foo", description = "List of strings") })
public Foo create(@RequestBody final Foo foo) { public Foo create(@RequestBody final Foo foo) {
foo.setId(Long.parseLong(randomNumeric(2))); foo.setId(Long.parseLong(randomNumeric(2)));
return foo; return foo;

View File

@ -10,27 +10,26 @@ import org.springframework.web.bind.annotation.ResponseStatus;
import com.baeldung.swagger2bootmvc.model.User; import com.baeldung.swagger2bootmvc.model.User;
import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.annotations.ApiParam; import io.swagger.v3.oas.annotations.Parameter;
@Controller @Controller
public class UserController { public class UserController {
public UserController() { public UserController() {
super(); super();
} //@formatter:off }
@RequestMapping(method = RequestMethod.POST, value = "/createUser", produces = "application/json; charset=UTF-8") @RequestMapping(method = RequestMethod.POST, value = "/createUser", produces = "application/json; charset=UTF-8")
@ResponseStatus(HttpStatus.CREATED) @ResponseStatus(HttpStatus.CREATED)
@ResponseBody @ResponseBody
@ApiOperation(value = "Create user", @Operation(summary = "Create user",
notes = "This method creates a new user") description = "This method creates a new user")
public User createUser(@ApiParam( public User createUser(@Parameter(
name = "firstName", name = "firstName",
type = "String", description = "First Name of the user",
value = "First Name of the user",
example = "Vatsal", example = "Vatsal",
required = true) @RequestParam String firstName) { //@formatter:on required = true) @RequestParam String firstName) {
User user = new User(firstName); User user = new User(firstName);
return user; return user;
} }

View File

@ -2,14 +2,13 @@ package com.baeldung.swagger2bootmvc.model;
import java.util.List; import java.util.List;
import io.swagger.annotations.ApiModel; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.annotations.ApiModelProperty;
@ApiModel @Schema
public class Foo { public class Foo {
private long id; private long id;
@ApiModelProperty(name = "name", dataType = "List", example = "[\"str1\", \"str2\", \"str3\"]") @Schema(name = "name", type = "array", example = "[\"str1\", \"str2\", \"str3\"]")
private List<String> name; private List<String> name;
public Foo() { public Foo() {

View File

@ -1,12 +1,11 @@
package com.baeldung.swagger2bootmvc.model; package com.baeldung.swagger2bootmvc.model;
import io.swagger.annotations.ApiModel; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.annotations.ApiModelProperty;
@ApiModel @Schema
public class User { public class User {
@ApiModelProperty(value = "first name of the user", name = "firstName", dataType = "String", example = "Vatsal") @Schema(description = "first name of the user", name = "firstName", type = "string", example = "Vatsal")
String firstName; String firstName;
public User() { public User() {

View File

@ -21,9 +21,9 @@
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>org.springdoc</groupId>
<artifactId>springfox-boot-starter</artifactId> <artifactId>springdoc-openapi-ui</artifactId>
<version>${springfox.version}</version> <version>${springdoc.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
@ -37,7 +37,7 @@
</build> </build>
<properties> <properties>
<springfox.version>3.0.0</springfox.version> <springdoc.version>1.7.0</springdoc.version>
</properties> </properties>
</project> </project>

View File

@ -3,54 +3,32 @@ package com.baeldung.swaggerjwt.configuration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors; import io.swagger.v3.oas.models.Components;
import springfox.documentation.builders.RequestHandlerSelectors; import io.swagger.v3.oas.models.OpenAPI;
import springfox.documentation.service.*; import io.swagger.v3.oas.models.info.Contact;
import springfox.documentation.spi.DocumentationType; import io.swagger.v3.oas.models.info.Info;
import springfox.documentation.spi.service.contexts.SecurityContext; import io.swagger.v3.oas.models.info.License;
import springfox.documentation.spring.web.plugins.Docket; import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@Configuration @Configuration
public class SwaggerConfiguration { public class SwaggerConfiguration {
public static final String AUTHORIZATION_HEADER = "Authorization";
private ApiInfo apiInfo() {
return new ApiInfo("My REST API", "Some custom description of API.", "1.0", "Terms of service", new Contact("Sallo Szrajbman", "www.baeldung.com", "salloszraj@gmail.com"), "License of API", "API license URL", Collections.emptyList());
}
@Bean @Bean
public Docket api() { public OpenAPI openAPI() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) return new OpenAPI().addSecurityItem(new SecurityRequirement().addList("Bearer Authentication"))
.securityContexts(Arrays.asList(securityContext())) .components(new Components().addSecuritySchemes("Bearer Authentication", createAPIKeyScheme()))
.securitySchemes(Arrays.asList(apiKey())) .info(new Info().title("My REST API")
.select() .description("Some custom description of API.")
.apis(RequestHandlerSelectors.any()) .version("1.0").contact(new Contact().name("Sallo Szrajbman").email( "www.baeldung.com").url("salloszraj@gmail.com"))
.paths(PathSelectors.any()) .license(new License().name("License of API")
.build(); .url("API license URL")));
} }
private ApiKey apiKey() { private SecurityScheme createAPIKeyScheme() {
return new ApiKey("JWT", AUTHORIZATION_HEADER, "header"); return new SecurityScheme().type(SecurityScheme.Type.HTTP)
} .bearerFormat("JWT")
.scheme("bearer");
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(List.of(defaultAuth()))
.operationSelector(o -> o.requestMappingPattern()
.matches("/.*"))
.build();
}
private SecurityReference defaultAuth() {
return SecurityReference.builder()
.scopes(new AuthorizationScope[0])
.reference("JWT")
.build();
} }
} }

View File

@ -3,20 +3,17 @@ package com.baeldung.swaggerjwt.controller;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import com.baeldung.swaggerjwt.configuration.SwaggerConfiguration;
import io.swagger.annotations.Api;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@RestController(value = "/clients") @RestController(value = "/clients")
@Api( tags = "Clients") @Tag(name = "Clients")
public class ClientsRestController { public class ClientsRestController {
@ApiOperation(value = "This method is used to get the clients.") @Operation(summary = "This method is used to get the clients.")
@GetMapping @GetMapping
public List<String> getClients() { public List<String> getClients() {
return Arrays.asList("First Client", "Second Client"); return Arrays.asList("First Client", "Second Client");

View File

@ -30,6 +30,11 @@
<artifactId>swagger-maven-plugin</artifactId> <artifactId>swagger-maven-plugin</artifactId>
<version>${swagger-maven-plugin.version}</version> <version>${swagger-maven-plugin.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>${springdoc.version}</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -82,6 +87,7 @@
<properties> <properties>
<springfox.version>3.0.0</springfox.version> <springfox.version>3.0.0</springfox.version>
<swagger-maven-plugin.version>3.1.1</swagger-maven-plugin.version> <swagger-maven-plugin.version>3.1.1</swagger-maven-plugin.version>
<springdoc.version>1.7.0</springdoc.version>
</properties> </properties>
</project> </project>

View File

@ -2,37 +2,26 @@ package com.baeldung.swaggerexample.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.Collections; import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
@Configuration @Configuration
@EnableWebMvc @EnableWebMvc
public class SwaggerConfig { public class SwaggerConfig {
@Bean @Bean
public Docket api() { public OpenAPI openAPI() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) return new OpenAPI().info(new Info().title("Products API")
.select() .description("API to let you add and view product")
.apis(RequestHandlerSelectors.basePackage("com.baeldung.swaggerexample")) .version("0.0.1")
.paths(PathSelectors.any()) .contact(new Contact().name("John Doe")
.build(); .email("myemail@company.com")
} .url("www.example.com"))
.license(new License().name("License of API")
private ApiInfo apiInfo() { .url("API license URL")));
return new ApiInfo(
"Products API",
"API to let you add and view product",
"0.0.1",
"Terms of service",
new Contact("John Doe", "www.example.com", "myemail@company.com"),
"License of API", "API license URL", Collections.emptyList());
} }
} }

View File

@ -1,33 +1,41 @@
package com.baeldung.swaggerexample.controller; package com.baeldung.swaggerexample.controller;
import com.baeldung.swaggerexample.entity.Product;
import io.swagger.annotations.*;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; 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.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.baeldung.swaggerexample.entity.Product;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
@RestController @RestController
@ApiOperation("Products API") @Tag(name = "Products API")
public class ProductController { public class ProductController {
@ApiOperation(value = "Create a new product", notes = "Creates a new product as per the request body") @Operation(summary = "Create a new product", description = "Creates a new product as per the request body")
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(code = 201, message = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "400", description = "Bad request - The product is not valid"),
@ApiResponse(code = 400, message = "Bad request - The product is not valid"), @ApiResponse(responseCode = "500", description = "Internal server error - Something went wrong")
@ApiResponse(code = 500, message = "Internal server error - Something went wrong")
}) })
@PostMapping(value = "/products") @PostMapping(value = "/products")
public ResponseEntity<Void> createProduct(@RequestBody Product product) { public ResponseEntity<Void> createProduct(@RequestBody Product product) {
return new ResponseEntity<>(HttpStatus.CREATED); return new ResponseEntity<>(HttpStatus.CREATED);
} }
@ApiOperation(value = "Get a product by id", notes = "Returns a product as per the id") @Operation(summary = "Get a product by id", description = "Returns a product as per the id")
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(code = 200, message = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "404", description = "Not found - The product was not found")
@ApiResponse(code = 404, message = "Not found - The product was not found")
}) })
@GetMapping("/products/{id}") @GetMapping("/products/{id}")
public ResponseEntity<Product> getProduct(@PathVariable("id") @ApiParam(name = "id", value = "Product id", example = "1") Long id) { public ResponseEntity<Product> getProduct(@PathVariable("id") @Parameter(name = "id", description = "Product id", example = "1") Long id) {
//retrieval logic //retrieval logic
return ResponseEntity.ok(new Product(1, "Product 1", "$21.99")); return ResponseEntity.ok(new Product(1, "Product 1", "$21.99"));
} }

View File

@ -1,15 +1,15 @@
package com.baeldung.swaggerexample.entity; package com.baeldung.swaggerexample.entity;
import io.swagger.annotations.ApiModelProperty; import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable; import java.io.Serializable;
public class Product implements Serializable { public class Product implements Serializable {
@ApiModelProperty(notes = "Product ID", example = "1", required = true)
@Schema(name = "Product ID", example = "1", required = true)
private Long id; private Long id;
@ApiModelProperty(notes = "Product name", example = "Product 1", required = false) @Schema(name = "Product name", example = "Product 1", required = false)
private String name; private String name;
@ApiModelProperty(notes = "Product price", example = "$100.00", required = true) @Schema(name = "Product price", example = "$100.00", required = true)
private String price; private String price;
// constructor and getter/setters // constructor and getter/setters

View File

@ -2,21 +2,20 @@ package com.baeldung.swaggerresponses.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.PathSelectors; import io.swagger.v3.oas.models.OpenAPI;
import springfox.documentation.builders.RequestHandlerSelectors; import io.swagger.v3.oas.models.info.Info;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@Configuration @Configuration
@EnableWebMvc
public class SwaggerConfiguration { public class SwaggerConfiguration {
@Bean @Bean
public Docket api() { public OpenAPI openAPI() {
return new Docket(DocumentationType.SWAGGER_2).select() return new OpenAPI().info(new Info().title("Swagger Application")
.apis(RequestHandlerSelectors.any()) .description("This is a sample application for difference between @Operation & @ApiResponse")
.paths(PathSelectors.any()) .version("1.0.0"));
.build();
} }
} }

View File

@ -4,10 +4,12 @@ import com.baeldung.swaggerresponses.response.CustomerResponse;
import com.baeldung.swaggerresponses.response.ErrorResponse; import com.baeldung.swaggerresponses.response.ErrorResponse;
import com.baeldung.swaggerresponses.service.CustomerService; import com.baeldung.swaggerresponses.service.CustomerService;
import io.swagger.annotations.Api; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.annotations.ApiResponse; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.annotations.ApiResponses; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -15,7 +17,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@Api("Customer Controller") @Tag(name = "Customer Controller")
@RestController @RestController
@RequestMapping("/customers") @RequestMapping("/customers")
public class CustomerController { public class CustomerController {
@ -26,11 +28,11 @@ public class CustomerController {
this.customerService = customerService; this.customerService = customerService;
} }
@ApiOperation(value = "Gets customer by ID", response = CustomerResponse.class, notes = "Customer must exist") @Operation(summary = "Gets customer by ID", description = "Customer must exist")
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(code = 400, message = "Invalid ID supplied"), @ApiResponse(responseCode = "200", description = "Ok", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = CustomerResponse.class)) }),
@ApiResponse(code = 404, message = "Customer not found"), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Customer not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ErrorResponse.class) }) @ApiResponse(responseCode = "500", description = "Internal server error", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class)) }) })
@GetMapping("/{id}") @GetMapping("/{id}")
public ResponseEntity<CustomerResponse> getCustomer(@PathVariable("id") Long id) { public ResponseEntity<CustomerResponse> getCustomer(@PathVariable("id") Long id) {
return ResponseEntity.ok(customerService.getById(id)); return ResponseEntity.ok(customerService.getById(id));