From 77df3d67708d3c8faff3ba7796cd8ff2baf211d3 Mon Sep 17 00:00:00 2001 From: Jim Schubert Date: Thu, 26 Jul 2018 05:36:08 -0400 Subject: [PATCH] Validate spec on generation by default (#251) * Validate spec on generation by default Adds a validation parameter to CodegenConfigurator, and passes through options from CLI, Maven Plugin and Gradle Plugin to that property. Default is to validate the spec during generation. If spec has errors, we will output errors as well as warnings to the user. Option can be disabled by passing false to validateSpec (Maven/Gradle) or --validate-spec (CLI). * Prepare version 3.1.1-SNAPSHOT * fix version * Use last prod version for the sample * Update README.md Fix * [cli] Option parser does not support true/false for boolean options --- .../openapitools/codegen/cmd/ConfigHelp.java | 2 +- .../openapitools/codegen/cmd/Generate.java | 9 ++ .../README.adoc | 5 + .../samples/local-spec/README.md | 1 + .../samples/local-spec/build.gradle | 13 ++ .../gradle/plugin/OpenApiGeneratorPlugin.kt | 1 + .../OpenApiGeneratorGenerateExtension.kt | 11 ++ .../gradle/plugin/tasks/GenerateTask.kt | 14 +- .../src/test/kotlin/GenerateTaskDslTest.kt | 2 +- .../openapi-generator-maven-plugin/README.md | 7 +- .../examples/java-client.xml | 2 +- .../examples/non-java-invalid-spec.xml | 34 +++++ .../examples/non-java.xml | 2 +- .../examples/petstore-v3.0-invalid.yaml | 103 ++++++++++++++ .../codegen/plugin/CodeGenMojo.java | 8 ++ .../codegen/SpecValidationException.java | 133 ++++++++++++++++++ .../codegen/config/CodegenConfigurator.java | 59 +++++++- 17 files changed, 391 insertions(+), 15 deletions(-) create mode 100644 modules/openapi-generator-maven-plugin/examples/non-java-invalid-spec.xml create mode 100644 modules/openapi-generator-maven-plugin/examples/petstore-v3.0-invalid.yaml create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/SpecValidationException.java diff --git a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/ConfigHelp.java b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/ConfigHelp.java index ba6c86466a2..b6c4f9b89bc 100644 --- a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/ConfigHelp.java +++ b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/ConfigHelp.java @@ -72,4 +72,4 @@ public class ConfigHelp implements Runnable { System.exit(1); } } -} \ No newline at end of file +} diff --git a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java index 7382a6d5595..8c4db2af9e4 100644 --- a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java +++ b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Generate.java @@ -194,6 +194,11 @@ public class Generate implements Runnable { description = CodegenConstants.REMOVE_OPERATION_ID_PREFIX_DESC) private Boolean removeOperationIdPrefix; + @Option(name = {"--skip-validate-spec"}, + title = "skip spec validation", + description = "Skips the default behavior of validating an input specification.") + private Boolean skipValidateSpec; + @Override public void run() { @@ -207,6 +212,10 @@ public class Generate implements Runnable { } // now override with any specified parameters + if (skipValidateSpec != null) { + configurator.setValidateSpec(false); + } + if (verbose != null) { configurator.setVerbose(verbose); } diff --git a/modules/openapi-generator-gradle-plugin/README.adoc b/modules/openapi-generator-gradle-plugin/README.adoc index e3752a5a627..b379a9f6130 100644 --- a/modules/openapi-generator-gradle-plugin/README.adoc +++ b/modules/openapi-generator-gradle-plugin/README.adoc @@ -59,6 +59,11 @@ The gradle plugin is not currently published to https://plugins.gradle.org/m2/. |false |The verbosity of generation +|validateSpec +|Boolean +|true +|Whether or not we should validate the input spec before generation. Invalid specs result in an error. + |generatorName |String |None diff --git a/modules/openapi-generator-gradle-plugin/samples/local-spec/README.md b/modules/openapi-generator-gradle-plugin/samples/local-spec/README.md index 2f6b2a5168c..b3d5dfc4f0b 100644 --- a/modules/openapi-generator-gradle-plugin/samples/local-spec/README.md +++ b/modules/openapi-generator-gradle-plugin/samples/local-spec/README.md @@ -11,6 +11,7 @@ gradle openApiGenerate gradle openApiMeta gradle openApiValidate gradle buildGoSdk +gradle generateGoWithInvalidSpec ``` The samples can be tested against other versions of the plugin using the `openApiGeneratorVersion` property. For example: diff --git a/modules/openapi-generator-gradle-plugin/samples/local-spec/build.gradle b/modules/openapi-generator-gradle-plugin/samples/local-spec/build.gradle index 4a79c8e6f9a..e9a5bb42e0e 100644 --- a/modules/openapi-generator-gradle-plugin/samples/local-spec/build.gradle +++ b/modules/openapi-generator-gradle-plugin/samples/local-spec/build.gradle @@ -54,3 +54,16 @@ task buildGoSdk(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTas dateLibrary: "threetenp" ] } + +task generateGoWithInvalidSpec(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask){ + validateSpec = true + generatorName = "go" + inputSpec = "$rootDir/petstore-v3.0-invalid.yaml".toString() + additionalProperties = [ + packageName: "petstore" + ] + outputDir = "$buildDir/go".toString() + configOptions = [ + dateLibrary: "threetenp" + ] +} diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt index dda1bfc2310..b4a2089c11b 100644 --- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt +++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt @@ -80,6 +80,7 @@ class OpenApiGeneratorPlugin : Plugin { description = "Generate code via Open API Tools Generator for Open API 2.0 or 3.x specification documents." verbose.set(generate.verbose) + validateSpec.set(generate.validateSpec) generatorName.set(generate.generatorName) outputDir.set(generate.outputDir) inputSpec.set(generate.inputSpec) diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt index a62efd0bc55..fa7726542cc 100644 --- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt +++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt @@ -32,6 +32,11 @@ open class OpenApiGeneratorGenerateExtension(project: Project) { */ val verbose = project.objects.property() + /** + * Whether or not an input specification should be validated upon generation. + */ + val validateSpec = project.objects.property() + /** * The name of the generator which will handle codegen. (see "openApiGenerators" task) */ @@ -262,6 +267,11 @@ open class OpenApiGeneratorGenerateExtension(project: Project) { val configOptions = project.objects.property>() init { + applyDefaults() + } + + @Suppress("MemberVisibilityCanBePrivate") + fun applyDefaults(){ releaseNote.set("Minor update") modelNamePrefix.set("") modelNameSuffix.set("") @@ -271,5 +281,6 @@ open class OpenApiGeneratorGenerateExtension(project: Project) { generateApiDocumentation.set(true) withXml.set(false) configOptions.set(mapOf()) + validateSpec.set(true) } } \ No newline at end of file diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt index dbe0424dbca..db901f021c7 100644 --- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt +++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/GenerateTask.kt @@ -28,7 +28,6 @@ import org.gradle.kotlin.dsl.property import org.openapitools.codegen.CodegenConstants import org.openapitools.codegen.DefaultGenerator import org.openapitools.codegen.config.CodegenConfigurator -import org.openapitools.codegen.config.CodegenConfiguratorUtils.* /** @@ -48,6 +47,12 @@ open class GenerateTask : DefaultTask() { @get:Internal val verbose = project.objects.property() + /** + * Whether or not an input specification should be validated upon generation. + */ + @get:Internal + val validateSpec = project.objects.property() + /** * The name of the generator which will handle codegen. (see "openApiGenerators" task) */ @@ -382,6 +387,10 @@ open class GenerateTask : DefaultTask() { configurator.isVerbose = value } + validateSpec.ifNotEmpty { value -> + configurator.isValidateSpec = value + } + skipOverwrite.ifNotEmpty { value -> configurator.isSkipOverwrite = value ?: false } @@ -528,8 +537,7 @@ open class GenerateTask : DefaultTask() { out.println("Successfully generated code to ${configurator.outputDir}") } catch (e: RuntimeException) { - logger.error(e.message) - throw GradleException("Code generation failed.") + throw GradleException("Code generation failed.", e) } } finally { originalEnvironmentVariables.forEach { entry -> diff --git a/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt b/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt index fe84a903bd7..c2a6e024420 100644 --- a/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt +++ b/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt @@ -31,7 +31,7 @@ class GenerateTaskDslTest : TestBase() { fun `openApiGenerate should create an expected file structure from DSL config`() { // Arrange val projectFiles = mapOf( - "spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0-invalid.yaml") + "spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0.yaml") ) withProject(defaultBuildGradle, projectFiles) diff --git a/modules/openapi-generator-maven-plugin/README.md b/modules/openapi-generator-maven-plugin/README.md index af7ec01fb8d..2a541850bcb 100644 --- a/modules/openapi-generator-maven-plugin/README.md +++ b/modules/openapi-generator-maven-plugin/README.md @@ -38,6 +38,7 @@ mvn clean compile ### General Configuration parameters - `inputSpec` - OpenAPI Spec file path +- `validateSpec` - Whether or not to validate the input spec prior to generation. Invalid specifications will result in an error. - `language` - target generation language (deprecated, replaced by `generatorName` as values here don't represent only 'language' any longer) - `generatorName` - target generator name - `output` - target output path (default is `${project.build.directory}/generated-sources/swagger`) @@ -102,4 +103,8 @@ Specifying a custom generator is a bit different. It doesn't support the classpa ### Sample configuration -- Please see [an example configuration](examples) for using the plugin +Please see [an example configuration](examples) for using the plugin. To run these examples, explicitly pass the file to maven. Example: + +```bash +mvn -f non-java.xml compile +``` diff --git a/modules/openapi-generator-maven-plugin/examples/java-client.xml b/modules/openapi-generator-maven-plugin/examples/java-client.xml index b538b3545e7..475f9cfa665 100644 --- a/modules/openapi-generator-maven-plugin/examples/java-client.xml +++ b/modules/openapi-generator-maven-plugin/examples/java-client.xml @@ -12,7 +12,7 @@ org.openapitools openapi-generator-maven-plugin - 3.0.1-SNAPSHOT + 3.1.1-SNAPSHOT diff --git a/modules/openapi-generator-maven-plugin/examples/non-java-invalid-spec.xml b/modules/openapi-generator-maven-plugin/examples/non-java-invalid-spec.xml new file mode 100644 index 00000000000..31da5677d95 --- /dev/null +++ b/modules/openapi-generator-maven-plugin/examples/non-java-invalid-spec.xml @@ -0,0 +1,34 @@ + + 4.0.0 + org.openapitools + sample-project + jar + 1.0-SNAPSHOT + sample-project + http://maven.apache.org + + + + + org.openapitools + openapi-generator-maven-plugin + 3.1.1-SNAPSHOT + + + + generate + + + false + petstore-v3.0-invalid.yaml + aspnetcore + + optionalProjectFile=true + + + + + + + + diff --git a/modules/openapi-generator-maven-plugin/examples/non-java.xml b/modules/openapi-generator-maven-plugin/examples/non-java.xml index 2210a3b686b..8592217bdce 100644 --- a/modules/openapi-generator-maven-plugin/examples/non-java.xml +++ b/modules/openapi-generator-maven-plugin/examples/non-java.xml @@ -12,7 +12,7 @@ org.openapitools openapi-generator-maven-plugin - 3.0.1-SNAPSHOT + 3.1.1-SNAPSHOT diff --git a/modules/openapi-generator-maven-plugin/examples/petstore-v3.0-invalid.yaml b/modules/openapi-generator-maven-plugin/examples/petstore-v3.0-invalid.yaml new file mode 100644 index 00000000000..0f5c6fc2982 --- /dev/null +++ b/modules/openapi-generator-maven-plugin/examples/petstore-v3.0-invalid.yaml @@ -0,0 +1,103 @@ +openapi: "3.0.0" +servers: + - url: http://petstore.swagger.io/v1 +paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + post: + summary: Create a pet + tags: + - pets + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" +components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string diff --git a/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java b/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java index 178caa62750..ffc4c843300 100644 --- a/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java +++ b/modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/CodeGenMojo.java @@ -60,6 +60,9 @@ public class CodeGenMojo extends AbstractMojo { private static final Logger LOGGER = LoggerFactory.getLogger(CodeGenMojo.class); + @Parameter(name="validateSpec", required = false, defaultValue = "true") + private Boolean validateSpec; + @Parameter(name = "verbose", required = false, defaultValue = "false") private boolean verbose; @@ -348,6 +351,11 @@ public class CodeGenMojo extends AbstractMojo { configurator.setVerbose(verbose); + // now override with any specified parameters + if (validateSpec != null) { + configurator.setValidateSpec(validateSpec); + } + if (skipOverwrite != null) { configurator.setSkipOverwrite(skipOverwrite); } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/SpecValidationException.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/SpecValidationException.java new file mode 100644 index 00000000000..1578918ba8c --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/SpecValidationException.java @@ -0,0 +1,133 @@ +package org.openapitools.codegen; + +import java.util.Set; + +public class SpecValidationException extends RuntimeException { + + private Set errors; + private Set warnings; + + /** + * Constructs a new runtime exception with {@code null} as its + * detail message. The cause is not initialized, and may subsequently be + * initialized by a call to {@link #initCause}. + */ + public SpecValidationException() { + } + + /** + * Constructs a new runtime exception with the specified detail message. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public SpecValidationException(String message) { + super(message); + } + + /** + * Constructs a new runtime exception with the specified detail message and + * cause.

Note that the detail message associated with + * {@code cause} is not automatically incorporated in + * this runtime exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public SpecValidationException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new runtime exception with the specified cause and a + * detail message of (cause==null ? null : cause.toString()) + * (which typically contains the class and detail message of + * cause). This constructor is useful for runtime exceptions + * that are little more than wrappers for other throwables. + * + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public SpecValidationException(Throwable cause) { + super(cause); + } + + /** + * Constructs a new runtime exception with the specified detail + * message, cause, suppression enabled or disabled, and writable + * stack trace enabled or disabled. + * + * @param message the detail message. + * @param cause the cause. (A {@code null} value is permitted, + * and indicates that the cause is nonexistent or unknown.) + * @param enableSuppression whether or not suppression is enabled + * or disabled + * @param writableStackTrace whether or not the stack trace should + * be writable + * @since 1.7 + */ + public SpecValidationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public Set getErrors() { + return errors; + } + + public Set getWarnings() { + return warnings; + } + + public void setErrors(Set errors) { + this.errors = errors; + } + + public void setWarnings(Set warnings) { + this.warnings = warnings; + } + + /** + * Returns the detail message string of this throwable. + * + * @return the detail message string of this {@code Throwable} instance + * (which may be {@code null}). + */ + @Override + public String getMessage() { + int errorCount = 0; + if (errors != null) { + errorCount = errors.size(); + } + int warningCount = 0; + if (warnings != null) { + warningCount = warnings.size(); + } + + StringBuilder sb = new StringBuilder(); + sb.append(System.lineSeparator()) + .append("Errors: ") + .append(System.lineSeparator()); + errors.forEach(msg -> + sb.append("\t-").append(msg).append(System.lineSeparator()) + ); + + if (!warnings.isEmpty()) { + sb.append("Warnings: ").append(System.lineSeparator()); + warnings.forEach(msg -> + sb.append("\t-").append(msg).append(System.lineSeparator()) + ); + } + return super.getMessage() + " | " + + "Error count: " + errorCount + ", Warning count: " + warningCount + sb.toString(); + } +} diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfigurator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfigurator.java index db72abdf88b..96492e5251c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfigurator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/CodegenConfigurator.java @@ -19,12 +19,8 @@ package org.openapitools.codegen.config; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; -import org.openapitools.codegen.CliOption; -import org.openapitools.codegen.ClientOptInput; -import org.openapitools.codegen.ClientOpts; -import org.openapitools.codegen.CodegenConfig; -import org.openapitools.codegen.CodegenConfigLoader; -import org.openapitools.codegen.CodegenConstants; +import io.swagger.v3.oas.models.OpenAPI; +import org.openapitools.codegen.*; import org.openapitools.codegen.auth.AuthParser; import io.swagger.parser.OpenAPIParser; import io.swagger.v3.core.util.Json; @@ -33,6 +29,7 @@ import io.swagger.v3.parser.core.models.ParseOptions; import io.swagger.v3.parser.core.models.SwaggerParseResult; import org.apache.commons.lang3.Validate; import org.openapitools.codegen.languages.*; +import org.openapitools.codegen.utils.ModelUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -80,6 +77,7 @@ public class CodegenConfigurator implements Serializable { private boolean verbose; private boolean skipOverwrite; private boolean removeOperationIdPrefix; + private boolean validateSpec; private String templateDir; private String auth; private String apiPackage; @@ -108,6 +106,7 @@ public class CodegenConfigurator implements Serializable { private final Map dynamicProperties = new HashMap(); //the map that holds the JsonAnySetter/JsonAnyGetter values public CodegenConfigurator() { + this.validateSpec = true; this.setOutputDir("."); } @@ -211,6 +210,15 @@ public class CodegenConfigurator implements Serializable { return this; } + public boolean isValidateSpec() { + return validateSpec; + } + + public CodegenConfigurator setValidateSpec(final boolean validateSpec) { + this.validateSpec = validateSpec; + return this; + } + public boolean isSkipOverwrite() { return skipOverwrite; } @@ -514,8 +522,45 @@ public class CodegenConfigurator implements Serializable { options.setResolve(true); options.setFlatten(true); SwaggerParseResult result = new OpenAPIParser().readLocation(inputSpec, authorizationValues, options); + + Set validationMessages = new HashSet<>(result.getMessages()); + OpenAPI specification = result.getOpenAPI(); + + // NOTE: We will only expose errors+warnings if there are already errors in the spec. + if (validationMessages.size() > 0) { + Set warnings = new HashSet<>(); + if (specification != null) { + List unusedModels = ModelUtils.getUnusedSchemas(specification); + if (unusedModels != null) unusedModels.forEach(name -> warnings.add("Unused model: " + name)); + } + + if (this.isValidateSpec()) { + SpecValidationException ex = new SpecValidationException("Specification has failed validation."); + ex.setErrors(validationMessages); + ex.setWarnings(warnings); + throw ex; + } else { + StringBuilder sb = new StringBuilder(); + sb.append("There were issues with the specification, but validation has been explicitly disabled."); + sb.append(System.lineSeparator()); + + sb.append("Errors: ").append(System.lineSeparator()); + validationMessages.forEach(msg -> + sb.append("\t-").append(msg).append(System.lineSeparator()) + ); + + if (!warnings.isEmpty()) { + sb.append("Warnings: ").append(System.lineSeparator()); + warnings.forEach(msg -> + sb.append("\t-").append(msg).append(System.lineSeparator()) + ); + } + LOGGER.warn(sb.toString()); + } + } + input.opts(new ClientOpts()) - .openAPI(result.getOpenAPI()); + .openAPI(specification); return input; }