From 6ff7f5b3c380189f5bdd0294a88838454d9e2ebb Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 06:54:39 +0200
Subject: [PATCH 01/18] Migrate annotation.Generated

---
 .../src/main/resources/JavaSpring/api.mustache        | 11 +++++++++++
 .../main/resources/JavaSpring/apiController.mustache  | 11 +++++++++++
 .../main/resources/JavaSpring/apiDelegate.mustache    |  5 +++++
 .../main/resources/JavaSpring/apiException.mustache   |  5 +++++
 .../resources/JavaSpring/apiOriginFilter.mustache     |  5 +++++
 .../resources/JavaSpring/apiResponseMessage.mustache  |  5 +++++
 .../src/main/resources/JavaSpring/model.mustache      |  5 +++++
 .../resources/JavaSpring/notFoundException.mustache   |  5 +++++
 .../JavaSpring/openapiDocumentationConfig.mustache    |  4 +++-
 9 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache
index a4beae55b51..4eedc52fa6b 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache
@@ -50,8 +50,14 @@ import org.springframework.http.codec.multipart.Part;
 {{/reactive}}
 
 {{#useBeanValidation}}
+{{#jakartaee}}
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.validation.Valid;
 import javax.validation.constraints.*;
+{{/jakartaee}}
 {{/useBeanValidation}}
 import java.util.List;
 import java.util.Map;
@@ -66,7 +72,12 @@ import java.util.Optional;
 {{#async}}
 import java.util.concurrent.CompletableFuture;
 {{/async}}
+{{#jakartaee}}
+import jakarta.annotation.Generated;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.annotation.Generated;
+{{/jakartaee}}
 
 {{>generatedAnnotation}}
 {{#useBeanValidation}}
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache
index dc64a84fe9e..87d4efe6f28 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache
@@ -36,14 +36,25 @@ import org.springframework.web.context.request.NativeWebRequest;
 {{/isDelegate}}
 
 {{#useBeanValidation}}
+{{#jakartaee}}
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.validation.constraints.*;
 import javax.validation.Valid;
+{{/jakartaee}}
 {{/useBeanValidation}}
 
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+{{#jakartaee}}
+import jakarta.annotation.Generated;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.annotation.Generated;
+{{/jakartaee}}
 
 {{>generatedAnnotation}}
 @Controller
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache
index de880d27c7a..79707c7303e 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache
@@ -20,7 +20,12 @@ import java.util.Optional;
 {{#async}}
 import java.util.concurrent.CompletableFuture;
 {{/async}}
+{{#jakartaee}}
+import jakarta.annotation.Generated;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.annotation.Generated;
+{{/jakartaee}}
 
 {{#operations}}
 /**
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiException.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiException.mustache
index 8230cce7664..658871c2158 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiException.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiException.mustache
@@ -1,6 +1,11 @@
 package {{apiPackage}};
 
+{{#jakartaee}}
+import jakarta.annotation.Generated;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.annotation.Generated;
+{{/jakartaee}}
 
 /**
  * The exception that can be used to store the HTTP status code returned by an API response.
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache
index 9fc5959c49c..4ebe1b81f30 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache
@@ -2,7 +2,12 @@ package {{apiPackage}};
 
 import java.io.IOException;
 
+{{#jakartaee}}
+import jakarta.annotation.Generated;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.annotation.Generated;
+{{/jakartaee}}
 import javax.servlet.*;
 import javax.servlet.http.HttpServletResponse;
 
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiResponseMessage.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiResponseMessage.mustache
index 8faf577c824..7f0af57e135 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiResponseMessage.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiResponseMessage.mustache
@@ -1,6 +1,11 @@
 package {{apiPackage}};
 
+{{#jakartaee}}
+import jakarta.annotation.Generated;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.annotation.Generated;
+{{/jakartaee}}
 import javax.xml.bind.annotation.XmlTransient;
 
 {{>generatedAnnotation}}
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache
index 7a82dabbcba..8ea5263c45f 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache
@@ -38,7 +38,12 @@ import org.springframework.hateoas.RepresentationModel;
 {{/parent}}
 
 import java.util.*;
+{{#jakartaee}}
+import jakarta.annotation.Generated;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.annotation.Generated;
+{{/jakartaee}}
 
 {{#models}}
 {{#model}}
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/notFoundException.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/notFoundException.mustache
index 9eb12cd17f4..57fe42f0586 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/notFoundException.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/notFoundException.mustache
@@ -1,6 +1,11 @@
 package {{apiPackage}};
 
+{{#jakartaee}}
+import jakarta.annotation.Generated;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.annotation.Generated;
+{{/jakartaee}}
 
 {{>generatedAnnotation}}
 public class NotFoundException extends ApiException {
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
index 4885990228c..e7ced209d4c 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
@@ -18,7 +18,9 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
 {{#useOptional}}
 import java.util.Optional;
 {{/useOptional}}
-import javax.annotation.Generated;
+
+import {{#jakartaee}}jakarta{{/jakartaee}}{{^jakartaee}}javax{{/jakartaee}}.annotation.Generated;
+
 import javax.servlet.ServletContext;
 
 {{>generatedAnnotation}}
-- 
GitLab


From cb11c0299305907047a5a557b78ab3546bee830d Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 08:55:47 +0200
Subject: [PATCH 02/18] Upgrade jakarta.servlet and jakarta.validation

---
 .../main/resources/JavaSpring/apiOriginFilter.mustache   | 4 ++--
 .../src/main/resources/JavaSpring/apiUtil.mustache       | 6 ++++++
 .../resources/JavaSpring/beanValidationCore.mustache     | 2 +-
 .../src/main/resources/JavaSpring/model.mustache         | 6 ++++++
 .../JavaSpring/openapiDocumentationConfig.mustache       | 9 +++++++--
 5 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache
index 4ebe1b81f30..ba92c5fe167 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache
@@ -4,12 +4,12 @@ import java.io.IOException;
 
 {{#jakartaee}}
 import jakarta.annotation.Generated;
+import jakarta.servlet.*;
+import jakarta.servlet.http.HttpServletResponse;
 {{/jakartaee}}
 {{^jakartaee}}
 import javax.annotation.Generated;
 {{/jakartaee}}
-import javax.servlet.*;
-import javax.servlet.http.HttpServletResponse;
 
 {{>generatedAnnotation}}
 public class ApiOriginFilter implements javax.servlet.Filter {
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache
index cf72ff100b4..b377f85dd2c 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache
@@ -12,7 +12,13 @@ import reactor.core.publisher.Mono;
 {{^reactive}}
 import org.springframework.web.context.request.NativeWebRequest;
 
+{{#jakartaee}}
+import jakarta.servlet.http.HttpServletResponse;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.servlet.http.HttpServletResponse;
+{{/jakartaee}}
+
 import java.io.IOException;
 {{/reactive}}
 
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/beanValidationCore.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/beanValidationCore.mustache
index 4e75048b371..f8aa5ab2a9a 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/beanValidationCore.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/beanValidationCore.mustache
@@ -12,7 +12,7 @@ minLength not set, maxLength set
 @Size: minItems not set && maxItems set
 }}{{^minItems}}{{#maxItems}}@Size(max = {{.}}) {{/maxItems}}{{/minItems}}{{!
 @Email: useBeanValidation set && isEmail set
-}}{{#useBeanValidation}}{{#isEmail}}@javax.validation.constraints.Email{{/isEmail}}{{/useBeanValidation}}{{!
+}}{{#useBeanValidation}}{{#isEmail}}@Email{{/isEmail}}{{/useBeanValidation}}{{!
 check for integer or long / all others=decimal type with @Decimal*
 isInteger set
 }}{{#isInteger}}{{#minimum}}@Min({{.}}) {{/minimum}}{{#maximum}}@Max({{.}}) {{/maximum}}{{/isInteger}}{{!
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache
index 8ea5263c45f..891de413133 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache
@@ -12,8 +12,14 @@ import java.io.Serializable;
 {{/serializableModel}}
 import java.time.OffsetDateTime;
 {{#useBeanValidation}}
+{{#jakartaee}}
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+{{/jakartaee}}
+{{^jakartaee}}
 import javax.validation.Valid;
 import javax.validation.constraints.*;
+{{/jakartaee}}
 {{/useBeanValidation}}
 {{#performBeanValidation}}
 import org.hibernate.validator.constraints.*;
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
index e7ced209d4c..18d67005e18 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
@@ -19,9 +19,14 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
 import java.util.Optional;
 {{/useOptional}}
 
-import {{#jakartaee}}jakarta{{/jakartaee}}{{^jakartaee}}javax{{/jakartaee}}.annotation.Generated;
-
+{{#jakartaee}}
+import jakarta.annotation.Generated;
+import jakarta.servlet.ServletContext;
+{{/jakartaee}}
+{{^jakartaee}}
+import javax.annotation.Generated;
 import javax.servlet.ServletContext;
+{{/jakartaee}}
 
 {{>generatedAnnotation}}
 @Configuration
-- 
GitLab


From acdb49c908092a6f0e80a7c502e8349cfe613e4e Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 10:25:49 +0200
Subject: [PATCH 03/18] Prepare pom.xml for spring boot 3

---
 .../libraries/spring-boot/pom-sb2.mustache    | 238 ++++++++++++++++++
 .../libraries/spring-boot/pom.mustache        |  35 +--
 2 files changed, 243 insertions(+), 30 deletions(-)
 create mode 100644 modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb2.mustache

diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb2.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb2.mustache
new file mode 100644
index 00000000000..f2dbeac4499
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb2.mustache
@@ -0,0 +1,238 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>{{groupId}}</groupId>
+    <artifactId>{{artifactId}}</artifactId>
+    <packaging>jar</packaging>
+    <name>{{artifactId}}</name>
+    <version>{{artifactVersion}}</version>
+    <properties>
+        <java.version>1.8</java.version>
+        <maven.compiler.source>${java.version}</maven.compiler.source>
+        <maven.compiler.target>${java.version}</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        {{#springFoxDocumentationProvider}}
+        <springfox.version>2.9.2</springfox.version>
+        {{/springFoxDocumentationProvider}}
+        {{#springDocDocumentationProvider}}
+        <springdoc.version>1.6.6</springdoc.version>
+        {{/springDocDocumentationProvider}}
+        {{^springFoxDocumentationProvider}}
+        {{^springDocDocumentationProvider}}
+        {{#swagger1AnnotationLibrary}}
+        <swagger-annotations.version>1.6.5</swagger-annotations.version>
+        {{/swagger1AnnotationLibrary}}
+        {{#swagger2AnnotationLibrary}}
+        <swagger-annotations.version>}2.1.13</swagger-annotations.version>
+        {{/swagger2AnnotationLibrary}}
+        {{/springDocDocumentationProvider}}
+        {{/springFoxDocumentationProvider}}
+        {{#useSwaggerUI}}
+        <swagger-ui.version>4.8.1</swagger-ui.version>
+        {{/useSwaggerUI}}
+    </properties>
+{{#parentOverridden}}
+    <parent>
+        <groupId>{{{parentGroupId}}}</groupId>
+        <artifactId>{{{parentArtifactId}}}</artifactId>
+        <version>{{{parentVersion}}}</version>
+    </parent>
+{{/parentOverridden}}
+{{^parentOverridden}}
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>{{#springFoxDocumentationProvider}}2.5.12{{/springFoxDocumentationProvider}}{{^springFoxDocumentationProvider}}2.6.6{{/springFoxDocumentationProvider}}</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+{{/parentOverridden}}
+    <build>
+        <sourceDirectory>src/main/java</sourceDirectory>
+        {{^interfaceOnly}}
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                {{#classifier}}
+                <configuration>
+                  <classifier>{{{classifier}}}</classifier>
+                </configuration>
+                {{/classifier}}
+            </plugin>
+            {{#apiFirst}}
+            <plugin>
+                <groupId>org.openapitools</groupId>
+                <artifactId>openapi-generator-maven-plugin</artifactId>
+                <version>{{{generatorVersion}}}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                        <configuration>
+                            <inputSpec>src/main/resources/openapi.yaml</inputSpec>
+                            <generatorName>spring</generatorName>
+                            <apiPackage>{{{apiPackage}}}</apiPackage>
+                            <modelPackage>{{{modelPackage}}}</modelPackage>
+                            <generateSupportingFiles>false</generateSupportingFiles>
+                            {{#modelNamePrefix}}
+                            <modelNamePrefix>{{{.}}}</modelNamePrefix>
+                            {{/modelNamePrefix}}
+                            {{#modelNameSuffix}}
+                            <modelNameSuffix>{{{.}}}</modelNameSuffix>
+                            {{/modelNameSuffix}}
+                            <configOptions>
+                            {{#configOptions}}
+                                <{{left}}>{{right}}</{{left}}>
+                            {{/configOptions}}
+                            </configOptions>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            {{/apiFirst}}
+        </plugins>
+        {{/interfaceOnly}}
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web{{#reactive}}flux{{/reactive}}</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-commons</artifactId>
+        </dependency>
+        {{#springDocDocumentationProvider}}
+          <!--SpringDoc dependencies -->
+        {{#useSwaggerUI}}
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-{{#reactive}}webflux-{{/reactive}}ui</artifactId>
+            <version>${springdoc.version}</version>
+        </dependency>
+        {{/useSwaggerUI}}
+        {{^useSwaggerUI}}
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-core</artifactId>
+            <version>${springdoc.version}</version>
+        </dependency>
+        {{/useSwaggerUI}}
+        {{/springDocDocumentationProvider}}
+        {{#springFoxDocumentationProvider}}
+        <!--SpringFox dependencies -->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>${springfox.version}</version>
+        </dependency>
+        {{/springFoxDocumentationProvider}}
+        {{#useSwaggerUI}}
+        {{^springDocDocumentationProvider}}
+        <dependency>
+            <groupId>org.webjars</groupId>
+            <artifactId>swagger-ui</artifactId>
+            <version>${swagger-ui.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.webjars</groupId>
+            <artifactId>webjars-locator-core</artifactId>
+        </dependency>
+        {{/springDocDocumentationProvider}}
+        {{/useSwaggerUI}}
+        {{^springFoxDocumentationProvider}}
+        {{^springDocDocumentationProvider}}
+        {{#swagger1AnnotationLibrary}}
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>${swagger-annotations.version}</version>
+        </dependency>
+        {{/swagger1AnnotationLibrary}}
+        {{#swagger2AnnotationLibrary}}
+        <dependency>
+            <groupId>io.swagger.core.v3</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>${swagger-annotations.version}</version>
+        </dependency>
+        {{/swagger2AnnotationLibrary}}
+        {{/springDocDocumentationProvider}}
+        {{/springFoxDocumentationProvider}}
+        <!-- @Nullable annotation -->
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <version>3.0.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-yaml</artifactId>
+        </dependency>
+        {{#withXml}}
+        <!-- XML processing: Jackson -->
+        <dependency>
+          <groupId>jakarta.xml.bind</groupId>
+          <artifactId>jakarta.xml.bind-api</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>com.fasterxml.jackson.dataformat</groupId>
+          <artifactId>jackson-dataformat-xml</artifactId>
+        </dependency>
+        {{/withXml}}
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
+        {{#joda}}
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-joda</artifactId>
+        </dependency>
+        {{/joda}}
+        {{#openApiNullable}}
+        <dependency>
+            <groupId>org.openapitools</groupId>
+            <artifactId>jackson-databind-nullable</artifactId>
+            <version>0.2.2</version>
+        </dependency>
+        {{/openApiNullable}}
+{{#useBeanValidation}}
+        <!-- Bean Validation API support -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+{{/useBeanValidation}}
+{{#virtualService}}
+    <!-- START Virtual Service API support -->
+        <dependency>
+            <groupId>io.virtualan</groupId>
+            <artifactId>virtualan-plugin</artifactId>
+            <version>2.2.1</version>
+        </dependency>
+        <!-- HyperSQL DB -->
+        <dependency>
+            <groupId>org.hsqldb</groupId>
+            <artifactId>hsqldb</artifactId>
+            <version>2.5.0</version>
+        </dependency>
+    <!-- END Virtual Service API support -->
+{{/virtualService}}
+{{#hateoas}}
+        <!-- Spring HATEOAS -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-hateoas</artifactId>
+        </dependency>
+{{/hateoas}}
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom.mustache
index f2dbeac4499..5da0cd024a4 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom.mustache
@@ -6,26 +6,18 @@
     <name>{{artifactId}}</name>
     <version>{{artifactVersion}}</version>
     <properties>
-        <java.version>1.8</java.version>
+        <java.version>17</java.version>
         <maven.compiler.source>${java.version}</maven.compiler.source>
         <maven.compiler.target>${java.version}</maven.compiler.target>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        {{#springFoxDocumentationProvider}}
-        <springfox.version>2.9.2</springfox.version>
-        {{/springFoxDocumentationProvider}}
         {{#springDocDocumentationProvider}}
-        <springdoc.version>1.6.6</springdoc.version>
+        <springdoc.version>2.0.0-M2</springdoc.version>
         {{/springDocDocumentationProvider}}
-        {{^springFoxDocumentationProvider}}
         {{^springDocDocumentationProvider}}
-        {{#swagger1AnnotationLibrary}}
-        <swagger-annotations.version>1.6.5</swagger-annotations.version>
-        {{/swagger1AnnotationLibrary}}
         {{#swagger2AnnotationLibrary}}
         <swagger-annotations.version>}2.1.13</swagger-annotations.version>
         {{/swagger2AnnotationLibrary}}
         {{/springDocDocumentationProvider}}
-        {{/springFoxDocumentationProvider}}
         {{#useSwaggerUI}}
         <swagger-ui.version>4.8.1</swagger-ui.version>
         {{/useSwaggerUI}}
@@ -41,7 +33,7 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>{{#springFoxDocumentationProvider}}2.5.12{{/springFoxDocumentationProvider}}{{^springFoxDocumentationProvider}}2.6.6{{/springFoxDocumentationProvider}}</version>
+        <version>3.0.0-M2</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
 {{/parentOverridden}}
@@ -107,26 +99,18 @@
         {{#useSwaggerUI}}
         <dependency>
             <groupId>org.springdoc</groupId>
-            <artifactId>springdoc-openapi-{{#reactive}}webflux-{{/reactive}}ui</artifactId>
+            <artifactId>springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-ui</artifactId>
             <version>${springdoc.version}</version>
         </dependency>
         {{/useSwaggerUI}}
         {{^useSwaggerUI}}
         <dependency>
             <groupId>org.springdoc</groupId>
-            <artifactId>springdoc-openapi-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-core</artifactId>
+          <artifactId>springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-api</artifactId>
             <version>${springdoc.version}</version>
         </dependency>
         {{/useSwaggerUI}}
         {{/springDocDocumentationProvider}}
-        {{#springFoxDocumentationProvider}}
-        <!--SpringFox dependencies -->
-        <dependency>
-            <groupId>io.springfox</groupId>
-            <artifactId>springfox-swagger2</artifactId>
-            <version>${springfox.version}</version>
-        </dependency>
-        {{/springFoxDocumentationProvider}}
         {{#useSwaggerUI}}
         {{^springDocDocumentationProvider}}
         <dependency>
@@ -140,15 +124,7 @@
         </dependency>
         {{/springDocDocumentationProvider}}
         {{/useSwaggerUI}}
-        {{^springFoxDocumentationProvider}}
         {{^springDocDocumentationProvider}}
-        {{#swagger1AnnotationLibrary}}
-        <dependency>
-            <groupId>io.swagger</groupId>
-            <artifactId>swagger-annotations</artifactId>
-            <version>${swagger-annotations.version}</version>
-        </dependency>
-        {{/swagger1AnnotationLibrary}}
         {{#swagger2AnnotationLibrary}}
         <dependency>
             <groupId>io.swagger.core.v3</groupId>
@@ -157,7 +133,6 @@
         </dependency>
         {{/swagger2AnnotationLibrary}}
         {{/springDocDocumentationProvider}}
-        {{/springFoxDocumentationProvider}}
         <!-- @Nullable annotation -->
         <dependency>
             <groupId>com.google.code.findbugs</groupId>
-- 
GitLab


From 6a23f753fdc57264a98c1fc588c357bdfc9f96ad Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 10:32:49 +0200
Subject: [PATCH 04/18] Introduce spring-boot-3 sample config.

---
 bin/configs/spring-boot-3.yaml | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 bin/configs/spring-boot-3.yaml

diff --git a/bin/configs/spring-boot-3.yaml b/bin/configs/spring-boot-3.yaml
new file mode 100644
index 00000000000..4fd86ead78a
--- /dev/null
+++ b/bin/configs/spring-boot-3.yaml
@@ -0,0 +1,12 @@
+generatorName: spring
+outputDir: samples/openapi3/server/petstore/springboot-3
+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"
+  jakartaee: true
+  useBeanValidation: true
+  hideGenerationTimestamp: "true"
-- 
GitLab


From 6374471512b0ccef21209071bd450a7cfccceef8 Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 10:33:01 +0200
Subject: [PATCH 05/18] Create spring-boot-3 sample.

---
 .../springboot-3/.openapi-generator-ignore    |  23 +
 .../springboot-3/.openapi-generator/FILES     |  22 +
 .../springboot-3/.openapi-generator/VERSION   |   1 +
 .../server/petstore/springboot-3/README.md    |  21 +
 .../server/petstore/springboot-3/pom.xml      |  80 ++
 .../OpenApiGeneratorApplication.java          |  23 +
 .../org/openapitools/RFC3339DateFormat.java   |  38 +
 .../java/org/openapitools/api/ApiUtil.java    |  20 +
 .../java/org/openapitools/api/PetApi.java     | 414 +++++++++
 .../openapitools/api/PetApiController.java    |  47 +
 .../java/org/openapitools/api/StoreApi.java   | 199 ++++
 .../openapitools/api/StoreApiController.java  |  47 +
 .../java/org/openapitools/api/UserApi.java    | 315 +++++++
 .../openapitools/api/UserApiController.java   |  48 +
 .../configuration/HomeController.java         |  20 +
 .../configuration/SpringDocConfiguration.java |  43 +
 .../java/org/openapitools/model/Category.java | 108 +++
 .../openapitools/model/ModelApiResponse.java  | 134 +++
 .../java/org/openapitools/model/Order.java    | 245 +++++
 .../main/java/org/openapitools/model/Pet.java | 261 ++++++
 .../main/java/org/openapitools/model/Tag.java | 108 +++
 .../java/org/openapitools/model/User.java     | 252 +++++
 .../src/main/resources/application.properties |   3 +
 .../src/main/resources/openapi.yaml           | 877 ++++++++++++++++++
 .../OpenApiGeneratorApplicationTests.java     |  13 +
 25 files changed, 3362 insertions(+)
 create mode 100644 samples/openapi3/server/petstore/springboot-3/.openapi-generator-ignore
 create mode 100644 samples/openapi3/server/petstore/springboot-3/.openapi-generator/FILES
 create mode 100644 samples/openapi3/server/petstore/springboot-3/.openapi-generator/VERSION
 create mode 100644 samples/openapi3/server/petstore/springboot-3/README.md
 create mode 100644 samples/openapi3/server/petstore/springboot-3/pom.xml
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/OpenApiGeneratorApplication.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/RFC3339DateFormat.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/ApiUtil.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/PetApi.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/PetApiController.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/StoreApi.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/StoreApiController.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/UserApi.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/UserApiController.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/configuration/HomeController.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/configuration/SpringDocConfiguration.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Category.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/ModelApiResponse.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Order.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Pet.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Tag.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/User.java
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/resources/application.properties
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/main/resources/openapi.yaml
 create mode 100644 samples/openapi3/server/petstore/springboot-3/src/test/java/org/openapitools/OpenApiGeneratorApplicationTests.java

diff --git a/samples/openapi3/server/petstore/springboot-3/.openapi-generator-ignore b/samples/openapi3/server/petstore/springboot-3/.openapi-generator-ignore
new file mode 100644
index 00000000000..7484ee590a3
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/.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/server/petstore/springboot-3/.openapi-generator/FILES b/samples/openapi3/server/petstore/springboot-3/.openapi-generator/FILES
new file mode 100644
index 00000000000..48cc8196064
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/.openapi-generator/FILES
@@ -0,0 +1,22 @@
+README.md
+pom.xml
+src/main/java/org/openapitools/OpenApiGeneratorApplication.java
+src/main/java/org/openapitools/RFC3339DateFormat.java
+src/main/java/org/openapitools/api/ApiUtil.java
+src/main/java/org/openapitools/api/PetApi.java
+src/main/java/org/openapitools/api/PetApiController.java
+src/main/java/org/openapitools/api/StoreApi.java
+src/main/java/org/openapitools/api/StoreApiController.java
+src/main/java/org/openapitools/api/UserApi.java
+src/main/java/org/openapitools/api/UserApiController.java
+src/main/java/org/openapitools/configuration/HomeController.java
+src/main/java/org/openapitools/configuration/SpringDocConfiguration.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
+src/main/resources/application.properties
+src/main/resources/openapi.yaml
+src/test/java/org/openapitools/OpenApiGeneratorApplicationTests.java
diff --git a/samples/openapi3/server/petstore/springboot-3/.openapi-generator/VERSION b/samples/openapi3/server/petstore/springboot-3/.openapi-generator/VERSION
new file mode 100644
index 00000000000..5f68295fc19
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/.openapi-generator/VERSION
@@ -0,0 +1 @@
+6.0.0-SNAPSHOT
\ No newline at end of file
diff --git a/samples/openapi3/server/petstore/springboot-3/README.md b/samples/openapi3/server/petstore/springboot-3/README.md
new file mode 100644
index 00000000000..5cd22b6081a
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/README.md
@@ -0,0 +1,21 @@
+# OpenAPI generated server
+
+Spring Boot Server
+
+## Overview
+This server was generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
+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.
+
+
+The underlying library integrating OpenAPI to Spring Boot is [springdoc](https://springdoc.org).
+Springdoc will generate an OpenAPI v3 specification based on the generated Controller and Model classes.
+The specification is available to download using the following url:
+http://localhost:8080/v3/api-docs/
+
+Start your server as a simple java application
+
+You can view the api documentation in swagger-ui by pointing to
+http://localhost:8080/swagger-ui.html
+
+Change default port value in application.properties
\ No newline at end of file
diff --git a/samples/openapi3/server/petstore/springboot-3/pom.xml b/samples/openapi3/server/petstore/springboot-3/pom.xml
new file mode 100644
index 00000000000..69a1674165b
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/pom.xml
@@ -0,0 +1,80 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.openapitools.openapi3</groupId>
+    <artifactId>springboot</artifactId>
+    <packaging>jar</packaging>
+    <name>springboot</name>
+    <version>1.0.0-SNAPSHOT</version>
+    <properties>
+        <java.version>17</java.version>
+        <maven.compiler.source>${java.version}</maven.compiler.source>
+        <maven.compiler.target>${java.version}</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <springdoc.version>2.0.0-M2</springdoc.version>
+        <swagger-ui.version>4.8.1</swagger-ui.version>
+    </properties>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>3.0.0-M2</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <build>
+        <sourceDirectory>src/main/java</sourceDirectory>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-commons</artifactId>
+        </dependency>
+          <!--SpringDoc dependencies -->
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
+            <version>${springdoc.version}</version>
+        </dependency>
+        <!-- @Nullable annotation -->
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <version>3.0.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-yaml</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.openapitools</groupId>
+            <artifactId>jackson-databind-nullable</artifactId>
+            <version>0.2.2</version>
+        </dependency>
+        <!-- Bean Validation API support -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/OpenApiGeneratorApplication.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/OpenApiGeneratorApplication.java
new file mode 100644
index 00000000000..f62fd6d9179
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/OpenApiGeneratorApplication.java
@@ -0,0 +1,23 @@
+package org.openapitools;
+
+import com.fasterxml.jackson.databind.Module;
+import org.openapitools.jackson.nullable.JsonNullableModule;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+
+@SpringBootApplication
+@ComponentScan(basePackages = {"org.openapitools", "org.openapitools.api" , "org.openapitools.configuration"})
+public class OpenApiGeneratorApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(OpenApiGeneratorApplication.class, args);
+    }
+
+    @Bean
+    public Module jsonNullableModule() {
+        return new JsonNullableModule();
+    }
+
+}
\ No newline at end of file
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/RFC3339DateFormat.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/RFC3339DateFormat.java
new file mode 100644
index 00000000000..bcd3936d8b3
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/RFC3339DateFormat.java
@@ -0,0 +1,38 @@
+package org.openapitools;
+
+import com.fasterxml.jackson.databind.util.StdDateFormat;
+
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+public class RFC3339DateFormat extends DateFormat {
+  private static final long serialVersionUID = 1L;
+  private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC");
+
+  private final StdDateFormat fmt = new StdDateFormat()
+          .withTimeZone(TIMEZONE_Z)
+          .withColonInTimeZone(true);
+
+  public RFC3339DateFormat() {
+    this.calendar = new GregorianCalendar();
+  }
+
+  @Override
+  public Date parse(String source, ParsePosition pos) {
+    return fmt.parse(source, pos);
+  }
+
+  @Override
+  public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
+    return fmt.format(date, toAppendTo, fieldPosition);
+  }
+
+  @Override
+  public Object clone() {
+    return this;
+  }
+}
\ No newline at end of file
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/ApiUtil.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/ApiUtil.java
new file mode 100644
index 00000000000..9ecf171bc47
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/ApiUtil.java
@@ -0,0 +1,20 @@
+package org.openapitools.api;
+
+import org.springframework.web.context.request.NativeWebRequest;
+
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.io.IOException;
+
+public class ApiUtil {
+    public static void setExampleResponse(NativeWebRequest req, String contentType, String example) {
+        try {
+            HttpServletResponse res = req.getNativeResponse(HttpServletResponse.class);
+            res.setCharacterEncoding("UTF-8");
+            res.addHeader("Content-Type", contentType);
+            res.getWriter().print(example);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/PetApi.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/PetApi.java
new file mode 100644
index 00000000000..f53d1b7e806
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/PetApi.java
@@ -0,0 +1,414 @@
+/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (6.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 io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+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;
+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
+@Tag(name = "pet", description = "Everything about your Pets")
+public interface PetApi {
+
+    default Optional<NativeWebRequest> getRequest() {
+        return Optional.empty();
+    }
+
+    /**
+     * 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)
+     */
+    @Operation(
+        operationId = "addPet",
+        summary = "Add a new pet to the store",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Pet.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))
+            }),
+            @ApiResponse(responseCode = "405", description = "Invalid input")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "write:pets", "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/pet",
+        produces = { "application/xml", "application/json" },
+        consumes = { "application/json", "application/xml" }
+    )
+    default ResponseEntity<Pet> addPet(
+        @Parameter(name = "Pet", description = "Pet object that needs to be added to the store", required = true) @Valid @RequestBody Pet pet
+    ) {
+        getRequest().ifPresent(request -> {
+            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
+                    String exampleString = "{ \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ], \"name\" : \"doggie\", \"id\" : 0, \"category\" : { \"name\" : \"name\", \"id\" : 6 }, \"tags\" : [ { \"name\" : \"name\", \"id\" : 1 }, { \"name\" : \"name\", \"id\" : 1 } ], \"status\" : \"available\" }";
+                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
+                    break;
+                }
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/xml"))) {
+                    String exampleString = "<Pet> <id>123456789</id> <name>doggie</name> <photoUrls> <photoUrls>aeiou</photoUrls> </photoUrls> <tags> </tags> <status>aeiou</status> </Pet>";
+                    ApiUtil.setExampleResponse(request, "application/xml", exampleString);
+                    break;
+                }
+            }
+        });
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * DELETE /pet/{petId} : Deletes a pet
+     * 
+     *
+     * @param petId Pet id to delete (required)
+     * @param apiKey  (optional)
+     * @return Invalid pet value (status code 400)
+     */
+    @Operation(
+        operationId = "deletePet",
+        summary = "Deletes a pet",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "400", description = "Invalid pet value")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "write:pets", "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.DELETE,
+        value = "/pet/{petId}"
+    )
+    default ResponseEntity<Void> deletePet(
+        @Parameter(name = "petId", description = "Pet id to delete", required = true) @PathVariable("petId") Long petId,
+        @Parameter(name = "api_key", description = "") @RequestHeader(value = "api_key", required = false) String apiKey
+    ) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * 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)
+     */
+    @Operation(
+        operationId = "findPetsByStatus",
+        summary = "Finds Pets by status",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Pet.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid status value")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/pet/findByStatus",
+        produces = { "application/xml", "application/json" }
+    )
+    default ResponseEntity<List<Pet>> findPetsByStatus(
+        @NotNull @Parameter(name = "status", description = "Status values that need to be considered for filter", required = true) @Valid @RequestParam(value = "status", required = true) List<String> status
+    ) {
+        getRequest().ifPresent(request -> {
+            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
+                    String exampleString = "{ \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ], \"name\" : \"doggie\", \"id\" : 0, \"category\" : { \"name\" : \"name\", \"id\" : 6 }, \"tags\" : [ { \"name\" : \"name\", \"id\" : 1 }, { \"name\" : \"name\", \"id\" : 1 } ], \"status\" : \"available\" }";
+                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
+                    break;
+                }
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/xml"))) {
+                    String exampleString = "<Pet> <id>123456789</id> <name>doggie</name> <photoUrls> <photoUrls>aeiou</photoUrls> </photoUrls> <tags> </tags> <status>aeiou</status> </Pet>";
+                    ApiUtil.setExampleResponse(request, "application/xml", exampleString);
+                    break;
+                }
+            }
+        });
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * 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
+     */
+    @Operation(
+        operationId = "findPetsByTags",
+        summary = "Finds Pets by tags",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Pet.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid tag value")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/pet/findByTags",
+        produces = { "application/xml", "application/json" }
+    )
+    default ResponseEntity<List<Pet>> findPetsByTags(
+        @NotNull @Parameter(name = "tags", description = "Tags to filter by", required = true) @Valid @RequestParam(value = "tags", required = true) List<String> tags
+    ) {
+        getRequest().ifPresent(request -> {
+            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
+                    String exampleString = "{ \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ], \"name\" : \"doggie\", \"id\" : 0, \"category\" : { \"name\" : \"name\", \"id\" : 6 }, \"tags\" : [ { \"name\" : \"name\", \"id\" : 1 }, { \"name\" : \"name\", \"id\" : 1 } ], \"status\" : \"available\" }";
+                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
+                    break;
+                }
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/xml"))) {
+                    String exampleString = "<Pet> <id>123456789</id> <name>doggie</name> <photoUrls> <photoUrls>aeiou</photoUrls> </photoUrls> <tags> </tags> <status>aeiou</status> </Pet>";
+                    ApiUtil.setExampleResponse(request, "application/xml", exampleString);
+                    break;
+                }
+            }
+        });
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * 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)
+     */
+    @Operation(
+        operationId = "getPetById",
+        summary = "Find pet by ID",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Pet.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
+            @ApiResponse(responseCode = "404", description = "Pet not found")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/pet/{petId}",
+        produces = { "application/xml", "application/json" }
+    )
+    default ResponseEntity<Pet> getPetById(
+        @Parameter(name = "petId", description = "ID of pet to return", required = true) @PathVariable("petId") Long petId
+    ) {
+        getRequest().ifPresent(request -> {
+            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
+                    String exampleString = "{ \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ], \"name\" : \"doggie\", \"id\" : 0, \"category\" : { \"name\" : \"name\", \"id\" : 6 }, \"tags\" : [ { \"name\" : \"name\", \"id\" : 1 }, { \"name\" : \"name\", \"id\" : 1 } ], \"status\" : \"available\" }";
+                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
+                    break;
+                }
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/xml"))) {
+                    String exampleString = "<Pet> <id>123456789</id> <name>doggie</name> <photoUrls> <photoUrls>aeiou</photoUrls> </photoUrls> <tags> </tags> <status>aeiou</status> </Pet>";
+                    ApiUtil.setExampleResponse(request, "application/xml", exampleString);
+                    break;
+                }
+            }
+        });
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * 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)
+     */
+    @Operation(
+        operationId = "updatePet",
+        summary = "Update an existing pet",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Pet.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
+            @ApiResponse(responseCode = "404", description = "Pet not found"),
+            @ApiResponse(responseCode = "405", description = "Validation exception")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "write:pets", "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.PUT,
+        value = "/pet",
+        produces = { "application/xml", "application/json" },
+        consumes = { "application/json", "application/xml" }
+    )
+    default ResponseEntity<Pet> updatePet(
+        @Parameter(name = "Pet", description = "Pet object that needs to be added to the store", required = true) @Valid @RequestBody Pet pet
+    ) {
+        getRequest().ifPresent(request -> {
+            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
+                    String exampleString = "{ \"photoUrls\" : [ \"photoUrls\", \"photoUrls\" ], \"name\" : \"doggie\", \"id\" : 0, \"category\" : { \"name\" : \"name\", \"id\" : 6 }, \"tags\" : [ { \"name\" : \"name\", \"id\" : 1 }, { \"name\" : \"name\", \"id\" : 1 } ], \"status\" : \"available\" }";
+                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
+                    break;
+                }
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/xml"))) {
+                    String exampleString = "<Pet> <id>123456789</id> <name>doggie</name> <photoUrls> <photoUrls>aeiou</photoUrls> </photoUrls> <tags> </tags> <status>aeiou</status> </Pet>";
+                    ApiUtil.setExampleResponse(request, "application/xml", exampleString);
+                    break;
+                }
+            }
+        });
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * 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)
+     */
+    @Operation(
+        operationId = "updatePetWithForm",
+        summary = "Updates a pet in the store with form data",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "405", description = "Invalid input")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "write:pets", "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/pet/{petId}",
+        consumes = { "application/x-www-form-urlencoded" }
+    )
+    default ResponseEntity<Void> updatePetWithForm(
+        @Parameter(name = "petId", description = "ID of pet that needs to be updated", required = true) @PathVariable("petId") Long petId,
+        @Parameter(name = "name", description = "Updated name of the pet") @Valid @RequestParam(value = "name", required = false) String name,
+        @Parameter(name = "status", description = "Updated status of the pet") @Valid @RequestParam(value = "status", required = false) String status
+    ) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * 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)
+     */
+    @Operation(
+        operationId = "uploadFile",
+        summary = "uploads an image",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/json", schema = @Schema(implementation = ModelApiResponse.class))
+            })
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "write:pets", "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/pet/{petId}/uploadImage",
+        produces = { "application/json" },
+        consumes = { "multipart/form-data" }
+    )
+    default ResponseEntity<ModelApiResponse> uploadFile(
+        @Parameter(name = "petId", description = "ID of pet to update", required = true) @PathVariable("petId") Long petId,
+        @Parameter(name = "additionalMetadata", description = "Additional data to pass to server") @Valid @RequestParam(value = "additionalMetadata", required = false) String additionalMetadata,
+        @Parameter(name = "file", description = "file to upload") @RequestPart(value = "file", required = false) MultipartFile file
+    ) {
+        getRequest().ifPresent(request -> {
+            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
+                    String exampleString = "{ \"code\" : 0, \"type\" : \"type\", \"message\" : \"message\" }";
+                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
+                    break;
+                }
+            }
+        });
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+}
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/PetApiController.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/PetApiController.java
new file mode 100644
index 00000000000..11972950264
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/PetApiController.java
@@ -0,0 +1,47 @@
+package org.openapitools.api;
+
+import org.openapitools.model.ModelApiResponse;
+import org.openapitools.model.Pet;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.context.request.NativeWebRequest;
+
+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")
+@Controller
+@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}")
+public class PetApiController implements PetApi {
+
+    private final NativeWebRequest request;
+
+    @Autowired
+    public PetApiController(NativeWebRequest request) {
+        this.request = request;
+    }
+
+    @Override
+    public Optional<NativeWebRequest> getRequest() {
+        return Optional.ofNullable(request);
+    }
+
+}
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/StoreApi.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/StoreApi.java
new file mode 100644
index 00000000000..c266470ba70
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/StoreApi.java
@@ -0,0 +1,199 @@
+/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (6.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 io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+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;
+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
+@Tag(name = "store", description = "Access to Petstore orders")
+public interface StoreApi {
+
+    default Optional<NativeWebRequest> getRequest() {
+        return Optional.empty();
+    }
+
+    /**
+     * DELETE /store/order/{orderId} : Delete purchase order by ID
+     * For valid response try integer IDs with value &lt; 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)
+     */
+    @Operation(
+        operationId = "deleteOrder",
+        summary = "Delete purchase order by ID",
+        tags = { "store" },
+        responses = {
+            @ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
+            @ApiResponse(responseCode = "404", description = "Order not found")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.DELETE,
+        value = "/store/order/{orderId}"
+    )
+    default ResponseEntity<Void> deleteOrder(
+        @Parameter(name = "orderId", description = "ID of the order that needs to be deleted", required = true) @PathVariable("orderId") String orderId
+    ) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * GET /store/inventory : Returns pet inventories by status
+     * Returns a map of status codes to quantities
+     *
+     * @return successful operation (status code 200)
+     */
+    @Operation(
+        operationId = "getInventory",
+        summary = "Returns pet inventories by status",
+        tags = { "store" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Map.class))
+            })
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/store/inventory",
+        produces = { "application/json" }
+    )
+    default ResponseEntity<Map<String, Integer>> getInventory(
+        
+    ) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * GET /store/order/{orderId} : Find purchase order by ID
+     * For valid response try integer IDs with value &lt;&#x3D; 5 or &gt; 10. Other values will generated exceptions
+     *
+     * @param orderId ID of pet that needs to be fetched (required)
+     * @return successful operation (status code 200)
+     *         or Invalid ID supplied (status code 400)
+     *         or Order not found (status code 404)
+     */
+    @Operation(
+        operationId = "getOrderById",
+        summary = "Find purchase order by ID",
+        tags = { "store" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Order.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Order.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
+            @ApiResponse(responseCode = "404", description = "Order not found")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/store/order/{orderId}",
+        produces = { "application/xml", "application/json" }
+    )
+    default ResponseEntity<Order> getOrderById(
+        @Min(1L) @Max(5L) @Parameter(name = "orderId", description = "ID of pet that needs to be fetched", required = true) @PathVariable("orderId") Long orderId
+    ) {
+        getRequest().ifPresent(request -> {
+            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
+                    String exampleString = "{ \"petId\" : 6, \"quantity\" : 1, \"id\" : 0, \"shipDate\" : \"2000-01-23T04:56:07.000+00:00\", \"complete\" : false, \"status\" : \"placed\" }";
+                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
+                    break;
+                }
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/xml"))) {
+                    String exampleString = "<Order> <id>123456789</id> <petId>123456789</petId> <quantity>123</quantity> <shipDate>2000-01-23T04:56:07.000Z</shipDate> <status>aeiou</status> <complete>true</complete> </Order>";
+                    ApiUtil.setExampleResponse(request, "application/xml", exampleString);
+                    break;
+                }
+            }
+        });
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * POST /store/order : Place an order for a pet
+     * 
+     *
+     * @param order order placed for purchasing the pet (required)
+     * @return successful operation (status code 200)
+     *         or Invalid Order (status code 400)
+     */
+    @Operation(
+        operationId = "placeOrder",
+        summary = "Place an order for a pet",
+        tags = { "store" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Order.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Order.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid Order")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/store/order",
+        produces = { "application/xml", "application/json" },
+        consumes = { "application/json" }
+    )
+    default ResponseEntity<Order> placeOrder(
+        @Parameter(name = "Order", description = "order placed for purchasing the pet", required = true) @Valid @RequestBody Order order
+    ) {
+        getRequest().ifPresent(request -> {
+            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
+                    String exampleString = "{ \"petId\" : 6, \"quantity\" : 1, \"id\" : 0, \"shipDate\" : \"2000-01-23T04:56:07.000+00:00\", \"complete\" : false, \"status\" : \"placed\" }";
+                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
+                    break;
+                }
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/xml"))) {
+                    String exampleString = "<Order> <id>123456789</id> <petId>123456789</petId> <quantity>123</quantity> <shipDate>2000-01-23T04:56:07.000Z</shipDate> <status>aeiou</status> <complete>true</complete> </Order>";
+                    ApiUtil.setExampleResponse(request, "application/xml", exampleString);
+                    break;
+                }
+            }
+        });
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+}
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/StoreApiController.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/StoreApiController.java
new file mode 100644
index 00000000000..eaca23c3f81
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/StoreApiController.java
@@ -0,0 +1,47 @@
+package org.openapitools.api;
+
+import java.util.Map;
+import org.openapitools.model.Order;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.context.request.NativeWebRequest;
+
+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")
+@Controller
+@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}")
+public class StoreApiController implements StoreApi {
+
+    private final NativeWebRequest request;
+
+    @Autowired
+    public StoreApiController(NativeWebRequest request) {
+        this.request = request;
+    }
+
+    @Override
+    public Optional<NativeWebRequest> getRequest() {
+        return Optional.ofNullable(request);
+    }
+
+}
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/UserApi.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/UserApi.java
new file mode 100644
index 00000000000..e4f89dc975f
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/UserApi.java
@@ -0,0 +1,315 @@
+/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (6.0.0-SNAPSHOT).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.api;
+
+import java.util.List;
+import java.time.OffsetDateTime;
+import org.openapitools.model.User;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+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;
+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
+@Tag(name = "user", description = "Operations about user")
+public interface UserApi {
+
+    default Optional<NativeWebRequest> getRequest() {
+        return Optional.empty();
+    }
+
+    /**
+     * POST /user : Create user
+     * This can only be done by the logged in user.
+     *
+     * @param user Created user object (required)
+     * @return successful operation (status code 200)
+     */
+    @Operation(
+        operationId = "createUser",
+        summary = "Create user",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/user",
+        consumes = { "application/json" }
+    )
+    default ResponseEntity<Void> createUser(
+        @Parameter(name = "User", description = "Created user object", required = true) @Valid @RequestBody User user
+    ) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * POST /user/createWithArray : Creates list of users with given input array
+     * 
+     *
+     * @param user List of user object (required)
+     * @return successful operation (status code 200)
+     */
+    @Operation(
+        operationId = "createUsersWithArrayInput",
+        summary = "Creates list of users with given input array",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/user/createWithArray",
+        consumes = { "application/json" }
+    )
+    default ResponseEntity<Void> createUsersWithArrayInput(
+        @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<User> user
+    ) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * POST /user/createWithList : Creates list of users with given input array
+     * 
+     *
+     * @param user List of user object (required)
+     * @return successful operation (status code 200)
+     */
+    @Operation(
+        operationId = "createUsersWithListInput",
+        summary = "Creates list of users with given input array",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/user/createWithList",
+        consumes = { "application/json" }
+    )
+    default ResponseEntity<Void> createUsersWithListInput(
+        @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<User> user
+    ) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * DELETE /user/{username} : Delete user
+     * This can only be done by the logged in user.
+     *
+     * @param username The name that needs to be deleted (required)
+     * @return Invalid username supplied (status code 400)
+     *         or User not found (status code 404)
+     */
+    @Operation(
+        operationId = "deleteUser",
+        summary = "Delete user",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "400", description = "Invalid username supplied"),
+            @ApiResponse(responseCode = "404", description = "User not found")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.DELETE,
+        value = "/user/{username}"
+    )
+    default ResponseEntity<Void> deleteUser(
+        @Parameter(name = "username", description = "The name that needs to be deleted", required = true) @PathVariable("username") String username
+    ) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * GET /user/{username} : Get user by user name
+     * 
+     *
+     * @param username The name that needs to be fetched. Use user1 for testing. (required)
+     * @return successful operation (status code 200)
+     *         or Invalid username supplied (status code 400)
+     *         or User not found (status code 404)
+     */
+    @Operation(
+        operationId = "getUserByName",
+        summary = "Get user by user name",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = User.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = User.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid username supplied"),
+            @ApiResponse(responseCode = "404", description = "User not found")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/user/{username}",
+        produces = { "application/xml", "application/json" }
+    )
+    default ResponseEntity<User> getUserByName(
+        @Parameter(name = "username", description = "The name that needs to be fetched. Use user1 for testing.", required = true) @PathVariable("username") String username
+    ) {
+        getRequest().ifPresent(request -> {
+            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
+                    String exampleString = "{ \"firstName\" : \"firstName\", \"lastName\" : \"lastName\", \"password\" : \"password\", \"userStatus\" : 6, \"phone\" : \"phone\", \"id\" : 0, \"email\" : \"email\", \"username\" : \"username\" }";
+                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
+                    break;
+                }
+                if (mediaType.isCompatibleWith(MediaType.valueOf("application/xml"))) {
+                    String exampleString = "<User> <id>123456789</id> <username>aeiou</username> <firstName>aeiou</firstName> <lastName>aeiou</lastName> <email>aeiou</email> <password>aeiou</password> <phone>aeiou</phone> <userStatus>123</userStatus> </User>";
+                    ApiUtil.setExampleResponse(request, "application/xml", exampleString);
+                    break;
+                }
+            }
+        });
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * GET /user/login : Logs user into the system
+     * 
+     *
+     * @param username The user name for login (required)
+     * @param password The password for login in clear text (required)
+     * @return successful operation (status code 200)
+     *         or Invalid username/password supplied (status code 400)
+     */
+    @Operation(
+        operationId = "loginUser",
+        summary = "Logs user into the system",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = String.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = String.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid username/password supplied")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/user/login",
+        produces = { "application/xml", "application/json" }
+    )
+    default ResponseEntity<String> loginUser(
+        @NotNull @Pattern(regexp = "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$") @Parameter(name = "username", description = "The user name for login", required = true) @Valid @RequestParam(value = "username", required = true) String username,
+        @NotNull @Parameter(name = "password", description = "The password for login in clear text", required = true) @Valid @RequestParam(value = "password", required = true) String password
+    ) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * GET /user/logout : Logs out current logged in user session
+     * 
+     *
+     * @return successful operation (status code 200)
+     */
+    @Operation(
+        operationId = "logoutUser",
+        summary = "Logs out current logged in user session",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/user/logout"
+    )
+    default ResponseEntity<Void> logoutUser(
+        
+    ) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+
+    /**
+     * PUT /user/{username} : Updated user
+     * This can only be done by the logged in user.
+     *
+     * @param username name that need to be deleted (required)
+     * @param user Updated user object (required)
+     * @return Invalid user supplied (status code 400)
+     *         or User not found (status code 404)
+     */
+    @Operation(
+        operationId = "updateUser",
+        summary = "Updated user",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "400", description = "Invalid user supplied"),
+            @ApiResponse(responseCode = "404", description = "User not found")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.PUT,
+        value = "/user/{username}",
+        consumes = { "application/json" }
+    )
+    default ResponseEntity<Void> updateUser(
+        @Parameter(name = "username", description = "name that need to be deleted", required = true) @PathVariable("username") String username,
+        @Parameter(name = "User", description = "Updated user object", required = true) @Valid @RequestBody User user
+    ) {
+        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+
+    }
+
+}
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/UserApiController.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/UserApiController.java
new file mode 100644
index 00000000000..412a400d7d0
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/UserApiController.java
@@ -0,0 +1,48 @@
+package org.openapitools.api;
+
+import java.util.List;
+import java.time.OffsetDateTime;
+import org.openapitools.model.User;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.context.request.NativeWebRequest;
+
+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")
+@Controller
+@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}")
+public class UserApiController implements UserApi {
+
+    private final NativeWebRequest request;
+
+    @Autowired
+    public UserApiController(NativeWebRequest request) {
+        this.request = request;
+    }
+
+    @Override
+    public Optional<NativeWebRequest> getRequest() {
+        return Optional.ofNullable(request);
+    }
+
+}
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/configuration/HomeController.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/configuration/HomeController.java
new file mode 100644
index 00000000000..9aa29284ab5
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/configuration/HomeController.java
@@ -0,0 +1,20 @@
+package org.openapitools.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.GetMapping;
+
+/**
+ * Home redirection to OpenAPI api documentation
+ */
+@Controller
+public class HomeController {
+
+    @RequestMapping("/")
+    public String index() {
+        return "redirect:swagger-ui.html";
+    }
+
+}
\ No newline at end of file
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/configuration/SpringDocConfiguration.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/configuration/SpringDocConfiguration.java
new file mode 100644
index 00000000000..fc42981e194
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/configuration/SpringDocConfiguration.java
@@ -0,0 +1,43 @@
+package org.openapitools.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.License;
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.security.SecurityScheme;
+
+@Configuration
+public class SpringDocConfiguration {
+
+    @Bean
+    OpenAPI apiInfo() {
+        return new OpenAPI()
+                .info(
+                        new Info()
+                                .title("OpenAPI Petstore")
+                                .description("This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.")
+                                .license(
+                                        new License()
+                                                .name("Apache-2.0")
+                                                .url("https://www.apache.org/licenses/LICENSE-2.0.html")
+                                )
+                                .version("1.0.0")
+                )
+                .components(
+                        new Components()
+                                .addSecuritySchemes("api_key", new SecurityScheme()
+                                        .type(SecurityScheme.Type.APIKEY)
+                                        .in(SecurityScheme.In.HEADER)
+                                        .name("api_key")
+                                )
+                                .addSecuritySchemes("petstore_auth", new SecurityScheme()
+                                        .type(SecurityScheme.Type.OAUTH2)
+                                )
+                )
+        ;
+    }
+}
\ No newline at end of file
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Category.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Category.java
new file mode 100644
index 00000000000..f15bed23288
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Category.java
@@ -0,0 +1,108 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * A category for a pet
+ */
+
+@Schema(name = "Category", description = "A category for a pet")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class Category {
+
+  @JsonProperty("id")
+  private Long id;
+
+  @JsonProperty("name")
+  private String name;
+
+  public Category id(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  /**
+   * Get id
+   * @return id
+  */
+  
+  @Schema(name = "id", required = false)
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Category name(String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Get name
+   * @return name
+  */
+  @Pattern(regexp = "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$") 
+  @Schema(name = "name", required = false)
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Category category = (Category) o;
+    return Objects.equals(this.id, category.id) &&
+        Objects.equals(this.name, category.name);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(id, name);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class Category {\n");
+    sb.append("    id: ").append(toIndentedString(id)).append("\n");
+    sb.append("    name: ").append(toIndentedString(name)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/ModelApiResponse.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/ModelApiResponse.java
new file mode 100644
index 00000000000..e74c0d15a18
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/ModelApiResponse.java
@@ -0,0 +1,134 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * Describes the result of uploading an image resource
+ */
+
+@Schema(name = "ApiResponse", description = "Describes the result of uploading an image resource")
+@JsonTypeName("ApiResponse")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class ModelApiResponse {
+
+  @JsonProperty("code")
+  private Integer code;
+
+  @JsonProperty("type")
+  private String type;
+
+  @JsonProperty("message")
+  private String message;
+
+  public ModelApiResponse code(Integer code) {
+    this.code = code;
+    return this;
+  }
+
+  /**
+   * Get code
+   * @return code
+  */
+  
+  @Schema(name = "code", required = false)
+  public Integer getCode() {
+    return code;
+  }
+
+  public void setCode(Integer code) {
+    this.code = code;
+  }
+
+  public ModelApiResponse type(String type) {
+    this.type = type;
+    return this;
+  }
+
+  /**
+   * Get type
+   * @return type
+  */
+  
+  @Schema(name = "type", required = false)
+  public String getType() {
+    return type;
+  }
+
+  public void setType(String type) {
+    this.type = type;
+  }
+
+  public ModelApiResponse message(String message) {
+    this.message = message;
+    return this;
+  }
+
+  /**
+   * Get message
+   * @return message
+  */
+  
+  @Schema(name = "message", required = false)
+  public String getMessage() {
+    return message;
+  }
+
+  public void setMessage(String message) {
+    this.message = message;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    ModelApiResponse _apiResponse = (ModelApiResponse) o;
+    return Objects.equals(this.code, _apiResponse.code) &&
+        Objects.equals(this.type, _apiResponse.type) &&
+        Objects.equals(this.message, _apiResponse.message);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(code, type, message);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class ModelApiResponse {\n");
+    sb.append("    code: ").append(toIndentedString(code)).append("\n");
+    sb.append("    type: ").append(toIndentedString(type)).append("\n");
+    sb.append("    message: ").append(toIndentedString(message)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Order.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Order.java
new file mode 100644
index 00000000000..e4a1030a073
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Order.java
@@ -0,0 +1,245 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import java.time.OffsetDateTime;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * An order for a pets from the pet store
+ */
+
+@Schema(name = "Order", description = "An order for a pets from the pet store")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class Order {
+
+  @JsonProperty("id")
+  private Long id;
+
+  @JsonProperty("petId")
+  private Long petId;
+
+  @JsonProperty("quantity")
+  private Integer quantity;
+
+  @JsonProperty("shipDate")
+  @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
+  private OffsetDateTime shipDate;
+
+  /**
+   * Order Status
+   */
+  public enum StatusEnum {
+    PLACED("placed"),
+    
+    APPROVED("approved"),
+    
+    DELIVERED("delivered");
+
+    private String value;
+
+    StatusEnum(String value) {
+      this.value = value;
+    }
+
+    @JsonValue
+    public String getValue() {
+      return value;
+    }
+
+    @Override
+    public String toString() {
+      return String.valueOf(value);
+    }
+
+    @JsonCreator
+    public static StatusEnum fromValue(String value) {
+      for (StatusEnum b : StatusEnum.values()) {
+        if (b.value.equals(value)) {
+          return b;
+        }
+      }
+      throw new IllegalArgumentException("Unexpected value '" + value + "'");
+    }
+  }
+
+  @JsonProperty("status")
+  private StatusEnum status;
+
+  @JsonProperty("complete")
+  private Boolean complete = false;
+
+  public Order id(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  /**
+   * Get id
+   * @return id
+  */
+  
+  @Schema(name = "id", required = false)
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Order petId(Long petId) {
+    this.petId = petId;
+    return this;
+  }
+
+  /**
+   * Get petId
+   * @return petId
+  */
+  
+  @Schema(name = "petId", required = false)
+  public Long getPetId() {
+    return petId;
+  }
+
+  public void setPetId(Long petId) {
+    this.petId = petId;
+  }
+
+  public Order quantity(Integer quantity) {
+    this.quantity = quantity;
+    return this;
+  }
+
+  /**
+   * Get quantity
+   * @return quantity
+  */
+  
+  @Schema(name = "quantity", required = false)
+  public Integer getQuantity() {
+    return quantity;
+  }
+
+  public void setQuantity(Integer quantity) {
+    this.quantity = quantity;
+  }
+
+  public Order shipDate(OffsetDateTime shipDate) {
+    this.shipDate = shipDate;
+    return this;
+  }
+
+  /**
+   * Get shipDate
+   * @return shipDate
+  */
+  @Valid 
+  @Schema(name = "shipDate", required = false)
+  public OffsetDateTime getShipDate() {
+    return shipDate;
+  }
+
+  public void setShipDate(OffsetDateTime shipDate) {
+    this.shipDate = shipDate;
+  }
+
+  public Order status(StatusEnum status) {
+    this.status = status;
+    return this;
+  }
+
+  /**
+   * Order Status
+   * @return status
+  */
+  
+  @Schema(name = "status", description = "Order Status", required = false)
+  public StatusEnum getStatus() {
+    return status;
+  }
+
+  public void setStatus(StatusEnum status) {
+    this.status = status;
+  }
+
+  public Order complete(Boolean complete) {
+    this.complete = complete;
+    return this;
+  }
+
+  /**
+   * Get complete
+   * @return complete
+  */
+  
+  @Schema(name = "complete", required = false)
+  public Boolean getComplete() {
+    return complete;
+  }
+
+  public void setComplete(Boolean complete) {
+    this.complete = complete;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Order order = (Order) o;
+    return Objects.equals(this.id, order.id) &&
+        Objects.equals(this.petId, order.petId) &&
+        Objects.equals(this.quantity, order.quantity) &&
+        Objects.equals(this.shipDate, order.shipDate) &&
+        Objects.equals(this.status, order.status) &&
+        Objects.equals(this.complete, order.complete);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(id, petId, quantity, shipDate, status, complete);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class Order {\n");
+    sb.append("    id: ").append(toIndentedString(id)).append("\n");
+    sb.append("    petId: ").append(toIndentedString(petId)).append("\n");
+    sb.append("    quantity: ").append(toIndentedString(quantity)).append("\n");
+    sb.append("    shipDate: ").append(toIndentedString(shipDate)).append("\n");
+    sb.append("    status: ").append(toIndentedString(status)).append("\n");
+    sb.append("    complete: ").append(toIndentedString(complete)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Pet.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Pet.java
new file mode 100644
index 00000000000..1e00d49524a
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Pet.java
@@ -0,0 +1,261 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import java.util.ArrayList;
+import java.util.List;
+import org.openapitools.model.Category;
+import org.openapitools.model.Tag;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * A pet for sale in the pet store
+ */
+
+@Schema(name = "Pet", description = "A pet for sale in the pet store")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class Pet {
+
+  @JsonProperty("id")
+  private Long id;
+
+  @JsonProperty("category")
+  private Category category;
+
+  @JsonProperty("name")
+  private String name;
+
+  @JsonProperty("photoUrls")
+  @Valid
+  private List<String> photoUrls = new ArrayList<>();
+
+  @JsonProperty("tags")
+  @Valid
+  private List<Tag> tags = null;
+
+  /**
+   * pet status in the store
+   */
+  public enum StatusEnum {
+    AVAILABLE("available"),
+    
+    PENDING("pending"),
+    
+    SOLD("sold");
+
+    private String value;
+
+    StatusEnum(String value) {
+      this.value = value;
+    }
+
+    @JsonValue
+    public String getValue() {
+      return value;
+    }
+
+    @Override
+    public String toString() {
+      return String.valueOf(value);
+    }
+
+    @JsonCreator
+    public static StatusEnum fromValue(String value) {
+      for (StatusEnum b : StatusEnum.values()) {
+        if (b.value.equals(value)) {
+          return b;
+        }
+      }
+      throw new IllegalArgumentException("Unexpected value '" + value + "'");
+    }
+  }
+
+  @JsonProperty("status")
+  private StatusEnum status;
+
+  public Pet id(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  /**
+   * Get id
+   * @return id
+  */
+  
+  @Schema(name = "id", required = false)
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Pet category(Category category) {
+    this.category = category;
+    return this;
+  }
+
+  /**
+   * Get category
+   * @return category
+  */
+  @Valid 
+  @Schema(name = "category", required = false)
+  public Category getCategory() {
+    return category;
+  }
+
+  public void setCategory(Category category) {
+    this.category = category;
+  }
+
+  public Pet name(String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Get name
+   * @return name
+  */
+  @NotNull 
+  @Schema(name = "name", example = "doggie", required = true)
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public Pet photoUrls(List<String> photoUrls) {
+    this.photoUrls = photoUrls;
+    return this;
+  }
+
+  public Pet addPhotoUrlsItem(String photoUrlsItem) {
+    this.photoUrls.add(photoUrlsItem);
+    return this;
+  }
+
+  /**
+   * Get photoUrls
+   * @return photoUrls
+  */
+  @NotNull 
+  @Schema(name = "photoUrls", required = true)
+  public List<String> getPhotoUrls() {
+    return photoUrls;
+  }
+
+  public void setPhotoUrls(List<String> photoUrls) {
+    this.photoUrls = photoUrls;
+  }
+
+  public Pet tags(List<Tag> tags) {
+    this.tags = tags;
+    return this;
+  }
+
+  public Pet addTagsItem(Tag tagsItem) {
+    if (this.tags == null) {
+      this.tags = new ArrayList<>();
+    }
+    this.tags.add(tagsItem);
+    return this;
+  }
+
+  /**
+   * Get tags
+   * @return tags
+  */
+  @Valid 
+  @Schema(name = "tags", required = false)
+  public List<Tag> getTags() {
+    return tags;
+  }
+
+  public void setTags(List<Tag> tags) {
+    this.tags = tags;
+  }
+
+  public Pet status(StatusEnum status) {
+    this.status = status;
+    return this;
+  }
+
+  /**
+   * pet status in the store
+   * @return status
+  */
+  
+  @Schema(name = "status", description = "pet status in the store", required = false)
+  public StatusEnum getStatus() {
+    return status;
+  }
+
+  public void setStatus(StatusEnum status) {
+    this.status = status;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Pet pet = (Pet) o;
+    return Objects.equals(this.id, pet.id) &&
+        Objects.equals(this.category, pet.category) &&
+        Objects.equals(this.name, pet.name) &&
+        Objects.equals(this.photoUrls, pet.photoUrls) &&
+        Objects.equals(this.tags, pet.tags) &&
+        Objects.equals(this.status, pet.status);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(id, category, name, photoUrls, tags, status);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class Pet {\n");
+    sb.append("    id: ").append(toIndentedString(id)).append("\n");
+    sb.append("    category: ").append(toIndentedString(category)).append("\n");
+    sb.append("    name: ").append(toIndentedString(name)).append("\n");
+    sb.append("    photoUrls: ").append(toIndentedString(photoUrls)).append("\n");
+    sb.append("    tags: ").append(toIndentedString(tags)).append("\n");
+    sb.append("    status: ").append(toIndentedString(status)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Tag.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Tag.java
new file mode 100644
index 00000000000..97130c50c03
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/Tag.java
@@ -0,0 +1,108 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * A tag for a pet
+ */
+
+@Schema(name = "Tag", description = "A tag for a pet")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class Tag {
+
+  @JsonProperty("id")
+  private Long id;
+
+  @JsonProperty("name")
+  private String name;
+
+  public Tag id(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  /**
+   * Get id
+   * @return id
+  */
+  
+  @Schema(name = "id", required = false)
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Tag name(String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Get name
+   * @return name
+  */
+  
+  @Schema(name = "name", required = false)
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Tag tag = (Tag) o;
+    return Objects.equals(this.id, tag.id) &&
+        Objects.equals(this.name, tag.name);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(id, name);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class Tag {\n");
+    sb.append("    id: ").append(toIndentedString(id)).append("\n");
+    sb.append("    name: ").append(toIndentedString(name)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/User.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/User.java
new file mode 100644
index 00000000000..0a193cf96c2
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/model/User.java
@@ -0,0 +1,252 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * A User who is purchasing from the pet store
+ */
+
+@Schema(name = "User", description = "A User who is purchasing from the pet store")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class User {
+
+  @JsonProperty("id")
+  private Long id;
+
+  @JsonProperty("username")
+  private String username;
+
+  @JsonProperty("firstName")
+  private String firstName;
+
+  @JsonProperty("lastName")
+  private String lastName;
+
+  @JsonProperty("email")
+  private String email;
+
+  @JsonProperty("password")
+  private String password;
+
+  @JsonProperty("phone")
+  private String phone;
+
+  @JsonProperty("userStatus")
+  private Integer userStatus;
+
+  public User id(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  /**
+   * Get id
+   * @return id
+  */
+  
+  @Schema(name = "id", required = false)
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public User username(String username) {
+    this.username = username;
+    return this;
+  }
+
+  /**
+   * Get username
+   * @return username
+  */
+  
+  @Schema(name = "username", required = false)
+  public String getUsername() {
+    return username;
+  }
+
+  public void setUsername(String username) {
+    this.username = username;
+  }
+
+  public User firstName(String firstName) {
+    this.firstName = firstName;
+    return this;
+  }
+
+  /**
+   * Get firstName
+   * @return firstName
+  */
+  
+  @Schema(name = "firstName", required = false)
+  public String getFirstName() {
+    return firstName;
+  }
+
+  public void setFirstName(String firstName) {
+    this.firstName = firstName;
+  }
+
+  public User lastName(String lastName) {
+    this.lastName = lastName;
+    return this;
+  }
+
+  /**
+   * Get lastName
+   * @return lastName
+  */
+  
+  @Schema(name = "lastName", required = false)
+  public String getLastName() {
+    return lastName;
+  }
+
+  public void setLastName(String lastName) {
+    this.lastName = lastName;
+  }
+
+  public User email(String email) {
+    this.email = email;
+    return this;
+  }
+
+  /**
+   * Get email
+   * @return email
+  */
+  
+  @Schema(name = "email", required = false)
+  public String getEmail() {
+    return email;
+  }
+
+  public void setEmail(String email) {
+    this.email = email;
+  }
+
+  public User password(String password) {
+    this.password = password;
+    return this;
+  }
+
+  /**
+   * Get password
+   * @return password
+  */
+  
+  @Schema(name = "password", required = false)
+  public String getPassword() {
+    return password;
+  }
+
+  public void setPassword(String password) {
+    this.password = password;
+  }
+
+  public User phone(String phone) {
+    this.phone = phone;
+    return this;
+  }
+
+  /**
+   * Get phone
+   * @return phone
+  */
+  
+  @Schema(name = "phone", required = false)
+  public String getPhone() {
+    return phone;
+  }
+
+  public void setPhone(String phone) {
+    this.phone = phone;
+  }
+
+  public User userStatus(Integer userStatus) {
+    this.userStatus = userStatus;
+    return this;
+  }
+
+  /**
+   * User Status
+   * @return userStatus
+  */
+  
+  @Schema(name = "userStatus", description = "User Status", required = false)
+  public Integer getUserStatus() {
+    return userStatus;
+  }
+
+  public void setUserStatus(Integer userStatus) {
+    this.userStatus = userStatus;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    User user = (User) o;
+    return Objects.equals(this.id, user.id) &&
+        Objects.equals(this.username, user.username) &&
+        Objects.equals(this.firstName, user.firstName) &&
+        Objects.equals(this.lastName, user.lastName) &&
+        Objects.equals(this.email, user.email) &&
+        Objects.equals(this.password, user.password) &&
+        Objects.equals(this.phone, user.phone) &&
+        Objects.equals(this.userStatus, user.userStatus);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(id, username, firstName, lastName, email, password, phone, userStatus);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class User {\n");
+    sb.append("    id: ").append(toIndentedString(id)).append("\n");
+    sb.append("    username: ").append(toIndentedString(username)).append("\n");
+    sb.append("    firstName: ").append(toIndentedString(firstName)).append("\n");
+    sb.append("    lastName: ").append(toIndentedString(lastName)).append("\n");
+    sb.append("    email: ").append(toIndentedString(email)).append("\n");
+    sb.append("    password: ").append(toIndentedString(password)).append("\n");
+    sb.append("    phone: ").append(toIndentedString(phone)).append("\n");
+    sb.append("    userStatus: ").append(toIndentedString(userStatus)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/resources/application.properties b/samples/openapi3/server/petstore/springboot-3/src/main/resources/application.properties
new file mode 100644
index 00000000000..7e90813e59b
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+server.port=8080
+spring.jackson.date-format=org.openapitools.RFC3339DateFormat
+spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/resources/openapi.yaml b/samples/openapi3/server/petstore/springboot-3/src/main/resources/openapi.yaml
new file mode 100644
index 00000000000..b629acd9d7f
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/resources/openapi.yaml
@@ -0,0 +1,877 @@
+openapi: 3.0.0
+info:
+  description: "This is a sample server Petstore server. For this sample, you can\
+    \ use the api key `special-key` to test the authorization filters."
+  license:
+    name: Apache-2.0
+    url: https://www.apache.org/licenses/LICENSE-2.0.html
+  title: OpenAPI Petstore
+  version: 1.0.0
+externalDocs:
+  description: Find out more about Swagger
+  url: http://swagger.io
+servers:
+- url: http://petstore.swagger.io/v2
+tags:
+- description: Everything about your Pets
+  name: pet
+- description: Access to Petstore orders
+  name: store
+- description: Operations about user
+  name: user
+paths:
+  /pet:
+    post:
+      description: ""
+      operationId: addPet
+      requestBody:
+        $ref: '#/components/requestBodies/Pet'
+      responses:
+        "200":
+          content:
+            application/xml:
+              schema:
+                $ref: '#/components/schemas/Pet'
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Pet'
+          description: successful operation
+        "405":
+          description: Invalid input
+      security:
+      - petstore_auth:
+        - write:pets
+        - read:pets
+      summary: Add a new pet to the store
+      tags:
+      - pet
+      x-content-type: application/json
+      x-accepts: application/json
+      x-tags:
+      - tag: pet
+    put:
+      description: ""
+      operationId: updatePet
+      requestBody:
+        $ref: '#/components/requestBodies/Pet'
+      responses:
+        "200":
+          content:
+            application/xml:
+              schema:
+                $ref: '#/components/schemas/Pet'
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Pet'
+          description: successful operation
+        "400":
+          description: Invalid ID supplied
+        "404":
+          description: Pet not found
+        "405":
+          description: Validation exception
+      security:
+      - petstore_auth:
+        - write:pets
+        - read:pets
+      summary: Update an existing pet
+      tags:
+      - pet
+      x-content-type: application/json
+      x-accepts: application/json
+      x-tags:
+      - tag: pet
+  /pet/findByStatus:
+    get:
+      description: Multiple status values can be provided with comma separated strings
+      operationId: findPetsByStatus
+      parameters:
+      - deprecated: true
+        description: Status values that need to be considered for filter
+        explode: false
+        in: query
+        name: status
+        required: true
+        schema:
+          items:
+            default: available
+            enum:
+            - available
+            - pending
+            - sold
+            type: string
+          type: array
+        style: form
+      responses:
+        "200":
+          content:
+            application/xml:
+              schema:
+                items:
+                  $ref: '#/components/schemas/Pet'
+                type: array
+            application/json:
+              schema:
+                items:
+                  $ref: '#/components/schemas/Pet'
+                type: array
+          description: successful operation
+        "400":
+          description: Invalid status value
+      security:
+      - petstore_auth:
+        - read:pets
+      summary: Finds Pets by status
+      tags:
+      - pet
+      x-accepts: application/json
+      x-tags:
+      - tag: pet
+  /pet/findByTags:
+    get:
+      deprecated: true
+      description: "Multiple tags can be provided with comma separated strings. Use\
+        \ tag1, tag2, tag3 for testing."
+      operationId: findPetsByTags
+      parameters:
+      - description: Tags to filter by
+        explode: false
+        in: query
+        name: tags
+        required: true
+        schema:
+          items:
+            type: string
+          type: array
+        style: form
+      responses:
+        "200":
+          content:
+            application/xml:
+              schema:
+                items:
+                  $ref: '#/components/schemas/Pet'
+                type: array
+            application/json:
+              schema:
+                items:
+                  $ref: '#/components/schemas/Pet'
+                type: array
+          description: successful operation
+        "400":
+          description: Invalid tag value
+      security:
+      - petstore_auth:
+        - read:pets
+      summary: Finds Pets by tags
+      tags:
+      - pet
+      x-accepts: application/json
+      x-tags:
+      - tag: pet
+  /pet/{petId}:
+    delete:
+      description: ""
+      operationId: deletePet
+      parameters:
+      - explode: false
+        in: header
+        name: api_key
+        required: false
+        schema:
+          type: string
+        style: simple
+      - description: Pet id to delete
+        explode: false
+        in: path
+        name: petId
+        required: true
+        schema:
+          format: int64
+          type: integer
+        style: simple
+      responses:
+        "400":
+          description: Invalid pet value
+      security:
+      - petstore_auth:
+        - write:pets
+        - read:pets
+      summary: Deletes a pet
+      tags:
+      - pet
+      x-accepts: application/json
+      x-tags:
+      - tag: pet
+    get:
+      description: Returns a single pet
+      operationId: getPetById
+      parameters:
+      - description: ID of pet to return
+        explode: false
+        in: path
+        name: petId
+        required: true
+        schema:
+          format: int64
+          type: integer
+        style: simple
+      responses:
+        "200":
+          content:
+            application/xml:
+              schema:
+                $ref: '#/components/schemas/Pet'
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Pet'
+          description: successful operation
+        "400":
+          description: Invalid ID supplied
+        "404":
+          description: Pet not found
+      security:
+      - api_key: []
+      summary: Find pet by ID
+      tags:
+      - pet
+      x-accepts: application/json
+      x-tags:
+      - tag: pet
+    post:
+      description: ""
+      operationId: updatePetWithForm
+      parameters:
+      - description: ID of pet that needs to be updated
+        explode: false
+        in: path
+        name: petId
+        required: true
+        schema:
+          format: int64
+          type: integer
+        style: simple
+      requestBody:
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/updatePetWithForm_request'
+      responses:
+        "405":
+          description: Invalid input
+      security:
+      - petstore_auth:
+        - write:pets
+        - read:pets
+      summary: Updates a pet in the store with form data
+      tags:
+      - pet
+      x-content-type: application/x-www-form-urlencoded
+      x-accepts: application/json
+      x-tags:
+      - tag: pet
+  /pet/{petId}/uploadImage:
+    post:
+      description: ""
+      operationId: uploadFile
+      parameters:
+      - description: ID of pet to update
+        explode: false
+        in: path
+        name: petId
+        required: true
+        schema:
+          format: int64
+          type: integer
+        style: simple
+      requestBody:
+        content:
+          multipart/form-data:
+            schema:
+              $ref: '#/components/schemas/uploadFile_request'
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ApiResponse'
+          description: successful operation
+      security:
+      - petstore_auth:
+        - write:pets
+        - read:pets
+      summary: uploads an image
+      tags:
+      - pet
+      x-content-type: multipart/form-data
+      x-accepts: application/json
+      x-tags:
+      - tag: pet
+  /store/inventory:
+    get:
+      description: Returns a map of status codes to quantities
+      operationId: getInventory
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                additionalProperties:
+                  format: int32
+                  type: integer
+                type: object
+          description: successful operation
+      security:
+      - api_key: []
+      summary: Returns pet inventories by status
+      tags:
+      - store
+      x-accepts: application/json
+      x-tags:
+      - tag: store
+  /store/order:
+    post:
+      description: ""
+      operationId: placeOrder
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/Order'
+        description: order placed for purchasing the pet
+        required: true
+      responses:
+        "200":
+          content:
+            application/xml:
+              schema:
+                $ref: '#/components/schemas/Order'
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Order'
+          description: successful operation
+        "400":
+          description: Invalid Order
+      summary: Place an order for a pet
+      tags:
+      - store
+      x-content-type: application/json
+      x-accepts: application/json
+      x-tags:
+      - tag: store
+  /store/order/{orderId}:
+    delete:
+      description: For valid response try integer IDs with value < 1000. Anything
+        above 1000 or nonintegers will generate API errors
+      operationId: deleteOrder
+      parameters:
+      - description: ID of the order that needs to be deleted
+        explode: false
+        in: path
+        name: orderId
+        required: true
+        schema:
+          type: string
+        style: simple
+      responses:
+        "400":
+          description: Invalid ID supplied
+        "404":
+          description: Order not found
+      summary: Delete purchase order by ID
+      tags:
+      - store
+      x-accepts: application/json
+      x-tags:
+      - tag: store
+    get:
+      description: For valid response try integer IDs with value <= 5 or > 10. Other
+        values will generated exceptions
+      operationId: getOrderById
+      parameters:
+      - description: ID of pet that needs to be fetched
+        explode: false
+        in: path
+        name: orderId
+        required: true
+        schema:
+          format: int64
+          maximum: 5
+          minimum: 1
+          type: integer
+        style: simple
+      responses:
+        "200":
+          content:
+            application/xml:
+              schema:
+                $ref: '#/components/schemas/Order'
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Order'
+          description: successful operation
+        "400":
+          description: Invalid ID supplied
+        "404":
+          description: Order not found
+      summary: Find purchase order by ID
+      tags:
+      - store
+      x-accepts: application/json
+      x-tags:
+      - tag: store
+  /user:
+    post:
+      description: This can only be done by the logged in user.
+      operationId: createUser
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/User'
+        description: Created user object
+        required: true
+      responses:
+        default:
+          description: successful operation
+      security:
+      - api_key: []
+      summary: Create user
+      tags:
+      - user
+      x-content-type: application/json
+      x-accepts: application/json
+      x-tags:
+      - tag: user
+  /user/createWithArray:
+    post:
+      description: ""
+      operationId: createUsersWithArrayInput
+      requestBody:
+        $ref: '#/components/requestBodies/UserArray'
+      responses:
+        default:
+          description: successful operation
+      security:
+      - api_key: []
+      summary: Creates list of users with given input array
+      tags:
+      - user
+      x-content-type: application/json
+      x-accepts: application/json
+      x-tags:
+      - tag: user
+  /user/createWithList:
+    post:
+      description: ""
+      operationId: createUsersWithListInput
+      requestBody:
+        $ref: '#/components/requestBodies/UserArray'
+      responses:
+        default:
+          description: successful operation
+      security:
+      - api_key: []
+      summary: Creates list of users with given input array
+      tags:
+      - user
+      x-content-type: application/json
+      x-accepts: application/json
+      x-tags:
+      - tag: user
+  /user/login:
+    get:
+      description: ""
+      operationId: loginUser
+      parameters:
+      - description: The user name for login
+        explode: true
+        in: query
+        name: username
+        required: true
+        schema:
+          pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$"
+          type: string
+        style: form
+      - description: The password for login in clear text
+        explode: true
+        in: query
+        name: password
+        required: true
+        schema:
+          type: string
+        style: form
+      responses:
+        "200":
+          content:
+            application/xml:
+              schema:
+                type: string
+            application/json:
+              schema:
+                type: string
+          description: successful operation
+          headers:
+            Set-Cookie:
+              description: Cookie authentication key for use with the `api_key` apiKey
+                authentication.
+              explode: false
+              schema:
+                example: AUTH_KEY=abcde12345; Path=/; HttpOnly
+                type: string
+              style: simple
+            X-Rate-Limit:
+              description: calls per hour allowed by the user
+              explode: false
+              schema:
+                format: int32
+                type: integer
+              style: simple
+            X-Expires-After:
+              description: date in UTC when token expires
+              explode: false
+              schema:
+                format: date-time
+                type: string
+              style: simple
+        "400":
+          description: Invalid username/password supplied
+      summary: Logs user into the system
+      tags:
+      - user
+      x-accepts: application/json
+      x-tags:
+      - tag: user
+  /user/logout:
+    get:
+      description: ""
+      operationId: logoutUser
+      responses:
+        default:
+          description: successful operation
+      security:
+      - api_key: []
+      summary: Logs out current logged in user session
+      tags:
+      - user
+      x-accepts: application/json
+      x-tags:
+      - tag: user
+  /user/{username}:
+    delete:
+      description: This can only be done by the logged in user.
+      operationId: deleteUser
+      parameters:
+      - description: The name that needs to be deleted
+        explode: false
+        in: path
+        name: username
+        required: true
+        schema:
+          type: string
+        style: simple
+      responses:
+        "400":
+          description: Invalid username supplied
+        "404":
+          description: User not found
+      security:
+      - api_key: []
+      summary: Delete user
+      tags:
+      - user
+      x-accepts: application/json
+      x-tags:
+      - tag: user
+    get:
+      description: ""
+      operationId: getUserByName
+      parameters:
+      - description: The name that needs to be fetched. Use user1 for testing.
+        explode: false
+        in: path
+        name: username
+        required: true
+        schema:
+          type: string
+        style: simple
+      responses:
+        "200":
+          content:
+            application/xml:
+              schema:
+                $ref: '#/components/schemas/User'
+            application/json:
+              schema:
+                $ref: '#/components/schemas/User'
+          description: successful operation
+        "400":
+          description: Invalid username supplied
+        "404":
+          description: User not found
+      summary: Get user by user name
+      tags:
+      - user
+      x-accepts: application/json
+      x-tags:
+      - tag: user
+    put:
+      description: This can only be done by the logged in user.
+      operationId: updateUser
+      parameters:
+      - description: name that need to be deleted
+        explode: false
+        in: path
+        name: username
+        required: true
+        schema:
+          type: string
+        style: simple
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/User'
+        description: Updated user object
+        required: true
+      responses:
+        "400":
+          description: Invalid user supplied
+        "404":
+          description: User not found
+      security:
+      - api_key: []
+      summary: Updated user
+      tags:
+      - user
+      x-content-type: application/json
+      x-accepts: application/json
+      x-tags:
+      - tag: user
+components:
+  requestBodies:
+    UserArray:
+      content:
+        application/json:
+          schema:
+            items:
+              $ref: '#/components/schemas/User'
+            type: array
+      description: List of user object
+      required: true
+    Pet:
+      content:
+        application/json:
+          schema:
+            $ref: '#/components/schemas/Pet'
+        application/xml:
+          schema:
+            $ref: '#/components/schemas/Pet'
+      description: Pet object that needs to be added to the store
+      required: true
+  schemas:
+    Order:
+      description: An order for a pets from the pet store
+      example:
+        petId: 6
+        quantity: 1
+        id: 0
+        shipDate: 2000-01-23T04:56:07.000+00:00
+        complete: false
+        status: placed
+      properties:
+        id:
+          format: int64
+          type: integer
+        petId:
+          format: int64
+          type: integer
+        quantity:
+          format: int32
+          type: integer
+        shipDate:
+          format: date-time
+          type: string
+        status:
+          description: Order Status
+          enum:
+          - placed
+          - approved
+          - delivered
+          type: string
+        complete:
+          default: false
+          type: boolean
+      title: Pet Order
+      type: object
+      xml:
+        name: Order
+    Category:
+      description: A category for a pet
+      example:
+        name: name
+        id: 6
+      properties:
+        id:
+          format: int64
+          type: integer
+        name:
+          pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$"
+          type: string
+      title: Pet category
+      type: object
+      xml:
+        name: Category
+    User:
+      description: A User who is purchasing from the pet store
+      example:
+        firstName: firstName
+        lastName: lastName
+        password: password
+        userStatus: 6
+        phone: phone
+        id: 0
+        email: email
+        username: username
+      properties:
+        id:
+          format: int64
+          type: integer
+        username:
+          type: string
+        firstName:
+          type: string
+        lastName:
+          type: string
+        email:
+          type: string
+        password:
+          type: string
+        phone:
+          type: string
+        userStatus:
+          description: User Status
+          format: int32
+          type: integer
+      title: a User
+      type: object
+      xml:
+        name: User
+    Tag:
+      description: A tag for a pet
+      example:
+        name: name
+        id: 1
+      properties:
+        id:
+          format: int64
+          type: integer
+        name:
+          type: string
+      title: Pet Tag
+      type: object
+      xml:
+        name: Tag
+    Pet:
+      description: A pet for sale in the pet store
+      example:
+        photoUrls:
+        - photoUrls
+        - photoUrls
+        name: doggie
+        id: 0
+        category:
+          name: name
+          id: 6
+        tags:
+        - name: name
+          id: 1
+        - name: name
+          id: 1
+        status: available
+      properties:
+        id:
+          format: int64
+          type: integer
+        category:
+          $ref: '#/components/schemas/Category'
+        name:
+          example: doggie
+          type: string
+        photoUrls:
+          items:
+            type: string
+          type: array
+          xml:
+            name: photoUrl
+            wrapped: true
+        tags:
+          items:
+            $ref: '#/components/schemas/Tag'
+          type: array
+          xml:
+            name: tag
+            wrapped: true
+        status:
+          deprecated: true
+          description: pet status in the store
+          enum:
+          - available
+          - pending
+          - sold
+          type: string
+      required:
+      - name
+      - photoUrls
+      title: a Pet
+      type: object
+      xml:
+        name: Pet
+    ApiResponse:
+      description: Describes the result of uploading an image resource
+      example:
+        code: 0
+        type: type
+        message: message
+      properties:
+        code:
+          format: int32
+          type: integer
+        type:
+          type: string
+        message:
+          type: string
+      title: An uploaded response
+      type: object
+    updatePetWithForm_request:
+      properties:
+        name:
+          description: Updated name of the pet
+          type: string
+        status:
+          description: Updated status of the pet
+          type: string
+      type: object
+    uploadFile_request:
+      properties:
+        additionalMetadata:
+          description: Additional data to pass to server
+          type: string
+        file:
+          description: file to upload
+          format: binary
+          type: string
+      type: object
+  securitySchemes:
+    petstore_auth:
+      flows:
+        implicit:
+          authorizationUrl: http://petstore.swagger.io/api/oauth/dialog
+          scopes:
+            write:pets: modify pets in your account
+            read:pets: read your pets
+      type: oauth2
+    api_key:
+      in: header
+      name: api_key
+      type: apiKey
diff --git a/samples/openapi3/server/petstore/springboot-3/src/test/java/org/openapitools/OpenApiGeneratorApplicationTests.java b/samples/openapi3/server/petstore/springboot-3/src/test/java/org/openapitools/OpenApiGeneratorApplicationTests.java
new file mode 100644
index 00000000000..3681f67e770
--- /dev/null
+++ b/samples/openapi3/server/petstore/springboot-3/src/test/java/org/openapitools/OpenApiGeneratorApplicationTests.java
@@ -0,0 +1,13 @@
+package org.openapitools;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class OpenApiGeneratorApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}
\ No newline at end of file
-- 
GitLab


From cf482799ece26d259891f55aff604e73a0b15884 Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 11:54:58 +0200
Subject: [PATCH 06/18] Introduce useSpringBoot3 cli option.

---
 bin/configs/spring-boot-3.yaml                |  2 +-
 .../codegen/languages/SpringCodegen.java      | 31 ++++++++++++++++++-
 .../main/resources/JavaSpring/api.mustache    | 16 +++++-----
 .../JavaSpring/apiController.mustache         | 16 +++++-----
 .../resources/JavaSpring/apiDelegate.mustache |  8 ++---
 .../JavaSpring/apiException.mustache          |  8 ++---
 .../JavaSpring/apiOriginFilter.mustache       |  8 ++---
 .../JavaSpring/apiResponseMessage.mustache    |  8 ++---
 .../resources/JavaSpring/apiUtil.mustache     |  8 ++---
 .../main/resources/JavaSpring/model.mustache  | 16 +++++-----
 .../JavaSpring/notFoundException.mustache     |  8 ++---
 .../openapiDocumentationConfig.mustache       |  8 ++---
 12 files changed, 83 insertions(+), 54 deletions(-)

diff --git a/bin/configs/spring-boot-3.yaml b/bin/configs/spring-boot-3.yaml
index 4fd86ead78a..5c8b97cdad1 100644
--- a/bin/configs/spring-boot-3.yaml
+++ b/bin/configs/spring-boot-3.yaml
@@ -7,6 +7,6 @@ additionalProperties:
   documentationProvider: springdoc
   artifactId: springboot
   snapshotVersion: "true"
-  jakartaee: true
+  useSpringBoot3: true
   useBeanValidation: true
   hideGenerationTimestamp: "true"
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 60af1731663..2597c58578f 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
@@ -99,6 +99,8 @@ public class SpringCodegen extends AbstractJavaCodegen
     public static final String HATEOAS = "hateoas";
     public static final String RETURN_SUCCESS_CODE = "returnSuccessCode";
     public static final String UNHANDLED_EXCEPTION_HANDLING = "unhandledException";
+    public static final String USE_SPRING_BOOT3 = "useSpringBoot3";
+    public static final String USE_JAKARTA_EE = "useJakartaEe";
 
     public static final String OPEN_BRACE = "{";
     public static final String CLOSE_BRACE = "}";
@@ -126,6 +128,7 @@ public class SpringCodegen extends AbstractJavaCodegen
     protected boolean unhandledException = false;
     protected boolean useSpringController = false;
     protected boolean useSwaggerUI = true;
+    protected boolean useSpringBoot3 = false;
 
     public SpringCodegen() {
         super();
@@ -204,6 +207,9 @@ public class SpringCodegen extends AbstractJavaCodegen
         cliOptions.add(CliOption.newBoolean(USE_SWAGGER_UI,
             "Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies",
             useSwaggerUI));
+        cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT3,
+            "Genrate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).",
+            useSwaggerUI));
 
         supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
         supportedLibraries.put(SPRING_CLOUD_LIBRARY,
@@ -415,6 +421,16 @@ public class SpringCodegen extends AbstractJavaCodegen
         }
         additionalProperties.put(UNHANDLED_EXCEPTION_HANDLING, this.isUnhandledException());
 
+        if (additionalProperties.containsKey(USE_SPRING_BOOT3)) {
+            this.setUseSpringBoot3(convertPropertyToBoolean(USE_SPRING_BOOT3));
+        }
+        if (isUseSpringBoot3()) {
+            writePropertyBack(USE_JAKARTA_EE, true);
+        } else {
+            writePropertyBack(USE_JAKARTA_EE, false);
+        }
+        writePropertyBack(USE_SPRING_BOOT3, isUseSpringBoot3());
+
         typeMapping.put("file", "org.springframework.core.io.Resource");
         importMapping.put("org.springframework.core.io.Resource", "org.springframework.core.io.Resource");
         importMapping.put("Pageable", "org.springframework.data.domain.Pageable");
@@ -431,7 +447,12 @@ public class SpringCodegen extends AbstractJavaCodegen
             additionalProperties.put("delegate-method", true);
         }
 
-        supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
+        if (isUseSpringBoot3()) {
+            supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
+        } else {
+            supportingFiles.add(new SupportingFile("pom-sb2.mustache", "", "pom.xml"));
+        }
+
         supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
 
         if (!interfaceOnly) {
@@ -1045,4 +1066,12 @@ public class SpringCodegen extends AbstractJavaCodegen
         extensions.add(VendorExtension.X_SPRING_PAGINATED);
         return extensions;
     }
+
+    public boolean isUseSpringBoot3() {
+        return useSpringBoot3;
+    }
+
+    public void setUseSpringBoot3(boolean useSpringBoot3) {
+        this.useSpringBoot3 = useSpringBoot3;
+    }
 }
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache
index 4eedc52fa6b..ca2aa103c87 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache
@@ -50,14 +50,14 @@ import org.springframework.http.codec.multipart.Part;
 {{/reactive}}
 
 {{#useBeanValidation}}
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.*;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.validation.Valid;
 import javax.validation.constraints.*;
-{{/jakartaee}}
+{{/useJakartaEe}}
 {{/useBeanValidation}}
 import java.util.List;
 import java.util.Map;
@@ -72,12 +72,12 @@ import java.util.Optional;
 {{#async}}
 import java.util.concurrent.CompletableFuture;
 {{/async}}
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.annotation.Generated;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.annotation.Generated;
-{{/jakartaee}}
+{{/useJakartaEe}}
 
 {{>generatedAnnotation}}
 {{#useBeanValidation}}
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache
index 87d4efe6f28..6f348a15a25 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache
@@ -36,25 +36,25 @@ import org.springframework.web.context.request.NativeWebRequest;
 {{/isDelegate}}
 
 {{#useBeanValidation}}
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.*;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.validation.constraints.*;
 import javax.validation.Valid;
-{{/jakartaee}}
+{{/useJakartaEe}}
 {{/useBeanValidation}}
 
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.annotation.Generated;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.annotation.Generated;
-{{/jakartaee}}
+{{/useJakartaEe}}
 
 {{>generatedAnnotation}}
 @Controller
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache
index 79707c7303e..b59f8bd01bf 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache
@@ -20,12 +20,12 @@ import java.util.Optional;
 {{#async}}
 import java.util.concurrent.CompletableFuture;
 {{/async}}
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.annotation.Generated;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.annotation.Generated;
-{{/jakartaee}}
+{{/useJakartaEe}}
 
 {{#operations}}
 /**
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiException.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiException.mustache
index 658871c2158..9fe41f182e4 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiException.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiException.mustache
@@ -1,11 +1,11 @@
 package {{apiPackage}};
 
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.annotation.Generated;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.annotation.Generated;
-{{/jakartaee}}
+{{/useJakartaEe}}
 
 /**
  * The exception that can be used to store the HTTP status code returned by an API response.
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache
index ba92c5fe167..149e566718f 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiOriginFilter.mustache
@@ -2,14 +2,14 @@ package {{apiPackage}};
 
 import java.io.IOException;
 
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.annotation.Generated;
 import jakarta.servlet.*;
 import jakarta.servlet.http.HttpServletResponse;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.annotation.Generated;
-{{/jakartaee}}
+{{/useJakartaEe}}
 
 {{>generatedAnnotation}}
 public class ApiOriginFilter implements javax.servlet.Filter {
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiResponseMessage.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiResponseMessage.mustache
index 7f0af57e135..2d22a425f3a 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiResponseMessage.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiResponseMessage.mustache
@@ -1,11 +1,11 @@
 package {{apiPackage}};
 
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.annotation.Generated;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.annotation.Generated;
-{{/jakartaee}}
+{{/useJakartaEe}}
 import javax.xml.bind.annotation.XmlTransient;
 
 {{>generatedAnnotation}}
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache
index b377f85dd2c..597ab6ecff5 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache
@@ -12,12 +12,12 @@ import reactor.core.publisher.Mono;
 {{^reactive}}
 import org.springframework.web.context.request.NativeWebRequest;
 
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.servlet.http.HttpServletResponse;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.servlet.http.HttpServletResponse;
-{{/jakartaee}}
+{{/useJakartaEe}}
 
 import java.io.IOException;
 {{/reactive}}
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache
index 891de413133..9cf46316b94 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/model.mustache
@@ -12,14 +12,14 @@ import java.io.Serializable;
 {{/serializableModel}}
 import java.time.OffsetDateTime;
 {{#useBeanValidation}}
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.*;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.validation.Valid;
 import javax.validation.constraints.*;
-{{/jakartaee}}
+{{/useJakartaEe}}
 {{/useBeanValidation}}
 {{#performBeanValidation}}
 import org.hibernate.validator.constraints.*;
@@ -44,12 +44,12 @@ import org.springframework.hateoas.RepresentationModel;
 {{/parent}}
 
 import java.util.*;
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.annotation.Generated;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.annotation.Generated;
-{{/jakartaee}}
+{{/useJakartaEe}}
 
 {{#models}}
 {{#model}}
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/notFoundException.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/notFoundException.mustache
index 57fe42f0586..11ad8c965ff 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/notFoundException.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/notFoundException.mustache
@@ -1,11 +1,11 @@
 package {{apiPackage}};
 
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.annotation.Generated;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.annotation.Generated;
-{{/jakartaee}}
+{{/useJakartaEe}}
 
 {{>generatedAnnotation}}
 public class NotFoundException extends ApiException {
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
index 18d67005e18..e9ce206c76b 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
@@ -19,14 +19,14 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
 import java.util.Optional;
 {{/useOptional}}
 
-{{#jakartaee}}
+{{#useJakartaEe}}
 import jakarta.annotation.Generated;
 import jakarta.servlet.ServletContext;
-{{/jakartaee}}
-{{^jakartaee}}
+{{/useJakartaEe}}
+{{^useJakartaEe}}
 import javax.annotation.Generated;
 import javax.servlet.ServletContext;
-{{/jakartaee}}
+{{/useJakartaEe}}
 
 {{>generatedAnnotation}}
 @Configuration
-- 
GitLab


From 395a0ce8d80810debacd20c30762430abe02f6e2 Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 11:59:40 +0200
Subject: [PATCH 07/18] Generate Docs

---
 docs/generators/java-camel.md | 1 +
 docs/generators/spring.md     | 1 +
 2 files changed, 2 insertions(+)

diff --git a/docs/generators/java-camel.md b/docs/generators/java-camel.md
index 69d3472e489..5ddede2f74e 100644
--- a/docs/generators/java-camel.md
+++ b/docs/generators/java-camel.md
@@ -91,6 +91,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
 |useBeanValidation|Use BeanValidation API annotations| |true|
 |useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
 |useOptional|Use Optional container for optional parameters| |false|
+|useSpringBoot3|Genrate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).| |true|
 |useSpringController|Annotate the generated API as a Spring Controller| |false|
 |useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|
 |useTags|use tags for creating interface and controller classnames| |false|
diff --git a/docs/generators/spring.md b/docs/generators/spring.md
index 68bc8ce3209..adc740402d6 100644
--- a/docs/generators/spring.md
+++ b/docs/generators/spring.md
@@ -84,6 +84,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
 |useBeanValidation|Use BeanValidation API annotations| |true|
 |useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
 |useOptional|Use Optional container for optional parameters| |false|
+|useSpringBoot3|Genrate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).| |true|
 |useSpringController|Annotate the generated API as a Spring Controller| |false|
 |useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|
 |useTags|use tags for creating interface and controller classnames| |false|
-- 
GitLab


From d9e3155e5c5ad168412879d1bedf0b3f69078bdd Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 12:03:34 +0200
Subject: [PATCH 08/18] Add spring milestone repo

---
 .../codegen/languages/SpringCodegen.java      |  4 +-
 .../resources/JavaSpring/apiUtil.mustache     |  1 -
 .../{pom-sb2.mustache => pom-sb3.mustache}    | 44 ++++++-------------
 .../libraries/spring-boot/pom.mustache        | 35 ++++++++++++---
 .../openapiDocumentationConfig.mustache       |  1 -
 5 files changed, 46 insertions(+), 39 deletions(-)
 rename modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/{pom-sb2.mustache => pom-sb3.mustache} (83%)

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 2597c58578f..0e7b5b25657 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
@@ -448,9 +448,9 @@ public class SpringCodegen extends AbstractJavaCodegen
         }
 
         if (isUseSpringBoot3()) {
-            supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
+            supportingFiles.add(new SupportingFile("pom-sb3.mustache", "", "pom.xml"));
         } else {
-            supportingFiles.add(new SupportingFile("pom-sb2.mustache", "", "pom.xml"));
+            supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
         }
 
         supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache
index 597ab6ecff5..d7c7819dba1 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiUtil.mustache
@@ -18,7 +18,6 @@ import jakarta.servlet.http.HttpServletResponse;
 {{^useJakartaEe}}
 import javax.servlet.http.HttpServletResponse;
 {{/useJakartaEe}}
-
 import java.io.IOException;
 {{/reactive}}
 
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb2.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache
similarity index 83%
rename from modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb2.mustache
rename to modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache
index f2dbeac4499..d1a9410526a 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb2.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache
@@ -6,26 +6,18 @@
     <name>{{artifactId}}</name>
     <version>{{artifactVersion}}</version>
     <properties>
-        <java.version>1.8</java.version>
+        <java.version>17</java.version>
         <maven.compiler.source>${java.version}</maven.compiler.source>
         <maven.compiler.target>${java.version}</maven.compiler.target>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        {{#springFoxDocumentationProvider}}
-        <springfox.version>2.9.2</springfox.version>
-        {{/springFoxDocumentationProvider}}
         {{#springDocDocumentationProvider}}
-        <springdoc.version>1.6.6</springdoc.version>
+        <springdoc.version>2.0.0-M2</springdoc.version>
         {{/springDocDocumentationProvider}}
-        {{^springFoxDocumentationProvider}}
         {{^springDocDocumentationProvider}}
-        {{#swagger1AnnotationLibrary}}
-        <swagger-annotations.version>1.6.5</swagger-annotations.version>
-        {{/swagger1AnnotationLibrary}}
         {{#swagger2AnnotationLibrary}}
         <swagger-annotations.version>}2.1.13</swagger-annotations.version>
         {{/swagger2AnnotationLibrary}}
         {{/springDocDocumentationProvider}}
-        {{/springFoxDocumentationProvider}}
         {{#useSwaggerUI}}
         <swagger-ui.version>4.8.1</swagger-ui.version>
         {{/useSwaggerUI}}
@@ -41,10 +33,19 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>{{#springFoxDocumentationProvider}}2.5.12{{/springFoxDocumentationProvider}}{{^springFoxDocumentationProvider}}2.6.6{{/springFoxDocumentationProvider}}</version>
+        <version>3.0.0-M2</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
 {{/parentOverridden}}
+
+    <repositories>
+        <repository>
+            <id>repository.spring.milestone</id>
+            <name>Spring Milestone Repository</name>
+            <url>http://repo.spring.io/milestone</url>
+        </repository>
+    </repositories>
+
     <build>
         <sourceDirectory>src/main/java</sourceDirectory>
         {{^interfaceOnly}}
@@ -107,26 +108,18 @@
         {{#useSwaggerUI}}
         <dependency>
             <groupId>org.springdoc</groupId>
-            <artifactId>springdoc-openapi-{{#reactive}}webflux-{{/reactive}}ui</artifactId>
+            <artifactId>springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-ui</artifactId>
             <version>${springdoc.version}</version>
         </dependency>
         {{/useSwaggerUI}}
         {{^useSwaggerUI}}
         <dependency>
             <groupId>org.springdoc</groupId>
-            <artifactId>springdoc-openapi-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-core</artifactId>
+          <artifactId>springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-api</artifactId>
             <version>${springdoc.version}</version>
         </dependency>
         {{/useSwaggerUI}}
         {{/springDocDocumentationProvider}}
-        {{#springFoxDocumentationProvider}}
-        <!--SpringFox dependencies -->
-        <dependency>
-            <groupId>io.springfox</groupId>
-            <artifactId>springfox-swagger2</artifactId>
-            <version>${springfox.version}</version>
-        </dependency>
-        {{/springFoxDocumentationProvider}}
         {{#useSwaggerUI}}
         {{^springDocDocumentationProvider}}
         <dependency>
@@ -140,15 +133,7 @@
         </dependency>
         {{/springDocDocumentationProvider}}
         {{/useSwaggerUI}}
-        {{^springFoxDocumentationProvider}}
         {{^springDocDocumentationProvider}}
-        {{#swagger1AnnotationLibrary}}
-        <dependency>
-            <groupId>io.swagger</groupId>
-            <artifactId>swagger-annotations</artifactId>
-            <version>${swagger-annotations.version}</version>
-        </dependency>
-        {{/swagger1AnnotationLibrary}}
         {{#swagger2AnnotationLibrary}}
         <dependency>
             <groupId>io.swagger.core.v3</groupId>
@@ -157,7 +142,6 @@
         </dependency>
         {{/swagger2AnnotationLibrary}}
         {{/springDocDocumentationProvider}}
-        {{/springFoxDocumentationProvider}}
         <!-- @Nullable annotation -->
         <dependency>
             <groupId>com.google.code.findbugs</groupId>
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom.mustache
index 5da0cd024a4..f2dbeac4499 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom.mustache
@@ -6,18 +6,26 @@
     <name>{{artifactId}}</name>
     <version>{{artifactVersion}}</version>
     <properties>
-        <java.version>17</java.version>
+        <java.version>1.8</java.version>
         <maven.compiler.source>${java.version}</maven.compiler.source>
         <maven.compiler.target>${java.version}</maven.compiler.target>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        {{#springFoxDocumentationProvider}}
+        <springfox.version>2.9.2</springfox.version>
+        {{/springFoxDocumentationProvider}}
         {{#springDocDocumentationProvider}}
-        <springdoc.version>2.0.0-M2</springdoc.version>
+        <springdoc.version>1.6.6</springdoc.version>
         {{/springDocDocumentationProvider}}
+        {{^springFoxDocumentationProvider}}
         {{^springDocDocumentationProvider}}
+        {{#swagger1AnnotationLibrary}}
+        <swagger-annotations.version>1.6.5</swagger-annotations.version>
+        {{/swagger1AnnotationLibrary}}
         {{#swagger2AnnotationLibrary}}
         <swagger-annotations.version>}2.1.13</swagger-annotations.version>
         {{/swagger2AnnotationLibrary}}
         {{/springDocDocumentationProvider}}
+        {{/springFoxDocumentationProvider}}
         {{#useSwaggerUI}}
         <swagger-ui.version>4.8.1</swagger-ui.version>
         {{/useSwaggerUI}}
@@ -33,7 +41,7 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>3.0.0-M2</version>
+        <version>{{#springFoxDocumentationProvider}}2.5.12{{/springFoxDocumentationProvider}}{{^springFoxDocumentationProvider}}2.6.6{{/springFoxDocumentationProvider}}</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
 {{/parentOverridden}}
@@ -99,18 +107,26 @@
         {{#useSwaggerUI}}
         <dependency>
             <groupId>org.springdoc</groupId>
-            <artifactId>springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-ui</artifactId>
+            <artifactId>springdoc-openapi-{{#reactive}}webflux-{{/reactive}}ui</artifactId>
             <version>${springdoc.version}</version>
         </dependency>
         {{/useSwaggerUI}}
         {{^useSwaggerUI}}
         <dependency>
             <groupId>org.springdoc</groupId>
-          <artifactId>springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-api</artifactId>
+            <artifactId>springdoc-openapi-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-core</artifactId>
             <version>${springdoc.version}</version>
         </dependency>
         {{/useSwaggerUI}}
         {{/springDocDocumentationProvider}}
+        {{#springFoxDocumentationProvider}}
+        <!--SpringFox dependencies -->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>${springfox.version}</version>
+        </dependency>
+        {{/springFoxDocumentationProvider}}
         {{#useSwaggerUI}}
         {{^springDocDocumentationProvider}}
         <dependency>
@@ -124,7 +140,15 @@
         </dependency>
         {{/springDocDocumentationProvider}}
         {{/useSwaggerUI}}
+        {{^springFoxDocumentationProvider}}
         {{^springDocDocumentationProvider}}
+        {{#swagger1AnnotationLibrary}}
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>${swagger-annotations.version}</version>
+        </dependency>
+        {{/swagger1AnnotationLibrary}}
         {{#swagger2AnnotationLibrary}}
         <dependency>
             <groupId>io.swagger.core.v3</groupId>
@@ -133,6 +157,7 @@
         </dependency>
         {{/swagger2AnnotationLibrary}}
         {{/springDocDocumentationProvider}}
+        {{/springFoxDocumentationProvider}}
         <!-- @Nullable annotation -->
         <dependency>
             <groupId>com.google.code.findbugs</groupId>
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
index e9ce206c76b..e33af717562 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache
@@ -18,7 +18,6 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
 {{#useOptional}}
 import java.util.Optional;
 {{/useOptional}}
-
 {{#useJakartaEe}}
 import jakarta.annotation.Generated;
 import jakarta.servlet.ServletContext;
-- 
GitLab


From 7952838aa7eb3c67cae80d872c148be0d7dc9292 Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 12:09:09 +0200
Subject: [PATCH 09/18] Generate Samples

---
 samples/openapi3/server/petstore/springboot-3/pom.xml    | 9 +++++++++
 .../src/main/java/org/openapitools/api/ApiUtil.java      | 1 -
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/samples/openapi3/server/petstore/springboot-3/pom.xml b/samples/openapi3/server/petstore/springboot-3/pom.xml
index 69a1674165b..c9c3d4ec746 100644
--- a/samples/openapi3/server/petstore/springboot-3/pom.xml
+++ b/samples/openapi3/server/petstore/springboot-3/pom.xml
@@ -19,6 +19,15 @@
         <version>3.0.0-M2</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
+
+    <repositories>
+        <repository>
+            <id>repository.spring.milestone</id>
+            <name>Spring Milestone Repository</name>
+            <url>http://repo.spring.io/milestone</url>
+        </repository>
+    </repositories>
+
     <build>
         <sourceDirectory>src/main/java</sourceDirectory>
         <plugins>
diff --git a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/ApiUtil.java b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/ApiUtil.java
index 9ecf171bc47..9bcd4f230ed 100644
--- a/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/ApiUtil.java
+++ b/samples/openapi3/server/petstore/springboot-3/src/main/java/org/openapitools/api/ApiUtil.java
@@ -3,7 +3,6 @@ package org.openapitools.api;
 import org.springframework.web.context.request.NativeWebRequest;
 
 import jakarta.servlet.http.HttpServletResponse;
-
 import java.io.IOException;
 
 public class ApiUtil {
-- 
GitLab


From f6eb32934d589d80b13ffc14e4376ef9b31e4850 Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 12:20:33 +0200
Subject: [PATCH 10/18] Adjust Unit Tests

---
 .../openapitools/codegen/java/spring/SpringCodegenTest.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

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 997d2335e3f..51fef65c2a7 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
@@ -684,12 +684,12 @@ public class SpringCodegenTest {
 
     @Test
     public void useBeanValidationTruePerformBeanValidationFalseJava8TrueForFormatEmail() throws IOException {
-        beanValidationForFormatEmail(true, false, true, "@javax.validation.constraints.Email", "@org.hibernate.validator.constraints.Email");
+        beanValidationForFormatEmail(true, false, true, "@Email", "@org.hibernate.validator.constraints.Email");
     }
 
     @Test
     public void useBeanValidationTruePerformBeanValidationTrueJava8FalseForFormatEmail() throws IOException {
-        beanValidationForFormatEmail(true, true, false, "@javax.validation.constraints.Email", "@org.hibernate.validator.constraints.Email");
+        beanValidationForFormatEmail(true, true, false, "@Email", "@org.hibernate.validator.constraints.Email");
     }
 
     // note: java8 option/mustache tag has been removed and default to true
@@ -726,7 +726,7 @@ public class SpringCodegenTest {
 
     @Test
     public void useBeanValidationTruePerformBeanValidationTrueJava8TrueForFormatEmail() throws IOException {
-        beanValidationForFormatEmail(true, true, true, "@javax.validation.constraints.Email", "@org.hibernate.validator.constraints.Email");
+        beanValidationForFormatEmail(true, true, true, "@Email", "@org.hibernate.validator.constraints.Email");
     }
 
     @Test
-- 
GitLab


From 086808edec842472241185a0e340f0840b673a65 Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 13:02:42 +0200
Subject: [PATCH 11/18] Add Spring Boot 3 Support to spring-cloud library

---
 bin/configs/spring-cloud-3.yaml               |  13 ++
 .../libraries/spring-boot/pom-sb3.mustache    |   2 +-
 .../libraries/spring-cloud/pom-sb3.mustache   | 151 ++++++++++++++++++
 3 files changed, 165 insertions(+), 1 deletion(-)
 create mode 100644 bin/configs/spring-cloud-3.yaml
 create mode 100644 modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache

diff --git a/bin/configs/spring-cloud-3.yaml b/bin/configs/spring-cloud-3.yaml
new file mode 100644
index 00000000000..392f4389537
--- /dev/null
+++ b/bin/configs/spring-cloud-3.yaml
@@ -0,0 +1,13 @@
+generatorName: spring
+library: spring-cloud
+outputDir: samples/openapi3/client/petstore/spring-cloud-3
+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: spring-cloud-oas3
+  useSpringBoot3: "true"
+  interfaceOnly: "true"
+  singleContentTypes: "true"
+  hideGenerationTimestamp: "true"
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache
index d1a9410526a..207e2680551 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache
@@ -15,7 +15,7 @@
         {{/springDocDocumentationProvider}}
         {{^springDocDocumentationProvider}}
         {{#swagger2AnnotationLibrary}}
-        <swagger-annotations.version>}2.1.13</swagger-annotations.version>
+        <swagger-annotations.version>}2.2.0</swagger-annotations.version>
         {{/swagger2AnnotationLibrary}}
         {{/springDocDocumentationProvider}}
         {{#useSwaggerUI}}
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache
new file mode 100644
index 00000000000..7071b64a966
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache
@@ -0,0 +1,151 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>{{groupId}}</groupId>
+    <artifactId>{{artifactId}}</artifactId>
+    <packaging>jar</packaging>
+    <name>{{artifactId}}</name>
+    <version>{{artifactVersion}}</version>
+    <properties>
+        <java.version>1.8</java.version>
+        <maven.compiler.source>${java.version}</maven.compiler.source>
+        <maven.compiler.target>${java.version}</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        {{#springDocDocumentationProvider}}
+        <springdoc.version>2.0.0-M2</springdoc.version>
+        {{/springDocDocumentationProvider}}
+        {{^springFoxDocumentationProvider}}
+        {{^springDocDocumentationProvider}}
+        {{#swagger2AnnotationLibrary}}
+        <swagger-annotations.version>}2.2.0</swagger-annotations.version>
+        {{/swagger2AnnotationLibrary}}
+        {{/springDocDocumentationProvider}}
+        {{/springFoxDocumentationProvider}}
+    </properties>
+{{#parentOverridden}}
+    <parent>
+        <groupId>{{{parentGroupId}}}</groupId>
+        <artifactId>{{{parentArtifactId}}}</artifactId>
+        <version>{{{parentVersion}}}</version>
+    </parent>
+{{/parentOverridden}}
+{{^parentOverridden}}
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>3.0.0-M2</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+{{/parentOverridden}}
+
+    <repositories>
+        <repository>
+            <id>repository.spring.milestone</id>
+            <name>Spring Milestone Repository</name>
+            <url>http://repo.spring.io/milestone</url>
+        </repository>
+    </repositories>
+
+    <build>
+        <sourceDirectory>src/main/java</sourceDirectory>
+    </build>
+
+{{^parentOverridden}}
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.cloud</groupId>
+                <artifactId>spring-cloud-starter-parent</artifactId>
+                <version>2022.0.0-M2</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+{{/parentOverridden}}
+    <dependencies>
+        {{#springDocDocumentationProvider}}
+        <!--SpringDoc dependencies -->
+          <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-ui</artifactId>
+            <version>${springdoc.version}</version>
+          </dependency>
+        {{/springDocDocumentationProvider}}
+        {{^springDocDocumentationProvider}}
+        {{#swagger2AnnotationLibrary}}
+        <dependency>
+            <groupId>io.swagger.core.v3</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>${swagger-annotations.version}</version>
+        </dependency>
+        {{/swagger2AnnotationLibrary}}
+        {{/springDocDocumentationProvider}}
+        <!-- @Nullable annotation -->
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            {{^parentOverridden}}
+            <version>3.0.2</version>
+            {{/parentOverridden}}
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-oauth2</artifactId>
+            {{^parentOverridden}}
+            <version>2.2.5.RELEASE</version>
+            {{/parentOverridden}}
+        </dependency>
+        {{#withXml}}
+        <!-- XML processing: Jackson -->
+        <dependency>
+          <groupId>com.fasterxml.jackson.dataformat</groupId>
+          <artifactId>jackson-dataformat-xml</artifactId>
+        </dependency>
+        {{/withXml}}
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
+        {{#joda}}
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-joda</artifactId>
+        </dependency>
+        {{/joda}}
+        {{#openApiNullable}}
+        <dependency>
+            <groupId>org.openapitools</groupId>
+            <artifactId>jackson-databind-nullable</artifactId>
+        {{^parentOverridden}}
+            <version>0.2.2</version>
+        {{/parentOverridden}}
+        </dependency>
+        {{/openApiNullable}}
+        {{#hateoas}}
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-hateoas</artifactId>
+        </dependency>
+        {{/hateoas}}
+        {{#useBeanValidation}}
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+        {{/useBeanValidation}}
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-commons</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
-- 
GitLab


From 031af01bff2143e7c35c8dbda8584f3ba660966a Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 13:03:27 +0200
Subject: [PATCH 12/18] generate spring cloud 3 sample

---
 .../spring-cloud-3/.openapi-generator-ignore  |  23 ++
 .../spring-cloud-3/.openapi-generator/FILES   |  11 +
 .../spring-cloud-3/.openapi-generator/VERSION |   1 +
 .../client/petstore/spring-cloud-3/README.md  |  26 ++
 .../client/petstore/spring-cloud-3/pom.xml    |  91 ++++++
 .../java/org/openapitools/api/PetApi.java     | 307 ++++++++++++++++++
 .../java/org/openapitools/api/StoreApi.java   | 155 +++++++++
 .../java/org/openapitools/api/UserApi.java    | 273 ++++++++++++++++
 .../java/org/openapitools/model/Category.java | 108 ++++++
 .../openapitools/model/ModelApiResponse.java  | 134 ++++++++
 .../java/org/openapitools/model/Order.java    | 245 ++++++++++++++
 .../main/java/org/openapitools/model/Pet.java | 261 +++++++++++++++
 .../main/java/org/openapitools/model/Tag.java | 108 ++++++
 .../java/org/openapitools/model/User.java     | 252 ++++++++++++++
 14 files changed, 1995 insertions(+)
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator-ignore
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator/FILES
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator/VERSION
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/README.md
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/pom.xml
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/PetApi.java
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/StoreApi.java
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/UserApi.java
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Category.java
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/ModelApiResponse.java
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Order.java
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Pet.java
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Tag.java
 create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/User.java

diff --git a/samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator-ignore b/samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator-ignore
new file mode 100644
index 00000000000..7484ee590a3
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/.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/.openapi-generator/FILES b/samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator/FILES
new file mode 100644
index 00000000000..5e5e7f60456
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator/FILES
@@ -0,0 +1,11 @@
+README.md
+pom.xml
+src/main/java/org/openapitools/api/PetApi.java
+src/main/java/org/openapitools/api/StoreApi.java
+src/main/java/org/openapitools/api/UserApi.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/.openapi-generator/VERSION b/samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator/VERSION
new file mode 100644
index 00000000000..5f68295fc19
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator/VERSION
@@ -0,0 +1 @@
+6.0.0-SNAPSHOT
\ No newline at end of file
diff --git a/samples/openapi3/client/petstore/spring-cloud-3/README.md b/samples/openapi3/client/petstore/spring-cloud-3/README.md
new file mode 100644
index 00000000000..a462be951ac
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/README.md
@@ -0,0 +1,26 @@
+# OpenAPI generated API stub
+
+Spring Framework stub
+
+
+## Overview
+This code was generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
+By using the [OpenAPI-Spec](https://openapis.org), you can easily generate an API stub.
+This is an example of building API stub interfaces in Java using the Spring framework.
+
+The stubs generated can be used in your existing Spring-MVC or Spring-Boot application to create controller endpoints
+by adding ```@Controller``` classes that implement the interface. Eg:
+```java
+@Controller
+public class PetController implements PetApi {
+// implement all PetApi methods
+}
+```
+
+You can also use the interface to create [Spring-Cloud Feign clients](http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign-inheritance).Eg:
+```java
+@FeignClient(name="pet", url="http://petstore.swagger.io/v2")
+public interface PetClient extends PetApi {
+
+}
+```
diff --git a/samples/openapi3/client/petstore/spring-cloud-3/pom.xml b/samples/openapi3/client/petstore/spring-cloud-3/pom.xml
new file mode 100644
index 00000000000..679e0c8ce3c
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/pom.xml
@@ -0,0 +1,91 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.openapitools.openapi3</groupId>
+    <artifactId>spring-cloud-oas3</artifactId>
+    <packaging>jar</packaging>
+    <name>spring-cloud-oas3</name>
+    <version>1.0.0</version>
+    <properties>
+        <java.version>1.8</java.version>
+        <maven.compiler.source>${java.version}</maven.compiler.source>
+        <maven.compiler.target>${java.version}</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <springdoc.version>2.0.0-M2</springdoc.version>
+    </properties>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>3.0.0-M2</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <repositories>
+        <repository>
+            <id>repository.spring.milestone</id>
+            <name>Spring Milestone Repository</name>
+            <url>http://repo.spring.io/milestone</url>
+        </repository>
+    </repositories>
+
+    <build>
+        <sourceDirectory>src/main/java</sourceDirectory>
+    </build>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.cloud</groupId>
+                <artifactId>spring-cloud-starter-parent</artifactId>
+                <version>2022.0.0-M2</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <!--SpringDoc dependencies -->
+          <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
+            <version>${springdoc.version}</version>
+          </dependency>
+        <!-- @Nullable annotation -->
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <version>3.0.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-oauth2</artifactId>
+            <version>2.2.5.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.openapitools</groupId>
+            <artifactId>jackson-databind-nullable</artifactId>
+            <version>0.2.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-commons</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/PetApi.java b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/PetApi.java
new file mode 100644
index 00000000000..6a4162bd6e7
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/PetApi.java
@@ -0,0 +1,307 @@
+/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (6.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 io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+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;
+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
+@Tag(name = "Pet", description = "Everything about your Pets")
+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)
+     */
+    @Operation(
+        operationId = "addPet",
+        summary = "Add a new pet to the store",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Pet.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))
+            }),
+            @ApiResponse(responseCode = "405", description = "Invalid input")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "write:pets", "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/pet",
+        produces = "application/json",
+        consumes = "application/json"
+    )
+    ResponseEntity<Pet> addPet(
+        @Parameter(name = "Pet", description = "Pet object that needs to be added to the store", required = true) @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)
+     */
+    @Operation(
+        operationId = "deletePet",
+        summary = "Deletes a pet",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "400", description = "Invalid pet value")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "write:pets", "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.DELETE,
+        value = "/pet/{petId}"
+    )
+    ResponseEntity<Void> deletePet(
+        @Parameter(name = "petId", description = "Pet id to delete", required = true) @PathVariable("petId") Long petId,
+        @Parameter(name = "api_key", description = "") @RequestHeader(value = "api_key", required = false) String 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)
+     */
+    @Operation(
+        operationId = "findPetsByStatus",
+        summary = "Finds Pets by status",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Pet.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid status value")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/pet/findByStatus",
+        produces = "application/json"
+    )
+    ResponseEntity<List<Pet>> findPetsByStatus(
+        @NotNull @Parameter(name = "status", description = "Status values that need to be considered for filter", required = true) @Valid @RequestParam(value = "status", required = true) List<String> 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
+     */
+    @Operation(
+        operationId = "findPetsByTags",
+        summary = "Finds Pets by tags",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Pet.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid tag value")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/pet/findByTags",
+        produces = "application/json"
+    )
+    ResponseEntity<List<Pet>> findPetsByTags(
+        @NotNull @Parameter(name = "tags", description = "Tags to filter by", required = true) @Valid @RequestParam(value = "tags", required = true) List<String> 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)
+     */
+    @Operation(
+        operationId = "getPetById",
+        summary = "Find pet by ID",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Pet.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
+            @ApiResponse(responseCode = "404", description = "Pet not found")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/pet/{petId}",
+        produces = "application/json"
+    )
+    ResponseEntity<Pet> getPetById(
+        @Parameter(name = "petId", description = "ID of pet to return", required = true) @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)
+     */
+    @Operation(
+        operationId = "updatePet",
+        summary = "Update an existing pet",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Pet.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
+            @ApiResponse(responseCode = "404", description = "Pet not found"),
+            @ApiResponse(responseCode = "405", description = "Validation exception")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "write:pets", "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.PUT,
+        value = "/pet",
+        produces = "application/json",
+        consumes = "application/json"
+    )
+    ResponseEntity<Pet> updatePet(
+        @Parameter(name = "Pet", description = "Pet object that needs to be added to the store", required = true) @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)
+     */
+    @Operation(
+        operationId = "updatePetWithForm",
+        summary = "Updates a pet in the store with form data",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "405", description = "Invalid input")
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "write:pets", "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/pet/{petId}",
+        consumes = "application/x-www-form-urlencoded"
+    )
+    ResponseEntity<Void> updatePetWithForm(
+        @Parameter(name = "petId", description = "ID of pet that needs to be updated", required = true) @PathVariable("petId") Long petId,
+        @Parameter(name = "name", description = "Updated name of the pet") @Valid @RequestParam(value = "name", required = false) String name,
+        @Parameter(name = "status", description = "Updated status of the pet") @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)
+     */
+    @Operation(
+        operationId = "uploadFile",
+        summary = "uploads an image",
+        tags = { "pet" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/json", schema = @Schema(implementation = ModelApiResponse.class))
+            })
+        },
+        security = {
+            @SecurityRequirement(name = "petstore_auth", scopes={ "write:pets", "read:pets" })
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/pet/{petId}/uploadImage",
+        produces = "application/json",
+        consumes = "multipart/form-data"
+    )
+    ResponseEntity<ModelApiResponse> uploadFile(
+        @Parameter(name = "petId", description = "ID of pet to update", required = true) @PathVariable("petId") Long petId,
+        @Parameter(name = "additionalMetadata", description = "Additional data to pass to server") @Valid @RequestParam(value = "additionalMetadata", required = false) String additionalMetadata,
+        @Parameter(name = "file", description = "file to upload") @RequestPart(value = "file", required = false) MultipartFile file
+    );
+
+}
diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/StoreApi.java b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/StoreApi.java
new file mode 100644
index 00000000000..62ec9c20082
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/StoreApi.java
@@ -0,0 +1,155 @@
+/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (6.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 io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+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;
+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
+@Tag(name = "Store", description = "Access to Petstore orders")
+public interface StoreApi {
+
+    /**
+     * DELETE /store/order/{orderId} : Delete purchase order by ID
+     * For valid response try integer IDs with value &lt; 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)
+     */
+    @Operation(
+        operationId = "deleteOrder",
+        summary = "Delete purchase order by ID",
+        tags = { "store" },
+        responses = {
+            @ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
+            @ApiResponse(responseCode = "404", description = "Order not found")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.DELETE,
+        value = "/store/order/{orderId}"
+    )
+    ResponseEntity<Void> deleteOrder(
+        @Parameter(name = "orderId", description = "ID of the order that needs to be deleted", required = true) @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)
+     */
+    @Operation(
+        operationId = "getInventory",
+        summary = "Returns pet inventories by status",
+        tags = { "store" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Map.class))
+            })
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/store/inventory",
+        produces = "application/json"
+    )
+    ResponseEntity<Map<String, Integer>> getInventory(
+        
+    );
+
+
+    /**
+     * GET /store/order/{orderId} : Find purchase order by ID
+     * For valid response try integer IDs with value &lt;&#x3D; 5 or &gt; 10. Other values will generated exceptions
+     *
+     * @param orderId ID of pet that needs to be fetched (required)
+     * @return successful operation (status code 200)
+     *         or Invalid ID supplied (status code 400)
+     *         or Order not found (status code 404)
+     */
+    @Operation(
+        operationId = "getOrderById",
+        summary = "Find purchase order by ID",
+        tags = { "store" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Order.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Order.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
+            @ApiResponse(responseCode = "404", description = "Order not found")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/store/order/{orderId}",
+        produces = "application/json"
+    )
+    ResponseEntity<Order> getOrderById(
+        @Min(1L) @Max(5L) @Parameter(name = "orderId", description = "ID of pet that needs to be fetched", required = true) @PathVariable("orderId") Long orderId
+    );
+
+
+    /**
+     * POST /store/order : Place an order for a pet
+     * 
+     *
+     * @param order order placed for purchasing the pet (required)
+     * @return successful operation (status code 200)
+     *         or Invalid Order (status code 400)
+     */
+    @Operation(
+        operationId = "placeOrder",
+        summary = "Place an order for a pet",
+        tags = { "store" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = Order.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = Order.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid Order")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/store/order",
+        produces = "application/json",
+        consumes = "application/json"
+    )
+    ResponseEntity<Order> placeOrder(
+        @Parameter(name = "Order", description = "order placed for purchasing the pet", required = true) @Valid @RequestBody Order order
+    );
+
+}
diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/UserApi.java b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/UserApi.java
new file mode 100644
index 00000000000..c2618e33363
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/api/UserApi.java
@@ -0,0 +1,273 @@
+/**
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (6.0.0-SNAPSHOT).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.api;
+
+import java.util.List;
+import java.time.OffsetDateTime;
+import org.openapitools.model.User;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+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;
+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
+@Tag(name = "User", description = "Operations about user")
+public interface UserApi {
+
+    /**
+     * POST /user : Create user
+     * This can only be done by the logged in user.
+     *
+     * @param user Created user object (required)
+     * @return successful operation (status code 200)
+     */
+    @Operation(
+        operationId = "createUser",
+        summary = "Create user",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/user",
+        consumes = "application/json"
+    )
+    ResponseEntity<Void> createUser(
+        @Parameter(name = "User", description = "Created user object", required = true) @Valid @RequestBody User user
+    );
+
+
+    /**
+     * POST /user/createWithArray : Creates list of users with given input array
+     * 
+     *
+     * @param user List of user object (required)
+     * @return successful operation (status code 200)
+     */
+    @Operation(
+        operationId = "createUsersWithArrayInput",
+        summary = "Creates list of users with given input array",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/user/createWithArray",
+        consumes = "application/json"
+    )
+    ResponseEntity<Void> createUsersWithArrayInput(
+        @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<User> user
+    );
+
+
+    /**
+     * POST /user/createWithList : Creates list of users with given input array
+     * 
+     *
+     * @param user List of user object (required)
+     * @return successful operation (status code 200)
+     */
+    @Operation(
+        operationId = "createUsersWithListInput",
+        summary = "Creates list of users with given input array",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.POST,
+        value = "/user/createWithList",
+        consumes = "application/json"
+    )
+    ResponseEntity<Void> createUsersWithListInput(
+        @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<User> user
+    );
+
+
+    /**
+     * DELETE /user/{username} : Delete user
+     * This can only be done by the logged in user.
+     *
+     * @param username The name that needs to be deleted (required)
+     * @return Invalid username supplied (status code 400)
+     *         or User not found (status code 404)
+     */
+    @Operation(
+        operationId = "deleteUser",
+        summary = "Delete user",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "400", description = "Invalid username supplied"),
+            @ApiResponse(responseCode = "404", description = "User not found")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.DELETE,
+        value = "/user/{username}"
+    )
+    ResponseEntity<Void> deleteUser(
+        @Parameter(name = "username", description = "The name that needs to be deleted", required = true) @PathVariable("username") String username
+    );
+
+
+    /**
+     * GET /user/{username} : Get user by user name
+     * 
+     *
+     * @param username The name that needs to be fetched. Use user1 for testing. (required)
+     * @return successful operation (status code 200)
+     *         or Invalid username supplied (status code 400)
+     *         or User not found (status code 404)
+     */
+    @Operation(
+        operationId = "getUserByName",
+        summary = "Get user by user name",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = User.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = User.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid username supplied"),
+            @ApiResponse(responseCode = "404", description = "User not found")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/user/{username}",
+        produces = "application/json"
+    )
+    ResponseEntity<User> getUserByName(
+        @Parameter(name = "username", description = "The name that needs to be fetched. Use user1 for testing.", required = true) @PathVariable("username") String username
+    );
+
+
+    /**
+     * GET /user/login : Logs user into the system
+     * 
+     *
+     * @param username The user name for login (required)
+     * @param password The password for login in clear text (required)
+     * @return successful operation (status code 200)
+     *         or Invalid username/password supplied (status code 400)
+     */
+    @Operation(
+        operationId = "loginUser",
+        summary = "Logs user into the system",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation", content = {
+                @Content(mediaType = "application/xml", schema = @Schema(implementation = String.class)),
+                @Content(mediaType = "application/json", schema = @Schema(implementation = String.class))
+            }),
+            @ApiResponse(responseCode = "400", description = "Invalid username/password supplied")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/user/login",
+        produces = "application/json"
+    )
+    ResponseEntity<String> loginUser(
+        @NotNull @Pattern(regexp = "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$") @Parameter(name = "username", description = "The user name for login", required = true) @Valid @RequestParam(value = "username", required = true) String username,
+        @NotNull @Parameter(name = "password", description = "The password for login in clear text", required = true) @Valid @RequestParam(value = "password", required = true) String password
+    );
+
+
+    /**
+     * GET /user/logout : Logs out current logged in user session
+     * 
+     *
+     * @return successful operation (status code 200)
+     */
+    @Operation(
+        operationId = "logoutUser",
+        summary = "Logs out current logged in user session",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "200", description = "successful operation")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.GET,
+        value = "/user/logout"
+    )
+    ResponseEntity<Void> logoutUser(
+        
+    );
+
+
+    /**
+     * PUT /user/{username} : Updated user
+     * This can only be done by the logged in user.
+     *
+     * @param username name that need to be deleted (required)
+     * @param user Updated user object (required)
+     * @return Invalid user supplied (status code 400)
+     *         or User not found (status code 404)
+     */
+    @Operation(
+        operationId = "updateUser",
+        summary = "Updated user",
+        tags = { "user" },
+        responses = {
+            @ApiResponse(responseCode = "400", description = "Invalid user supplied"),
+            @ApiResponse(responseCode = "404", description = "User not found")
+        },
+        security = {
+            @SecurityRequirement(name = "api_key")
+        }
+    )
+    @RequestMapping(
+        method = RequestMethod.PUT,
+        value = "/user/{username}",
+        consumes = "application/json"
+    )
+    ResponseEntity<Void> updateUser(
+        @Parameter(name = "username", description = "name that need to be deleted", required = true) @PathVariable("username") String username,
+        @Parameter(name = "User", description = "Updated user object", required = true) @Valid @RequestBody User user
+    );
+
+}
diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Category.java b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Category.java
new file mode 100644
index 00000000000..f15bed23288
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Category.java
@@ -0,0 +1,108 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * A category for a pet
+ */
+
+@Schema(name = "Category", description = "A category for a pet")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class Category {
+
+  @JsonProperty("id")
+  private Long id;
+
+  @JsonProperty("name")
+  private String name;
+
+  public Category id(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  /**
+   * Get id
+   * @return id
+  */
+  
+  @Schema(name = "id", required = false)
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Category name(String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Get name
+   * @return name
+  */
+  @Pattern(regexp = "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$") 
+  @Schema(name = "name", required = false)
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Category category = (Category) o;
+    return Objects.equals(this.id, category.id) &&
+        Objects.equals(this.name, category.name);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(id, name);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class Category {\n");
+    sb.append("    id: ").append(toIndentedString(id)).append("\n");
+    sb.append("    name: ").append(toIndentedString(name)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/ModelApiResponse.java b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/ModelApiResponse.java
new file mode 100644
index 00000000000..e74c0d15a18
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/ModelApiResponse.java
@@ -0,0 +1,134 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * Describes the result of uploading an image resource
+ */
+
+@Schema(name = "ApiResponse", description = "Describes the result of uploading an image resource")
+@JsonTypeName("ApiResponse")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class ModelApiResponse {
+
+  @JsonProperty("code")
+  private Integer code;
+
+  @JsonProperty("type")
+  private String type;
+
+  @JsonProperty("message")
+  private String message;
+
+  public ModelApiResponse code(Integer code) {
+    this.code = code;
+    return this;
+  }
+
+  /**
+   * Get code
+   * @return code
+  */
+  
+  @Schema(name = "code", required = false)
+  public Integer getCode() {
+    return code;
+  }
+
+  public void setCode(Integer code) {
+    this.code = code;
+  }
+
+  public ModelApiResponse type(String type) {
+    this.type = type;
+    return this;
+  }
+
+  /**
+   * Get type
+   * @return type
+  */
+  
+  @Schema(name = "type", required = false)
+  public String getType() {
+    return type;
+  }
+
+  public void setType(String type) {
+    this.type = type;
+  }
+
+  public ModelApiResponse message(String message) {
+    this.message = message;
+    return this;
+  }
+
+  /**
+   * Get message
+   * @return message
+  */
+  
+  @Schema(name = "message", required = false)
+  public String getMessage() {
+    return message;
+  }
+
+  public void setMessage(String message) {
+    this.message = message;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    ModelApiResponse _apiResponse = (ModelApiResponse) o;
+    return Objects.equals(this.code, _apiResponse.code) &&
+        Objects.equals(this.type, _apiResponse.type) &&
+        Objects.equals(this.message, _apiResponse.message);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(code, type, message);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class ModelApiResponse {\n");
+    sb.append("    code: ").append(toIndentedString(code)).append("\n");
+    sb.append("    type: ").append(toIndentedString(type)).append("\n");
+    sb.append("    message: ").append(toIndentedString(message)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Order.java b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Order.java
new file mode 100644
index 00000000000..e4a1030a073
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Order.java
@@ -0,0 +1,245 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import java.time.OffsetDateTime;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * An order for a pets from the pet store
+ */
+
+@Schema(name = "Order", description = "An order for a pets from the pet store")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class Order {
+
+  @JsonProperty("id")
+  private Long id;
+
+  @JsonProperty("petId")
+  private Long petId;
+
+  @JsonProperty("quantity")
+  private Integer quantity;
+
+  @JsonProperty("shipDate")
+  @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
+  private OffsetDateTime shipDate;
+
+  /**
+   * Order Status
+   */
+  public enum StatusEnum {
+    PLACED("placed"),
+    
+    APPROVED("approved"),
+    
+    DELIVERED("delivered");
+
+    private String value;
+
+    StatusEnum(String value) {
+      this.value = value;
+    }
+
+    @JsonValue
+    public String getValue() {
+      return value;
+    }
+
+    @Override
+    public String toString() {
+      return String.valueOf(value);
+    }
+
+    @JsonCreator
+    public static StatusEnum fromValue(String value) {
+      for (StatusEnum b : StatusEnum.values()) {
+        if (b.value.equals(value)) {
+          return b;
+        }
+      }
+      throw new IllegalArgumentException("Unexpected value '" + value + "'");
+    }
+  }
+
+  @JsonProperty("status")
+  private StatusEnum status;
+
+  @JsonProperty("complete")
+  private Boolean complete = false;
+
+  public Order id(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  /**
+   * Get id
+   * @return id
+  */
+  
+  @Schema(name = "id", required = false)
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Order petId(Long petId) {
+    this.petId = petId;
+    return this;
+  }
+
+  /**
+   * Get petId
+   * @return petId
+  */
+  
+  @Schema(name = "petId", required = false)
+  public Long getPetId() {
+    return petId;
+  }
+
+  public void setPetId(Long petId) {
+    this.petId = petId;
+  }
+
+  public Order quantity(Integer quantity) {
+    this.quantity = quantity;
+    return this;
+  }
+
+  /**
+   * Get quantity
+   * @return quantity
+  */
+  
+  @Schema(name = "quantity", required = false)
+  public Integer getQuantity() {
+    return quantity;
+  }
+
+  public void setQuantity(Integer quantity) {
+    this.quantity = quantity;
+  }
+
+  public Order shipDate(OffsetDateTime shipDate) {
+    this.shipDate = shipDate;
+    return this;
+  }
+
+  /**
+   * Get shipDate
+   * @return shipDate
+  */
+  @Valid 
+  @Schema(name = "shipDate", required = false)
+  public OffsetDateTime getShipDate() {
+    return shipDate;
+  }
+
+  public void setShipDate(OffsetDateTime shipDate) {
+    this.shipDate = shipDate;
+  }
+
+  public Order status(StatusEnum status) {
+    this.status = status;
+    return this;
+  }
+
+  /**
+   * Order Status
+   * @return status
+  */
+  
+  @Schema(name = "status", description = "Order Status", required = false)
+  public StatusEnum getStatus() {
+    return status;
+  }
+
+  public void setStatus(StatusEnum status) {
+    this.status = status;
+  }
+
+  public Order complete(Boolean complete) {
+    this.complete = complete;
+    return this;
+  }
+
+  /**
+   * Get complete
+   * @return complete
+  */
+  
+  @Schema(name = "complete", required = false)
+  public Boolean getComplete() {
+    return complete;
+  }
+
+  public void setComplete(Boolean complete) {
+    this.complete = complete;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Order order = (Order) o;
+    return Objects.equals(this.id, order.id) &&
+        Objects.equals(this.petId, order.petId) &&
+        Objects.equals(this.quantity, order.quantity) &&
+        Objects.equals(this.shipDate, order.shipDate) &&
+        Objects.equals(this.status, order.status) &&
+        Objects.equals(this.complete, order.complete);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(id, petId, quantity, shipDate, status, complete);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class Order {\n");
+    sb.append("    id: ").append(toIndentedString(id)).append("\n");
+    sb.append("    petId: ").append(toIndentedString(petId)).append("\n");
+    sb.append("    quantity: ").append(toIndentedString(quantity)).append("\n");
+    sb.append("    shipDate: ").append(toIndentedString(shipDate)).append("\n");
+    sb.append("    status: ").append(toIndentedString(status)).append("\n");
+    sb.append("    complete: ").append(toIndentedString(complete)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Pet.java b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Pet.java
new file mode 100644
index 00000000000..1e00d49524a
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Pet.java
@@ -0,0 +1,261 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import java.util.ArrayList;
+import java.util.List;
+import org.openapitools.model.Category;
+import org.openapitools.model.Tag;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * A pet for sale in the pet store
+ */
+
+@Schema(name = "Pet", description = "A pet for sale in the pet store")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class Pet {
+
+  @JsonProperty("id")
+  private Long id;
+
+  @JsonProperty("category")
+  private Category category;
+
+  @JsonProperty("name")
+  private String name;
+
+  @JsonProperty("photoUrls")
+  @Valid
+  private List<String> photoUrls = new ArrayList<>();
+
+  @JsonProperty("tags")
+  @Valid
+  private List<Tag> tags = null;
+
+  /**
+   * pet status in the store
+   */
+  public enum StatusEnum {
+    AVAILABLE("available"),
+    
+    PENDING("pending"),
+    
+    SOLD("sold");
+
+    private String value;
+
+    StatusEnum(String value) {
+      this.value = value;
+    }
+
+    @JsonValue
+    public String getValue() {
+      return value;
+    }
+
+    @Override
+    public String toString() {
+      return String.valueOf(value);
+    }
+
+    @JsonCreator
+    public static StatusEnum fromValue(String value) {
+      for (StatusEnum b : StatusEnum.values()) {
+        if (b.value.equals(value)) {
+          return b;
+        }
+      }
+      throw new IllegalArgumentException("Unexpected value '" + value + "'");
+    }
+  }
+
+  @JsonProperty("status")
+  private StatusEnum status;
+
+  public Pet id(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  /**
+   * Get id
+   * @return id
+  */
+  
+  @Schema(name = "id", required = false)
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Pet category(Category category) {
+    this.category = category;
+    return this;
+  }
+
+  /**
+   * Get category
+   * @return category
+  */
+  @Valid 
+  @Schema(name = "category", required = false)
+  public Category getCategory() {
+    return category;
+  }
+
+  public void setCategory(Category category) {
+    this.category = category;
+  }
+
+  public Pet name(String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Get name
+   * @return name
+  */
+  @NotNull 
+  @Schema(name = "name", example = "doggie", required = true)
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public Pet photoUrls(List<String> photoUrls) {
+    this.photoUrls = photoUrls;
+    return this;
+  }
+
+  public Pet addPhotoUrlsItem(String photoUrlsItem) {
+    this.photoUrls.add(photoUrlsItem);
+    return this;
+  }
+
+  /**
+   * Get photoUrls
+   * @return photoUrls
+  */
+  @NotNull 
+  @Schema(name = "photoUrls", required = true)
+  public List<String> getPhotoUrls() {
+    return photoUrls;
+  }
+
+  public void setPhotoUrls(List<String> photoUrls) {
+    this.photoUrls = photoUrls;
+  }
+
+  public Pet tags(List<Tag> tags) {
+    this.tags = tags;
+    return this;
+  }
+
+  public Pet addTagsItem(Tag tagsItem) {
+    if (this.tags == null) {
+      this.tags = new ArrayList<>();
+    }
+    this.tags.add(tagsItem);
+    return this;
+  }
+
+  /**
+   * Get tags
+   * @return tags
+  */
+  @Valid 
+  @Schema(name = "tags", required = false)
+  public List<Tag> getTags() {
+    return tags;
+  }
+
+  public void setTags(List<Tag> tags) {
+    this.tags = tags;
+  }
+
+  public Pet status(StatusEnum status) {
+    this.status = status;
+    return this;
+  }
+
+  /**
+   * pet status in the store
+   * @return status
+  */
+  
+  @Schema(name = "status", description = "pet status in the store", required = false)
+  public StatusEnum getStatus() {
+    return status;
+  }
+
+  public void setStatus(StatusEnum status) {
+    this.status = status;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Pet pet = (Pet) o;
+    return Objects.equals(this.id, pet.id) &&
+        Objects.equals(this.category, pet.category) &&
+        Objects.equals(this.name, pet.name) &&
+        Objects.equals(this.photoUrls, pet.photoUrls) &&
+        Objects.equals(this.tags, pet.tags) &&
+        Objects.equals(this.status, pet.status);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(id, category, name, photoUrls, tags, status);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class Pet {\n");
+    sb.append("    id: ").append(toIndentedString(id)).append("\n");
+    sb.append("    category: ").append(toIndentedString(category)).append("\n");
+    sb.append("    name: ").append(toIndentedString(name)).append("\n");
+    sb.append("    photoUrls: ").append(toIndentedString(photoUrls)).append("\n");
+    sb.append("    tags: ").append(toIndentedString(tags)).append("\n");
+    sb.append("    status: ").append(toIndentedString(status)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Tag.java b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Tag.java
new file mode 100644
index 00000000000..97130c50c03
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/Tag.java
@@ -0,0 +1,108 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * A tag for a pet
+ */
+
+@Schema(name = "Tag", description = "A tag for a pet")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class Tag {
+
+  @JsonProperty("id")
+  private Long id;
+
+  @JsonProperty("name")
+  private String name;
+
+  public Tag id(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  /**
+   * Get id
+   * @return id
+  */
+  
+  @Schema(name = "id", required = false)
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Tag name(String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Get name
+   * @return name
+  */
+  
+  @Schema(name = "name", required = false)
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Tag tag = (Tag) o;
+    return Objects.equals(this.id, tag.id) &&
+        Objects.equals(this.name, tag.name);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(id, name);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class Tag {\n");
+    sb.append("    id: ").append(toIndentedString(id)).append("\n");
+    sb.append("    name: ").append(toIndentedString(name)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/User.java b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/User.java
new file mode 100644
index 00000000000..0a193cf96c2
--- /dev/null
+++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/model/User.java
@@ -0,0 +1,252 @@
+package org.openapitools.model;
+
+import java.net.URI;
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import org.openapitools.jackson.nullable.JsonNullable;
+import java.time.OffsetDateTime;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+
+import java.util.*;
+import jakarta.annotation.Generated;
+
+/**
+ * A User who is purchasing from the pet store
+ */
+
+@Schema(name = "User", description = "A User who is purchasing from the pet store")
+@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
+public class User {
+
+  @JsonProperty("id")
+  private Long id;
+
+  @JsonProperty("username")
+  private String username;
+
+  @JsonProperty("firstName")
+  private String firstName;
+
+  @JsonProperty("lastName")
+  private String lastName;
+
+  @JsonProperty("email")
+  private String email;
+
+  @JsonProperty("password")
+  private String password;
+
+  @JsonProperty("phone")
+  private String phone;
+
+  @JsonProperty("userStatus")
+  private Integer userStatus;
+
+  public User id(Long id) {
+    this.id = id;
+    return this;
+  }
+
+  /**
+   * Get id
+   * @return id
+  */
+  
+  @Schema(name = "id", required = false)
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public User username(String username) {
+    this.username = username;
+    return this;
+  }
+
+  /**
+   * Get username
+   * @return username
+  */
+  
+  @Schema(name = "username", required = false)
+  public String getUsername() {
+    return username;
+  }
+
+  public void setUsername(String username) {
+    this.username = username;
+  }
+
+  public User firstName(String firstName) {
+    this.firstName = firstName;
+    return this;
+  }
+
+  /**
+   * Get firstName
+   * @return firstName
+  */
+  
+  @Schema(name = "firstName", required = false)
+  public String getFirstName() {
+    return firstName;
+  }
+
+  public void setFirstName(String firstName) {
+    this.firstName = firstName;
+  }
+
+  public User lastName(String lastName) {
+    this.lastName = lastName;
+    return this;
+  }
+
+  /**
+   * Get lastName
+   * @return lastName
+  */
+  
+  @Schema(name = "lastName", required = false)
+  public String getLastName() {
+    return lastName;
+  }
+
+  public void setLastName(String lastName) {
+    this.lastName = lastName;
+  }
+
+  public User email(String email) {
+    this.email = email;
+    return this;
+  }
+
+  /**
+   * Get email
+   * @return email
+  */
+  
+  @Schema(name = "email", required = false)
+  public String getEmail() {
+    return email;
+  }
+
+  public void setEmail(String email) {
+    this.email = email;
+  }
+
+  public User password(String password) {
+    this.password = password;
+    return this;
+  }
+
+  /**
+   * Get password
+   * @return password
+  */
+  
+  @Schema(name = "password", required = false)
+  public String getPassword() {
+    return password;
+  }
+
+  public void setPassword(String password) {
+    this.password = password;
+  }
+
+  public User phone(String phone) {
+    this.phone = phone;
+    return this;
+  }
+
+  /**
+   * Get phone
+   * @return phone
+  */
+  
+  @Schema(name = "phone", required = false)
+  public String getPhone() {
+    return phone;
+  }
+
+  public void setPhone(String phone) {
+    this.phone = phone;
+  }
+
+  public User userStatus(Integer userStatus) {
+    this.userStatus = userStatus;
+    return this;
+  }
+
+  /**
+   * User Status
+   * @return userStatus
+  */
+  
+  @Schema(name = "userStatus", description = "User Status", required = false)
+  public Integer getUserStatus() {
+    return userStatus;
+  }
+
+  public void setUserStatus(Integer userStatus) {
+    this.userStatus = userStatus;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    User user = (User) o;
+    return Objects.equals(this.id, user.id) &&
+        Objects.equals(this.username, user.username) &&
+        Objects.equals(this.firstName, user.firstName) &&
+        Objects.equals(this.lastName, user.lastName) &&
+        Objects.equals(this.email, user.email) &&
+        Objects.equals(this.password, user.password) &&
+        Objects.equals(this.phone, user.phone) &&
+        Objects.equals(this.userStatus, user.userStatus);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(id, username, firstName, lastName, email, password, phone, userStatus);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("class User {\n");
+    sb.append("    id: ").append(toIndentedString(id)).append("\n");
+    sb.append("    username: ").append(toIndentedString(username)).append("\n");
+    sb.append("    firstName: ").append(toIndentedString(firstName)).append("\n");
+    sb.append("    lastName: ").append(toIndentedString(lastName)).append("\n");
+    sb.append("    email: ").append(toIndentedString(email)).append("\n");
+    sb.append("    password: ").append(toIndentedString(password)).append("\n");
+    sb.append("    phone: ").append(toIndentedString(phone)).append("\n");
+    sb.append("    userStatus: ").append(toIndentedString(userStatus)).append("\n");
+    sb.append("}");
+    return sb.toString();
+  }
+
+  /**
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    if (o == null) {
+      return "null";
+    }
+    return o.toString().replace("\n", "\n    ");
+  }
+}
+
-- 
GitLab


From 75ccee59e1c371935cbbf820d1f0f6b5147ad70c Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 13:07:46 +0200
Subject: [PATCH 13/18] Remove springfox

---
 .../JavaSpring/libraries/spring-cloud/pom-sb3.mustache          | 2 --
 1 file changed, 2 deletions(-)

diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache
index 7071b64a966..8904d573b5b 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache
@@ -13,13 +13,11 @@
         {{#springDocDocumentationProvider}}
         <springdoc.version>2.0.0-M2</springdoc.version>
         {{/springDocDocumentationProvider}}
-        {{^springFoxDocumentationProvider}}
         {{^springDocDocumentationProvider}}
         {{#swagger2AnnotationLibrary}}
         <swagger-annotations.version>}2.2.0</swagger-annotations.version>
         {{/swagger2AnnotationLibrary}}
         {{/springDocDocumentationProvider}}
-        {{/springFoxDocumentationProvider}}
     </properties>
 {{#parentOverridden}}
     <parent>
-- 
GitLab


From 25d8ffd70832f7026346bd6942973e482651febc Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 15:35:57 +0200
Subject: [PATCH 14/18] Fix typo.

---
 .../java/org/openapitools/codegen/languages/SpringCodegen.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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 0e7b5b25657..f8b01bd909b 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
@@ -208,7 +208,7 @@ public class SpringCodegen extends AbstractJavaCodegen
             "Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies",
             useSwaggerUI));
         cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT3,
-            "Genrate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).",
+            "Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).",
             useSwaggerUI));
 
         supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
-- 
GitLab


From dba5b11f9885389f2eea1792bb6a1b670bb2354d Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 15:43:56 +0200
Subject: [PATCH 15/18] No longer support SpringFox and Swagger1 with Spring
 Boot > 3.x

---
 .../org/openapitools/codegen/languages/SpringCodegen.java   | 6 ++++++
 1 file changed, 6 insertions(+)

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 f8b01bd909b..5b085dbe556 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
@@ -425,6 +425,12 @@ public class SpringCodegen extends AbstractJavaCodegen
             this.setUseSpringBoot3(convertPropertyToBoolean(USE_SPRING_BOOT3));
         }
         if (isUseSpringBoot3()) {
+            if (DocumentationProvider.SPRINGFOX.equals(getDocumentationProvider())) {
+                throw new IllegalArgumentException(DocumentationProvider.SPRINGFOX.getPropertyName() + " is not supported with Spring Boot > 3.x");
+            }
+            if (AnnotationLibrary.SWAGGER1.equals(getAnnotationLibrary())) {
+                throw new IllegalArgumentException(AnnotationLibrary.SWAGGER1.getPropertyName() + " is not supported with Spring Boot > 3.x");
+            }
             writePropertyBack(USE_JAKARTA_EE, true);
         } else {
             writePropertyBack(USE_JAKARTA_EE, false);
-- 
GitLab


From 5f321859f68b7a3731d780d1f2e11c4a6b019ae6 Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 15:47:36 +0200
Subject: [PATCH 16/18] Generate Docs

---
 docs/generators/java-camel.md | 2 +-
 docs/generators/spring.md     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/generators/java-camel.md b/docs/generators/java-camel.md
index 5ddede2f74e..3358089706f 100644
--- a/docs/generators/java-camel.md
+++ b/docs/generators/java-camel.md
@@ -91,7 +91,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
 |useBeanValidation|Use BeanValidation API annotations| |true|
 |useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
 |useOptional|Use Optional container for optional parameters| |false|
-|useSpringBoot3|Genrate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).| |true|
+|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).| |true|
 |useSpringController|Annotate the generated API as a Spring Controller| |false|
 |useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|
 |useTags|use tags for creating interface and controller classnames| |false|
diff --git a/docs/generators/spring.md b/docs/generators/spring.md
index adc740402d6..12793618f70 100644
--- a/docs/generators/spring.md
+++ b/docs/generators/spring.md
@@ -84,7 +84,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
 |useBeanValidation|Use BeanValidation API annotations| |true|
 |useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
 |useOptional|Use Optional container for optional parameters| |false|
-|useSpringBoot3|Genrate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).| |true|
+|useSpringBoot3|Generate code and provide dependencies for use with Spring Boot 3.x. (Use jakarta instead of javax in imports).| |true|
 |useSpringController|Annotate the generated API as a Spring Controller| |false|
 |useSwaggerUI|Open the OpenApi specification in swagger-ui. Will also import and configure needed dependencies| |true|
 |useTags|use tags for creating interface and controller classnames| |false|
-- 
GitLab


From 4e4daa06b5fa4b8505a3ebe85de6c698aa479c28 Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 17:19:56 +0200
Subject: [PATCH 17/18] Use Spring Boot 3.0.0-M3

---
 .../resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache | 2 +-
 .../JavaSpring/libraries/spring-cloud/pom-sb3.mustache          | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache
index 207e2680551..8d297379924 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/pom-sb3.mustache
@@ -33,7 +33,7 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>3.0.0-M2</version>
+        <version>3.0.0-M3</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
 {{/parentOverridden}}
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache
index 8904d573b5b..1d35db88d8a 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache
@@ -30,7 +30,7 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>3.0.0-M2</version>
+        <version>3.0.0-M3</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
 {{/parentOverridden}}
-- 
GitLab


From f4a532ca6be7b2eb5c1c89d04ddf24ce2f29df06 Mon Sep 17 00:00:00 2001
From: Lars Uffmann <lars.uffmann@vitroconnect.de>
Date: Fri, 20 May 2022 17:28:57 +0200
Subject: [PATCH 18/18] Generate Samples

---
 samples/openapi3/client/petstore/spring-cloud-3/pom.xml | 2 +-
 samples/openapi3/server/petstore/springboot-3/pom.xml   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/samples/openapi3/client/petstore/spring-cloud-3/pom.xml b/samples/openapi3/client/petstore/spring-cloud-3/pom.xml
index 679e0c8ce3c..921000f10fa 100644
--- a/samples/openapi3/client/petstore/spring-cloud-3/pom.xml
+++ b/samples/openapi3/client/petstore/spring-cloud-3/pom.xml
@@ -15,7 +15,7 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>3.0.0-M2</version>
+        <version>3.0.0-M3</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
 
diff --git a/samples/openapi3/server/petstore/springboot-3/pom.xml b/samples/openapi3/server/petstore/springboot-3/pom.xml
index c9c3d4ec746..09dcd5a651e 100644
--- a/samples/openapi3/server/petstore/springboot-3/pom.xml
+++ b/samples/openapi3/server/petstore/springboot-3/pom.xml
@@ -16,7 +16,7 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>3.0.0-M2</version>
+        <version>3.0.0-M3</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
 
-- 
GitLab