Skip to content

Commit

Permalink
Integrate DocumentationProviderFeatures in SpringCodegen
Browse files Browse the repository at this point in the history
  • Loading branch information
cachescrubber committed Jan 8, 2022
1 parent 9865887 commit 4fc7f38
Show file tree
Hide file tree
Showing 18 changed files with 182 additions and 124 deletions.
10 changes: 10 additions & 0 deletions bin/configs/spring-boot-springdoc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
generatorName: spring
outputDir: samples/openapi3/server/petstore/spring-boot-springdoc
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaSpring
additionalProperties:
documentationProvider: springdoc
groupId: org.openapitools.openapi3
artifactId: spring-boot-springdoc
snapshotVersion: "true"
hideGenerationTimestamp: "true"
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import java.util.Map;
import java.util.regex.Matcher;
import java.util.stream.Collectors;

import org.apache.commons.lang3.tuple.Pair;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
Expand Down Expand Up @@ -90,7 +89,6 @@ public class SpringCodegen extends AbstractJavaCodegen
public static final String IMPLICIT_HEADERS = "implicitHeaders";
public static final String OPENAPI_DOCKET_CONFIG = "swaggerDocketConfig";
public static final String API_FIRST = "apiFirst";
public static final String OAS3 = "oas3";
public static final String SPRING_CONTROLLER = "useSpringController";
public static final String HATEOAS = "hateoas";
public static final String RETURN_SUCCESS_CODE = "returnSuccessCode";
Expand Down Expand Up @@ -123,7 +121,6 @@ public class SpringCodegen extends AbstractJavaCodegen
protected boolean returnSuccessCode = false;
protected boolean unhandledException = false;
protected boolean useSpringController = false;
protected boolean oas3 = false;

public SpringCodegen() {
super();
Expand Down Expand Up @@ -199,7 +196,6 @@ public SpringCodegen() {
CliOption.newBoolean(HATEOAS, "Use Spring HATEOAS library to allow adding HATEOAS links", hateoas));
cliOptions
.add(CliOption.newBoolean(RETURN_SUCCESS_CODE, "Generated server returns 2xx code", returnSuccessCode));
cliOptions.add(CliOption.newBoolean(OAS3, "Use OAS 3 Swagger annotations instead of OAS 2 annotations", oas3));
cliOptions.add(CliOption.newBoolean(SPRING_CONTROLLER, "Annotate the generated API as a Spring Controller", useSpringController));
cliOptions.add(CliOption.newBoolean(UNHANDLED_EXCEPTION_HANDLING,
"Declare operation methods to throw a generic exception and allow unhandled exceptions (useful for Spring `@ControllerAdvice` directives).",
Expand Down Expand Up @@ -240,6 +236,29 @@ public String getHelp() {
return "Generates a Java SpringBoot Server application using the SpringFox integration.";
}

@Override
public DocumentationProvider defaultDocumentationProvider() {
return DocumentationProvider.SPRINGDOC;
}

public List<DocumentationProvider> supportedDocumentationProvider() {
List<DocumentationProvider> supportedProviders = new ArrayList<>();
supportedProviders.add(DocumentationProvider.NONE);
supportedProviders.add(DocumentationProvider.SOURCE);
supportedProviders.add(DocumentationProvider.SPRINGFOX);
supportedProviders.add(DocumentationProvider.SPRINGDOC);
return supportedProviders;
}

@Override
public List<AnnotationLibrary> supportedAnnotationLibraries() {
List<AnnotationLibrary> supportedLibraries = new ArrayList<>();
supportedLibraries.add(AnnotationLibrary.NONE);
supportedLibraries.add(AnnotationLibrary.SWAGGER1);
supportedLibraries.add(AnnotationLibrary.SWAGGER2);
return supportedLibraries;
}

@Override
public void processOpts() {

Expand Down Expand Up @@ -372,11 +391,6 @@ public void processOpts() {
}
writePropertyBack(SPRING_CONTROLLER, useSpringController);

if (additionalProperties.containsKey(OAS3)) {
this.setOas3(convertPropertyToBoolean(OAS3));
}
writePropertyBack(OAS3, oas3);

if (additionalProperties.containsKey(RETURN_SUCCESS_CODE)) {
this.setReturnSuccessCode(Boolean.parseBoolean(additionalProperties.get(RETURN_SUCCESS_CODE).toString()));
}
Expand Down Expand Up @@ -513,15 +527,6 @@ public void processOpts() {
additionalProperties.put(RESPONSE_WRAPPER, "Callable");
}

// Springfox cannot be used with oas3 or apiFirst or reactive. So, write the property back after determining
// whether it should be enabled or not.
boolean useSpringFox = false;
if (!apiFirst && !reactive && !oas3) {
useSpringFox = true;
additionalProperties.put("useSpringfox", true);
}
writePropertyBack("useSpringfox", useSpringFox);

// Some well-known Spring or Spring-Cloud response wrappers
if (isNotEmpty(responseWrapper)) {
additionalProperties.put("jdk8", false);
Expand Down Expand Up @@ -880,10 +885,6 @@ public void setUseSpringController(boolean useSpringController) {
this.useSpringController = useSpringController;
}

public void setOas3(boolean oas3) {
this.oas3 = oas3;
}

public void setReturnSuccessCode(boolean returnSuccessCode) {
this.returnSuccessCode = returnSuccessCode;
}
Expand Down Expand Up @@ -927,8 +928,8 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
@Override
public CodegenModel fromModel(String name, Schema model) {
CodegenModel codegenModel = super.fromModel(name, model);
if (oas3) {
// remove swagger2 imports
if (getAnnotationLibrary() != AnnotationLibrary.SWAGGER1) {
// remove swagger imports
codegenModel.imports.remove("ApiModelProperty");
codegenModel.imports.remove("ApiModel");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{{#allowableValues}}allowableValues ={{#oas3}} { {{#values}}"{{{.}}}"{{^-last}}, {{/-last}}{{/values}} }{{/oas3}}{{^oas3}} "{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/oas3}}{{/allowableValues}}
{{#allowableValues}}allowableValues ={{#swagger2AnnotationLibrary}} { {{#values}}"{{{.}}}"{{^-last}}, {{/-last}}{{/values}} }{{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}} "{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/swagger1AnnotationLibrary}}{{/allowableValues}}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package {{package}};

{{#imports}}import {{import}};
{{/imports}}
{{#oas3}}
{{#swagger2AnnotationLibrary}}
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
Expand All @@ -16,10 +16,10 @@ import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
{{/oas3}}
{{^oas3}}
{{/swagger2AnnotationLibrary}}
{{#swagger1AnnotationLibrary}}
import io.swagger.annotations.*;
{{/oas3}}
{{/swagger1AnnotationLibrary}}
{{#jdk8-no-delegate}}
{{#virtualService}}
import io.virtualan.annotation.ApiVirtual;
Expand Down Expand Up @@ -73,7 +73,7 @@ import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture
{{#useSpringController}}
@Controller
{{/useSpringController}}
{{#oas3}}@Tag(name = "{{{baseName}}}", description = "the {{{baseName}}} API"){{/oas3}}{{^oas3}}@Api(value = "{{{baseName}}}", description = "the {{{baseName}}} API"){{/oas3}}
{{#swagger2AnnotationLibrary}}@Tag(name = "{{{baseName}}}", description = "the {{{baseName}}} API"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}@Api(value = "{{{baseName}}}", description = "the {{{baseName}}} API"){{/swagger1AnnotationLibrary}}
{{#operations}}
{{#virtualService}}
@VirtualService
Expand Down Expand Up @@ -119,7 +119,7 @@ public interface {{classname}} {
{{#virtualService}}
@ApiVirtual
{{/virtualService}}
{{#oas3}}
{{#swagger2AnnotationLibrary}}
@Operation(
summary = "{{{summary}}}",
tags = { {{#vendorExtensions.x-tags}}"{{tag}}"{{^-last}}, {{/-last}}{{/vendorExtensions.x-tags}} },
Expand All @@ -134,8 +134,8 @@ public interface {{classname}} {
{{/authMethods}}
}{{/hasAuthMethods}}
)
{{/oas3}}
{{^oas3}}
{{/swagger2AnnotationLibrary}}
{{#swagger1AnnotationLibrary}}
@ApiOperation(
tags = { {{#vendorExtensions.x-tags}}"{{tag}}"{{^-last}}, {{/-last}}{{/vendorExtensions.x-tags}} },
value = "{{{summary}}}",
Expand All @@ -162,20 +162,20 @@ public interface {{classname}} {
@ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{.}}}.class{{/baseType}}{{#containerType}}, responseContainer = "{{{.}}}"{{/containerType}}){{^-last}},{{/-last}}
{{/responses}}
})
{{/oas3}}
{{/swagger1AnnotationLibrary}}
{{#implicitHeaders}}
{{#oas3}}
{{#swagger2AnnotationLibrary}}
@Parameters({
{{#headerParams}}
{{>paramDoc}}{{^-last}},{{/-last}}
{{/headerParams}}
{{/oas3}}
{{^oas3}}
{{/swagger2AnnotationLibrary}}
{{#swagger1AnnotationLibrary}}
@ApiImplicitParams({
{{#headerParams}}
{{>implicitHeader}}{{^-last}},{{/-last}}
{{/headerParams}}
{{/oas3}}
{{/swagger1AnnotationLibrary}}
})
{{/implicitHeaders}}
@RequestMapping(
Expand All @@ -189,15 +189,15 @@ public interface {{classname}} {
{{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{#delegate-method}}_{{/delegate-method}}{{operationId}}(
{{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{>cookieParams}}{{^-last}},
{{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}},
{{/hasParams}}{{#oas3}}@Parameter(hidden = true){{/oas3}}{{#useSpringfox}}@springfox.documentation.annotations.ApiIgnore{{/useSpringfox}} final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}},
{{/hasParams}}{{#useSpringfox}}@springfox.documentation.annotations.ApiIgnore {{/useSpringfox}}final org.springframework.data.domain.Pageable pageable{{/vendorExtensions.x-spring-paginated}}
{{/hasParams}}{{#swagger2AnnotationLibrary}}@Parameter(hidden = true){{/swagger2AnnotationLibrary}}{{#springFoxDocumentationProvider}}@springfox.documentation.annotations.ApiIgnore{{/springFoxDocumentationProvider}} final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}},
{{/hasParams}}{{#springFoxDocumentationProvider}}@springfox.documentation.annotations.ApiIgnore {{/springFoxDocumentationProvider}}{{#springDocDocumentationProvider}}@ParameterObject{{/springDocDocumentationProvider}}final org.springframework.data.domain.Pageable pageable{{/vendorExtensions.x-spring-paginated}}
){{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}}{{#unhandledException}} throws Exception{{/unhandledException}} {
{{#delegate-method}}
return {{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}});
}

// Override this method
{{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}{{#useSpringfox}}@springfox.documentation.annotations.ApiIgnore{{/useSpringfox}} final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, {{#useSpringfox}}@springfox.documentation.annotations.ApiIgnore{{/useSpringfox}} final org.springframework.data.domain.Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}} {
{{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}{{#springFoxDocumentationProvider}}@springfox.documentation.annotations.ApiIgnore{{/springFoxDocumentationProvider}} final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, {{#springFoxDocumentationProvider}}@springfox.documentation.annotations.ApiIgnore{{/springFoxDocumentationProvider}} final org.springframework.data.domain.Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}} {
{{/delegate-method}}
{{^isDelegate}}
{{>methodBody}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ package {{package}};
{{^jdk8}}
{{#imports}}import {{import}};
{{/imports}}
{{#oas3}}
{{#swagger2AnnotationLibrary}}
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
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.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
{{/oas3}}
{{^oas3}}
{{/swagger2AnnotationLibrary}}
{{^swagger1AnnotationLibrary}}
import io.swagger.annotations.*;
{{/oas3}}
{{/swagger1AnnotationLibrary}}
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -132,7 +132,7 @@ public class {{classname}}Controller implements {{classname}} {
public {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}(
{{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{>cookieParams}}{{^-last}},
{{/-last}}{{/allParams}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}},
{{/hasParams}}{{#useSpringfox}}@springfox.documentation.annotations.ApiIgnore {{/useSpringfox}}final Pageable pageable{{/vendorExtensions.x-spring-paginated}}
{{/hasParams}}{{#springFoxDocumentationProvider}}@springfox.documentation.annotations.ApiIgnore {{/springFoxDocumentationProvider}}final Pageable pageable{{/vendorExtensions.x-spring-paginated}}
) {
{{^isDelegate}}
{{^async}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
package {{configPackage}};

{{^useSpringfox}}
{{^springFoxDocumentationProvider}}
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.Resource;
{{/useSpringfox}}
{{/springFoxDocumentationProvider}}
import org.springframework.stereotype.Controller;
{{^useSpringfox}}
{{^springFoxDocumentationProvider}}
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.GetMapping;
{{/useSpringfox}}
{{/springFoxDocumentationProvider}}
import org.springframework.web.bind.annotation.RequestMapping;
{{^useSpringfox}}
{{^springFoxDocumentationProvider}}
import org.springframework.web.bind.annotation.ResponseBody;
{{/useSpringfox}}
{{/springFoxDocumentationProvider}}
{{#reactive}}
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
{{/reactive}}

{{^useSpringfox}}
{{^springFoxDocumentationProvider}}
import java.io.IOException;
import java.io.InputStream;
{{/useSpringfox}}
{{/springFoxDocumentationProvider}}
{{#reactive}}
import java.net.URI;
{{/reactive}}
{{^useSpringfox}}
{{^springFoxDocumentationProvider}}
import java.nio.charset.Charset;
{{/useSpringfox}}
{{/springFoxDocumentationProvider}}
{{#reactive}}

import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
Expand All @@ -42,7 +42,7 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.r
@Controller
public class HomeController {
{{^useSpringfox}}
{{^springFoxDocumentationProvider}}
private static YAMLMapper yamlMapper = new YAMLMapper();

@Value("classpath:/openapi.yaml")
Expand All @@ -67,20 +67,20 @@ public class HomeController {
return yamlMapper.readValue(openapiContent(), Object.class);
}

{{/useSpringfox}}
{{/springFoxDocumentationProvider}}
{{#reactive}}
@Bean
RouterFunction<ServerResponse> index() {
return route(
GET("/"),
req -> ServerResponse.temporaryRedirect(URI.create("{{#useSpringfox}}swagger-ui.html{{/useSpringfox}}{{^useSpringfox}}swagger-ui/index.html?url=../openapi.json{{/useSpringfox}}")).build()
req -> ServerResponse.temporaryRedirect(URI.create("{{#springFoxDocumentationProvider}}swagger-ui.html{{/springFoxDocumentationProvider}}{{^springFoxDocumentationProvider}}swagger-ui/index.html?url=../openapi.json{{/springFoxDocumentationProvider}}")).build()
);
}
{{/reactive}}
{{^reactive}}
@RequestMapping("/")
public String index() {
return "redirect:{{#useSpringfox}}swagger-ui.html{{/useSpringfox}}{{^useSpringfox}}swagger-ui/index.html?url=../openapi.json{{/useSpringfox}}";
return "redirect:{{#springFoxDocumentationProvider}}swagger-ui.html{{/springFoxDocumentationProvider}}{{^springFoxDocumentationProvider}}swagger-ui/index.html?url=../openapi.json{{/springFoxDocumentationProvider}}";
}
{{/reactive}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ This server was generated by the [OpenAPI Generator](https://openapi-generator.t
By using the [OpenAPI-Spec](https://openapis.org), you can easily generate a server stub.
This is an example of building a OpenAPI-enabled server in Java using the SpringBoot framework.

{{#useSpringfox}}
{{#springFoxDocumentationProvider}}
The underlying library integrating OpenAPI to SpringBoot is [springfox](https://github.com/springfox/springfox)

{{/useSpringfox}}
{{/springFoxDocumentationProvider}}
Start your server as a simple java application

{{^reactive}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{#useSpringfox}}
{{#springFoxDocumentationProvider}}
springfox.documentation.swagger.v2.path=/api-docs
{{/useSpringfox}}
{{/springFoxDocumentationProvider}}
server.port={{serverPort}}
spring.jackson.date-format={{basePackage}}.RFC3339DateFormat
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
Expand Down
Loading

0 comments on commit 4fc7f38

Please sign in to comment.