Skip to content

Commit

Permalink
fix siblings in annotated request body param schemas OAS 3.1 resolvin…
Browse files Browse the repository at this point in the history
…g, add skipResolveAppPath
  • Loading branch information
frantuma committed Jun 27, 2023
1 parent 836eaaf commit 2b21241
Show file tree
Hide file tree
Showing 20 changed files with 346 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,11 @@
**/
String ref() default "";

/**
* Set to true to resolve the request body schema from parameter type
*
* @since 2.2.15
**/
boolean useParameterTypeSchema() default false;

}
Original file line number Diff line number Diff line change
Expand Up @@ -934,29 +934,31 @@ public static Optional<Server> getServer(io.swagger.v3.oas.annotations.servers.S
return Optional.empty();
}
io.swagger.v3.oas.annotations.servers.ServerVariable[] serverVariables = server.variables();
ServerVariables serverVariablesObject = new ServerVariables();
for (io.swagger.v3.oas.annotations.servers.ServerVariable serverVariable : serverVariables) {
ServerVariable serverVariableObject = new ServerVariable();
if (StringUtils.isNotBlank(serverVariable.description())) {
serverVariableObject.setDescription(serverVariable.description());
}
if (StringUtils.isNotBlank(serverVariable.defaultValue())) {
serverVariableObject.setDefault(serverVariable.defaultValue());
}
if (serverVariable.allowableValues() != null && serverVariable.allowableValues().length > 0) {
if (StringUtils.isNotBlank(serverVariable.allowableValues()[0])) {
serverVariableObject.setEnum(Arrays.asList(serverVariable.allowableValues()));
if (serverVariables.length > 0) {
ServerVariables serverVariablesObject = new ServerVariables();
for (io.swagger.v3.oas.annotations.servers.ServerVariable serverVariable : serverVariables) {
ServerVariable serverVariableObject = new ServerVariable();
if (StringUtils.isNotBlank(serverVariable.description())) {
serverVariableObject.setDescription(serverVariable.description());
}
if (StringUtils.isNotBlank(serverVariable.defaultValue())) {
serverVariableObject.setDefault(serverVariable.defaultValue());
}
if (serverVariable.allowableValues() != null && serverVariable.allowableValues().length > 0) {
if (StringUtils.isNotBlank(serverVariable.allowableValues()[0])) {
serverVariableObject.setEnum(Arrays.asList(serverVariable.allowableValues()));
}
}
}
if (serverVariable.extensions() != null && serverVariable.extensions().length > 0) {
Map<String, Object> extensions = AnnotationsUtils.getExtensions(serverVariable.extensions());
if (extensions != null) {
extensions.forEach(serverVariableObject::addExtension);
if (serverVariable.extensions() != null && serverVariable.extensions().length > 0) {
Map<String, Object> extensions = AnnotationsUtils.getExtensions(serverVariable.extensions());
if (extensions != null) {
extensions.forEach(serverVariableObject::addExtension);
}
}
serverVariablesObject.addServerVariable(serverVariable.name(), serverVariableObject);
}
serverVariablesObject.addServerVariable(serverVariable.name(), serverVariableObject);
serverObject.setVariables(serverVariablesObject);
}
serverObject.setVariables(serverVariablesObject);

return Optional.of(serverObject);
}
Expand Down
5 changes: 3 additions & 2 deletions modules/swagger-gradle-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Parameter | Description | Required | Default
`prettyPrint`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`TRUE`
`sortOutput`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE`
`alwaysResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE`
`skipResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE`
`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|
`filterClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|
`readerClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|
Expand Down Expand Up @@ -119,5 +120,5 @@ info:
Since version 2.1.6, `sortOutput` parameter is available, allowing to sort object properties and map keys alphabetically.
Since version 2.1.6, `objectMapperProcessorClass` allows to configure also the ObjectMapper instance used to serialize the resolved OpenAPI
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)

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)
Since version 2.1.15, `skipResolveAppPath` parameter is available, allowing to skip resolving of Application Path from annotation
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public enum Format {JSON, YAML, JSONANDYAML};

private Boolean sortOutput = Boolean.FALSE;
private Boolean alwaysResolveAppPath = Boolean.FALSE;
private Boolean skipResolveAppPath = Boolean.FALSE;


private String contextId;
Expand Down Expand Up @@ -322,6 +323,22 @@ public void setAlwaysResolveAppPath(Boolean alwaysResolveAppPath) {
this.alwaysResolveAppPath = alwaysResolveAppPath;
}

/**
* @since 2.2.15
*/
@Input
@Optional
public Boolean getSkipResolveAppPath() {
return skipResolveAppPath;
}

/**
* @since 2.2.15
*/
public void setSkipResolveAppPath(Boolean skipResolveAppPath) {
this.skipResolveAppPath = skipResolveAppPath;
}

/**
* @since 2.2.0
*/
Expand Down Expand Up @@ -453,6 +470,9 @@ public void resolve() throws GradleException {
method=swaggerLoaderClass.getDeclaredMethod("setAlwaysResolveAppPath", Boolean.class);
method.invoke(swaggerLoader, alwaysResolveAppPath);

method=swaggerLoaderClass.getDeclaredMethod("setSkipResolveAppPath", Boolean.class);
method.invoke(swaggerLoader, skipResolveAppPath);

method=swaggerLoaderClass.getDeclaredMethod("setReadAllResources", Boolean.class);
method.invoke(swaggerLoader, readAllResources);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,9 @@ private OpenAPIConfiguration mergeParentConfiguration(OpenAPIConfiguration confi
if (merged.isAlwaysResolveAppPath() == null) {
merged.setAlwaysResolveAppPath(parentConfig.isAlwaysResolveAppPath());
}
if (merged.isSkipResolveAppPath() == null) {
merged.setSkipResolveAppPath(parentConfig.isSkipResolveAppPath());
}
if (merged.isReadAllResources() == null) {
merged.setReadAllResources(parentConfig.isReadAllResources());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public class SwaggerConfiguration implements OpenAPIConfiguration {

private Boolean alwaysResolveAppPath;

private Boolean skipResolveAppPath;

private Boolean openAPI31 = false;

private Boolean convertToOpenAPI31;
Expand Down Expand Up @@ -286,6 +288,29 @@ public SwaggerConfiguration alwaysResolveAppPath(Boolean alwaysResolveAppPath) {
return this;
}

/**
* @since 2.1.15
*/
@Override
public Boolean isSkipResolveAppPath() {
return skipResolveAppPath;
}

/**
* @since 2.1.15
*/
public void setSkipResolveAppPath(Boolean skipResolveAppPath) {
this.skipResolveAppPath = skipResolveAppPath;
}

/**
* @since 2.1.15
*/
public SwaggerConfiguration skipResolveAppPath(Boolean skipResolveAppPath) {
setAlwaysResolveAppPath(skipResolveAppPath);
return this;
}

/**
* @since 2.1.9
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ public interface OpenAPIConfiguration {
*/
Boolean isAlwaysResolveAppPath();

/**
* @since 2.1.15
*/
Boolean isSkipResolveAppPath();

/**
* @since 2.2.12
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public OpenAPI read(Set<Class<?>> classes) {
LOGGER.error("Failed to create ReaderListener", e);
}
}
if (config != null && Boolean.TRUE.equals(config.isAlwaysResolveAppPath())) {
if (config != null && Boolean.TRUE.equals(config.isAlwaysResolveAppPath()) && !Boolean.TRUE.equals(config.isSkipResolveAppPath())) {
if (Application.class.isAssignableFrom(cls)) {
ApplicationPath appPathAnnotation = ReflectionUtils.getAnnotation(cls, ApplicationPath.class);
if (appPathAnnotation != null) {
Expand Down Expand Up @@ -225,7 +225,7 @@ public OpenAPI read(Set<Class<?>> classes, Map<String, Object> resources) {
}

protected String resolveApplicationPath() {
if (application != null) {
if (application != null && !Boolean.TRUE.equals(config.isSkipResolveAppPath())) {
Class<?> applicationToScan = this.application.getClass();
ApplicationPath applicationPath;
//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
Expand Down Expand Up @@ -773,18 +773,36 @@ protected void processRequestBody(Parameter requestBodyParameter, Operation oper
requestBody.getContent() != null &&
!requestBody.getContent().isEmpty()) {
if (requestBodyParameter.getSchema() != null) {
for (MediaType mediaType : requestBody.getContent().values()) {
Map<String, MediaType> reresolvedMediaTypes = new LinkedHashMap<>();
for (String key: requestBody.getContent().keySet()) {
MediaType mediaType = requestBody.getContent().get(key);
if (mediaType.getSchema() == null) {
if (requestBodyParameter.getSchema() == null) {
mediaType.setSchema(new Schema());
} else {
mediaType.setSchema(requestBodyParameter.getSchema());
}
} else if (mediaType.getSchema() != null && requestBodyAnnotation.useParameterTypeSchema()) {
if (requestBodyParameter.getSchema() != null) {
MediaType newMediaType = clone(mediaType);
Schema parameterSchema = clone(requestBodyParameter.getSchema());
Optional<io.swagger.v3.oas.annotations.media.Content> content = Arrays.stream(requestBodyAnnotation.content()).filter(c -> c.mediaType().equals(key)).findFirst();
if (content.isPresent()) {
Optional<Schema> reResolvedSchema = AnnotationsUtils.getSchemaFromAnnotation(content.get().schema(), components, null, config.isOpenAPI31(), parameterSchema);
if (reResolvedSchema.isPresent()) {
parameterSchema = reResolvedSchema.get();
}

}
newMediaType.schema(parameterSchema);
reresolvedMediaTypes.put(key, newMediaType);
}
}
if (StringUtils.isBlank(mediaType.getSchema().getType())) {
if (StringUtils.isBlank(mediaType.getSchema().getType()) || requestBodyAnnotation.useParameterTypeSchema()) {
mediaType.getSchema().setType(requestBodyParameter.getSchema().getType());
}
}
requestBody.getContent().putAll(reresolvedMediaTypes);
}
}
operation.setRequestBody(requestBody);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public class ServletConfigContextUtils {
*/
public static final String OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY = "openApi.configuration.alwaysResolveAppPath";

/**
* @since 2.1.15
*/
public static final String OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY = "openApi.configuration.skipResolveAppPath";

/**
* @since 2.0.6
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_READALLRESOURCES_KEY;
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_READER_KEY;
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SCANNER_KEY;
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY;
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SORTOUTPUT_KEY;
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY;
import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.getBooleanInitParam;
Expand Down Expand Up @@ -59,6 +60,7 @@ public OpenAPIConfiguration load(String path) throws IOException {
.prettyPrint(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_PRETTYPRINT_KEY))
.sortOutput(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_SORTOUTPUT_KEY))
.alwaysResolveAppPath(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY))
.skipResolveAppPath(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY))
.readerClass(getInitParam(servletConfig, OPENAPI_CONFIGURATION_READER_KEY))
.cacheTTL(getLongInitParam(servletConfig, OPENAPI_CONFIGURATION_CACHE_TTL_KEY))
.scannerClass(getInitParam(servletConfig, OPENAPI_CONFIGURATION_SCANNER_KEY))
Expand Down Expand Up @@ -121,6 +123,9 @@ public boolean exists(String path) {
if (getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY) != null) {
return true;
}
if (getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY) != null) {
return true;
}
if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_READER_KEY) != null) {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public class SwaggerLoader {

private Boolean alwaysResolveAppPath = false;

private Boolean skipResolveAppPath = false;

private Boolean openAPI31 = false;

private Boolean convertToOpenAPI31 = false;
Expand Down Expand Up @@ -197,6 +199,20 @@ public void setAlwaysResolveAppPath(Boolean alwaysResolveAppPath) {
this.alwaysResolveAppPath = alwaysResolveAppPath;
}

/**
* @since 2.1.15
*/
public Boolean getSkipResolveAppPath() {
return skipResolveAppPath;
}

/**
* @since 2.1.15
*/
public void setSkipResolveAppPath(Boolean skipResolveAppPath) {
this.skipResolveAppPath = skipResolveAppPath;
}

public Boolean getOpenAPI31() {
return openAPI31;
}
Expand Down Expand Up @@ -266,6 +282,7 @@ public Map<String, String> resolve() throws Exception{
.modelConverterClasses(modelConverterSet)
.sortOutput(sortOutput)
.alwaysResolveAppPath(alwaysResolveAppPath)
.skipResolveAppPath(skipResolveAppPath)
.openAPI31(openAPI31)
.convertToOpenAPI31(convertToOpenAPI31);
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3653,6 +3653,27 @@ public void testSiblingsOnResourceRequestBodyMultiple() {
" description: default response\n" +
" content:\n" +
" '*/*': {}\n" +
" /test/bodyparam:\n" +
" get:\n" +
" operationId: getBodyParam\n" +
" requestBody:\n" +
" description: test\n" +
" content:\n" +
" application/json:\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet\n" +
" writeOnly: true\n" +
" application/xml:\n" +
" schema:\n" +
" $ref: '#/components/schemas/PetSimple'\n" +
" description: resource pet xml\n" +
" writeOnly: true\n" +
" responses:\n" +
" default:\n" +
" description: default response\n" +
" content:\n" +
" '*/*': {}\n" +
"components:\n" +
" schemas:\n" +
" PetSimple:\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,26 @@ public Response getBodyImplParam(@RequestBody(
}) Object body) {
return null;
}

@Path("/bodyparam")
@GET
public Response getBodyParam(
@RequestBody(
description = "test",
useParameterTypeSchema = true,
content = {
@Content(
mediaType = "application/json",
schema = @Schema(
description = "resource pet",
accessMode = Schema.AccessMode.WRITE_ONLY)),
@Content(
mediaType = "application/xml",
schema = @Schema(
description = "resource pet xml",
accessMode = Schema.AccessMode.WRITE_ONLY))
}
) PetSimple pet) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ externalDocs:
servers:
- url: http://foo
description: server 1
variables: {}
security:
- req 1:
- a
Expand Down Expand Up @@ -622,7 +621,6 @@ paths:
servers:
- url: http://foo2
description: server 2
variables: {}
/arrayschema:
post:
description: "subscribes a client to updates relevant to the requestor's account,\
Expand Down
Loading

0 comments on commit 2b21241

Please sign in to comment.