diff --git a/.github/workflows/samples-spring.yaml b/.github/workflows/samples-spring.yaml
index 0ba66f74a5ea..9c7760d8cac2 100644
--- a/.github/workflows/samples-spring.yaml
+++ b/.github/workflows/samples-spring.yaml
@@ -26,6 +26,7 @@ jobs:
- samples/openapi3/client/petstore/spring-stubs-skip-default-interface
- samples/openapi3/client/petstore/spring-cloud-async
- samples/openapi3/client/petstore/spring-cloud-spring-pageable
+ - samples/openapi3/client/petstore/spring-cloud-3-with-optional.yaml
# servers
- samples/server/petstore/springboot
- samples/openapi3/server/petstore/springboot
diff --git a/bin/configs/spring-cloud-3-with-optional.yaml b/bin/configs/spring-cloud-3-with-optional.yaml
new file mode 100644
index 000000000000..d9b875f072d3
--- /dev/null
+++ b/bin/configs/spring-cloud-3-with-optional.yaml
@@ -0,0 +1,14 @@
+generatorName: spring
+library: spring-cloud
+outputDir: samples/openapi3/client/petstore/spring-cloud-3-with-optional
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
+templateDir: modules/openapi-generator/src/main/resources/JavaSpring
+additionalProperties:
+ groupId: org.openapitools.openapi3
+ artifactId: spring-cloud-oas3
+ useSpringBoot3: "true"
+ dateLibrary: "java8"
+ useOptional: "true"
+ useSwaggerUI: "false"
+ hideGenerationTimestamp: "true"
+ documentationProvider: none
diff --git a/bin/configs/spring-cloud-3.yaml b/bin/configs/spring-cloud-3.yaml
index 392f43895371..18e3797f0ca3 100644
--- a/bin/configs/spring-cloud-3.yaml
+++ b/bin/configs/spring-cloud-3.yaml
@@ -8,6 +8,6 @@ additionalProperties:
documentationProvider: springdoc
artifactId: spring-cloud-oas3
useSpringBoot3: "true"
- interfaceOnly: "true"
+ interfaceOnly: "false"
singleContentTypes: "true"
hideGenerationTimestamp: "true"
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache
index a356d1fe059e..6eb263c20b9c 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache
@@ -21,7 +21,12 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
{{#authMethods}}
{{#isOAuth}}
+{{#useSpringBoot3}}
+import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor;
+{{/useSpringBoot3}}
+{{^useSpringBoot3}}
import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor;
+{{/useSpringBoot3}}
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
{{#isApplication}}
diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator-ignore b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator-ignore
new file mode 100644
index 000000000000..7484ee590a38
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator/FILES b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator/FILES
new file mode 100644
index 000000000000..3510d2b2d276
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator/FILES
@@ -0,0 +1,16 @@
+README.md
+pom.xml
+src/main/java/org/openapitools/api/PetApi.java
+src/main/java/org/openapitools/api/PetApiClient.java
+src/main/java/org/openapitools/api/StoreApi.java
+src/main/java/org/openapitools/api/StoreApiClient.java
+src/main/java/org/openapitools/api/UserApi.java
+src/main/java/org/openapitools/api/UserApiClient.java
+src/main/java/org/openapitools/configuration/ApiKeyRequestInterceptor.java
+src/main/java/org/openapitools/configuration/ClientConfiguration.java
+src/main/java/org/openapitools/model/Category.java
+src/main/java/org/openapitools/model/ModelApiResponse.java
+src/main/java/org/openapitools/model/Order.java
+src/main/java/org/openapitools/model/Pet.java
+src/main/java/org/openapitools/model/Tag.java
+src/main/java/org/openapitools/model/User.java
diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator/VERSION b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator/VERSION
new file mode 100644
index 000000000000..757e67400401
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator/VERSION
@@ -0,0 +1 @@
+7.0.0-SNAPSHOT
\ No newline at end of file
diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/README.md b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/README.md
new file mode 100644
index 000000000000..417d91840cb4
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/README.md
@@ -0,0 +1,53 @@
+# spring-cloud-oas3
+
+## Requirements
+
+Building the API client library requires [Maven](https://maven.apache.org/) to be installed.
+
+## Installation
+
+To install the API client library to your local Maven repository, simply execute:
+
+```shell
+mvn install
+```
+
+To deploy it to a remote Maven repository instead, configure the settings of the repository and execute:
+
+```shell
+mvn deploy
+```
+
+Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information.
+
+### Maven users
+
+Add this dependency to your project's POM:
+
+```xml
+
+ org.openapitools.openapi3
+ spring-cloud-oas3
+ 1.0.0
+ compile
+
+```
+
+### Gradle users
+
+Add this dependency to your project's build file:
+
+```groovy
+compile "org.openapitools.openapi3:spring-cloud-oas3:1.0.0"
+```
+
+### Others
+
+At first generate the JAR by executing:
+
+mvn package
+
+Then manually install the following JARs:
+
+* target/spring-cloud-oas3-1.0.0.jar
+* target/lib/*.jar
diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/pom.xml b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/pom.xml
new file mode 100644
index 000000000000..ae5724e75e82
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/pom.xml
@@ -0,0 +1,84 @@
+
+ 4.0.0
+ org.openapitools.openapi3
+ spring-cloud-oas3
+ jar
+ spring-cloud-oas3
+ 1.0.0
+
+ 1.8
+ ${java.version}
+ ${java.version}
+ UTF-8
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.0.0
+
+
+
+
+
+ repository.spring.milestone
+ Spring Milestone Repository
+ https://repo.spring.io/milestone
+
+
+
+
+ src/main/java
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-parent
+ 2022.0.0
+ pom
+ import
+
+
+
+
+
+
+
+ com.google.code.findbugs
+ jsr305
+ 3.0.2
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+ org.springframework.cloud
+ spring-cloud-starter-oauth2
+ 2.2.5.RELEASE
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+ org.openapitools
+ jackson-databind-nullable
+ 0.2.6
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.springframework.data
+ spring-data-commons
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/PetApi.java b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/PetApi.java
new file mode 100644
index 000000000000..b1b1de4bc655
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/PetApi.java
@@ -0,0 +1,188 @@
+/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.0.0-SNAPSHOT).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.api;
+
+import org.openapitools.model.ModelApiResponse;
+import org.openapitools.model.Pet;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.multipart.MultipartFile;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import jakarta.annotation.Generated;
+
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+@Validated
+public interface PetApi {
+
+ /**
+ * POST /pet : Add a new pet to the store
+ *
+ *
+ * @param pet Pet object that needs to be added to the store (required)
+ * @return successful operation (status code 200)
+ * or Invalid input (status code 405)
+ */
+ @RequestMapping(
+ method = RequestMethod.POST,
+ value = "/pet",
+ produces = "application/json",
+ consumes = "application/json"
+ )
+ ResponseEntity addPet(
+ @Valid @RequestBody Pet pet
+ );
+
+
+ /**
+ * DELETE /pet/{petId} : Deletes a pet
+ *
+ *
+ * @param petId Pet id to delete (required)
+ * @param apiKey (optional)
+ * @return Invalid pet value (status code 400)
+ */
+ @RequestMapping(
+ method = RequestMethod.DELETE,
+ value = "/pet/{petId}"
+ )
+ ResponseEntity deletePet(
+ @PathVariable("petId") Long petId,
+ @RequestHeader(value = "api_key", required = false) Optional apiKey
+ );
+
+
+ /**
+ * GET /pet/findByStatus : Finds Pets by status
+ * Multiple status values can be provided with comma separated strings
+ *
+ * @param status Status values that need to be considered for filter (required)
+ * @return successful operation (status code 200)
+ * or Invalid status value (status code 400)
+ */
+ @RequestMapping(
+ method = RequestMethod.GET,
+ value = "/pet/findByStatus",
+ produces = "application/json"
+ )
+ ResponseEntity> findPetsByStatus(
+ @NotNull @Valid @RequestParam(value = "status", required = true) List status
+ );
+
+
+ /**
+ * GET /pet/findByTags : Finds Pets by tags
+ * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
+ *
+ * @param tags Tags to filter by (required)
+ * @return successful operation (status code 200)
+ * or Invalid tag value (status code 400)
+ * @deprecated
+ */
+ @Deprecated
+ @RequestMapping(
+ method = RequestMethod.GET,
+ value = "/pet/findByTags",
+ produces = "application/json"
+ )
+ ResponseEntity> findPetsByTags(
+ @NotNull @Valid @RequestParam(value = "tags", required = true) List tags
+ );
+
+
+ /**
+ * GET /pet/{petId} : Find pet by ID
+ * Returns a single pet
+ *
+ * @param petId ID of pet to return (required)
+ * @return successful operation (status code 200)
+ * or Invalid ID supplied (status code 400)
+ * or Pet not found (status code 404)
+ */
+ @RequestMapping(
+ method = RequestMethod.GET,
+ value = "/pet/{petId}",
+ produces = "application/json"
+ )
+ ResponseEntity getPetById(
+ @PathVariable("petId") Long petId
+ );
+
+
+ /**
+ * PUT /pet : Update an existing pet
+ *
+ *
+ * @param pet Pet object that needs to be added to the store (required)
+ * @return successful operation (status code 200)
+ * or Invalid ID supplied (status code 400)
+ * or Pet not found (status code 404)
+ * or Validation exception (status code 405)
+ * API documentation for the updatePet operation
+ * @see Update an existing pet Documentation
+ */
+ @RequestMapping(
+ method = RequestMethod.PUT,
+ value = "/pet",
+ produces = "application/json",
+ consumes = "application/json"
+ )
+ ResponseEntity updatePet(
+ @Valid @RequestBody Pet pet
+ );
+
+
+ /**
+ * POST /pet/{petId} : Updates a pet in the store with form data
+ *
+ *
+ * @param petId ID of pet that needs to be updated (required)
+ * @param name Updated name of the pet (optional)
+ * @param status Updated status of the pet (optional)
+ * @return Invalid input (status code 405)
+ */
+ @RequestMapping(
+ method = RequestMethod.POST,
+ value = "/pet/{petId}",
+ consumes = "application/x-www-form-urlencoded"
+ )
+ ResponseEntity updatePetWithForm(
+ @PathVariable("petId") Long petId,
+ @Valid @RequestParam(value = "name", required = false) String name,
+ @Valid @RequestParam(value = "status", required = false) String status
+ );
+
+
+ /**
+ * POST /pet/{petId}/uploadImage : uploads an image
+ *
+ *
+ * @param petId ID of pet to update (required)
+ * @param additionalMetadata Additional data to pass to server (optional)
+ * @param file file to upload (optional)
+ * @return successful operation (status code 200)
+ */
+ @RequestMapping(
+ method = RequestMethod.POST,
+ value = "/pet/{petId}/uploadImage",
+ produces = "application/json",
+ consumes = "multipart/form-data"
+ )
+ ResponseEntity uploadFile(
+ @PathVariable("petId") Long petId,
+ @Valid @RequestParam(value = "additionalMetadata", required = false) String additionalMetadata,
+ @RequestPart(value = "file", required = false) MultipartFile file
+ );
+
+}
diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/PetApiClient.java b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/PetApiClient.java
new file mode 100644
index 000000000000..f80fe4ddc678
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/PetApiClient.java
@@ -0,0 +1,8 @@
+package org.openapitools.api;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.openapitools.configuration.ClientConfiguration;
+
+@FeignClient(name="${pet.name:pet}", url="${pet.url:http://petstore.swagger.io/v2}", configuration = ClientConfiguration.class)
+public interface PetApiClient extends PetApi {
+}
diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/StoreApi.java b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/StoreApi.java
new file mode 100644
index 000000000000..0eea3379c77a
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/StoreApi.java
@@ -0,0 +1,99 @@
+/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.0.0-SNAPSHOT).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.api;
+
+import java.util.Map;
+import org.openapitools.model.Order;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.multipart.MultipartFile;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import jakarta.annotation.Generated;
+
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+@Validated
+public interface StoreApi {
+
+ /**
+ * DELETE /store/order/{orderId} : Delete purchase order by ID
+ * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
+ *
+ * @param orderId ID of the order that needs to be deleted (required)
+ * @return Invalid ID supplied (status code 400)
+ * or Order not found (status code 404)
+ */
+ @RequestMapping(
+ method = RequestMethod.DELETE,
+ value = "/store/order/{orderId}"
+ )
+ ResponseEntity deleteOrder(
+ @PathVariable("orderId") String orderId
+ );
+
+
+ /**
+ * GET /store/inventory : Returns pet inventories by status
+ * Returns a map of status codes to quantities
+ *
+ * @return successful operation (status code 200)
+ */
+ @RequestMapping(
+ method = RequestMethod.GET,
+ value = "/store/inventory",
+ produces = "application/json"
+ )
+ ResponseEntity