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.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.ApiInfoBuilder;
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;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
@Configuration
@EnableWebMvc
@EnableSwagger2
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() {
return new ApiInfoBuilder().title("Swagger Array")
@Bean
public OpenAPI openAPI() {
return new OpenAPI().info(new Info().title("Swagger Array")
.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")
.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 io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
@Controller
public class FooController {
@ -26,7 +26,7 @@ public class FooController {
@RequestMapping(method = RequestMethod.POST, value = "/foos")
@ResponseStatus(HttpStatus.CREATED)
@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) {
foo.setId(Long.parseLong(randomNumeric(2)));
return foo;

View File

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

View File

@ -2,14 +2,13 @@ package com.baeldung.swagger2bootmvc.model;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
@ApiModel
@Schema
public class Foo {
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;
public Foo() {

View File

@ -1,12 +1,11 @@
package com.baeldung.swagger2bootmvc.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
@ApiModel
@Schema
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;
public User() {

View File

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

View File

@ -3,54 +3,32 @@ package com.baeldung.swaggerjwt.configuration;
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.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import io.swagger.v3.oas.models.Components;
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;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
@Configuration
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
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.securityContexts(Arrays.asList(securityContext()))
.securitySchemes(Arrays.asList(apiKey()))
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
public OpenAPI openAPI() {
return new OpenAPI().addSecurityItem(new SecurityRequirement().addList("Bearer Authentication"))
.components(new Components().addSecuritySchemes("Bearer Authentication", createAPIKeyScheme()))
.info(new Info().title("My REST API")
.description("Some custom description of API.")
.version("1.0").contact(new Contact().name("Sallo Szrajbman").email( "www.baeldung.com").url("salloszraj@gmail.com"))
.license(new License().name("License of API")
.url("API license URL")));
}
private ApiKey apiKey() {
return new ApiKey("JWT", AUTHORIZATION_HEADER, "header");
}
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();
private SecurityScheme createAPIKeyScheme() {
return new SecurityScheme().type(SecurityScheme.Type.HTTP)
.bearerFormat("JWT")
.scheme("bearer");
}
}

View File

@ -3,20 +3,17 @@ package com.baeldung.swaggerjwt.controller;
import java.util.Arrays;
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.RequestHeader;
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")
@Api( tags = "Clients")
@Tag(name = "Clients")
public class ClientsRestController {
@ApiOperation(value = "This method is used to get the clients.")
@Operation(summary = "This method is used to get the clients.")
@GetMapping
public List<String> getClients() {
return Arrays.asList("First Client", "Second Client");

View File

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

View File

@ -2,37 +2,26 @@ package com.baeldung.swaggerexample.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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
@EnableWebMvc
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.baeldung.swaggerexample"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
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());
public OpenAPI openAPI() {
return new OpenAPI().info(new Info().title("Products API")
.description("API to let you add and view product")
.version("0.0.1")
.contact(new Contact().name("John Doe")
.email("myemail@company.com")
.url("www.example.com"))
.license(new License().name("License of API")
.url("API license URL")));
}
}

View File

@ -1,33 +1,41 @@
package com.baeldung.swaggerexample.controller;
import com.baeldung.swaggerexample.entity.Product;
import io.swagger.annotations.*;
import org.springframework.http.HttpStatus;
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
@ApiOperation("Products API")
@Tag(name = "Products API")
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 = {
@ApiResponse(code = 201, message = "Successfully created"),
@ApiResponse(code = 400, message = "Bad request - The product is not valid"),
@ApiResponse(code = 500, message = "Internal server error - Something went wrong")
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "400", description = "Bad request - The product is not valid"),
@ApiResponse(responseCode = "500", description = "Internal server error - Something went wrong")
})
@PostMapping(value = "/products")
public ResponseEntity<Void> createProduct(@RequestBody Product product) {
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 = {
@ApiResponse(code = 200, message = "Successfully retrieved"),
@ApiResponse(code = 404, message = "Not found - The product was not found")
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "404", description = "Not found - The product was not found")
})
@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
return ResponseEntity.ok(new Product(1, "Product 1", "$21.99"));
}

View File

@ -1,15 +1,15 @@
package com.baeldung.swaggerexample.entity;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.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;
@ApiModelProperty(notes = "Product name", example = "Product 1", required = false)
@Schema(name = "Product name", example = "Product 1", required = false)
private String name;
@ApiModelProperty(notes = "Product price", example = "$100.00", required = true)
@Schema(name = "Product price", example = "$100.00", required = true)
private String price;
// 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.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
@Configuration
@EnableWebMvc
public class SwaggerConfiguration {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
public OpenAPI openAPI() {
return new OpenAPI().info(new Info().title("Swagger Application")
.description("This is a sample application for difference between @Operation & @ApiResponse")
.version("1.0.0"));
}
}

View File

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