Repository: springdoc/springdoc-openapi
Pull request #2443 (2023-12-04 10:26:33)

Respect schema annotations when using spring mvc with kotlin
This PR fixes a bug when using kotlin and spring mvc. The field `noRequiredNoNullableDefault` in `springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app9/DemoController.kt` will be marked as required when it should not, it has a default value in the swagger annotation.

When adding `AnnotationIntrospectors`, the order matters. The fact that the `SpringDocJacksonKotlinModuleConfiguration` was dependent on `ObjectMapperProvider` and `SpringDocConfiguration` made it so that the `SpringDocRequiredModule` was added before the `KotlinModule`.

To fix this bug we create a primary bean for the `ObjectMapperProvider` when `KotlinModule` is on the class path to ensure that this module is added before `SpringDocRequiredModule`.

Tests are added for spring mvc using kotlin

Co-authored-by: Ola Petersson <olbpetersson@gmail.com>
Co-authored-by: Simon Lindhen <simon.lindhen@gmail.com>


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b96481e9..c8c5d0d8b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,35 +5,6 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
-## [2.3.0] - 2023-12-03
-
-### Added
-
-- #2340 - Add support OIDC with Spring Authorization Server
-- #2345 - Support Schema added in OpenAPI Specification v3.1 
-- #2387 - Support get javadoc description from getter method 
-- #2404 - Update condition to register links schema customizer
-- #2359 - Update condition to register links schema customizer
-- #2348 - Enhance resource path processing
-- #2438, #2315 - Support for @JsonProperty with Javadoc Change in springdoc-openapi
-
-### Changed
-
-- Upgrade spring-boot to 3.2.0
-- Upgrade swagger-core to 2.2.19
-- Upgrade swagger-ui to 5.10.3
-
-### Fixed
-
-- #2366 - Fix the failed test due to hardcoded file separators
-- #2370, #2371 - No empty description for polymorphic subtypes 
-- #2373 - SchemaProperty.array Schema is ignored in /api-docs or api-docs.yaml 
-- #2366 - Refactoring AbstractSwaggerResourceResolver.findWebJarResourcePath
-- #2320 - javadoc for class attribute ignored when in EntityModel.
-- #2347 - Not working if a property of entity contains generic parameters.
-- #2399 - SpringdocRouteBuilder.onError is overriding last route defined. 
-- #2426 -  StackOverflowError when using @ParameterObject on groovy class.
-
 ## [2.2.0] - 2023-08-06
 
 ### Added
diff --git a/pom.xml b/pom.xml
index 92ba2d6e0..b8ea139b4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>org.springdoc</groupId>
 	<artifactId>springdoc-openapi</artifactId>
-	<version>2.3.1-SNAPSHOT</version>
+	<version>2.2.1-SNAPSHOT</version>
 	<packaging>pom</packaging>
 	<name>Spring openapi documentation</name>
 	<description>Spring openapi documentation</description>
@@ -11,7 +11,7 @@
 	<parent>
 		<groupId>org.springframework.boot</groupId>
 		<artifactId>spring-boot-starter-parent</artifactId>
-		<version>3.2.0</version>
+		<version>3.1.2</version>
 	</parent>
 
 	<licenses>
@@ -62,7 +62,7 @@
 		<maven-release-plugin.version>2.5.3</maven-release-plugin.version>
 		<nexus-staging-maven-plugin>1.6.8</nexus-staging-maven-plugin>
 		<swagger-api.version>2.2.19</swagger-api.version>
-		<swagger-ui.version>5.10.3</swagger-ui.version>
+		<swagger-ui.version>5.9.0</swagger-ui.version>
 		<gmavenplus-plugin.version>1.13.1</gmavenplus-plugin.version>
 		<jaxb-impl.version>2.1</jaxb-impl.version>
 		<javax.jws-api.version>1.1</javax.jws-api.version>
diff --git a/springdoc-openapi-starter-common/pom.xml b/springdoc-openapi-starter-common/pom.xml
index 127b1bf9d..cd4e32097 100644
--- a/springdoc-openapi-starter-common/pom.xml
+++ b/springdoc-openapi-starter-common/pom.xml
@@ -3,7 +3,7 @@
 	<parent>
 		<groupId>org.springdoc</groupId>
 		<artifactId>springdoc-openapi</artifactId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<artifactId>springdoc-openapi-starter-common</artifactId>
 	<dependencies>
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocHateoasConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocHateoasConfiguration.java
index 54f13f9b2..94da82d15 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocHateoasConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocHateoasConfiguration.java
@@ -97,11 +97,11 @@ public class SpringDocHateoasConfiguration {
 	 * @param halProvider the hal provider
 	 * @param springDocConfigProperties the spring doc config properties
 	 * @param objectMapperProvider the object mapper provider
-	 * @return the open api customizer
+	 * @return the open api customiser
 	 * @see org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider) org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)
 	 */
 	@Bean(Constants.LINKS_SCHEMA_CUSTOMISER)
-	@ConditionalOnMissingBean(name = Constants.LINKS_SCHEMA_CUSTOMISER)
+	@ConditionalOnMissingBean
 	@Lazy(false)
 	GlobalOpenApiCustomizer linksSchemaCustomizer(HateoasHalProvider halProvider, SpringDocConfigProperties springDocConfigProperties,
 			ObjectMapperProvider objectMapperProvider) {
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJacksonKotlinModuleConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJacksonKotlinModuleConfiguration.java
index 274ffcd67..21fe11497 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJacksonKotlinModuleConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocJacksonKotlinModuleConfiguration.java
@@ -1,15 +1,16 @@
 package org.springdoc.core.configuration;
 
 import com.fasterxml.jackson.module.kotlin.KotlinModule;
-import com.fasterxml.jackson.module.kotlin.KotlinModule.Builder;
+import org.springdoc.core.properties.SpringDocConfigProperties;
 import org.springdoc.core.providers.ObjectMapperProvider;
 
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Lazy;
+import org.springframework.context.annotation.Primary;
 
 /**
  * The type Spring doc kotlin module configuration.
@@ -21,16 +22,19 @@ import org.springframework.context.annotation.Lazy;
 @ConditionalOnClass(KotlinModule.class)
 @ConditionalOnExpression("${springdoc.api-docs.enabled:true} and ${springdoc.enable-kotlin:true}")
 @ConditionalOnWebApplication
-@ConditionalOnBean(SpringDocConfiguration.class)
 class SpringDocJacksonKotlinModuleConfiguration {
 
 	/**
-	 * Instantiates a new Spring doc kotlin module configuration.
+	 * Instantiates a new objectMapperProvider with a kotlin module.
 	 *
-	 * @param objectMapperProvider the object mapper provider
+	 * @param springDocConfigProperties the spring doc config properties
 	 */
-	public SpringDocJacksonKotlinModuleConfiguration(ObjectMapperProvider objectMapperProvider) {
-		objectMapperProvider.jsonMapper()
-				.registerModule(new Builder().build());
+
+	@Bean
+	@Primary
+	ObjectMapperProvider objectMapperProvider(SpringDocConfigProperties springDocConfigProperties) {
+		ObjectMapperProvider mapperProvider =  new ObjectMapperProvider(springDocConfigProperties);
+		mapperProvider.jsonMapper().registerModule(new KotlinModule.Builder().build());
+		return mapperProvider;
 	}
 }
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationResponse.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationResponse.java
index f62c8d0c0..f115b8673 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationResponse.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/oauth2/SpringDocOidcClientRegistrationResponse.java
@@ -1,5 +1,6 @@
 package org.springdoc.core.configuration.oauth2;
 
+import java.time.Instant;
 import java.util.List;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/JavadocPropertyCustomizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/JavadocPropertyCustomizer.java
index 0975d9f14..ef7aa664d 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/JavadocPropertyCustomizer.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/JavadocPropertyCustomizer.java
@@ -33,17 +33,18 @@ import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.Set;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.introspect.SimpleMixInResolver;
 import io.swagger.v3.core.converter.AnnotatedType;
 import io.swagger.v3.core.converter.ModelConverter;
 import io.swagger.v3.core.converter.ModelConverterContext;
 import io.swagger.v3.core.converter.ModelConverterContextImpl;
 import io.swagger.v3.core.util.AnnotationsUtils;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
 import io.swagger.v3.oas.models.media.Schema;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.reflect.FieldUtils;
@@ -157,7 +158,7 @@ public record JavadocPropertyCustomizer(JavadocProvider javadocProvider,
 				properties.entrySet().stream()
 						.filter(stringSchemaEntry -> StringUtils.isBlank(stringSchemaEntry.getValue().getDescription()))
 						.forEach(stringSchemaEntry -> {
-							Optional<Field> optionalField = fields.stream().filter(field1 -> findFields(stringSchemaEntry, field1)).findAny();
+							Optional<Field> optionalField = fields.stream().filter(field1 -> field1.getName().equals(stringSchemaEntry.getKey())).findAny();
 							optionalField.ifPresent(field -> {
 								String fieldJavadoc = javadocProvider.getFieldJavadoc(field);
 								if (StringUtils.isNotBlank(fieldJavadoc))
@@ -175,27 +176,4 @@ public record JavadocPropertyCustomizer(JavadocProvider javadocProvider,
 			}
 		}
 	}
-
-	/**
-	 * Find fields boolean.
-	 *
-	 * @param stringSchemaEntry the string schema entry
-	 * @param field             the field
-	 * @return the boolean
-	 */
-	private static boolean findFields(Entry<String, Schema> stringSchemaEntry, Field field) {
-		if (field.getName().equals(stringSchemaEntry.getKey())){
-			return true;
-		}
-		else {
-			JsonProperty jsonPropertyAnnotation = field.getAnnotation(JsonProperty.class);
-			if (jsonPropertyAnnotation != null) {
-				String jsonPropertyName = jsonPropertyAnnotation.value();
-				if (jsonPropertyName.equals(stringSchemaEntry.getKey())){
-					return true;
-				}
-			}
-			return false;
-		}
-	}
 }
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/MethodParameterPojoExtractor.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/MethodParameterPojoExtractor.java
index ff8e3f0c1..a1f4bcaba 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/MethodParameterPojoExtractor.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/extractor/MethodParameterPojoExtractor.java
@@ -93,7 +93,6 @@ public class MethodParameterPojoExtractor {
 		SIMPLE_TYPE_PREDICATES.add(Class::isEnum);
 		SIMPLE_TYPE_PREDICATES.add(Class::isArray);
 		SIMPLE_TYPE_PREDICATES.add(MethodParameterPojoExtractor::isSwaggerPrimitiveType);
-		SIMPLE_TYPE_PREDICATES.add(aClass -> aClass.getName().startsWith("org.codehaus.groovy.reflection"));
 	}
 
 	/**
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SpringDocDataRestUtils.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SpringDocDataRestUtils.java
index b878c64f4..9a26d1c25 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SpringDocDataRestUtils.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SpringDocDataRestUtils.java
@@ -59,7 +59,6 @@ import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
 import org.springframework.data.rest.core.mapping.ResourceMappings;
 import org.springframework.data.rest.core.mapping.ResourceMetadata;
 import org.springframework.data.rest.webmvc.RestMediaTypes;
-import org.springframework.data.util.TypeInformation;
 import org.springframework.hateoas.server.LinkRelationProvider;
 import org.springframework.util.CollectionUtils;
 
@@ -119,21 +118,22 @@ public class SpringDocDataRestUtils {
 	 */
 	public void customise(OpenAPI openAPI, ResourceMappings mappings, PersistentEntities persistentEntities) {
 
-		for (PersistentEntity<?, ? extends PersistentProperty<?>> persistentEntity : persistentEntities) {
-			TypeInformation<?> typeInformation = persistentEntity.getTypeInformation();
-			Class domainType = typeInformation.getType();
-			ResourceMetadata resourceMetadata = mappings.getMetadataFor(domainType);
-			final PersistentEntity<?, ?> entity = persistentEntities.getRequiredPersistentEntity(domainType);
-			EntityInfo entityInfo = new EntityInfo();
-			entityInfo.setDomainType(domainType);
-			List<String> ignoredFields = getIgnoredFields(resourceMetadata, entity);
-			if (!repositoryRestConfiguration.isIdExposedFor(entity.getType()))
-				entityInfo.setIgnoredFields(ignoredFields);
-			List<String> associationsFields = getAssociationsFields(resourceMetadata, entity);
-			entityInfo.setAssociationsFields(associationsFields);
-			entityInoMap.put(domainType.getSimpleName(), entityInfo);
-		}
-		
+		persistentEntities.getManagedTypes().stream().forEach(typeInformation ->
+				{
+					Class domainType = typeInformation.getType();
+					ResourceMetadata resourceMetadata = mappings.getMetadataFor(domainType);
+					final PersistentEntity<?, ?> entity = persistentEntities.getRequiredPersistentEntity(domainType);
+					EntityInfo entityInfo = new EntityInfo();
+					entityInfo.setDomainType(domainType);
+					List<String> ignoredFields = getIgnoredFields(resourceMetadata, entity);
+					if (!repositoryRestConfiguration.isIdExposedFor(entity.getType()))
+						entityInfo.setIgnoredFields(ignoredFields);
+					List<String> associationsFields = getAssociationsFields(resourceMetadata, entity);
+					entityInfo.setAssociationsFields(associationsFields);
+					entityInoMap.put(domainType.getSimpleName(), entityInfo);
+				}
+		);
+
 		openAPI.getPaths().entrySet().stream()
 				.forEach(stringPathItemEntry -> {
 					PathItem pathItem = stringPathItemEntry.getValue();
diff --git a/springdoc-openapi-starter-webflux-api/pom.xml b/springdoc-openapi-starter-webflux-api/pom.xml
index 0a42199fc..2c14167f5 100644
--- a/springdoc-openapi-starter-webflux-api/pom.xml
+++ b/springdoc-openapi-starter-webflux-api/pom.xml
@@ -3,7 +3,7 @@
 	<parent>
 		<groupId>org.springdoc</groupId>
 		<artifactId>springdoc-openapi</artifactId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<artifactId>springdoc-openapi-starter-webflux-api</artifactId>
 	<dependencies>
diff --git a/springdoc-openapi-starter-webflux-api/src/main/java/org/springdoc/webflux/core/fn/SpringdocRouteBuilder.java b/springdoc-openapi-starter-webflux-api/src/main/java/org/springdoc/webflux/core/fn/SpringdocRouteBuilder.java
index 21ba89ac7..84c88249c 100644
--- a/springdoc-openapi-starter-webflux-api/src/main/java/org/springdoc/webflux/core/fn/SpringdocRouteBuilder.java
+++ b/springdoc-openapi-starter-webflux-api/src/main/java/org/springdoc/webflux/core/fn/SpringdocRouteBuilder.java
@@ -651,10 +651,12 @@ public class SpringdocRouteBuilder extends AbstractSpringdocRouteBuilder {
 	 *
 	 * @param predicate the predicate
 	 * @param responseProvider the response provider
+	 * @param operationsConsumer the operations consumer
 	 * @return the springdoc route builder
 	 */
-	public SpringdocRouteBuilder onError(Predicate<? super Throwable> predicate, BiFunction<? super Throwable, ServerRequest, Mono<ServerResponse>> responseProvider) {
-		this.delegate.onError(predicate, responseProvider);
+	public SpringdocRouteBuilder onError(Predicate<? super Throwable> predicate, BiFunction<? super Throwable, ServerRequest, Mono<ServerResponse>> responseProvider, Consumer<Builder> operationsConsumer) {
+		Builder builder = getOperationBuilder(operationsConsumer);
+		this.delegate.onError(predicate, responseProvider).withAttribute(OPERATION_ATTRIBUTE, builder);
 		return this;
 	}
 
@@ -665,10 +667,12 @@ public class SpringdocRouteBuilder extends AbstractSpringdocRouteBuilder {
 	 * @param <T>    the type parameter
 	 * @param exceptionType the exception type
 	 * @param responseProvider the response provider
+	 * @param operationsConsumer the operations consumer
 	 * @return the springdoc route builder
 	 */
-	public <T extends Throwable> SpringdocRouteBuilder onError(Class<T> exceptionType, BiFunction<? super T, ServerRequest, Mono<ServerResponse>> responseProvider) {
-		this.delegate.onError(exceptionType, responseProvider);
+	public <T extends Throwable> SpringdocRouteBuilder onError(Class<T> exceptionType, BiFunction<? super T, ServerRequest, Mono<ServerResponse>> responseProvider, Consumer<Builder> operationsConsumer) {
+		Builder builder = getOperationBuilder(operationsConsumer);
+		this.delegate.onError(exceptionType, responseProvider).withAttribute(OPERATION_ATTRIBUTE, builder);
 		return this;
 	}
 
diff --git a/springdoc-openapi-starter-webflux-ui/pom.xml b/springdoc-openapi-starter-webflux-ui/pom.xml
index 457a82f0b..d678709da 100644
--- a/springdoc-openapi-starter-webflux-ui/pom.xml
+++ b/springdoc-openapi-starter-webflux-ui/pom.xml
@@ -3,7 +3,7 @@
 	<parent>
 		<groupId>org.springdoc</groupId>
 		<artifactId>springdoc-openapi</artifactId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
 	<dependencies>
diff --git a/springdoc-openapi-starter-webflux-ui/src/main/java/org/springdoc/webflux/ui/SwaggerResourceResolver.java b/springdoc-openapi-starter-webflux-ui/src/main/java/org/springdoc/webflux/ui/SwaggerResourceResolver.java
index 343227120..11ee7dbad 100644
--- a/springdoc-openapi-starter-webflux-ui/src/main/java/org/springdoc/webflux/ui/SwaggerResourceResolver.java
+++ b/springdoc-openapi-starter-webflux-ui/src/main/java/org/springdoc/webflux/ui/SwaggerResourceResolver.java
@@ -30,29 +30,23 @@ public class SwaggerResourceResolver extends AbstractSwaggerResourceResolver imp
 
 	@Override
 	public Mono<Resource> resolveResource(ServerWebExchange exchange, String requestPath, List<? extends Resource> locations, ResourceResolverChain chain) {
-		return chain.resolveResource(exchange, requestPath, locations)
-				.switchIfEmpty(Mono.defer(() -> {
-					String webJarsResourcePath = findWebJarResourcePath(requestPath);
-					if (webJarsResourcePath != null) {
-						return chain.resolveResource(exchange, webJarsResourcePath, locations);
-					}
-					else {
-						return Mono.empty();
-					}
-				}));
+		Mono<Resource> resolved = chain.resolveResource(exchange, requestPath, locations);
+		if (!Mono.empty().equals(resolved)) {
+			String webJarResourcePath = findWebJarResourcePath(requestPath);
+			if (webJarResourcePath != null)
+				return chain.resolveResource(exchange, webJarResourcePath, locations);
+		}
+		return resolved;
 	}
 
 	@Override
-	public Mono<String> resolveUrlPath(String resourceUrlPath, List<? extends Resource> locations, ResourceResolverChain chain) {
-		return chain.resolveUrlPath(resourceUrlPath, locations)
-				.switchIfEmpty(Mono.defer(() -> {
-					String webJarResourcePath = findWebJarResourcePath(resourceUrlPath);
-					if (webJarResourcePath != null) {
-						return chain.resolveUrlPath(webJarResourcePath, locations);
-					}
-					else {
-						return Mono.empty();
-					}
-				}));
+	public Mono<String> resolveUrlPath(String resourcePath, List<? extends Resource> locations, ResourceResolverChain chain) {
+		Mono<String> path = chain.resolveUrlPath(resourcePath, locations);
+		if (!Mono.empty().equals(path)) {
+			String webJarResourcePath = findWebJarResourcePath(resourcePath);
+			if (webJarResourcePath != null)
+				return chain.resolveUrlPath(webJarResourcePath, locations);
+		}
+		return path;
 	}
 }
\ No newline at end of file
diff --git a/springdoc-openapi-starter-webmvc-api/pom.xml b/springdoc-openapi-starter-webmvc-api/pom.xml
index abbc359f1..77eb0b322 100644
--- a/springdoc-openapi-starter-webmvc-api/pom.xml
+++ b/springdoc-openapi-starter-webmvc-api/pom.xml
@@ -3,7 +3,7 @@
 	<parent>
 		<groupId>org.springdoc</groupId>
 		<artifactId>springdoc-openapi</artifactId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
 	<dependencies>
diff --git a/springdoc-openapi-starter-webmvc-api/src/main/java/org/springdoc/webmvc/core/fn/SpringdocRouteBuilder.java b/springdoc-openapi-starter-webmvc-api/src/main/java/org/springdoc/webmvc/core/fn/SpringdocRouteBuilder.java
index 1a6be0f2a..1208a8173 100644
--- a/springdoc-openapi-starter-webmvc-api/src/main/java/org/springdoc/webmvc/core/fn/SpringdocRouteBuilder.java
+++ b/springdoc-openapi-starter-webmvc-api/src/main/java/org/springdoc/webmvc/core/fn/SpringdocRouteBuilder.java
@@ -651,10 +651,12 @@ public class SpringdocRouteBuilder extends AbstractSpringdocRouteBuilder {
 	 *
 	 * @param predicate the predicate
 	 * @param responseProvider the response provider
+	 * @param operationsConsumer the operations consumer
 	 * @return the springdoc route builder
 	 */
-	public SpringdocRouteBuilder onError(Predicate<Throwable> predicate, BiFunction<Throwable, ServerRequest, ServerResponse> responseProvider) {
-		this.delegate.onError(predicate, responseProvider);
+	public SpringdocRouteBuilder onError(Predicate<Throwable> predicate, BiFunction<Throwable, ServerRequest, ServerResponse> responseProvider, Consumer<Builder> operationsConsumer) {
+		Builder builder = getOperationBuilder(operationsConsumer);
+		this.delegate.onError(predicate, responseProvider).withAttribute(OPERATION_ATTRIBUTE, builder);
 		return this;
 	}
 
@@ -665,10 +667,12 @@ public class SpringdocRouteBuilder extends AbstractSpringdocRouteBuilder {
 	 * @param <T>    the type parameter
 	 * @param exceptionType the exception type
 	 * @param responseProvider the response provider
+	 * @param operationsConsumer the operations consumer
 	 * @return the springdoc route builder
 	 */
-	public <T extends Throwable> SpringdocRouteBuilder onError(Class<T> exceptionType, BiFunction<Throwable, ServerRequest, ServerResponse> responseProvider) {
-		this.delegate.onError(exceptionType, responseProvider);
+	public <T extends Throwable> SpringdocRouteBuilder onError(Class<T> exceptionType, BiFunction<Throwable, ServerRequest, ServerResponse> responseProvider, Consumer<Builder> operationsConsumer) {
+		Builder builder = getOperationBuilder(operationsConsumer);
+		this.delegate.onError(exceptionType, responseProvider).withAttribute(OPERATION_ATTRIBUTE, builder);
 		return this;
 	}
 
diff --git a/springdoc-openapi-starter-webmvc-ui/pom.xml b/springdoc-openapi-starter-webmvc-ui/pom.xml
index f86afe0ee..4b6d8733d 100644
--- a/springdoc-openapi-starter-webmvc-ui/pom.xml
+++ b/springdoc-openapi-starter-webmvc-ui/pom.xml
@@ -3,7 +3,7 @@
 	<parent>
 		<groupId>org.springdoc</groupId>
 		<artifactId>springdoc-openapi</artifactId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
 	<dependencies>


Test patch:
diff --git a/springdoc-openapi-starter-common/src/test/java/org/springdoc/core/configuration/SpringDocHateoasConfigurationTest.java b/springdoc-openapi-starter-common/src/test/java/org/springdoc/core/configuration/SpringDocHateoasConfigurationTest.java
deleted file mode 100644
index c99de580c..000000000
--- a/springdoc-openapi-starter-common/src/test/java/org/springdoc/core/configuration/SpringDocHateoasConfigurationTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.springdoc.core.configuration;
-
-import org.junit.jupiter.api.Test;
-import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
-import org.springdoc.core.customizers.OpenApiHateoasLinksCustomizer;
-import org.springdoc.core.properties.SpringDocConfigProperties;
-
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
-import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
-import org.springframework.hateoas.config.HateoasConfiguration;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.springdoc.core.utils.Constants.LINKS_SCHEMA_CUSTOMISER;
-
-class SpringDocHateoasConfigurationTest {
-
-    @Test
-    void linksSchemaCustomizerShouldBeRegistered() {
-        new WebApplicationContextRunner()
-                .withPropertyValues(
-                        "springdoc.api-docs.enabled=true",
-                        "springdoc.enable-hateoas=true"
-                )
-                .withConfiguration(AutoConfigurations.of(
-                        WebMvcAutoConfiguration.class,
-                        HateoasConfiguration.class,
-                        SpringDocConfiguration.class,
-                        SpringDocConfigProperties.class,
-                        SpringDocHateoasConfiguration.class
-                ))
-                .run(context -> {
-                    assertThat(context).getBeanNames(GlobalOpenApiCustomizer.class)
-                        .hasSize(1)
-                        .containsExactly(LINKS_SCHEMA_CUSTOMISER);
-                    assertThat(context.getBean(LINKS_SCHEMA_CUSTOMISER)).isExactlyInstanceOf(OpenApiHateoasLinksCustomizer.class);
-                });
-    }
-
-    @Test
-    void linksSchemaCustomizerShouldBeRegisteredWithMultipleGlobalOpenApiCustomizer() {
-        new WebApplicationContextRunner()
-                .withPropertyValues(
-                        "springdoc.api-docs.enabled=true",
-                        "springdoc.enable-hateoas=true"
-                )
-                .withConfiguration(AutoConfigurations.of(
-                        WebMvcAutoConfiguration.class,
-                        HateoasConfiguration.class,
-                        SpringDocConfiguration.class,
-                        SpringDocConfigProperties.class,
-                        SpringDocHateoasConfiguration.class
-                ))
-                .withBean("globalOpenApiCustomizer", GlobalOpenApiCustomizer.class, () -> mock(GlobalOpenApiCustomizer.class))
-                .run(context -> {
-                    assertThat(context).getBeanNames(GlobalOpenApiCustomizer.class)
-                            .hasSize(2)
-                            .containsExactlyInAnyOrder(LINKS_SCHEMA_CUSTOMISER, "globalOpenApiCustomizer");
-                });
-    }
-
-    @Test
-    void linksSchemaCustomizerShouldNotBeRegisteredIfBeanWithSameNameAlreadyExists() {
-        new WebApplicationContextRunner()
-                .withPropertyValues(
-                        "springdoc.api-docs.enabled=true",
-                        "springdoc.enable-hateoas=true"
-                )
-                .withConfiguration(AutoConfigurations.of(
-                        WebMvcAutoConfiguration.class,
-                        HateoasConfiguration.class,
-                        SpringDocConfiguration.class,
-                        SpringDocConfigProperties.class,
-                        SpringDocHateoasConfiguration.class
-                ))
-                .withBean(LINKS_SCHEMA_CUSTOMISER, GlobalOpenApiCustomizer.class, () -> mock(GlobalOpenApiCustomizer.class))
-                .run(context -> {
-                    assertThat(context).getBeanNames(GlobalOpenApiCustomizer.class)
-                            .hasSize(1)
-                            .containsExactly(LINKS_SCHEMA_CUSTOMISER);
-                    assertThat(context.getBean(LINKS_SCHEMA_CUSTOMISER)).isNotExactlyInstanceOf(OpenApiHateoasLinksCustomizer.class);
-                });
-    }
-}
\ No newline at end of file
diff --git a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app8/ExamplesResponse.java b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app8/ExamplesResponse.java
index aeb3d7ea9..8bbb89fee 100644
--- a/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app8/ExamplesResponse.java
+++ b/springdoc-openapi-starter-webmvc-api/src/test/java/test/org/springdoc/api/v31/app8/ExamplesResponse.java
@@ -1,9 +1,9 @@
 package test.org.springdoc.api.v31.app8;
 
-import java.util.List;
-
 import io.swagger.v3.oas.annotations.media.Schema;
 
+import java.util.List;
+
 import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED;
 import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
 
diff --git a/springdoc-openapi-tests/pom.xml b/springdoc-openapi-tests/pom.xml
index e5f5fcdcb..45a7c9640 100644
--- a/springdoc-openapi-tests/pom.xml
+++ b/springdoc-openapi-tests/pom.xml
@@ -2,7 +2,7 @@
 	<parent>
 		<artifactId>springdoc-openapi</artifactId>
 		<groupId>org.springdoc</groupId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<packaging>pom</packaging>
 	<modelVersion>4.0.0</modelVersion>
@@ -18,6 +18,7 @@
 		<module>springdoc-openapi-actuator-webflux-tests</module>
 		<module>springdoc-openapi-actuator-webmvc-tests</module>
 		<module>springdoc-openapi-kotlin-tests</module>
+		<module>springdoc-openapi-kotlin-mvc-tests</module>
 		<module>springdoc-openapi-hateoas-tests</module>
 		<module>springdoc-openapi-data-rest-tests</module>
 	</modules>
diff --git a/springdoc-openapi-tests/springdoc-openapi-actuator-webflux-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-actuator-webflux-tests/pom.xml
index 7600cad85..5cdb0ed36 100644
--- a/springdoc-openapi-tests/springdoc-openapi-actuator-webflux-tests/pom.xml
+++ b/springdoc-openapi-tests/springdoc-openapi-actuator-webflux-tests/pom.xml
@@ -2,7 +2,7 @@
 	<parent>
 		<artifactId>springdoc-openapi-tests</artifactId>
 		<groupId>org.springdoc</groupId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 
diff --git a/springdoc-openapi-tests/springdoc-openapi-actuator-webmvc-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-actuator-webmvc-tests/pom.xml
index 7fd113f91..e74d577b4 100644
--- a/springdoc-openapi-tests/springdoc-openapi-actuator-webmvc-tests/pom.xml
+++ b/springdoc-openapi-tests/springdoc-openapi-actuator-webmvc-tests/pom.xml
@@ -2,7 +2,7 @@
 	<parent>
 		<artifactId>springdoc-openapi-tests</artifactId>
 		<groupId>org.springdoc</groupId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 
diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/pom.xml
index 013ca9e72..d867901a8 100644
--- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/pom.xml
+++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/pom.xml
@@ -2,7 +2,7 @@
 	<parent>
 		<artifactId>springdoc-openapi-tests</artifactId>
 		<groupId>org.springdoc</groupId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>springdoc-openapi-data-rest-tests</artifactId>
diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/app20/CodeLookupRepository.java b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/app20/CodeLookupRepository.java
index 01e6e8792..efd859b9e 100644
--- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/app20/CodeLookupRepository.java
+++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/java/test/org/springdoc/api/app20/CodeLookupRepository.java
@@ -4,7 +4,7 @@ import org.springframework.data.repository.NoRepositoryBean;
 import org.springframework.data.repository.query.Param;
 
 @NoRepositoryBean
-public interface CodeLookupRepository<EntityT,  KeyT extends String> {
+public interface CodeLookupRepository<EntityT, KeyT> {
 	EntityT findOneByCode(@Param("code") KeyT code);
 
 	Long countByCode(KeyT code);
diff --git a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/app20.json b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/app20.json
index 3ebaa3cd8..1bd475e16 100644
--- a/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/app20.json
+++ b/springdoc-openapi-tests/springdoc-openapi-data-rest-tests/src/test/resources/results/app20.json
@@ -117,7 +117,7 @@
             "name": "code",
             "in": "query",
             "schema": {
-              "type": "string"
+              "type": "object"
             }
           }
         ],
@@ -150,7 +150,7 @@
             "name": "code",
             "in": "query",
             "schema": {
-              "type": "string"
+              "type": "object"
             }
           }
         ],
diff --git a/springdoc-openapi-tests/springdoc-openapi-function-webflux-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-function-webflux-tests/pom.xml
index 749900483..cb3b78082 100644
--- a/springdoc-openapi-tests/springdoc-openapi-function-webflux-tests/pom.xml
+++ b/springdoc-openapi-tests/springdoc-openapi-function-webflux-tests/pom.xml
@@ -2,7 +2,7 @@
 	<parent>
 		<artifactId>springdoc-openapi-tests</artifactId>
 		<groupId>org.springdoc</groupId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 
diff --git a/springdoc-openapi-tests/springdoc-openapi-function-webmvc-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-function-webmvc-tests/pom.xml
index 4f1e98b52..a90585ac3 100644
--- a/springdoc-openapi-tests/springdoc-openapi-function-webmvc-tests/pom.xml
+++ b/springdoc-openapi-tests/springdoc-openapi-function-webmvc-tests/pom.xml
@@ -2,7 +2,7 @@
 	<parent>
 		<artifactId>springdoc-openapi-tests</artifactId>
 		<groupId>org.springdoc</groupId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 
diff --git a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/pom.xml
index 64f3bcee8..e51b397c8 100644
--- a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/pom.xml
+++ b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/pom.xml
@@ -3,7 +3,7 @@
 	<parent>
 		<groupId>org.springdoc</groupId>
 		<artifactId>springdoc-openapi-tests</artifactId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<artifactId>springdoc-openapi-groovy-tests</artifactId>
 	<dependencies>
diff --git a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/groovy/test/org/springdoc/api/app1/CarController.groovy b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/groovy/test/org/springdoc/api/app1/CarController.groovy
index 3bc1a246e..e8ffbde5b 100644
--- a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/groovy/test/org/springdoc/api/app1/CarController.groovy
+++ b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/groovy/test/org/springdoc/api/app1/CarController.groovy
@@ -20,7 +20,6 @@
 
 package test.org.springdoc.api.app1
 
-import org.springdoc.core.annotations.ParameterObject
 
 import org.springframework.web.bind.annotation.GetMapping
 import org.springframework.web.bind.annotation.PathVariable
@@ -34,18 +33,14 @@ class CarController {
 	CarController(CarService carService) {
 		this.carService = carService
 	}
-	
-	@GetMapping(path = 'cars/{carId}')
-	Car getCar(@PathVariable(value = 'carId') Long carId) {
-		return carService.getCar(carId)
-	}
 
 	@GetMapping(path = '/cars')
-	List<Car> getCars(@ParameterObject CarsFilter filter) {
+	List<Car> getCars() {
 		return carService.getCars()
 	}
 
-	static class CarsFilter {
-		String name;
+	@GetMapping(path = 'cars/{carId}')
+	Car getCar(@PathVariable(value = 'carId') Long carId) {
+		return carService.getCar(carId)
 	}
 }
diff --git a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/groovy/test/org/springdoc/api/app2/CarController.groovy b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/groovy/test/org/springdoc/api/app2/CarController.groovy
index 0e76487e8..40a5d9331 100644
--- a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/groovy/test/org/springdoc/api/app2/CarController.groovy
+++ b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/groovy/test/org/springdoc/api/app2/CarController.groovy
@@ -20,7 +20,6 @@
 
 package test.org.springdoc.api.app2
 
-import org.springdoc.core.annotations.ParameterObject
 
 import org.springframework.web.bind.annotation.GetMapping
 import org.springframework.web.bind.annotation.PathVariable
@@ -36,14 +35,10 @@ class CarController {
 	}
 
 	@GetMapping(path = '/cars')
-	List<test.org.springdoc.api.app1.Car> getCars(@ParameterObject CarsFilter filter) {
+	List<test.org.springdoc.api.app2.Car> getCars() {
 		return carService.getCars()
 	}
 
-	static class CarsFilter {
-		String name;
-	}
-
 	@GetMapping(path = 'cars/{carId}')
 	test.org.springdoc.api.app2.Car getCar(@PathVariable(value = 'carId') Long carId) {
 		return carService.getCar(carId)
diff --git a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/resources/results/app1.json b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/resources/results/app1.json
index 802d051cf..762e14364 100644
--- a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/resources/results/app1.json
+++ b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/resources/results/app1.json
@@ -17,16 +17,6 @@
           "car-controller"
         ],
         "operationId": "getCars",
-        "parameters": [
-          {
-            "name": "name",
-            "in": "query",
-            "required": false,
-            "schema": {
-              "type": "string"
-            }
-          }
-        ],
         "responses": {
           "200": {
             "description": "OK",
@@ -151,13 +141,13 @@
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "text": {
             "type": "string"
           },
@@ -317,23 +307,23 @@
             "type": "integer",
             "format": "int32"
           },
-          "description": {
-            "type": "string"
+          "anExpression": {
+            "type": "boolean"
           },
           "startLine": {
             "type": "integer",
             "format": "int32"
           },
+          "rootText": {
+            "type": "string"
+          },
           "startColumn": {
             "type": "integer",
             "format": "int32"
           },
-          "rootText": {
+          "description": {
             "type": "string"
           },
-          "anExpression": {
-            "type": "boolean"
-          },
           "meaning": {
             "type": "integer",
             "format": "int32"
@@ -424,8 +414,9 @@
           "void": {
             "type": "boolean"
           },
-          "typeDescription": {
-            "type": "string"
+          "superClassDistance": {
+            "type": "integer",
+            "format": "int32"
           },
           "newMetaMethods": {
             "type": "array",
@@ -436,9 +427,8 @@
           "callSiteLoader": {
             "$ref": "#/components/schemas/CallSiteClassLoader"
           },
-          "superClassDistance": {
-            "type": "integer",
-            "format": "int32"
+          "typeDescription": {
+            "type": "string"
           }
         }
       },
@@ -2591,14 +2581,14 @@
           "weakMetaClass": {
             "$ref": "#/components/schemas/MetaClass"
           },
+          "cachedClass": {
+            "$ref": "#/components/schemas/CachedClass"
+          },
           "modifiedExpando": {
             "$ref": "#/components/schemas/ExpandoMetaClass"
           },
           "metaClassForClass": {
             "$ref": "#/components/schemas/MetaClass"
-          },
-          "cachedClass": {
-            "$ref": "#/components/schemas/CachedClass"
           }
         }
       },
@@ -3114,8 +3104,30 @@
           "text": {
             "type": "string"
           },
-          "outerClass": {
-            "$ref": "#/components/schemas/ClassNode"
+          "objectInitializerStatements": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/Statement"
+            }
+          },
+          "allInterfaces": {
+            "uniqueItems": true,
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/ClassNode"
+            }
+          },
+          "allDeclaredMethods": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/MethodNode"
+            }
+          },
+          "abstractMethods": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/MethodNode"
+            }
           },
           "genericsPlaceHolder": {
             "type": "boolean"
@@ -3169,41 +3181,19 @@
           "annotationDefinition": {
             "type": "boolean"
           },
-          "abstractMethods": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/MethodNode"
-            }
-          },
-          "allInterfaces": {
-            "uniqueItems": true,
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/ClassNode"
-            }
-          },
-          "allDeclaredMethods": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/MethodNode"
-            }
-          },
-          "objectInitializerStatements": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/Statement"
-            }
+          "outerClass": {
+            "$ref": "#/components/schemas/ClassNode"
           },
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "sourcePosition": {
             "$ref": "#/components/schemas/ASTNode"
           },
@@ -3711,13 +3701,13 @@
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "sourcePosition": {
             "$ref": "#/components/schemas/ASTNode"
           },
@@ -3747,14 +3737,14 @@
           "configuration": {
             "$ref": "#/components/schemas/CompilerConfiguration"
           },
-          "warningCount": {
+          "errorCount": {
             "type": "integer",
             "format": "int32"
           },
           "lastError": {
             "$ref": "#/components/schemas/Message"
           },
-          "errorCount": {
+          "warningCount": {
             "type": "integer",
             "format": "int32"
           }
@@ -5038,13 +5028,13 @@
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "text": {
             "type": "string"
           },
@@ -5155,13 +5145,13 @@
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "text": {
             "type": "string"
           },
@@ -5688,13 +5678,13 @@
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "sourcePosition": {
             "$ref": "#/components/schemas/ASTNode"
           },
@@ -5846,12 +5836,12 @@
           "anonymous": {
             "type": "boolean"
           },
-          "variableScope": {
-            "$ref": "#/components/schemas/VariableScope"
-          },
           "outerMostClass": {
             "$ref": "#/components/schemas/ClassNode"
           },
+          "variableScope": {
+            "$ref": "#/components/schemas/VariableScope"
+          },
           "interface": {
             "type": "boolean"
           },
@@ -5891,6 +5881,31 @@
           "text": {
             "type": "string"
           },
+          "objectInitializerStatements": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/Statement"
+            }
+          },
+          "allInterfaces": {
+            "uniqueItems": true,
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/ClassNode"
+            }
+          },
+          "allDeclaredMethods": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/MethodNode"
+            }
+          },
+          "abstractMethods": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/MethodNode"
+            }
+          },
           "genericsPlaceHolder": {
             "type": "boolean"
           },
@@ -5943,41 +5958,16 @@
           "annotationDefinition": {
             "type": "boolean"
           },
-          "abstractMethods": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/MethodNode"
-            }
-          },
-          "allInterfaces": {
-            "uniqueItems": true,
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/ClassNode"
-            }
-          },
-          "allDeclaredMethods": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/MethodNode"
-            }
-          },
-          "objectInitializerStatements": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/Statement"
-            }
-          },
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "sourcePosition": {
             "$ref": "#/components/schemas/ASTNode"
           },
@@ -6029,9 +6019,6 @@
       "MetaClassRegistry": {
         "type": "object",
         "properties": {
-          "metaClassCreationHandle": {
-            "$ref": "#/components/schemas/MetaClassCreationHandle"
-          },
           "metaClassCreationHandler": {
             "$ref": "#/components/schemas/MetaClassCreationHandle"
           },
@@ -6040,6 +6027,9 @@
             "items": {
               "$ref": "#/components/schemas/MetaClassRegistryChangeEventListener"
             }
+          },
+          "metaClassCreationHandle": {
+            "$ref": "#/components/schemas/MetaClassCreationHandle"
           }
         }
       },
@@ -6248,13 +6238,13 @@
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "sourcePosition": {
             "$ref": "#/components/schemas/ASTNode"
           },
@@ -6439,8 +6429,30 @@
           "text": {
             "type": "string"
           },
-          "outerClass": {
-            "$ref": "#/components/schemas/ClassNode"
+          "objectInitializerStatements": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/Statement"
+            }
+          },
+          "allInterfaces": {
+            "uniqueItems": true,
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/ClassNode"
+            }
+          },
+          "allDeclaredMethods": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/MethodNode"
+            }
+          },
+          "abstractMethods": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/MethodNode"
+            }
           },
           "genericsPlaceHolder": {
             "type": "boolean"
@@ -6494,41 +6506,19 @@
           "annotationDefinition": {
             "type": "boolean"
           },
-          "abstractMethods": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/MethodNode"
-            }
-          },
-          "allInterfaces": {
-            "uniqueItems": true,
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/ClassNode"
-            }
-          },
-          "allDeclaredMethods": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/MethodNode"
-            }
-          },
-          "objectInitializerStatements": {
-            "type": "array",
-            "items": {
-              "$ref": "#/components/schemas/Statement"
-            }
+          "outerClass": {
+            "$ref": "#/components/schemas/ClassNode"
           },
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "sourcePosition": {
             "$ref": "#/components/schemas/ASTNode"
           },
@@ -6629,10 +6619,10 @@
           "context": {
             "$ref": "#/components/schemas/SourceUnit"
           },
-          "scriptClassDummy": {
+          "scriptBaseClassFromConfig": {
             "$ref": "#/components/schemas/ClassNode"
           },
-          "scriptBaseClassFromConfig": {
+          "scriptClassDummy": {
             "$ref": "#/components/schemas/ClassNode"
           },
           "text": {
@@ -6695,13 +6685,13 @@
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "sourcePosition": {
             "$ref": "#/components/schemas/ASTNode"
           },
@@ -6781,13 +6771,13 @@
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "text": {
             "type": "string"
           },
@@ -6884,12 +6874,18 @@
           "private": {
             "type": "boolean"
           },
-          "dynamicTyped": {
-            "type": "boolean"
+          "setterNameOrDefault": {
+            "type": "string"
+          },
+          "getterNameOrDefault": {
+            "type": "string"
           },
           "initialExpression": {
             "$ref": "#/components/schemas/Expression"
           },
+          "dynamicTyped": {
+            "type": "boolean"
+          },
           "inStaticContext": {
             "type": "boolean"
           },
@@ -6900,22 +6896,16 @@
           "originType": {
             "$ref": "#/components/schemas/ClassNode"
           },
-          "getterNameOrDefault": {
-            "type": "string"
-          },
-          "setterNameOrDefault": {
-            "type": "string"
-          },
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "text": {
             "type": "string"
           },
@@ -6988,13 +6978,13 @@
           "instance": {
             "$ref": "#/components/schemas/AnnotatedNode"
           },
+          "groovydoc": {
+            "$ref": "#/components/schemas/Groovydoc"
+          },
           "hasNoRealSourcePosition": {
             "type": "boolean",
             "writeOnly": true
           },
-          "groovydoc": {
-            "$ref": "#/components/schemas/Groovydoc"
-          },
           "text": {
             "type": "string"
           },
@@ -7025,18 +7015,18 @@
             "type": "integer",
             "format": "int32"
           },
-          "description": {
-            "type": "string"
-          },
           "startLine": {
             "type": "integer",
             "format": "int32"
           },
+          "rootText": {
+            "type": "string"
+          },
           "startColumn": {
             "type": "integer",
             "format": "int32"
           },
-          "rootText": {
+          "description": {
             "type": "string"
           },
           "meaning": {
@@ -7164,11 +7154,11 @@
           "empty": {
             "type": "boolean"
           },
-          "description": {
-            "type": "string"
-          },
           "anExpression": {
             "type": "boolean"
+          },
+          "description": {
+            "type": "string"
           }
         }
       },
@@ -7185,12 +7175,12 @@
           "type": {
             "$ref": "#/components/schemas/ClassNode"
           },
-          "dynamicTyped": {
-            "type": "boolean"
-          },
           "initialExpression": {
             "$ref": "#/components/schemas/Expression"
           },
+          "dynamicTyped": {
+            "type": "boolean"
+          },
           "inStaticContext": {
             "type": "boolean"
           },
diff --git a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/resources/results/app2.json b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/resources/results/app2.json
index 2c5bad0bf..6f43d6996 100644
--- a/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/resources/results/app2.json
+++ b/springdoc-openapi-tests/springdoc-openapi-groovy-tests/src/test/resources/results/app2.json
@@ -17,16 +17,6 @@
           "car-controller"
         ],
         "operationId": "getCars",
-        "parameters": [
-          {
-            "name": "name",
-            "in": "query",
-            "required": false,
-            "schema": {
-              "type": "string"
-            }
-          }
-        ],
         "responses": {
           "200": {
             "description": "OK",
diff --git a/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/pom.xml
index 5e9be340c..dbdc2ef97 100644
--- a/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/pom.xml
+++ b/springdoc-openapi-tests/springdoc-openapi-hateoas-tests/pom.xml
@@ -2,7 +2,7 @@
 	<parent>
 		<artifactId>springdoc-openapi-tests</artifactId>
 		<groupId>org.springdoc</groupId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>springdoc-openapi-hateoas-tests</artifactId>
diff --git a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml
index bdcca77df..70649fe75 100644
--- a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml
+++ b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/pom.xml
@@ -2,7 +2,7 @@
 	<parent>
 		<groupId>org.springdoc</groupId>
 		<artifactId>springdoc-openapi-tests</artifactId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 
diff --git a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/java/test/org/springdoc/api/app97/StudentV2.java b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/java/test/org/springdoc/api/app97/StudentV2.java
index be99618e6..dbbd3192c 100644
--- a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/java/test/org/springdoc/api/app97/StudentV2.java
+++ b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/java/test/org/springdoc/api/app97/StudentV2.java
@@ -10,7 +10,7 @@ public class StudentV2 {
 	/**
 	 * The Name.
 	 */
-	@JsonProperty("bb")
+	@JsonProperty("name")
 	private String name;
 
 	/**
diff --git a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/app97.json b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/app97.json
index 0a77107dd..ec408d329 100644
--- a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/app97.json
+++ b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/results/app97.json
@@ -132,7 +132,7 @@
       "StudentV2": {
         "type": "object",
         "properties": {
-          "bb": {
+          "name": {
             "type": "string",
             "description": "The Name."
           }
@@ -151,4 +151,4 @@
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/.gitignore b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/.gitignore
new file mode 100644
index 000000000..ab21548c1
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/.gitignore
@@ -0,0 +1,144 @@
+######################
+# Project Specific
+######################
+/target/www/**
+/src/test/javascript/coverage/
+
+######################
+# Node
+######################
+/node/
+node_tmp/
+node_modules/
+npm-debug.log.*
+/.awcache/*
+/.cache-loader/*
+
+######################
+# SASS
+######################
+.sass-cache/
+
+######################
+# Eclipse
+######################
+*.pydevproject
+.project
+.metadata
+tmp/
+tmp/**/*
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.classpath
+.settings/
+.loadpath
+.factorypath
+/src/main/resources/rebel.xml
+
+# External tool builders
+.externalToolBuilders/**
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath
+
+######################
+# Intellij
+######################
+.idea/
+*.iml
+*.iws
+*.ipr
+*.ids
+*.orig
+classes/
+out/
+
+######################
+# Visual Studio Code
+######################
+.vscode/
+
+######################
+# Maven
+######################
+/log/
+/target/
+
+######################
+# Gradle
+######################
+.gradle/
+/build/
+
+######################
+# Package Files
+######################
+*.jar
+*.war
+*.ear
+*.db
+
+######################
+# Windows
+######################
+# Windows image file caches
+Thumbs.db
+
+# Folder config file
+Desktop.ini
+
+######################
+# Mac OSX
+######################
+.DS_Store
+.svn
+
+# Thumbnails
+._*
+
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
+
+######################
+# Directories
+######################
+/bin/
+/deploy/
+
+######################
+# Logs
+######################
+*.log*
+
+######################
+# Others
+######################
+*.class
+*.*~
+*~
+.merge_file*
+
+######################
+# Gradle Wrapper
+######################
+!gradle/wrapper/gradle-wrapper.jar
+
+######################
+# Maven Wrapper
+######################
+!.mvn/wrapper/maven-wrapper.jar
+
+######################
+# ESLint
+######################
+.eslintcache
\ No newline at end of file
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/pom.xml
new file mode 100644
index 000000000..a18785cab
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/pom.xml
@@ -0,0 +1,83 @@
+<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/xsd/maven-4.0.0.xsd">
+	<parent>
+		<artifactId>springdoc-openapi-tests</artifactId>
+		<groupId>org.springdoc</groupId>
+		<version>2.2.1-SNAPSHOT</version>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<artifactId>springdoc-openapi-kotlin-mvc-tests</artifactId>
+
+	<dependencies>
+		<dependency>
+			<groupId>com.fasterxml.jackson.module</groupId>
+			<artifactId>jackson-module-kotlin</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springdoc</groupId>
+			<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.jetbrains.kotlin</groupId>
+			<artifactId>kotlin-stdlib-jdk8</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>kotlin-maven-plugin</artifactId>
+				<groupId>org.jetbrains.kotlin</groupId>
+				<executions>
+					<execution>
+						<id>compile</id>
+						<phase>process-sources</phase>
+						<goals>
+							<goal>compile</goal>
+						</goals>
+						<configuration>
+							<sourceDirs>
+								<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
+							</sourceDirs>
+						</configuration>
+					</execution>
+					<execution>
+						<id>test-compile</id>
+						<goals>
+							<goal>test-compile</goal>
+						</goals>
+						<configuration>
+							<sourceDirs>
+								<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
+							</sourceDirs>
+						</configuration>
+					</execution>
+				</executions>
+				<configuration>
+					<compilerPlugins>
+						<plugin>spring</plugin>
+					</compilerPlugins>
+				</configuration>
+				<dependencies>
+					<dependency>
+						<groupId>org.jetbrains.kotlin</groupId>
+						<artifactId>kotlin-maven-allopen</artifactId>
+						<version>${kotlin.version}</version>
+					</dependency>
+				</dependencies>
+			</plugin>
+		</plugins>
+	</build>
+</project>
\ No newline at end of file
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/AbstractKotlinSpringDocMVCTest.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/AbstractKotlinSpringDocMVCTest.kt
new file mode 100644
index 000000000..2a0e48a19
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/AbstractKotlinSpringDocMVCTest.kt
@@ -0,0 +1,81 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api
+
+import org.junit.jupiter.api.Test
+import org.skyscreamer.jsonassert.JSONAssert
+import org.slf4j.LoggerFactory
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.ActiveProfiles
+import org.springframework.test.web.servlet.MockMvc
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers
+import java.nio.charset.StandardCharsets
+import java.nio.file.Files
+import java.nio.file.Paths
+
+@SpringBootTest
+@AutoConfigureMockMvc
+@ActiveProfiles("test")
+abstract class AbstractKotlinSpringDocMVCTest {
+
+    @Autowired
+    val mockMvc: MockMvc? = null
+
+    private val logger = LoggerFactory.getLogger(AbstractKotlinSpringDocMVCTest::class.java)
+
+    @Test
+    fun testApp() {
+        var result: String? = null
+        try {
+            val response = mockMvc!!.perform(MockMvcRequestBuilders.get("/v3/api-docs"))
+                    .andExpect(MockMvcResultMatchers.status().isOk).andReturn()
+
+            result = response.response.contentAsString
+            val className = javaClass.simpleName
+            val testNumber = className.replace("[^0-9]".toRegex(), "")
+
+            val expected = getContent("results/app$testNumber.json")
+            JSONAssert.assertEquals(expected, result, true)
+        } catch (e: AssertionError) {
+            logger.error(result)
+            throw e
+        }
+    }
+
+    companion object {
+        @Throws(Exception::class)
+        fun getContent(fileName: String): String {
+            try {
+                val path = Paths.get(
+                    AbstractKotlinSpringDocMVCTest::class.java.classLoader.getResource(
+                        fileName
+                    )!!.toURI()
+                )
+                val fileBytes = Files.readAllBytes(path)
+                return String(fileBytes, StandardCharsets.UTF_8)
+            } catch (e: Exception) {
+                throw RuntimeException("Failed to read file: $fileName", e)
+            }
+
+        }
+    }
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app10/ExampleController.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app10/ExampleController.kt
new file mode 100644
index 000000000..077d6bc2f
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app10/ExampleController.kt
@@ -0,0 +1,20 @@
+package test.org.springdoc.api.app10
+
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestParam
+import org.springframework.web.bind.annotation.RestController
+import test.org.springdoc.api.app8.Greeting
+
+data class Greeting(val greeting: String)
+
+@RestController
+class ExampleController {
+	@GetMapping("/")
+	fun greet(@RequestParam name: String?) = Greeting("Hello ${name ?: "world"}")
+
+	@GetMapping("/test")
+	fun test(@RequestParam name: String) = Greeting("Hello $name")
+
+	@GetMapping("/test-with-default")
+	fun testWithDefault(@RequestParam(defaultValue = "world") name: String) = Greeting("Hello $name")
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app10/SpringDocApp10Test.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app10/SpringDocApp10Test.kt
new file mode 100644
index 000000000..300a3c02d
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app10/SpringDocApp10Test.kt
@@ -0,0 +1,31 @@
+/*
+ *
+ *  * Copyright 2019-2023 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app10
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.context.annotation.ComponentScan
+import test.org.springdoc.api.AbstractKotlinSpringDocMVCTest
+
+class SpringDocApp10Test : AbstractKotlinSpringDocMVCTest() {
+
+	@SpringBootApplication
+	@ComponentScan(basePackages = ["org.springdoc", "test.org.springdoc.api.app10"])
+	class DemoApplication
+
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app2/SpringDocApp2Test.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app2/SpringDocApp2Test.kt
new file mode 100644
index 000000000..253caa4be
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app2/SpringDocApp2Test.kt
@@ -0,0 +1,29 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app2
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import test.org.springdoc.api.AbstractKotlinSpringDocMVCTest
+
+class SpringDocApp2Test : AbstractKotlinSpringDocMVCTest() {
+
+    @SpringBootApplication
+    class DemoApplication
+
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app2/SystemStatusController.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app2/SystemStatusController.kt
new file mode 100644
index 000000000..5205485dd
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app2/SystemStatusController.kt
@@ -0,0 +1,43 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app2
+
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+enum class SystemStatus(val status: String) {
+	OK("OK")
+}
+
+data class SystemStatusResponse(
+	val status: SystemStatus
+)
+
+@RestController
+@RequestMapping("/status")
+class SystemStatusController {
+	@GetMapping
+	fun index() = SystemStatusResponse(SystemStatus.OK)
+
+	@GetMapping("/foo")
+	fun foo() =
+		SystemStatusResponse(SystemStatus.OK)
+
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app3/SpringDocApp3Test.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app3/SpringDocApp3Test.kt
new file mode 100644
index 000000000..856022f3a
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app3/SpringDocApp3Test.kt
@@ -0,0 +1,31 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app3
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.context.annotation.ComponentScan
+import test.org.springdoc.api.AbstractKotlinSpringDocMVCTest
+
+class SpringDocApp3Test : AbstractKotlinSpringDocMVCTest() {
+
+	@SpringBootApplication
+	@ComponentScan(basePackages = ["org.springdoc", "test.org.springdoc.api.app3"])
+	class DemoApplication
+
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app3/SystemStatusController.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app3/SystemStatusController.kt
new file mode 100644
index 000000000..c07452e9c
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app3/SystemStatusController.kt
@@ -0,0 +1,43 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app3
+
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+enum class SystemStatus(val status: String) {
+	OK("OK")
+}
+
+data class SystemStatusResponse(
+	val status: SystemStatus
+)
+
+@RestController
+@RequestMapping("/status")
+class SystemStatusController {
+	@GetMapping
+	fun index() = SystemStatusResponse(SystemStatus.OK)
+
+	@GetMapping("/foo")
+	@Deprecated("")
+	fun foo() = SystemStatusResponse(SystemStatus.OK)
+
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app4/HelloController.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app4/HelloController.kt
new file mode 100644
index 000000000..6d0d9199e
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app4/HelloController.kt
@@ -0,0 +1,37 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app4
+
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+
+data class Person(
+	val name: String,
+	val nickname: String?
+)
+
+@RestController
+@RequestMapping("/test")
+class HelloController {
+	@GetMapping
+	suspend fun index(s: Person) = s
+
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app4/SpringDocApp4Test.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app4/SpringDocApp4Test.kt
new file mode 100644
index 000000000..d66e0fd9f
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app4/SpringDocApp4Test.kt
@@ -0,0 +1,31 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app4
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.context.annotation.ComponentScan
+import test.org.springdoc.api.AbstractKotlinSpringDocMVCTest
+
+class SpringDocApp4Test : AbstractKotlinSpringDocMVCTest() {
+
+	@SpringBootApplication
+	@ComponentScan(basePackages = ["org.springdoc", "test.org.springdoc.api.app4"])
+	class DemoApplication
+
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app5/ListController.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app5/ListController.kt
new file mode 100644
index 000000000..262f508b8
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app5/ListController.kt
@@ -0,0 +1,31 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app5
+
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+@RequestMapping("/test")
+class ListController {
+
+    @GetMapping("/")
+    fun foo(): List<Int> = listOf(1, 2, 3)
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app5/SpringDocApp5Test.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app5/SpringDocApp5Test.kt
new file mode 100644
index 000000000..6d87b74dd
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app5/SpringDocApp5Test.kt
@@ -0,0 +1,31 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app5
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.context.annotation.ComponentScan
+import test.org.springdoc.api.AbstractKotlinSpringDocMVCTest
+
+class SpringDocApp5Test : AbstractKotlinSpringDocMVCTest() {
+
+	@SpringBootApplication
+	@ComponentScan(basePackages = ["org.springdoc", "test.org.springdoc.api.app5"])
+	class DemoApplication
+
+}
\ No newline at end of file
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app6/ByteArrayController.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app6/ByteArrayController.kt
new file mode 100644
index 000000000..f3de98487
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app6/ByteArrayController.kt
@@ -0,0 +1,34 @@
+/*
+ *
+ *  * Copyright 2019-2022 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app6
+
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+data class Foo(val data: ByteArray)
+
+@RestController
+@RequestMapping("/bytearray")
+class ByteArrayController {
+
+	@GetMapping("/")
+	fun getByteArray(): Foo = Foo(byteArrayOf(0))
+
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app6/SpringDocApp6Test.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app6/SpringDocApp6Test.kt
new file mode 100644
index 000000000..ef9ca29a5
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app6/SpringDocApp6Test.kt
@@ -0,0 +1,31 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app6
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.context.annotation.ComponentScan
+import test.org.springdoc.api.AbstractKotlinSpringDocMVCTest
+
+class SpringDocApp6Test : AbstractKotlinSpringDocMVCTest() {
+
+	@SpringBootApplication
+	@ComponentScan(basePackages = ["org.springdoc", "test.org.springdoc.api.app6"])
+	class DemoApplication
+
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app7/ExampleController.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app7/ExampleController.kt
new file mode 100644
index 000000000..4f8ca13de
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app7/ExampleController.kt
@@ -0,0 +1,17 @@
+package test.org.springdoc.api.app7
+
+import io.swagger.v3.oas.annotations.Parameter
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestParam
+import org.springframework.web.bind.annotation.RestController
+
+data class Greeting(val greeting: String)
+
+@RestController
+interface ExampleController {
+    @GetMapping("/")
+    fun greet(@RequestParam name: String?): Greeting
+
+	@GetMapping("/test")
+	fun test(@RequestParam @Parameter(required = true) name: String?): Greeting
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app7/SpringDocApp7Test.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app7/SpringDocApp7Test.kt
new file mode 100644
index 000000000..5b321c55f
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app7/SpringDocApp7Test.kt
@@ -0,0 +1,46 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app7
+
+import org.springframework.aop.framework.ProxyFactory
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.ComponentScan
+import org.springframework.context.support.GenericApplicationContext
+import test.org.springdoc.api.AbstractKotlinSpringDocMVCTest
+
+class SpringDocApp7Test : AbstractKotlinSpringDocMVCTest() {
+
+	@SpringBootApplication
+	@ComponentScan(basePackages = ["org.springdoc", "test.org.springdoc.api.app7"])
+	class DemoApplication{
+		@Bean
+		fun controller(applicationContext: GenericApplicationContext): ExampleController {
+			return createProxy(ExampleController::class.java)
+		}
+
+		private fun <T> createProxy(clazz: Class<T>): T {
+			val proxyFactory = ProxyFactory(clazz)
+			proxyFactory.targetClass = clazz
+			@Suppress("UNCHECKED_CAST")
+			return proxyFactory.proxy as T
+		}
+	}
+
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app8/ExampleController.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app8/ExampleController.kt
new file mode 100644
index 000000000..061b2b9eb
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app8/ExampleController.kt
@@ -0,0 +1,17 @@
+package test.org.springdoc.api.app8
+
+import io.swagger.v3.oas.annotations.Parameter
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestParam
+import org.springframework.web.bind.annotation.RestController
+
+data class Greeting(val greeting: String)
+
+@RestController
+interface ExampleController {
+    @GetMapping("/")
+    fun greet(@RequestParam name: String?): Greeting
+
+	@GetMapping("/test")
+	fun test(@RequestParam @Parameter(required = true) name: String?): Greeting
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app8/SpringDocApp8Test.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app8/SpringDocApp8Test.kt
new file mode 100644
index 000000000..3d00589d4
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app8/SpringDocApp8Test.kt
@@ -0,0 +1,49 @@
+/*
+ *
+ *  * Copyright 2019-2020 the original author or authors.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *      https://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package test.org.springdoc.api.app8
+
+import org.springdoc.core.utils.Constants
+import org.springframework.aop.framework.ProxyFactory
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.ComponentScan
+import org.springframework.context.support.GenericApplicationContext
+import org.springframework.test.context.TestPropertySource
+import test.org.springdoc.api.AbstractKotlinSpringDocMVCTest
+
+@TestPropertySource(properties =  [Constants.SPRINGDOC_NULLABLE_REQUEST_PARAMETER_ENABLED+"=false"])
+class SpringDocApp8Test : AbstractKotlinSpringDocMVCTest() {
+
+	@SpringBootApplication
+	@ComponentScan(basePackages = ["org.springdoc", "test.org.springdoc.api.app8"])
+	class DemoApplication{
+		@Bean
+		fun controller(applicationContext: GenericApplicationContext): ExampleController {
+			return createProxy(ExampleController::class.java)
+		}
+
+		private fun <T> createProxy(clazz: Class<T>): T {
+			val proxyFactory = ProxyFactory(clazz)
+			proxyFactory.targetClass = clazz
+			@Suppress("UNCHECKED_CAST")
+			return proxyFactory.proxy as T
+		}
+	}
+
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app9/DemoController.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app9/DemoController.kt
new file mode 100644
index 000000000..6b8793276
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app9/DemoController.kt
@@ -0,0 +1,71 @@
+package test.org.springdoc.api.app9
+
+import io.swagger.v3.oas.annotations.media.Schema
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+@RequestMapping("/api/demo")
+class DocumentsApiController {
+
+    @GetMapping
+    suspend fun getDocuments( request: DemoRequest
+    ): DemoDto = DemoDto(42)
+}
+
+data class DemoDto(
+    var id: Long,
+)
+
+class DemoRequest (
+
+	@field:Schema(required = true, defaultValue = "a default value")
+	val requiredNullableDefault: String?,
+
+	@field:Schema(required = true)
+	val requiredNullableNoDefault: String?,
+
+	@field:Schema(required = true, defaultValue = "a default value")
+	val requiredNoNullableDefault: String,
+
+	@field:Schema(required = true)
+	val requiredNoNullableNoDefault: String,
+
+	@field:Schema(requiredMode = Schema.RequiredMode.REQUIRED, defaultValue = "a default value")
+	val requiredNullableDefault1: String?,
+
+	@field:Schema(requiredMode = Schema.RequiredMode.REQUIRED)
+	val requiredNullableNoDefault1: String?,
+
+	@field:Schema(requiredMode = Schema.RequiredMode.REQUIRED, defaultValue = "a default value")
+	val requiredNoNullableDefault1: String,
+
+	@field:Schema(requiredMode = Schema.RequiredMode.REQUIRED)
+	val requiredNoNullableNoDefault1: String,
+
+	@field:Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED, defaultValue = "a default value")
+	val noRequiredNullableDefault2: String?,
+
+	@field:Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+	val noRequiredNullableNoDefault2: String?,
+
+	@field:Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED, defaultValue = "a default value")
+	val noRequiredNoNullableDefault2: String,
+
+	@field:Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED)
+	val noRequiredNoNullableNoDefault2: String,
+
+	@field:Schema(defaultValue = "a default value")
+	val noRequiredNullableDefault: String?,
+
+	@field:Schema
+	val noRequiredNullableNoDefault: String?,
+
+	@field:Schema(defaultValue = "a default value")
+	val noRequiredNoNullableDefault: String,
+
+	@field:Schema
+	val noRequiredNoNullableNoDefault: String,
+
+)
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app9/SpringDocApp9Test.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app9/SpringDocApp9Test.kt
new file mode 100644
index 000000000..424b16a56
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/kotlin/test/org/springdoc/api/app9/SpringDocApp9Test.kt
@@ -0,0 +1,9 @@
+package test.org.springdoc.api.app9
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import test.org.springdoc.api.AbstractKotlinSpringDocMVCTest
+
+class SpringDocApp9Test: AbstractKotlinSpringDocMVCTest() {
+    @SpringBootApplication
+    class DemoApplication
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/application-test.yml b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/application-test.yml
new file mode 100644
index 000000000..544f357e4
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/application-test.yml
@@ -0,0 +1,9 @@
+spring:
+  main:
+    banner-mode: "off"
+    lazy-initialization: true
+logging:
+  level:
+    root: ERROR
+  pattern:
+    console: '%m%n'
\ No newline at end of file
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/logback-test.xml b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/logback-test.xml
new file mode 100644
index 000000000..a715d5a44
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/logback-test.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+	<include resource="org/springframework/boot/logging/logback/base.xml"/>
+	<logger name="org.springframework" level="ERROR"/>
+	<logger name="test.org.springdoc.api" level="ERROR"/>
+</configuration>
\ No newline at end of file
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app1.json b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app1.json
new file mode 100644
index 000000000..2c599857a
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app1.json
@@ -0,0 +1,51 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "Kotlin API",
+    "license": {
+      "name": "Apache 2.0",
+      "url": "http://springdoc.org"
+    },
+    "version": "v1"
+  },
+  "servers": [
+    {
+      "url": "",
+      "description": "Generated server url"
+    }
+  ],
+  "paths": {
+    "/test/{id}": {
+      "get": {
+        "tags": [
+          "controller-with-continuation-parameter"
+        ],
+        "summary": "Ignore Continuation parameter",
+        "operationId": "get",
+        "parameters": [
+          {
+            "name": "id",
+            "in": "path",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "string"
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components": {}
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app10.json b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app10.json
new file mode 100644
index 000000000..748116b2e
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app10.json
@@ -0,0 +1,121 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "OpenAPI definition",
+    "version": "v0"
+  },
+  "servers": [
+    {
+      "url": "http://localhost",
+      "description": "Generated server url"
+    }
+  ],
+  "paths": {
+    "/": {
+      "get": {
+        "tags": [
+          "example-controller"
+        ],
+        "operationId": "greet",
+        "parameters": [
+          {
+            "name": "name",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/Greeting"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/test": {
+      "get": {
+        "tags": [
+          "example-controller"
+        ],
+        "operationId": "test",
+        "parameters": [
+          {
+            "name": "name",
+            "in": "query",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/Greeting"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/test-with-default": {
+      "get": {
+        "tags": [
+          "example-controller"
+        ],
+        "operationId": "testWithDefault",
+        "parameters": [
+          {
+            "name": "name",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": "string",
+              "default": "world"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/Greeting"
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "Greeting": {
+        "required": [
+          "greeting"
+        ],
+        "type": "object",
+        "properties": {
+          "greeting": {
+            "type": "string"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app2.json b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app2.json
new file mode 100644
index 000000000..b555db2b4
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app2.json
@@ -0,0 +1,73 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "OpenAPI definition",
+    "version": "v0"
+  },
+  "servers": [
+    {
+      "url": "http://localhost",
+      "description": "Generated server url"
+    }
+  ],
+  "paths": {
+    "/status": {
+      "get": {
+        "tags": [
+          "system-status-controller"
+        ],
+        "operationId": "index",
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/SystemStatusResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/status/foo": {
+      "get": {
+        "tags": [
+          "system-status-controller"
+        ],
+        "operationId": "foo",
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/SystemStatusResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "SystemStatusResponse": {
+        "required": [
+          "status"
+        ],
+        "type": "object",
+        "properties": {
+          "status": {
+            "type": "string",
+            "enum": [
+              "OK"
+            ]
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app3.json b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app3.json
new file mode 100644
index 000000000..2791ec557
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app3.json
@@ -0,0 +1,74 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "OpenAPI definition",
+    "version": "v0"
+  },
+  "servers": [
+    {
+      "url": "http://localhost",
+      "description": "Generated server url"
+    }
+  ],
+  "paths": {
+    "/status": {
+      "get": {
+        "tags": [
+          "system-status-controller"
+        ],
+        "operationId": "index",
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/SystemStatusResponse"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/status/foo": {
+      "get": {
+        "tags": [
+          "system-status-controller"
+        ],
+        "operationId": "foo",
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/SystemStatusResponse"
+                }
+              }
+            }
+          }
+        },
+        "deprecated": true
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "SystemStatusResponse": {
+        "required": [
+          "status"
+        ],
+        "type": "object",
+        "properties": {
+          "status": {
+            "type": "string",
+            "enum": [
+              "OK"
+            ]
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app4.json b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app4.json
new file mode 100644
index 000000000..c0a5acd97
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app4.json
@@ -0,0 +1,63 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "OpenAPI definition",
+    "version": "v0"
+  },
+  "servers": [
+    {
+      "url": "http://localhost",
+      "description": "Generated server url"
+    }
+  ],
+  "paths": {
+    "/test": {
+      "get": {
+        "tags": [
+          "hello-controller"
+        ],
+        "operationId": "index",
+        "parameters": [
+          {
+            "name": "s",
+            "in": "query",
+            "required": true,
+            "schema": {
+              "$ref": "#/components/schemas/Person"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/Person"
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "Person": {
+        "required": [
+          "name"
+        ],
+        "type": "object",
+        "properties": {
+          "name": {
+            "type": "string"
+          },
+          "nickname": {
+            "type": "string"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app5.json b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app5.json
new file mode 100644
index 000000000..5e7be5662
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app5.json
@@ -0,0 +1,40 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "OpenAPI definition",
+    "version": "v0"
+  },
+  "servers": [
+    {
+      "url": "http://localhost",
+      "description": "Generated server url"
+    }
+  ],
+  "paths": {
+    "/test/": {
+      "get": {
+        "tags": [
+          "list-controller"
+        ],
+        "operationId": "foo",
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "type": "integer",
+                    "format": "int32"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components": {}
+}
\ No newline at end of file
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app6.json b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app6.json
new file mode 100644
index 000000000..03e359ee6
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app6.json
@@ -0,0 +1,51 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "OpenAPI definition",
+    "version": "v0"
+  },
+  "servers": [
+    {
+      "url": "http://localhost",
+      "description": "Generated server url"
+    }
+  ],
+  "paths": {
+    "/bytearray/": {
+      "get": {
+        "tags": [
+          "byte-array-controller"
+        ],
+        "operationId": "getByteArray",
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/Foo"
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "Foo": {
+        "required": [
+          "data"
+        ],
+        "type": "object",
+        "properties": {
+          "data": {
+            "type": "string",
+            "format": "byte"
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app7.json b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app7.json
new file mode 100644
index 000000000..a501dc369
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app7.json
@@ -0,0 +1,90 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "OpenAPI definition",
+    "version": "v0"
+  },
+  "servers": [
+    {
+      "url": "http://localhost",
+      "description": "Generated server url"
+    }
+  ],
+  "paths": {
+    "/": {
+      "get": {
+        "tags": [
+          "example-controller"
+        ],
+        "operationId": "greet",
+        "parameters": [
+          {
+            "name": "name",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/Greeting"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/test": {
+      "get": {
+        "tags": [
+          "example-controller"
+        ],
+        "operationId": "test",
+        "parameters": [
+          {
+            "name": "name",
+            "in": "query",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/Greeting"
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "Greeting": {
+        "required": [
+          "greeting"
+        ],
+        "type": "object",
+        "properties": {
+          "greeting": {
+            "type": "string"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app8.json b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app8.json
new file mode 100644
index 000000000..a501dc369
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app8.json
@@ -0,0 +1,90 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "OpenAPI definition",
+    "version": "v0"
+  },
+  "servers": [
+    {
+      "url": "http://localhost",
+      "description": "Generated server url"
+    }
+  ],
+  "paths": {
+    "/": {
+      "get": {
+        "tags": [
+          "example-controller"
+        ],
+        "operationId": "greet",
+        "parameters": [
+          {
+            "name": "name",
+            "in": "query",
+            "required": false,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/Greeting"
+                }
+              }
+            }
+          }
+        }
+      }
+    },
+    "/test": {
+      "get": {
+        "tags": [
+          "example-controller"
+        ],
+        "operationId": "test",
+        "parameters": [
+          {
+            "name": "name",
+            "in": "query",
+            "required": true,
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/Greeting"
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "Greeting": {
+        "required": [
+          "greeting"
+        ],
+        "type": "object",
+        "properties": {
+          "greeting": {
+            "type": "string"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app9.json b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app9.json
new file mode 100644
index 000000000..16afb1792
--- /dev/null
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-mvc-tests/src/test/resources/results/app9.json
@@ -0,0 +1,133 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "OpenAPI definition",
+    "version": "v0"
+  },
+  "servers": [
+    {
+      "url": "http://localhost",
+      "description": "Generated server url"
+    }
+  ],
+  "paths": {
+    "/api/demo": {
+      "get": {
+        "tags": [
+          "documents-api-controller"
+        ],
+        "operationId": "getDocuments",
+        "parameters": [
+          {
+            "name": "request",
+            "in": "query",
+            "required": true,
+            "schema": {
+              "$ref": "#/components/schemas/DemoRequest"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "*/*": {
+                "schema": {
+                  "$ref": "#/components/schemas/DemoDto"
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "DemoRequest": {
+        "required": [
+          "noRequiredNoNullableNoDefault",
+          "requiredNoNullableDefault",
+          "requiredNoNullableDefault1",
+          "requiredNoNullableNoDefault",
+          "requiredNoNullableNoDefault1",
+          "requiredNullableDefault",
+          "requiredNullableDefault1",
+          "requiredNullableNoDefault",
+          "requiredNullableNoDefault1"
+        ],
+        "type": "object",
+        "properties": {
+          "requiredNullableDefault": {
+            "type": "string",
+            "default": "a default value"
+          },
+          "requiredNullableNoDefault": {
+            "type": "string"
+          },
+          "requiredNoNullableDefault": {
+            "type": "string",
+            "default": "a default value"
+          },
+          "requiredNoNullableNoDefault": {
+            "type": "string"
+          },
+          "requiredNullableDefault1": {
+            "type": "string",
+            "default": "a default value"
+          },
+          "requiredNullableNoDefault1": {
+            "type": "string"
+          },
+          "requiredNoNullableDefault1": {
+            "type": "string",
+            "default": "a default value"
+          },
+          "requiredNoNullableNoDefault1": {
+            "type": "string"
+          },
+          "noRequiredNullableDefault2": {
+            "type": "string",
+            "default": "a default value"
+          },
+          "noRequiredNullableNoDefault2": {
+            "type": "string"
+          },
+          "noRequiredNoNullableDefault2": {
+            "type": "string",
+            "default": "a default value"
+          },
+          "noRequiredNoNullableNoDefault2": {
+            "type": "string"
+          },
+          "noRequiredNullableDefault": {
+            "type": "string",
+            "default": "a default value"
+          },
+          "noRequiredNullableNoDefault": {
+            "type": "string"
+          },
+          "noRequiredNoNullableDefault": {
+            "type": "string",
+            "default": "a default value"
+          },
+          "noRequiredNoNullableNoDefault": {
+            "type": "string"
+          }
+        }
+      },
+      "DemoDto": {
+        "required": [
+          "id"
+        ],
+        "type": "object",
+        "properties": {
+          "id": {
+            "type": "integer",
+            "format": "int64"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-kotlin-tests/pom.xml
index b4059565e..0efe31d01 100644
--- a/springdoc-openapi-tests/springdoc-openapi-kotlin-tests/pom.xml
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-tests/pom.xml
@@ -2,7 +2,7 @@
 	<parent>
 		<artifactId>springdoc-openapi-tests</artifactId>
 		<groupId>org.springdoc</groupId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>springdoc-openapi-kotlin-tests</artifactId>
diff --git a/springdoc-openapi-tests/springdoc-openapi-security-tests/pom.xml b/springdoc-openapi-tests/springdoc-openapi-security-tests/pom.xml
index d87bdc7e0..b43ff6b70 100644
--- a/springdoc-openapi-tests/springdoc-openapi-security-tests/pom.xml
+++ b/springdoc-openapi-tests/springdoc-openapi-security-tests/pom.xml
@@ -3,7 +3,7 @@
 	<parent>
 		<groupId>org.springdoc</groupId>
 		<artifactId>springdoc-openapi-tests</artifactId>
-		<version>2.3.1-SNAPSHOT</version>
+		<version>2.2.1-SNAPSHOT</version>
 	</parent>
 	<artifactId>springdoc-openapi-security-tests</artifactId>
 	<properties>