Skip to content

Commit 5af0cde

Browse files
committed
fix siblings in annotated request body param schemas OAS 3.1 resolving, add skipResolveAppPath
1 parent c9438ad commit 5af0cde

File tree

20 files changed

+346
-29
lines changed

20 files changed

+346
-29
lines changed

modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/parameters/RequestBody.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,11 @@
6060
**/
6161
String ref() default "";
6262

63+
/**
64+
* Set to true to resolve the request body schema from parameter type
65+
*
66+
* @since 2.2.15
67+
**/
68+
boolean useParameterTypeSchema() default false;
69+
6370
}

modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -934,29 +934,31 @@ public static Optional<Server> getServer(io.swagger.v3.oas.annotations.servers.S
934934
return Optional.empty();
935935
}
936936
io.swagger.v3.oas.annotations.servers.ServerVariable[] serverVariables = server.variables();
937-
ServerVariables serverVariablesObject = new ServerVariables();
938-
for (io.swagger.v3.oas.annotations.servers.ServerVariable serverVariable : serverVariables) {
939-
ServerVariable serverVariableObject = new ServerVariable();
940-
if (StringUtils.isNotBlank(serverVariable.description())) {
941-
serverVariableObject.setDescription(serverVariable.description());
942-
}
943-
if (StringUtils.isNotBlank(serverVariable.defaultValue())) {
944-
serverVariableObject.setDefault(serverVariable.defaultValue());
945-
}
946-
if (serverVariable.allowableValues() != null && serverVariable.allowableValues().length > 0) {
947-
if (StringUtils.isNotBlank(serverVariable.allowableValues()[0])) {
948-
serverVariableObject.setEnum(Arrays.asList(serverVariable.allowableValues()));
937+
if (serverVariables.length > 0) {
938+
ServerVariables serverVariablesObject = new ServerVariables();
939+
for (io.swagger.v3.oas.annotations.servers.ServerVariable serverVariable : serverVariables) {
940+
ServerVariable serverVariableObject = new ServerVariable();
941+
if (StringUtils.isNotBlank(serverVariable.description())) {
942+
serverVariableObject.setDescription(serverVariable.description());
943+
}
944+
if (StringUtils.isNotBlank(serverVariable.defaultValue())) {
945+
serverVariableObject.setDefault(serverVariable.defaultValue());
946+
}
947+
if (serverVariable.allowableValues() != null && serverVariable.allowableValues().length > 0) {
948+
if (StringUtils.isNotBlank(serverVariable.allowableValues()[0])) {
949+
serverVariableObject.setEnum(Arrays.asList(serverVariable.allowableValues()));
950+
}
949951
}
950-
}
951-
if (serverVariable.extensions() != null && serverVariable.extensions().length > 0) {
952-
Map<String, Object> extensions = AnnotationsUtils.getExtensions(serverVariable.extensions());
953-
if (extensions != null) {
954-
extensions.forEach(serverVariableObject::addExtension);
952+
if (serverVariable.extensions() != null && serverVariable.extensions().length > 0) {
953+
Map<String, Object> extensions = AnnotationsUtils.getExtensions(serverVariable.extensions());
954+
if (extensions != null) {
955+
extensions.forEach(serverVariableObject::addExtension);
956+
}
955957
}
958+
serverVariablesObject.addServerVariable(serverVariable.name(), serverVariableObject);
956959
}
957-
serverVariablesObject.addServerVariable(serverVariable.name(), serverVariableObject);
960+
serverObject.setVariables(serverVariablesObject);
958961
}
959-
serverObject.setVariables(serverVariablesObject);
960962

961963
return Optional.of(serverObject);
962964
}

modules/swagger-gradle-plugin/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ Parameter | Description | Required | Default
8585
`prettyPrint`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`TRUE`
8686
`sortOutput`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE`
8787
`alwaysResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE`
88+
`skipResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE`
8889
`openApiFile`|openapi file to be merged with resolved specification, equivalent to [config](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties) openAPI|false|
8990
`filterClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|
9091
`readerClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|
@@ -119,5 +120,5 @@ info:
119120
120121
Since version 2.1.6, `sortOutput` parameter is available, allowing to sort object properties and map keys alphabetically.
121122
Since version 2.1.6, `objectMapperProcessorClass` allows to configure also the ObjectMapper instance used to serialize the resolved OpenAPI
122-
Since version 2.1.9, `alwaysResolveAppPath` parameter is available, allowing to trigger resolving of Application Path from annotaion also not in runtime (e.g. using servlet in separate application, or in maven plugin at build time, etc)
123-
123+
Since version 2.1.9, `alwaysResolveAppPath` parameter is available, allowing to trigger resolving of Application Path from annotation also not in runtime (e.g. using servlet in separate application, or in maven plugin at build time, etc)
124+
Since version 2.1.15, `skipResolveAppPath` parameter is available, allowing to skip resolving of Application Path from annotation

modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/tasks/ResolveTask.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public enum Format {JSON, YAML, JSONANDYAML};
6868

6969
private Boolean sortOutput = Boolean.FALSE;
7070
private Boolean alwaysResolveAppPath = Boolean.FALSE;
71+
private Boolean skipResolveAppPath = Boolean.FALSE;
7172

7273

7374
private String contextId;
@@ -322,6 +323,22 @@ public void setAlwaysResolveAppPath(Boolean alwaysResolveAppPath) {
322323
this.alwaysResolveAppPath = alwaysResolveAppPath;
323324
}
324325

326+
/**
327+
* @since 2.2.15
328+
*/
329+
@Input
330+
@Optional
331+
public Boolean getSkipResolveAppPath() {
332+
return skipResolveAppPath;
333+
}
334+
335+
/**
336+
* @since 2.2.15
337+
*/
338+
public void setSkipResolveAppPath(Boolean skipResolveAppPath) {
339+
this.skipResolveAppPath = skipResolveAppPath;
340+
}
341+
325342
/**
326343
* @since 2.2.0
327344
*/
@@ -453,6 +470,9 @@ public void resolve() throws GradleException {
453470
method=swaggerLoaderClass.getDeclaredMethod("setAlwaysResolveAppPath", Boolean.class);
454471
method.invoke(swaggerLoader, alwaysResolveAppPath);
455472

473+
method=swaggerLoaderClass.getDeclaredMethod("setSkipResolveAppPath", Boolean.class);
474+
method.invoke(swaggerLoader, skipResolveAppPath);
475+
456476
method=swaggerLoaderClass.getDeclaredMethod("setReadAllResources", Boolean.class);
457477
method.invoke(swaggerLoader, readAllResources);
458478

modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiContext.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,9 @@ private OpenAPIConfiguration mergeParentConfiguration(OpenAPIConfiguration confi
612612
if (merged.isAlwaysResolveAppPath() == null) {
613613
merged.setAlwaysResolveAppPath(parentConfig.isAlwaysResolveAppPath());
614614
}
615+
if (merged.isSkipResolveAppPath() == null) {
616+
merged.setSkipResolveAppPath(parentConfig.isSkipResolveAppPath());
617+
}
615618
if (merged.isReadAllResources() == null) {
616619
merged.setReadAllResources(parentConfig.isReadAllResources());
617620
}

modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/SwaggerConfiguration.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public class SwaggerConfiguration implements OpenAPIConfiguration {
3434

3535
private Boolean alwaysResolveAppPath;
3636

37+
private Boolean skipResolveAppPath;
38+
3739
private Boolean openAPI31 = false;
3840

3941
private Boolean convertToOpenAPI31;
@@ -286,6 +288,29 @@ public SwaggerConfiguration alwaysResolveAppPath(Boolean alwaysResolveAppPath) {
286288
return this;
287289
}
288290

291+
/**
292+
* @since 2.1.15
293+
*/
294+
@Override
295+
public Boolean isSkipResolveAppPath() {
296+
return skipResolveAppPath;
297+
}
298+
299+
/**
300+
* @since 2.1.15
301+
*/
302+
public void setSkipResolveAppPath(Boolean skipResolveAppPath) {
303+
this.skipResolveAppPath = skipResolveAppPath;
304+
}
305+
306+
/**
307+
* @since 2.1.15
308+
*/
309+
public SwaggerConfiguration skipResolveAppPath(Boolean skipResolveAppPath) {
310+
setAlwaysResolveAppPath(skipResolveAppPath);
311+
return this;
312+
}
313+
289314
/**
290315
* @since 2.1.9
291316
*/

modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenAPIConfiguration.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ public interface OpenAPIConfiguration {
4949
*/
5050
Boolean isAlwaysResolveAppPath();
5151

52+
/**
53+
* @since 2.1.15
54+
*/
55+
Boolean isSkipResolveAppPath();
56+
5257
/**
5358
* @since 2.2.12
5459
*/

modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/Reader.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ public OpenAPI read(Set<Class<?>> classes) {
170170
LOGGER.error("Failed to create ReaderListener", e);
171171
}
172172
}
173-
if (config != null && Boolean.TRUE.equals(config.isAlwaysResolveAppPath())) {
173+
if (config != null && Boolean.TRUE.equals(config.isAlwaysResolveAppPath()) && !Boolean.TRUE.equals(config.isSkipResolveAppPath())) {
174174
if (Application.class.isAssignableFrom(cls)) {
175175
ApplicationPath appPathAnnotation = ReflectionUtils.getAnnotation(cls, ApplicationPath.class);
176176
if (appPathAnnotation != null) {
@@ -225,7 +225,7 @@ public OpenAPI read(Set<Class<?>> classes, Map<String, Object> resources) {
225225
}
226226

227227
protected String resolveApplicationPath() {
228-
if (application != null) {
228+
if (application != null && !Boolean.TRUE.equals(config.isSkipResolveAppPath())) {
229229
Class<?> applicationToScan = this.application.getClass();
230230
ApplicationPath applicationPath;
231231
//search up in the hierarchy until we find one with the annotation, this is needed because for example Weld proxies will not have the annotation and the right class will be the superClass
@@ -773,18 +773,36 @@ protected void processRequestBody(Parameter requestBodyParameter, Operation oper
773773
requestBody.getContent() != null &&
774774
!requestBody.getContent().isEmpty()) {
775775
if (requestBodyParameter.getSchema() != null) {
776-
for (MediaType mediaType : requestBody.getContent().values()) {
776+
Map<String, MediaType> reresolvedMediaTypes = new LinkedHashMap<>();
777+
for (String key: requestBody.getContent().keySet()) {
778+
MediaType mediaType = requestBody.getContent().get(key);
777779
if (mediaType.getSchema() == null) {
778780
if (requestBodyParameter.getSchema() == null) {
779781
mediaType.setSchema(new Schema());
780782
} else {
781783
mediaType.setSchema(requestBodyParameter.getSchema());
782784
}
785+
} else if (mediaType.getSchema() != null && requestBodyAnnotation.useParameterTypeSchema()) {
786+
if (requestBodyParameter.getSchema() != null) {
787+
MediaType newMediaType = clone(mediaType);
788+
Schema parameterSchema = clone(requestBodyParameter.getSchema());
789+
Optional<io.swagger.v3.oas.annotations.media.Content> content = Arrays.stream(requestBodyAnnotation.content()).filter(c -> c.mediaType().equals(key)).findFirst();
790+
if (content.isPresent()) {
791+
Optional<Schema> reResolvedSchema = AnnotationsUtils.getSchemaFromAnnotation(content.get().schema(), components, null, config.isOpenAPI31(), parameterSchema);
792+
if (reResolvedSchema.isPresent()) {
793+
parameterSchema = reResolvedSchema.get();
794+
}
795+
796+
}
797+
newMediaType.schema(parameterSchema);
798+
reresolvedMediaTypes.put(key, newMediaType);
799+
}
783800
}
784-
if (StringUtils.isBlank(mediaType.getSchema().getType())) {
801+
if (StringUtils.isBlank(mediaType.getSchema().getType()) || requestBodyAnnotation.useParameterTypeSchema()) {
785802
mediaType.getSchema().setType(requestBodyParameter.getSchema().getType());
786803
}
787804
}
805+
requestBody.getContent().putAll(reresolvedMediaTypes);
788806
}
789807
}
790808
operation.setRequestBody(requestBody);

modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletConfigContextUtils.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ public class ServletConfigContextUtils {
3636
*/
3737
public static final String OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY = "openApi.configuration.alwaysResolveAppPath";
3838

39+
/**
40+
* @since 2.1.15
41+
*/
42+
public static final String OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY = "openApi.configuration.skipResolveAppPath";
43+
3944
/**
4045
* @since 2.0.6
4146
*/

modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletOpenApiConfigurationLoader.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_READALLRESOURCES_KEY;
2424
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_READER_KEY;
2525
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SCANNER_KEY;
26+
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY;
2627
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SORTOUTPUT_KEY;
2728
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY;
2829
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.getBooleanInitParam;
@@ -59,6 +60,7 @@ public OpenAPIConfiguration load(String path) throws IOException {
5960
.prettyPrint(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_PRETTYPRINT_KEY))
6061
.sortOutput(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_SORTOUTPUT_KEY))
6162
.alwaysResolveAppPath(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY))
63+
.skipResolveAppPath(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY))
6264
.readerClass(getInitParam(servletConfig, OPENAPI_CONFIGURATION_READER_KEY))
6365
.cacheTTL(getLongInitParam(servletConfig, OPENAPI_CONFIGURATION_CACHE_TTL_KEY))
6466
.scannerClass(getInitParam(servletConfig, OPENAPI_CONFIGURATION_SCANNER_KEY))
@@ -121,6 +123,9 @@ public boolean exists(String path) {
121123
if (getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY) != null) {
122124
return true;
123125
}
126+
if (getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY) != null) {
127+
return true;
128+
}
124129
if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_READER_KEY) != null) {
125130
return true;
126131
}

0 commit comments

Comments
 (0)