diff --git a/docs/generators/java-camel.md b/docs/generators/java-camel.md index c17f9e2620a..9b1c3c37162 100644 --- a/docs/generators/java-camel.md +++ b/docs/generators/java-camel.md @@ -58,6 +58,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|
**false**
No changes to the enum's are made, this is the default option.
**true**
With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.
|false| |generateBuilders|Whether to generate builders for models| |false| |generateConstructorWithAllArgs|whether to generate a constructor for all arguments| |false| +|generateGenericResponseEntity|Use a generic type for the `ResponseEntity` wrapping return values of generated API methods. If enabled, method are generated with return type ResponseEntity<?>| |false| |generatedConstructorWithRequiredArgs|Whether to generate constructors with required args for models| |true| |groupId|groupId in generated pom.xml| |org.openapitools| |hateoas|Use Spring HATEOAS library to allow adding HATEOAS links| |false| diff --git a/docs/generators/spring.md b/docs/generators/spring.md index 11081f66121..54d0433256e 100644 --- a/docs/generators/spring.md +++ b/docs/generators/spring.md @@ -51,6 +51,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|
**false**
No changes to the enum's are made, this is the default option.
**true**
With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.
|false| |generateBuilders|Whether to generate builders for models| |false| |generateConstructorWithAllArgs|whether to generate a constructor for all arguments| |false| +|generateGenericResponseEntity|Use a generic type for the `ResponseEntity` wrapping return values of generated API methods. If enabled, method are generated with return type ResponseEntity<?>| |false| |generatedConstructorWithRequiredArgs|Whether to generate constructors with required args for models| |true| |groupId|groupId in generated pom.xml| |org.openapitools| |hateoas|Use Spring HATEOAS library to allow adding HATEOAS links| |false| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java index 4d1f9438f05..621c91bfa84 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java @@ -90,6 +90,7 @@ public class SpringCodegen extends AbstractJavaCodegen public static final String RETURN_SUCCESS_CODE = "returnSuccessCode"; public static final String UNHANDLED_EXCEPTION_HANDLING = "unhandledException"; public static final String USE_RESPONSE_ENTITY = "useResponseEntity"; + 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 REQUEST_MAPPING_OPTION = "requestMappingMode"; @@ -147,6 +148,7 @@ public class SpringCodegen extends AbstractJavaCodegen @Setter protected boolean useSpringController = false; protected boolean useSwaggerUI = true; @Setter protected boolean useResponseEntity = true; + @Setter protected boolean generateGenericResponseEntity = false; @Setter protected boolean useEnumCaseInsensitive = false; @Getter @Setter protected boolean useSpringBoot3 = false; @@ -256,6 +258,10 @@ public class SpringCodegen extends AbstractJavaCodegen "Use the `ResponseEntity` type to wrap return values of generated API methods. " + "If disabled, method are annotated using a `@ResponseStatus` annotation, which has the status of the first response declared in the Api definition", useResponseEntity)); + cliOptions.add(CliOption.newBoolean(GENERATE_GENERIC_RESPONSE_ENTITY, + "Use a generic type for the `ResponseEntity` wrapping return values of generated API methods. " + + "If enabled, method are generated with return type ResponseEntity", + generateGenericResponseEntity)); cliOptions.add(CliOption.newBoolean(USE_ENUM_CASE_INSENSITIVE, "Use `equalsIgnoreCase` when String for enum comparison", useEnumCaseInsensitive)); @@ -433,6 +439,11 @@ public class SpringCodegen extends AbstractJavaCodegen convertPropertyToBooleanAndWriteBack(UNHANDLED_EXCEPTION_HANDLING, this::setUnhandledException); convertPropertyToBooleanAndWriteBack(USE_RESPONSE_ENTITY, this::setUseResponseEntity); + convertPropertyToBooleanAndWriteBack(GENERATE_GENERIC_RESPONSE_ENTITY, this::setGenerateGenericResponseEntity); + if (!useResponseEntity) { + this.setGenerateGenericResponseEntity(false); + this.additionalProperties.put(GENERATE_GENERIC_RESPONSE_ENTITY, false); + } convertPropertyToBooleanAndWriteBack(OPTIONAL_ACCEPT_NULLABLE, this::setOptionalAcceptNullable); convertPropertyToBooleanAndWriteBack(USE_SPRING_BUILT_IN_VALIDATION, this::setUseSpringBuiltInValidation); diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/returnTypes.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/returnTypes.mustache index 70bad00b884..757696365ae 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/returnTypes.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/returnTypes.mustache @@ -1 +1 @@ -{{#isMap}}Map{{/isMap}}{{#isArray}}{{#reactive}}{{{returnType}}}{{/reactive}}{{^reactive}}{{{returnContainer}}}<{{{returnType}}}>{{/reactive}}{{/isArray}}{{^returnContainer}}{{#useResponseEntity}}{{{returnType}}}{{/useResponseEntity}}{{^useResponseEntity}}{{#isDelegate}}{{#isVoid}}{{#responseWrapper}}{{{returnType}}}{{/responseWrapper}}{{^responseWrapper}}void{{/responseWrapper}}{{/isVoid}}{{^isVoid}}{{{returnType}}}{{/isVoid}}{{/isDelegate}}{{^isDelegate}}{{#async}}{{{returnType}}}{{/async}}{{^async}}{{#isVoid}}{{#responseWrapper}}{{{returnType}}}{{/responseWrapper}}{{^responseWrapper}}void{{/responseWrapper}}{{/isVoid}}{{^isVoid}}{{{returnType}}}{{/isVoid}}{{/async}}{{/isDelegate}}{{/useResponseEntity}}{{/returnContainer}} \ No newline at end of file +{{#isMap}}Map{{/isMap}}{{#isArray}}{{#reactive}}{{{returnType}}}{{/reactive}}{{^reactive}}{{#generateGenericResponseEntity}}?{{/generateGenericResponseEntity}}{{^generateGenericResponseEntity}}{{{returnContainer}}}<{{{returnType}}}>{{/generateGenericResponseEntity}}{{/reactive}}{{/isArray}}{{^returnContainer}}{{#useResponseEntity}}{{#generateGenericResponseEntity}}?{{/generateGenericResponseEntity}}{{^generateGenericResponseEntity}}{{{returnType}}}{{/generateGenericResponseEntity}}{{/useResponseEntity}}{{^useResponseEntity}}{{#isDelegate}}{{#isVoid}}{{#responseWrapper}}{{{returnType}}}{{/responseWrapper}}{{^responseWrapper}}void{{/responseWrapper}}{{/isVoid}}{{^isVoid}}{{{returnType}}}{{/isVoid}}{{/isDelegate}}{{^isDelegate}}{{#async}}{{{returnType}}}{{/async}}{{^async}}{{#isVoid}}{{#responseWrapper}}{{{returnType}}}{{/responseWrapper}}{{^responseWrapper}}void{{/responseWrapper}}{{/isVoid}}{{^isVoid}}{{{returnType}}}{{/isVoid}}{{/async}}{{/isDelegate}}{{/useResponseEntity}}{{/returnContainer}} \ No newline at end of file diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java index 30a7c092d8c..f0992bf3657 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java @@ -5532,4 +5532,42 @@ public class SpringCodegenTest { .fileContains("private @Nullable List stringList;") .fileContains("private List stringRequiredList = new ArrayList<>();"); } + + @Test + public void testGenericReturnTypeWhenUsingResponseEntity_issue1096() throws IOException { + Map additionalProperties = new HashMap<>(); + additionalProperties.put(SpringCodegen.USE_RESPONSE_ENTITY, "true"); + additionalProperties.put(SpringCodegen.GENERATE_GENERIC_RESPONSE_ENTITY, "true"); + additionalProperties.put(SpringCodegen.USE_SPRING_BOOT3, "true"); + additionalProperties.put(CodegenConstants.MODEL_TESTS, "false"); + additionalProperties.put(CodegenConstants.MODEL_DOCS, "false"); + additionalProperties.put(CodegenConstants.APIS, "true"); + additionalProperties.put(CodegenConstants.SUPPORTING_FILES, "false"); + + Map files = generateFromContract("src/test/resources/3_0/petstore.yaml", SPRING_BOOT, additionalProperties); + + JavaFileAssert.assertThat(files.get("PetApi.java")) + .assertMethod("getPetById").hasReturnType("ResponseEntity") + .toFileAssert() + .assertMethod("findPetsByStatus").hasReturnType("ResponseEntity"); + } + + @Test + public void testGenericReturnTypeWhenNotUsingResponseEntity_issue1096() throws IOException { + Map additionalProperties = new HashMap<>(); + additionalProperties.put(SpringCodegen.USE_RESPONSE_ENTITY, "false"); + additionalProperties.put(SpringCodegen.GENERATE_GENERIC_RESPONSE_ENTITY, "true"); + additionalProperties.put(SpringCodegen.USE_SPRING_BOOT3, "true"); + additionalProperties.put(CodegenConstants.MODEL_TESTS, "false"); + additionalProperties.put(CodegenConstants.MODEL_DOCS, "false"); + additionalProperties.put(CodegenConstants.APIS, "true"); + additionalProperties.put(CodegenConstants.SUPPORTING_FILES, "false"); + + Map files = generateFromContract("src/test/resources/3_0/petstore.yaml", SPRING_BOOT, additionalProperties); + + JavaFileAssert.assertThat(files.get("PetApi.java")) + .assertMethod("getPetById").hasReturnType("Pet") + .toFileAssert() + .assertMethod("findPetsByStatus").hasReturnType("List"); + } }