Skip to content
Draft
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .github/workflows/samples-jdk17.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ on:
- samples/client/petstore/java-helidon-client/v3/mp/**
- samples/client/petstore/java-helidon-client/v3/se/**
- samples/client/petstore/spring-http-interface-reactive/**
- samples/client/petstore/spring-http-interface-reactive-bean-validation/**
- samples/client/petstore/spring-http-interface-bean-validation/**
- samples/client/petstore/spring-http-interface/**
- samples/client/petstore/spring-http-interface-reactive-noResponseEntity/**
- samples/client/petstore/spring-http-interface-noResponseEntity/**
Expand All @@ -27,6 +29,8 @@ on:
- samples/client/petstore/java-helidon-client/v3/mp/**
- samples/client/petstore/java-helidon-client/v3/se/**
- samples/client/petstore/spring-http-interface-reactive/**
- samples/client/petstore/spring-http-interface-reactive-bean-validation/**
- samples/client/petstore/spring-http-interface-bean-validation/**
- samples/client/petstore/spring-http-interface/**
- samples/client/petstore/spring-http-interface-reactive-noResponseEntity/**
- samples/client/petstore/spring-http-interface-noResponseEntity/**
Expand All @@ -53,6 +57,8 @@ jobs:
- samples/client/petstore/java-helidon-client/v3/mp/
- samples/client/petstore/java-helidon-client/v3/se
- samples/client/petstore/spring-http-interface-reactive
- samples/client/petstore/spring-http-interface-reactive-bean-validation
- samples/client/petstore/spring-http-interface-bean-validation
- samples/client/petstore/spring-http-interface
- samples/client/petstore/spring-http-interface-reactive-noResponseEntity
- samples/client/petstore/spring-http-interface-noResponseEntity
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/samples-kotlin-server-jdk17.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ jobs:
- samples/server/petstore/kotlin-server-modelMutable
- samples/server/petstore/kotlin-misk
- samples/server/petstore/kotlin-spring-declarative-interface
- samples/server/petstore/kotlin-spring-declarative-interface-bean-validation
- samples/server/petstore/kotlin-spring-declarative-interface-reactive-coroutines
- samples/server/petstore/kotlin-spring-declarative-interface-reactive-reactor-wrapped
- samples/server/petstore/kotlin-spring-declarative-interface-wrapped
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
generatorName: kotlin-spring
outputDir: samples/server/petstore/kotlin-spring-declarative-interface-bean-validation
library: spring-declarative-http-interface
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-spring
additionalProperties:
documentationProvider: springDoc
annotationLibrary: swagger2
useSwaggerUI: "false"
serializableModel: "true"
interfaceOnly: true
reactive: false
useResponseEntity: true
useFlowForArrayReturnType: false
useBeanValidation: "true"
18 changes: 18 additions & 0 deletions bin/configs/spring-http-interface-bean-validation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
generatorName: spring
library: spring-http-interface
outputDir: samples/client/petstore/spring-http-interface-bean-validation
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:
artifactId: spring-http-interface
snapshotVersion: "true"
hideGenerationTimestamp: "true"
modelNameSuffix: 'Dto'
generatedConstructorWithRequiredArgs: "false"
# validation should be respected
useBeanValidation: "true"
# documentation provider should be ignored
documentationProvider: "springdoc"
# annotation provider should be ignored
annotationLibrary: "swagger2"
useSpringBoot3: "true"
5 changes: 2 additions & 3 deletions bin/configs/spring-http-interface-noResponseEntity.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ additionalProperties:
documentationProvider: "springdoc"
# annotation provider should be ignored
annotationLibrary: "swagger2"
# validation should be ignored
useBeanValidation: "true"
performBeanValidation: "true"
# useBeanValidation should default to "false" when not specified
# performBeanValidation should default to "false" when not specified
useResponseEntity: "false"
useSpringBoot3: "true"
17 changes: 17 additions & 0 deletions bin/configs/spring-http-interface-reactive-bean-validation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
generatorName: spring
library: spring-http-interface
outputDir: samples/client/petstore/spring-http-interface-reactive-bean-validation
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:
artifactId: spring-http-interface-reactive
snapshotVersion: "true"
hideGenerationTimestamp: "true"
reactive: "true"
# validation should be respected
useBeanValidation: "true"
# documentation provider should be ignored
documentationProvider: "springfox"
# annotation provider should be ignored
annotationLibrary: "swagger1"
useSpringBoot3: "true"
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ additionalProperties:
documentationProvider: "springdoc"
# annotation provider should be ignored
annotationLibrary: "swagger1"
# validation should be ignored
useBeanValidation: "true"
performBeanValidation: "true"
# useBeanValidation should default to "false" when not specified
# performBeanValidation should default to "false" when not specified
useResponseEntity: "false"
useSpringBoot3: "true"

5 changes: 2 additions & 3 deletions bin/configs/spring-http-interface-reactive.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ additionalProperties:
documentationProvider: "springdoc"
# annotation provider should be ignored
annotationLibrary: "swagger1"
# validation should be ignored
useBeanValidation: "true"
performBeanValidation: "true"
# useBeanValidation should default to "false" when not specified
# performBeanValidation should default to "false" when not specified
useSpringBoot3: "true"

1 change: 0 additions & 1 deletion bin/configs/spring-http-interface-springboot-4.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ additionalProperties:
documentationProvider: "springdoc"
# annotation provider should be ignored
annotationLibrary: "swagger2"
# validation should be ignored
useBeanValidation: "true"
performBeanValidation: "true"
useSpringBoot4: "true"
Expand Down
5 changes: 2 additions & 3 deletions bin/configs/spring-http-interface.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ additionalProperties:
documentationProvider: "springdoc"
# annotation provider should be ignored
annotationLibrary: "swagger2"
# validation should be ignored
useBeanValidation: "true"
performBeanValidation: "true"
# useBeanValidation should default to "false" when not specified
# performBeanValidation should default to "false" when not specified
useSpringBoot3: "true"
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,18 @@ public void processOpts() {
documentationProvider = DocumentationProvider.NONE;
annotationLibrary = AnnotationLibrary.NONE;
useJakartaEe = true;
useBeanValidation = false;
performBeanValidation = false;
if(additionalProperties.containsKey(USE_BEANVALIDATION)) {
useBeanValidation = convertPropertyToBoolean(USE_BEANVALIDATION);
} else {
//default to false if not specified
useBeanValidation = false;
}
if(additionalProperties.containsKey(PERFORM_BEANVALIDATION)) {
performBeanValidation = convertPropertyToBoolean(PERFORM_BEANVALIDATION);
} else {
//default to false if not specified
performBeanValidation = false;
}

additionalProperties.put(USE_JAKARTA_EE, useJakartaEe);
additionalProperties.put(USE_BEANVALIDATION, useBeanValidation);
Expand All @@ -486,8 +496,7 @@ public void processOpts() {

applyJakartaPackage();

LOGGER.warn("For Spring HTTP Interface following options are disabled: documentProvider, annotationLibrary, useBeanValidation, performBeanValidation. "
+ "useJakartaEe defaulted to 'true'");
LOGGER.warn("For Spring HTTP Interface following options are disabled: documentProvider, annotationLibrary. useJakartaEe defaulted to 'true'. useBeanValidation and performBeanValidation are supported.");
}

// clear model and api doc template as this codegen
Expand Down Expand Up @@ -692,7 +701,6 @@ public void processOpts() {

supportingFiles.add(new SupportingFile(httpInterfacesAbstractConfiguratorFile,
(sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "HttpInterfacesAbstractConfigurator.java"));
writePropertyBack(USE_BEANVALIDATION, false);

writePropertyBack(HTTP_INTERFACES_CONFIGURATOR_DEPENDENCY,
useHttpServiceProxyFactoryInterfacesConfigurator ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.service.annotation.*;
import org.springframework.web.multipart.MultipartFile;
{{#useBeanValidation}}
import {{javaxPackage}}.validation.Valid;
import {{javaxPackage}}.validation.constraints.*;
{{^useSpringBuiltInValidation}}import org.springframework.validation.annotation.Validated;{{/useSpringBuiltInValidation}}
{{/useBeanValidation}}
{{#reactive}}

import org.springframework.http.codec.multipart.Part;
Expand All @@ -29,6 +34,7 @@ import java.util.Optional;
import {{javaxPackage}}.annotation.Generated;


{{#useBeanValidation}}{{^useSpringBuiltInValidation}}@Validated{{/useSpringBuiltInValidation}}{{/useBeanValidation}}
{{>generatedAnnotation}}

{{#operations}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@
<optional>true</optional>
</dependency>
{{/lombok}}
{{#useBeanValidation}}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
{{/useBeanValidation}}
{{^useBeanValidation}}{{#performBeanValidation}}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
{{/performBeanValidation}}{{/useBeanValidation}}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@
<optional>true</optional>
</dependency>
{{/lombok}}
{{#useBeanValidation}}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
{{/useBeanValidation}}
{{^useBeanValidation}}{{#performBeanValidation}}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
{{/performBeanValidation}}{{/useBeanValidation}}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-{{#reactive}}web{{/reactive}}{{^reactive}}rest{{/reactive}}client-test</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ public {{>sealed}}class {{classname}}{{#parent}} extends {{{parent}}}{{/parent}}
@Deprecated
{{/deprecated}}
{{#isContainer}}
{{#useBeanValidation}}@Valid{{/useBeanValidation}}
{{#openApiNullable}}
private {{>nullableAnnotation}}{{#isNullable}}{{>nullableDataTypeBeanValidation}} {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined();{{/isNullable}}{{^required}}{{^isNullable}}{{>nullableDataTypeBeanValidation}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};{{/isNullable}}{{/required}}{{#required}}{{^isNullable}}{{>nullableDataTypeBeanValidation}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};{{/isNullable}}{{/required}}
{{/openApiNullable}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<!-- Bean Validation implementation (server-side execution) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>{{/useBeanValidation}}
<dependency>
<groupId>jakarta.annotation</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<!-- Bean Validation implementation (server-side execution) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>{{/useBeanValidation}}
<dependency>
<groupId>jakarta.annotation</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6694,6 +6694,129 @@ public void shouldNotHaveDocumentationAnnotationWhenUsingLibrarySpringHttpInterf
.assertMethod("addPet").assertParameter("pet").assertParameterAnnotations().doesNotContainWithName("Parameter");
}

@Test
public void testSpringHttpInterfaceUseBeanValidationRespected() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');

final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/petstore-echo.yaml");
final SpringCodegen codegen = new SpringCodegen();
codegen.setOpenAPI(openAPI);
codegen.setOutputDir(output.getAbsolutePath());
codegen.setLibrary(SPRING_HTTP_INTERFACE);
codegen.setUseSpringBoot3(true);
codegen.additionalProperties().put(BeanValidationFeatures.USE_BEANVALIDATION, "true");

ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);

DefaultGenerator generator = new DefaultGenerator();
generator.setGenerateMetadata(false);

generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));

JavaFileAssert.assertThat(Paths.get(outputPath + "/src/main/java/org/openapitools/api/StoreApi.java"))
.hasImports("jakarta.validation.Valid")
.hasImports("jakarta.validation.constraints")
.assertTypeAnnotations().containsWithName("Validated");
}

@Test
public void testSpringHttpInterfaceUseBeanValidationFalseHasNoValidationAnnotations() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');

final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/petstore-echo.yaml");
final SpringCodegen codegen = new SpringCodegen();
codegen.setOpenAPI(openAPI);
codegen.setOutputDir(output.getAbsolutePath());
codegen.setLibrary(SPRING_HTTP_INTERFACE);
codegen.setUseSpringBoot3(true);
codegen.additionalProperties().put(BeanValidationFeatures.USE_BEANVALIDATION, "false");

ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);

DefaultGenerator generator = new DefaultGenerator();
generator.setGenerateMetadata(false);

generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));

JavaFileAssert.assertThat(Paths.get(outputPath + "/src/main/java/org/openapitools/api/StoreApi.java"))
.hasNoImports("jakarta.validation.Valid")
.hasNoImports("jakarta.validation.constraints")
.assertTypeAnnotations().doesNotContainWithName("Validated");
}

@Test
public void testSpringHttpInterfaceUseBeanValidationDefaultsToFalse() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');

final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/petstore-echo.yaml");
final SpringCodegen codegen = new SpringCodegen();
codegen.setOpenAPI(openAPI);
codegen.setOutputDir(output.getAbsolutePath());
codegen.setLibrary(SPRING_HTTP_INTERFACE);
codegen.setUseSpringBoot3(true);
// useBeanValidation not set — should default to false

ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);

DefaultGenerator generator = new DefaultGenerator();
generator.setGenerateMetadata(false);

generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));

JavaFileAssert.assertThat(Paths.get(outputPath + "/src/main/java/org/openapitools/api/StoreApi.java"))
.hasNoImports("jakarta.validation.Valid")
.hasNoImports("jakarta.validation.constraints")
.assertTypeAnnotations().doesNotContainWithName("Validated");
}

@Test
public void testSpringHttpInterfaceConstraintAnnotationsOnParams() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');

final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/petstore-echo.yaml");
final SpringCodegen codegen = new SpringCodegen();
codegen.setOpenAPI(openAPI);
codegen.setOutputDir(output.getAbsolutePath());
codegen.setLibrary(SPRING_HTTP_INTERFACE);
codegen.setUseSpringBoot3(true);
codegen.additionalProperties().put(BeanValidationFeatures.USE_BEANVALIDATION, "true");

ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);

DefaultGenerator generator = new DefaultGenerator();
generator.setGenerateMetadata(false);

generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));

// getOrderById has minimum:1 and maximum:5 on orderId path param
JavaFileAssert.assertThat(Paths.get(outputPath + "/src/main/java/org/openapitools/api/StoreApi.java"))
.assertMethod("getOrderById")
.assertParameter("orderId")
.assertParameterAnnotations()
.containsWithName("Min")
.containsWithName("Max");
}

@DataProvider(name = "jspecifyLibraries")
public Object[][] jspecifyLibraries() {
return new Object[][]{
Expand Down
Loading
Loading