Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/samples-jdk17.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ on:
- samples/client/petstore/java/microprofile-rest-client-outer-enum/**
# servers
- samples/openapi3/server/petstore/springboot-3/**
- samples/openapi3/server/petstore/springboot-3-include-http-request-context/**
- samples/server/petstore/springboot-x-implements-skip/**
- samples/server/petstore/java-camel/**
- samples/server/petstore/java-helidon-server/v3/mp/**
Expand All @@ -32,6 +33,7 @@ on:
- samples/client/petstore/java/microprofile-rest-client-outer-enum/**
# servers
- samples/openapi3/server/petstore/springboot-3/**
- samples/openapi3/server/petstore/springboot-3-include-http-request-context/**
- samples/server/petstore/springboot-x-implements-skip/**
- samples/server/petstore/java-camel/**
- samples/server/petstore/java-helidon-server/v3/mp/**
Expand All @@ -56,6 +58,7 @@ jobs:
- samples/client/petstore/java/microprofile-rest-client-outer-enum
# servers
- samples/openapi3/server/petstore/springboot-3
- samples/openapi3/server/petstore/springboot-3-include-http-request-context
- samples/server/petstore/springboot-x-implements-skip
- samples/server/petstore/java-camel/
- samples/server/petstore/java-helidon-server/v3/mp/
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/samples-spring.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ jobs:
- samples/server/petstore/spring-boot-nullable-set
- samples/server/petstore/spring-boot-defaultInterface-unhandledExcp
- samples/server/petstore/springboot
- samples/server/petstore/springboot-include-http-request-context
- samples/server/petstore/springboot-beanvalidation
- samples/server/petstore/springboot-builtin-validation
- samples/server/petstore/springboot-delegate
Expand Down
16 changes: 16 additions & 0 deletions bin/configs/spring-boot-3-include-http-request-context.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
generatorName: spring
outputDir: samples/openapi3/server/petstore/springboot-3-include-http-request-context
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaSpring
additionalProperties:
groupId: org.openapitools.openapi3
documentationProvider: springdoc
artifactId: springboot
snapshotVersion: "true"
useSpringBoot3: true
useBeanValidation: true
withXml: true
hideGenerationTimestamp: "true"
generateConstructorWithAllArgs: true
generateBuilders: true
includeHttpRequestContext: "true"
12 changes: 12 additions & 0 deletions bin/configs/spring-boot-include-http-request-context.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
generatorName: spring
outputDir: samples/server/petstore/springboot-include-http-request-context
inputSpec: modules/openapi-generator/src/test/resources/3_0/spring/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaSpring
additionalProperties:
documentationProvider: springfox
artifactId: springboot
snapshotVersion: "true"
hideGenerationTimestamp: "true"
camelCaseDollarSign: "true"
modelNameSuffix: 'Dto'
includeHttpRequestContext: "true"
1 change: 1 addition & 0 deletions bin/configs/spring-boot-reactive-noResponseEntity.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ additionalProperties:
hideGenerationTimestamp: "true"
delegatePattern: "true"
useResponseEntity: "false"
includeHttpRequestContext: "false"
1 change: 1 addition & 0 deletions docs/generators/java-camel.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|ignoreAnyOfInEnum|Ignore anyOf keyword in enum| |false|
|implicitHeaders|Skip header parameters in the generated API methods using @ApiImplicitParams annotation.| |false|
|implicitHeadersRegex|Skip header parameters that matches given regex in the generated API methods using @ApiImplicitParams annotation. Note: this parameter is ignored when implicitHeaders=true| |null|
|includeHttpRequestContext|Whether to include HttpServletRequest (blocking) or ServerWebExchange (reactive) as additional parameter in generated methods. Defaults to 'true' for reactive and 'false' for blocking.| |true (reactive) / false (blocking)|
|interfaceOnly|Whether to generate only API interface stubs without the server files.| |false|
|invokerPackage|root package for generated code| |org.openapitools.api|
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|false|
Expand Down
1 change: 1 addition & 0 deletions docs/generators/spring.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|ignoreAnyOfInEnum|Ignore anyOf keyword in enum| |false|
|implicitHeaders|Skip header parameters in the generated API methods using @ApiImplicitParams annotation.| |false|
|implicitHeadersRegex|Skip header parameters that matches given regex in the generated API methods using @ApiImplicitParams annotation. Note: this parameter is ignored when implicitHeaders=true| |null|
|includeHttpRequestContext|Whether to include HttpServletRequest (blocking) or ServerWebExchange (reactive) as additional parameter in generated methods. Defaults to 'true' for reactive and 'false' for blocking.| |true (reactive) / false (blocking)|
|interfaceOnly|Whether to generate only API interface stubs without the server files.| |false|
|invokerPackage|root package for generated code| |org.openapitools.api|
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|false|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.servers.Server;
import io.swagger.v3.oas.models.tags.Tag;
import io.swagger.v3.parser.util.SchemaTypeUtil;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -93,6 +94,7 @@ public class SpringCodegen extends AbstractJavaCodegen
public static final String GENERATE_GENERIC_RESPONSE_ENTITY = "generateGenericResponseEntity";
public static final String USE_ENUM_CASE_INSENSITIVE = "useEnumCaseInsensitive";
public static final String USE_SPRING_BOOT3 = "useSpringBoot3";
public static final String INCLUDE_HTTP_REQUEST_CONTEXT = "includeHttpRequestContext";
public static final String REQUEST_MAPPING_OPTION = "requestMappingMode";
public static final String USE_REQUEST_MAPPING_ON_CONTROLLER = "useRequestMappingOnController";
public static final String USE_REQUEST_MAPPING_ON_INTERFACE = "useRequestMappingOnInterface";
Expand Down Expand Up @@ -154,6 +156,12 @@ public enum RequestMappingMode {
@Setter protected boolean useEnumCaseInsensitive = false;
@Getter @Setter
protected boolean useSpringBoot3 = false;
@Getter @Setter
private Boolean includeHttpRequestContext = null;
@Getter
private final boolean defaultIncludeHttpRequestContextForReactive = true;
@Getter
private final boolean defaultIncludeHttpRequestContextForBlocking = false;
protected boolean generatedConstructorWithRequiredArgs = true;
@Getter @Setter
protected RequestMappingMode requestMappingMode = RequestMappingMode.controller;
Expand Down Expand Up @@ -281,6 +289,9 @@ public SpringCodegen() {
cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT3,
"Generate code and provide dependencies for use with Spring Boot ≥ 3 (use jakarta instead of javax in imports). Enabling this option will also enable `useJakartaEe`.",
useSpringBoot3));
cliOptions.add(new CliOption(INCLUDE_HTTP_REQUEST_CONTEXT,
"Whether to include HttpServletRequest (blocking) or ServerWebExchange (reactive) as additional parameter in generated methods. Defaults to 'true' for reactive and 'false' for blocking.",
SchemaTypeUtil.BOOLEAN_TYPE).defaultValue("true (reactive) / false (blocking)"));
cliOptions.add(CliOption.newBoolean(GENERATE_CONSTRUCTOR_WITH_REQUIRED_ARGS,
"Whether to generate constructors with required args for models",
generatedConstructorWithRequiredArgs));
Expand Down Expand Up @@ -432,6 +443,22 @@ public void processOpts() {
convertPropertyToBooleanAndWriteBack(REACTIVE, this::setReactive);
convertPropertyToBooleanAndWriteBack(SSE, this::setSse);
}
if (additionalProperties.containsKey(INCLUDE_HTTP_REQUEST_CONTEXT)) {
convertPropertyToBooleanAndWriteBack(INCLUDE_HTTP_REQUEST_CONTEXT, this::setIncludeHttpRequestContext);
}
//set default value for includeHttpRequestContext based on reactive/blocking
if (includeHttpRequestContext == null) {
if (this.reactive) {
//default to true for reactive
this.setIncludeHttpRequestContext(this.isDefaultIncludeHttpRequestContextForReactive());
LOGGER.info("Defaulting {} to '{}' for reactive", INCLUDE_HTTP_REQUEST_CONTEXT, this.isDefaultIncludeHttpRequestContextForReactive());
} else {
//default to false for blocking
this.setIncludeHttpRequestContext(this.isDefaultIncludeHttpRequestContextForBlocking());
LOGGER.info("Defaulting {} to '{}' for blocking", INCLUDE_HTTP_REQUEST_CONTEXT, this.isDefaultIncludeHttpRequestContextForBlocking());
}
additionalProperties.put(INCLUDE_HTTP_REQUEST_CONTEXT, this.getIncludeHttpRequestContext());
}

convertPropertyToStringAndWriteBack(RESPONSE_WRAPPER, this::setResponseWrapper);
convertPropertyToBooleanAndWriteBack(USE_TAGS, this::setUseTags);
Expand Down Expand Up @@ -1031,7 +1058,6 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation
// add org.springframework.format.annotation.DateTimeFormat when needed
codegenOperation.allParams.stream().filter(p -> p.isDate || p.isDateTime).findFirst()
.ifPresent(p -> codegenOperation.imports.add("DateTimeFormat"));

// add org.springframework.data.domain.Pageable import when needed
if (codegenOperation.vendorExtensions.containsKey("x-spring-paginated")) {
codegenOperation.imports.add("Pageable");
Expand All @@ -1057,13 +1083,12 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation

addSpringNullableImportForOperation(codegenOperation);

if (reactive) {
if (DocumentationProvider.SPRINGFOX.equals(getDocumentationProvider())) {
codegenOperation.imports.add("ApiIgnore");
}
if (sse) {
var MEDIA_EVENT_STREAM = "text/event-stream";
// inspecting used streaming media types
if (DocumentationProvider.SPRINGFOX.equals(getDocumentationProvider()) && includeHttpRequestContext != null && includeHttpRequestContext) {
codegenOperation.imports.add("ApiIgnore");
}
if (reactive && sse) {
var MEDIA_EVENT_STREAM = "text/event-stream";
// inspecting used streaming media types
/*
expected definition:
content:
Expand All @@ -1075,36 +1100,35 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation
type: <type> or
$ref: <typeRef>
*/
Map<String, List<Schema>> schemaTypes = operation.getResponses().entrySet().stream()
.map(e -> Pair.of(e.getValue(), fromResponse(e.getKey(), e.getValue())))
.filter(p -> p.getRight().is2xx) // consider only success
.map(p -> p.getLeft().getContent().get(MEDIA_EVENT_STREAM))
.map(MediaType::getSchema)
.collect(Collectors.toList()).stream()
.collect(Collectors.groupingBy(Schema::getType));
if (schemaTypes.containsKey("array")) {
// we have a match with SSE pattern
// double check potential conflicting, multiple specs
if (schemaTypes.keySet().size() > 1) {
throw new RuntimeException("only 1 response media type supported, when SSE is detected");
}
// double check schema format
List<Schema> eventTypes = schemaTypes.get("array");
if (eventTypes.stream().anyMatch(schema -> !"event-stream".equalsIgnoreCase(schema.getFormat()))) {
throw new RuntimeException("schema format 'event-stream' is required, when SSE is detected");
}
// double check item types
Set<String> itemTypes = eventTypes.stream()
.map(schema -> schema.getItems().getType() != null
? schema.getItems().getType()
: schema.getItems().get$ref())
.collect(Collectors.toSet());
if (itemTypes.size() > 1) {
throw new RuntimeException("only single item type is supported, when SSE is detected");
}
codegenOperation.vendorExtensions.put("x-sse", true);
} // Not an SSE compliant definition
}
Map<String, List<Schema>> schemaTypes = operation.getResponses().entrySet().stream()
.map(e -> Pair.of(e.getValue(), fromResponse(e.getKey(), e.getValue())))
.filter(p -> p.getRight().is2xx) // consider only success
.map(p -> p.getLeft().getContent().get(MEDIA_EVENT_STREAM))
.map(MediaType::getSchema)
.collect(Collectors.toList()).stream()
.collect(Collectors.groupingBy(Schema::getType));
if (schemaTypes.containsKey("array")) {
// we have a match with SSE pattern
// double check potential conflicting, multiple specs
if (schemaTypes.keySet().size() > 1) {
throw new RuntimeException("only 1 response media type supported, when SSE is detected");
}
// double check schema format
List<Schema> eventTypes = schemaTypes.get("array");
if (eventTypes.stream().anyMatch(schema -> !"event-stream".equalsIgnoreCase(schema.getFormat()))) {
throw new RuntimeException("schema format 'event-stream' is required, when SSE is detected");
}
// double check item types
Set<String> itemTypes = eventTypes.stream()
.map(schema -> schema.getItems().getType() != null
? schema.getItems().getType()
: schema.getItems().get$ref())
.collect(Collectors.toSet());
if (itemTypes.size() > 1) {
throw new RuntimeException("only single item type is supported, when SSE is detected");
}
codegenOperation.vendorExtensions.put("x-sse", true);
} // Not an SSE compliant definition
}
return codegenOperation;
}
Expand Down
Loading
Loading