From dcbf62c0eadd7fd9c121364f6579b34af528d36a Mon Sep 17 00:00:00 2001 From: Romain Grecourt Date: Fri, 22 Sep 2023 19:32:54 -0700 Subject: [PATCH] save work --- .../builder/processor/FactoryMethods.java | 1 - .../processor/GenerateAbstractBuilder.java | 1 - .../common/testing/junit5/MapMatcher.java | 11 ++ .../io/helidon/config/ConfigChangesTest.java | 2 +- .../openapi/ExpandedTypeDescription.java | 9 +- .../JsonpAnnotationScannerExtension.java | 12 +- .../openapi/MpOpenApiManager.java | 11 +- .../MpOpenApiManagerConfigBlueprint.java | 2 +- .../microprofile/openapi/OpenApiHelper.java | 17 +-- .../openapi/OpenApiSerializer.java | 4 +- .../SmallRyeOpenApiConfigBlueprint.java | 120 ------------------ .../openapi/AdditionalPropertiesTest.java | 43 ++----- .../microprofile/openapi/BasicServerTest.java | 4 +- .../FilteredIndexViewsBuilderTest.java | 6 +- .../openapi/OpenApiConfigTest.java | 24 +--- .../openapi/OpenApiParserTest.java | 31 ++--- .../openapi/OpenApiSerializerTest.java | 36 +++--- .../openapi/ServerConfigTest.java | 2 +- .../openapi/ServerModelReaderTest.java | 15 ++- .../{YamlQuery.java => TestUtils.java} | 59 ++++++++- .../io/helidon/openapi/OpenApiUiProvider.java | 29 ----- .../helidon/openapi/{ => ui}/OpenApiUi.java | 3 +- .../{ => ui}/OpenApiUiConfigBlueprint.java | 4 +- .../helidon/openapi/ui/OpenApiUiProvider.java | 44 +++++++ .../openapi/{ => ui}/package-info.java | 2 +- .../openapi-ui/src/main/java/module-info.java | 6 +- .../openapi/{ => ui}/OpenApiUiTest.java | 53 ++++---- .../io/helidon/openapi/OpenApiManager.java | 15 +++ .../helidon-openapi/native-image.properties | 2 +- .../openapi/src/test/resources/greeting.yml | 2 +- .../src/test/resources/time-server.yml | 2 +- 31 files changed, 250 insertions(+), 322 deletions(-) delete mode 100644 microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/SmallRyeOpenApiConfigBlueprint.java rename microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/{YamlQuery.java => TestUtils.java} (52%) delete mode 100644 openapi/openapi-ui/src/main/java/io/helidon/openapi/OpenApiUiProvider.java rename openapi/openapi-ui/src/main/java/io/helidon/openapi/{ => ui}/OpenApiUi.java (98%) rename openapi/openapi-ui/src/main/java/io/helidon/openapi/{ => ui}/OpenApiUiConfigBlueprint.java (95%) create mode 100644 openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/OpenApiUiProvider.java rename openapi/openapi-ui/src/main/java/io/helidon/openapi/{ => ui}/package-info.java (95%) rename openapi/openapi-ui/src/test/java/io/helidon/openapi/{ => ui}/OpenApiUiTest.java (61%) diff --git a/builder/processor/src/main/java/io/helidon/builder/processor/FactoryMethods.java b/builder/processor/src/main/java/io/helidon/builder/processor/FactoryMethods.java index 7f383e9706c..14d151a35fe 100644 --- a/builder/processor/src/main/java/io/helidon/builder/processor/FactoryMethods.java +++ b/builder/processor/src/main/java/io/helidon/builder/processor/FactoryMethods.java @@ -29,7 +29,6 @@ import static io.helidon.builder.processor.Types.CONFIG_TYPE; import static io.helidon.builder.processor.Types.FACTORY_METHOD_TYPE; -import static io.helidon.builder.processor.Types.PROTOTYPE_TYPE; import static io.helidon.builder.processor.Types.RUNTIME_OBJECT_TYPE; import static io.helidon.common.types.TypeNames.OBJECT; diff --git a/builder/processor/src/main/java/io/helidon/builder/processor/GenerateAbstractBuilder.java b/builder/processor/src/main/java/io/helidon/builder/processor/GenerateAbstractBuilder.java index be2ce3f5a42..c384da04e91 100644 --- a/builder/processor/src/main/java/io/helidon/builder/processor/GenerateAbstractBuilder.java +++ b/builder/processor/src/main/java/io/helidon/builder/processor/GenerateAbstractBuilder.java @@ -37,7 +37,6 @@ import io.helidon.common.processor.classmodel.TypeArgument; import io.helidon.common.types.AccessModifier; import io.helidon.common.types.TypeName; -import io.helidon.common.types.TypeNames; import static io.helidon.builder.processor.Types.CHAR_ARRAY_TYPE; import static io.helidon.builder.processor.Types.CONFIG_TYPE; diff --git a/common/testing/junit5/src/main/java/io/helidon/common/testing/junit5/MapMatcher.java b/common/testing/junit5/src/main/java/io/helidon/common/testing/junit5/MapMatcher.java index 3adeaf6a26f..ee3b4d4ecb3 100644 --- a/common/testing/junit5/src/main/java/io/helidon/common/testing/junit5/MapMatcher.java +++ b/common/testing/junit5/src/main/java/io/helidon/common/testing/junit5/MapMatcher.java @@ -28,6 +28,8 @@ * Hamcrest matchers for {@link java.util.Map}. */ public final class MapMatcher { + private MapMatcher() { + } /** * A matcher for an {@link java.util.Map} that performs a deep equality. @@ -37,6 +39,15 @@ public final class MapMatcher { * assertThat(actualMap, isMapEqualTo(expectedMap)); * * + * This method targets trees implemented using {@link java.util.Map} where values of type {@link java.util.Map} + * are considered tree nodes, and values with other types are considered leaf nodes. + *

+ * The deep-equality is performed by diffing a flat string representation of each map. If the diff yields no differences, + * the maps are considered deeply equal. + *

+ * The entries are compared using strings, both keys and leaf nodes must implement {@link Object#toString()}. + * + * @param expected expected map * @param type of the map keys * @param type of the map values * @return matcher validating the {@link java.util.Map} is deeply equal diff --git a/config/config/src/test/java/io/helidon/config/ConfigChangesTest.java b/config/config/src/test/java/io/helidon/config/ConfigChangesTest.java index 4faaf2dd11f..5c26b794908 100644 --- a/config/config/src/test/java/io/helidon/config/ConfigChangesTest.java +++ b/config/config/src/test/java/io/helidon/config/ConfigChangesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020 Oracle and/or its affiliates. + * Copyright (c) 2017, 2023 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/ExpandedTypeDescription.java b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/ExpandedTypeDescription.java index 052fcff675f..f0304ee8790 100644 --- a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/ExpandedTypeDescription.java +++ b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/ExpandedTypeDescription.java @@ -218,10 +218,8 @@ Property defaultProperty() { private static boolean setupExtensionType(String key, Node valueNode) { if (isExtension(key)) { - /* - * The nodeId in a node is more like node "category" in SnakeYAML. For those OpenAPI interfaces which implement - * Extensible we need to set the node's type if the extension is a List or Map. - */ + // The nodeId in a node is more like node "category" in SnakeYAML. For those OpenAPI interfaces which implement + // Extensible we need to set the node's type if the extension is a List or Map. switch (valueNode.getNodeId()) { case sequence -> { valueNode.setType(List.class); @@ -231,6 +229,9 @@ private static boolean setupExtensionType(String key, Node valueNode) { valueNode.setType(Map.class); return true; } + default -> { + return false; + } } } return false; diff --git a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/JsonpAnnotationScannerExtension.java b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/JsonpAnnotationScannerExtension.java index 5ce9b0e16cf..90f7d777ae7 100644 --- a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/JsonpAnnotationScannerExtension.java +++ b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/JsonpAnnotationScannerExtension.java @@ -37,9 +37,7 @@ class JsonpAnnotationScannerExtension implements AnnotationScannerExtension { private static final System.Logger LOGGER = System.getLogger(JsonpAnnotationScannerExtension.class.getName()); - private static final JsonReaderFactory JSON_READER_FACTORY = Json.createReaderFactory(Collections.emptyMap()); - private static final Representer MISSING_FIELD_TOLERANT_REPRESENTER; static { @@ -47,6 +45,12 @@ class JsonpAnnotationScannerExtension implements AnnotationScannerExtension { MISSING_FIELD_TOLERANT_REPRESENTER.getPropertyUtils().setSkipMissingProperties(true); } + private final OpenApiHelper openApiHelper; + + JsonpAnnotationScannerExtension(OpenApiHelper openApiHelper) { + this.openApiHelper = openApiHelper; + } + @Override public Object parseExtension(String key, String value) { try { @@ -93,6 +97,8 @@ public Object parseValue(String value) { throw ex; } } + default -> { + } } // Treat as JSON string. @@ -101,7 +107,7 @@ public Object parseValue(String value) { @Override public Schema parseSchema(String jsonSchema) { - return OpenApiParser.parse(OpenApiHelper.types(), + return OpenApiParser.parse(openApiHelper.types(), Schema.class, new StringReader(jsonSchema), MISSING_FIELD_TOLERANT_REPRESENTER); diff --git a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/MpOpenApiManager.java b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/MpOpenApiManager.java index f0abbe0a9bd..b1fdb0c28c4 100644 --- a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/MpOpenApiManager.java +++ b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/MpOpenApiManager.java @@ -48,7 +48,6 @@ final class MpOpenApiManager implements OpenApiManager { private static final System.Logger LOGGER = System.getLogger(MpOpenApiManager.class.getName()); - private static final List SCANNER_EXTENSIONS = List.of(new JsonpAnnotationScannerExtension()); private static final String CONFIG_EXT_PREFIX = "mp.openapi.extensions.helidon."; /** @@ -58,6 +57,8 @@ final class MpOpenApiManager implements OpenApiManager { private final MpOpenApiManagerConfig managerConfig; private final OpenApiConfig openApiConfig; + private final OpenApiHelper openApiHelper; + private final List scannerExtensions; private final LazyValue> filteredIndexViews = LazyValue.create(this::buildFilteredIndexViews); MpOpenApiManager(Config config) { @@ -65,7 +66,9 @@ final class MpOpenApiManager implements OpenApiManager { .update(builder -> config.getOptionalValue(USE_JAXRS_SEMANTICS_KEY, Boolean.class) .ifPresent(builder::useJaxRsSemantics)) .build(); + this.openApiHelper = new OpenApiHelper(config); this.openApiConfig = new OpenApiConfigImpl(config); + this.scannerExtensions = List.of(new JsonpAnnotationScannerExtension(openApiHelper)); } @Override @@ -85,7 +88,7 @@ public OpenAPI load(String content) { OpenApiDocument.INSTANCE.config(openApiConfig); OpenApiDocument.INSTANCE.modelFromReader(OpenApiProcessor.modelFromReader(openApiConfig, contextClassLoader)); if (!content.isBlank()) { - OpenAPI document = OpenApiParser.parse(OpenApiHelper.types(), OpenAPI.class, new StringReader(content)); + OpenAPI document = OpenApiParser.parse(openApiHelper.types(), OpenAPI.class, new StringReader(content)); OpenApiDocument.INSTANCE.modelFromStaticFile(document); } if (!openApiConfig.scanDisable()) { @@ -104,7 +107,7 @@ public OpenAPI load(String content) { @Override public String format(OpenAPI model, OpenApiFormat format) { StringWriter sw = new StringWriter(); - OpenApiSerializer.serialize(OpenApiHelper.types(), model, format, sw); + OpenApiSerializer.serialize(openApiHelper.types(), model, format, sw); return sw.toString(); } @@ -127,7 +130,7 @@ private void processAnnotations() { // merging the resulting OpenAPI models into one. OpenAPI model = new OpenAPIImpl(); // Start with skeletal model for (IndexView indexView : indexViews) { - OpenApiAnnotationScanner scanner = new OpenApiAnnotationScanner(openApiConfig, indexView, SCANNER_EXTENSIONS); + OpenApiAnnotationScanner scanner = new OpenApiAnnotationScanner(openApiConfig, indexView, scannerExtensions); OpenAPI scanned = scanner.scan(); if (LOGGER.isLoggable(Level.DEBUG)) { LOGGER.log(Level.DEBUG, String.format( diff --git a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/MpOpenApiManagerConfigBlueprint.java b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/MpOpenApiManagerConfigBlueprint.java index 45753fe312e..62eb7aeb3ce 100644 --- a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/MpOpenApiManagerConfigBlueprint.java +++ b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/MpOpenApiManagerConfigBlueprint.java @@ -26,7 +26,7 @@ */ @Prototype.Blueprint @Configured -interface MpOpenApiManagerConfigBlueprint extends SmallRyeOpenApiConfigBlueprint { +interface MpOpenApiManagerConfigBlueprint { /** * If {@code true} and the {@code jakarta.ws.rs.core.Application} class returns a non-empty set, endpoints defined by diff --git a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/OpenApiHelper.java b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/OpenApiHelper.java index de42880edff..ca57e7c0de6 100644 --- a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/OpenApiHelper.java +++ b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/OpenApiHelper.java @@ -20,10 +20,7 @@ import java.util.Map; import java.util.Set; -import io.helidon.common.LazyValue; -import io.helidon.common.config.Config; -import io.helidon.common.config.GlobalConfig; - +import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.openapi.models.Extensible; import org.eclipse.microprofile.openapi.models.Operation; import org.eclipse.microprofile.openapi.models.PathItem; @@ -44,15 +41,11 @@ final class OpenApiHelper { private static final java.util.logging.Logger SNAKE_YAML_INTROSPECTOR_LOGGER = java.util.logging.Logger.getLogger(org.yaml.snakeyaml.introspector.PropertySubstitute.class.getPackage().getName()); - private static final LazyValue, ExpandedTypeDescription>> TYPES = LazyValue.create( - () -> new OpenApiHelper().generatedHelper.types()); - // The SnakeYAMLParserHelper is generated by a maven plug-in. private final SnakeYAMLParserHelper generatedHelper; - private OpenApiHelper() { - Config config = GlobalConfig.config(); - boolean warningsEnabled = config.get("openapi.parsing.warnings.enabled").asBoolean().orElse(false); + OpenApiHelper(Config config) { + boolean warningsEnabled = config.getOptionalValue("mp.openapi.parsing.warnings.enabled", Boolean.class).orElse(false); if (SNAKE_YAML_INTROSPECTOR_LOGGER.isLoggable(java.util.logging.Level.WARNING) && !warningsEnabled) { SNAKE_YAML_INTROSPECTOR_LOGGER.setLevel(java.util.logging.Level.SEVERE); } @@ -65,8 +58,8 @@ private OpenApiHelper() { * * @return types of this helper */ - static Map, ExpandedTypeDescription> types() { - return TYPES.get(); + Map, ExpandedTypeDescription> types() { + return generatedHelper.types(); } private static void adjustTypeDescriptions(Map, ExpandedTypeDescription> types) { diff --git a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/OpenApiSerializer.java b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/OpenApiSerializer.java index cba59177b51..8d76326634c 100644 --- a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/OpenApiSerializer.java +++ b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/OpenApiSerializer.java @@ -216,8 +216,8 @@ protected MappingNode representJavaBean(Set properties, Object javaBea // property assigned. MappingNode result = super.representJavaBean(properties, javaBean); - // Now promote the individual sub-nodes for each extension property (if any) up one level so that they are peers of the - // other properties. Also remove the "extensions" node. + // Now promote the individual sub-nodes for each extension property (if any) up one level so that they are peers of + // the other properties. Also remove the "extensions" node. processExtensions(result, javaBean); // Clearing representedObjects is an awkward but effective way of preventing SnakeYAML from using anchors and diff --git a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/SmallRyeOpenApiConfigBlueprint.java b/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/SmallRyeOpenApiConfigBlueprint.java deleted file mode 100644 index ea5b6f58335..00000000000 --- a/microprofile/openapi/src/main/java/io/helidon/microprofile/openapi/SmallRyeOpenApiConfigBlueprint.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2023 Oracle and/or its affiliates. - * - * 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 - * - * http://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 io.helidon.microprofile.openapi; - -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -import io.helidon.builder.api.Prototype; -import io.helidon.config.metadata.Configured; -import io.helidon.config.metadata.ConfiguredOption; - -import io.smallrye.openapi.api.OpenApiConfig; -import io.smallrye.openapi.api.OpenApiConfig.OperationIdStrategy; - -/** - * Configuration prototype that mirrors {@link io.smallrye.openapi.api.OpenApiConfig}. - */ -@Prototype.Blueprint -@Configured -interface SmallRyeOpenApiConfigBlueprint { - - @ConfiguredOption - boolean scanDependenciesDisable(); - - @ConfiguredOption - Set scanDependenciesJars(); - - @ConfiguredOption - boolean arrayReferencesEnable(); - - @ConfiguredOption - Optional customSchemaRegistryClass(); - - @ConfiguredOption - boolean applicationPathDisable(); - - @ConfiguredOption - boolean privatePropertiesEnable(); - - @ConfiguredOption - Optional propertyNamingStrategy(); - - @ConfiguredOption - boolean sortedPropertiesEnable(); - - @ConfiguredOption(key = "schema") - @Prototype.Singular - Map schemas(); - - @ConfiguredOption - Optional openApiVersion(); - - @ConfiguredOption - Optional infoTitle(); - - @ConfiguredOption - Optional infoVersion(); - - @ConfiguredOption - Optional infoDescription(); - - @ConfiguredOption - Optional infoTermsOfService(); - - @ConfiguredOption - Optional infoContactEmail(); - - @ConfiguredOption - Optional infoContactName(); - - @ConfiguredOption - Optional infoContactUrl(); - - @ConfiguredOption - Optional infoLicenseName(); - - @ConfiguredOption - Optional infoLicenseUrl(); - - @ConfiguredOption - Optional operationIdStrategy(); - - @ConfiguredOption(value = "WARN") - OpenApiConfig.DuplicateOperationIdBehavior duplicateOperationIdBehavior(); - - @ConfiguredOption - Optional defaultProduces(); - - @ConfiguredOption - Optional defaultConsumes(); - - @ConfiguredOption - Set scanProfiles(); - - @ConfiguredOption - Set scanExcludeProfiles(); - - @ConfiguredOption - Map scanResourceClasses(); - - @ConfiguredOption - boolean removeUnusedSchemas(); - - @ConfiguredOption - Optional maximumStaticFileSize(); -} diff --git a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/AdditionalPropertiesTest.java b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/AdditionalPropertiesTest.java index 0f8f5c0fe47..bfb30aa0d57 100644 --- a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/AdditionalPropertiesTest.java +++ b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/AdditionalPropertiesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Oracle and/or its affiliates. + * Copyright (c) 2021, 2023 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,7 @@ */ package io.helidon.microprofile.openapi; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.StringReader; import java.io.StringWriter; import java.util.Map; @@ -28,6 +26,9 @@ import org.junit.jupiter.api.Test; import org.yaml.snakeyaml.Yaml; +import static io.helidon.microprofile.openapi.TestUtils.OAI_HELPER; +import static io.helidon.microprofile.openapi.TestUtils.query; +import static io.helidon.microprofile.openapi.TestUtils.resource; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasKey; @@ -39,7 +40,7 @@ class AdditionalPropertiesTest { @Test - void checkParsingBooleanAdditionalProperties() throws IOException { + void checkParsingBooleanAdditionalProperties() { OpenAPI openAPI = parse("/withBooleanAddlProps.yml"); Schema itemSchema = openAPI.getComponents().getSchemas().get("item"); @@ -52,7 +53,7 @@ void checkParsingBooleanAdditionalProperties() throws IOException { } @Test - void checkParsingSchemaAdditionalProperties() throws IOException { + void checkParsingSchemaAdditionalProperties() { OpenAPI openAPI = parse("/withSchemaAddlProps.yml"); Schema itemSchema = openAPI.getComponents().getSchemas().get("item"); @@ -68,7 +69,7 @@ void checkParsingSchemaAdditionalProperties() throws IOException { } @Test - void checkWritingSchemaAdditionalProperties() throws IOException { + void checkWritingSchemaAdditionalProperties() { OpenAPI openAPI = parse("/withSchemaAddlProps.yml"); String document = format(openAPI); @@ -82,43 +83,27 @@ void checkWritingSchemaAdditionalProperties() throws IOException { // type: string Yaml yaml = new Yaml(); Map model = yaml.load(document); - Map item = asMap(model, "components", "schemas", "item"); - - Object additionalProperties = item.get("additionalProperties"); + Object additionalProperties = query(model, "components.schemas.item.additionalProperties", Object.class); assertThat(additionalProperties, is(instanceOf(Map.class))); - } @Test - void checkWritingBooleanAdditionalProperties() throws IOException { + void checkWritingBooleanAdditionalProperties() { OpenAPI openAPI = parse("/withBooleanAddlProps.yml"); String document = format(openAPI); assertThat(document, containsString("additionalProperties: false")); } - @SuppressWarnings("unchecked") - private static Map asMap(Map map, String... keys) { - Map m = map; - for (String key : keys) { - m = (Map) m.get(key); - } - return m; - } - private static String format(OpenAPI model) { StringWriter sw = new StringWriter(); - OpenApiSerializer.serialize(OpenApiHelper.types(), model, OpenApiFormat.YAML, sw); + OpenApiSerializer.serialize(OAI_HELPER.types(), model, OpenApiFormat.YAML, sw); return sw.toString(); } - private static OpenAPI parse(String path) throws IOException { - try (InputStream is = AdditionalPropertiesTest.class.getResourceAsStream(path)) { - if (is == null) { - throw new IllegalArgumentException("Resource not found: " + path); - } - return OpenApiParser.parse(OpenApiHelper.types(), OpenAPI.class, new InputStreamReader(is)); - } + private static OpenAPI parse(String path) { + String document = resource(path); + return OpenApiParser.parse(OAI_HELPER.types(), OpenAPI.class, new StringReader(document)); } } \ No newline at end of file diff --git a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/BasicServerTest.java b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/BasicServerTest.java index b347cdc4931..b9857ab57c0 100644 --- a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/BasicServerTest.java +++ b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/BasicServerTest.java @@ -49,14 +49,14 @@ class BasicServerTest { @Test public void simpleTest() { Map document = document(); - String summary = YamlQuery.get(document, "paths./testapp/go.get.summary", String.class); + String summary = TestUtils.query(document, "paths./testapp/go.get.summary", String.class); assertThat(summary, is(equalTo(TestApp.GO_SUMMARY))); } @Test public void testMultipleApps() { Map document = document(); - String summary = YamlQuery.get(document, "paths./testapp3/go3.get.summary", String.class); + String summary = TestUtils.query(document, "paths./testapp3/go3.get.summary", String.class); assertThat(summary, is(equalTo(TestApp3.GO_SUMMARY))); } diff --git a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/FilteredIndexViewsBuilderTest.java b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/FilteredIndexViewsBuilderTest.java index cc0349e720b..708ee87749c 100644 --- a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/FilteredIndexViewsBuilderTest.java +++ b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/FilteredIndexViewsBuilderTest.java @@ -24,12 +24,11 @@ import io.smallrye.openapi.api.OpenApiConfig; import io.smallrye.openapi.api.OpenApiConfigImpl; import io.smallrye.openapi.runtime.scanner.FilteredIndexView; -import org.eclipse.microprofile.config.Config; -import org.eclipse.microprofile.config.spi.ConfigProviderResolver; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.junit.jupiter.api.Test; +import static io.helidon.microprofile.openapi.TestUtils.config; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; @@ -75,7 +74,6 @@ void testMultipleIndexFiles() { } private static OpenApiConfig openApiConfig() { - Config config = ConfigProviderResolver.instance().getBuilder().build(); - return new OpenApiConfigImpl(config); + return new OpenApiConfigImpl(config()); } } diff --git a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiConfigTest.java b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiConfigTest.java index d2c631b95e4..52cb0bf510d 100644 --- a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiConfigTest.java +++ b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiConfigTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021 Oracle and/or its affiliates. + * Copyright (c) 2019, 2023 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,19 +15,14 @@ */ package io.helidon.microprofile.openapi; -import java.util.Arrays; import java.util.Map; import java.util.StringJoiner; -import io.helidon.config.mp.MpConfigSources; - import io.smallrye.openapi.api.OpenApiConfig; import io.smallrye.openapi.api.OpenApiConfigImpl; -import org.eclipse.microprofile.config.Config; -import org.eclipse.microprofile.config.spi.ConfigProviderResolver; -import org.eclipse.microprofile.config.spi.ConfigSource; import org.junit.jupiter.api.Test; +import static io.helidon.microprofile.openapi.TestUtils.config; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.hasKey; @@ -94,19 +89,4 @@ void checkSchemaConfig() { private static OpenApiConfig openApiConfig(Map... configSources) { return new OpenApiConfigImpl(config(configSources)); } - - @SafeVarargs - private static Config config(Map... configSources) { - return ConfigProviderResolver.instance() - .getBuilder() - .withSources(configSources(configSources)) - .build(); - } - - @SafeVarargs - private static ConfigSource[] configSources(Map... configSources) { - return Arrays.stream(configSources) - .map(MpConfigSources::create) - .toArray(ConfigSource[]::new); - } } diff --git a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiParserTest.java b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiParserTest.java index 4e847b79aeb..36545ab1d43 100644 --- a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiParserTest.java +++ b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiParserTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022 Oracle and/or its affiliates. + * Copyright (c) 2020, 2023 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,7 @@ */ package io.helidon.microprofile.openapi; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.StringReader; import java.util.List; import java.util.Map; @@ -29,11 +27,12 @@ import org.junit.jupiter.api.Test; import static io.helidon.common.testing.junit5.OptionalMatcher.optionalValue; +import static io.helidon.microprofile.openapi.TestUtils.OAI_HELPER; +import static io.helidon.microprofile.openapi.TestUtils.resource; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; /** * Tests {@link OpenApiParser}. @@ -41,7 +40,7 @@ class OpenApiParserTest { @Test - void testParserUsingYAML() throws IOException { + void testParserUsingYAML() { OpenAPI openAPI = parse("/petstore.yaml"); assertThat(openAPI.getOpenapi(), is("3.0.0")); assertThat(openAPI.getPaths().getPathItem("/pets").getGET().getParameters().get(0).getIn(), @@ -49,7 +48,7 @@ void testParserUsingYAML() throws IOException { } @Test - void testExtensions() throws IOException { + void testExtensions() { OpenAPI openAPI = parse("/openapi-greeting.yml"); Object xMyPersonalMap = openAPI.getExtensions().get("x-my-personal-map"); assertThat(xMyPersonalMap, is(instanceOf(Map.class))); @@ -86,7 +85,7 @@ void testExtensions() throws IOException { @Test - void testYamlRef() throws IOException { + void testYamlRef() { OpenAPI openAPI = parse("/petstore.yaml"); Paths paths = openAPI.getPaths(); String ref = paths.getPathItem("/pets") @@ -102,7 +101,7 @@ void testYamlRef() throws IOException { } @Test - void testJsonRef() throws IOException { + void testJsonRef() { OpenAPI openAPI = parse("/petstore.json"); Paths paths = openAPI.getPaths(); String ref = paths.getPathItem("/user") @@ -117,7 +116,7 @@ void testJsonRef() throws IOException { } @Test - void testParserUsingJSON() throws IOException { + void testParserUsingJSON() { OpenAPI openAPI = parse("/petstore.json"); assertThat(openAPI.getOpenapi(), is("3.0.0")); @@ -128,7 +127,7 @@ void testParserUsingJSON() throws IOException { @Test @SuppressWarnings("HttpUrlsUsage") - void testComplicatedPetstoreDocument() throws IOException { + void testComplicatedPetstoreDocument() { OpenAPI openAPI = parse("/petstore-with-fake-endpoints-models.yaml"); assertThat(openAPI.getOpenapi(), is("3.0.0")); assertThat("Default for server variable 'port'", @@ -144,12 +143,8 @@ void testComplicatedPetstoreDocument() throws IOException { optionalValue(is("petstore"))); } - private static OpenAPI parse(String path) throws IOException { - try (InputStream is = OpenApiParserTest.class.getResourceAsStream(path)) { - if (is == null) { - throw new IllegalArgumentException("Resource not found: " + path); - } - return OpenApiParser.parse(OpenApiHelper.types(), OpenAPI.class, new InputStreamReader(is)); - } + private static OpenAPI parse(String path) { + String document = resource(path); + return OpenApiParser.parse(OAI_HELPER.types(), OpenAPI.class, new StringReader(document)); } } \ No newline at end of file diff --git a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiSerializerTest.java b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiSerializerTest.java index d4ff542a82f..264a7d69590 100644 --- a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiSerializerTest.java +++ b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/OpenApiSerializerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021 Oracle and/or its affiliates. + * Copyright (c) 2020, 2023 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,6 @@ package io.helidon.microprofile.openapi; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.Reader; import java.io.StringReader; @@ -39,6 +37,8 @@ import org.eclipse.microprofile.openapi.models.OpenAPI; import org.junit.jupiter.api.Test; +import static io.helidon.microprofile.openapi.TestUtils.config; +import static io.helidon.microprofile.openapi.TestUtils.resource; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.hasItem; import static org.hamcrest.CoreMatchers.instanceOf; @@ -48,11 +48,13 @@ class OpenApiSerializerTest { + private static final OpenApiHelper OAI_HELPER = new OpenApiHelper(config()); + @Test - public void testJSONSerialization() throws IOException { + public void testJSONSerialization() { OpenAPI openAPI = parse("/openapi-greeting.yml"); Writer writer = new StringWriter(); - OpenApiSerializer.serialize(OpenApiHelper.types(), openAPI, OpenApiFormat.JSON, writer); + OpenApiSerializer.serialize(OAI_HELPER.types(), openAPI, OpenApiFormat.JSON, writer); JsonStructure json = readJson(writer.toString()); @@ -111,9 +113,9 @@ public void testJSONSerialization() throws IOException { public void testYAMLSerialization() throws IOException { OpenAPI openAPI = parse("/openapi-greeting.yml"); Writer writer = new StringWriter(); - OpenApiSerializer.serialize(OpenApiHelper.types(), openAPI, OpenApiFormat.YAML, writer); + OpenApiSerializer.serialize(OAI_HELPER.types(), openAPI, OpenApiFormat.YAML, writer); try (Reader reader = new StringReader(writer.toString())) { - openAPI = OpenApiParser.parse(OpenApiHelper.types(), OpenAPI.class, reader); + openAPI = OpenApiParser.parse(OAI_HELPER.types(), OpenAPI.class, reader); } Object candidateMap = openAPI.getExtensions() .get("x-my-personal-map"); @@ -140,10 +142,10 @@ public void testYAMLSerialization() throws IOException { void testRefSerializationAsOpenAPI() throws IOException { OpenAPI openAPI = parse("/petstore.yaml"); Writer writer = new StringWriter(); - OpenApiSerializer.serialize(OpenApiHelper.types(), openAPI, OpenApiFormat.YAML, writer); + OpenApiSerializer.serialize(OAI_HELPER.types(), openAPI, OpenApiFormat.YAML, writer); try (Reader reader = new StringReader(writer.toString())) { - openAPI = OpenApiParser.parse(OpenApiHelper.types(), OpenAPI.class, reader); + openAPI = OpenApiParser.parse(OAI_HELPER.types(), OpenAPI.class, reader); } String ref = openAPI.getPaths() @@ -167,7 +169,7 @@ void testRefSerializationAsText() throws IOException { OpenAPI openAPI = parse("/petstore.yaml"); Writer writer = new StringWriter(); - OpenApiSerializer.serialize(OpenApiHelper.types(), openAPI, OpenApiFormat.YAML, writer); + OpenApiSerializer.serialize(OAI_HELPER.types(), openAPI, OpenApiFormat.YAML, writer); try (LineNumberReader reader = new LineNumberReader(new StringReader(writer.toString()))) { String line; @@ -199,18 +201,14 @@ private static void checkJsonIntValue(JsonValue val, int expected) { assertThat(Integer.valueOf(val.toString()), is(expected)); } - private static OpenAPI parse(String path) throws IOException { - try (InputStream is = OpenApiSerializerTest.class.getResourceAsStream(path)) { - if (is == null) { - throw new IllegalArgumentException("Resource not found: " + path); - } - return OpenApiParser.parse(OpenApiHelper.types(), OpenAPI.class, new InputStreamReader(is)); - } - } - private static JsonStructure readJson(String str) { try (JsonReader jsonReader = Json.createReader(new StringReader(str))) { return jsonReader.read(); } } + + private static OpenAPI parse(String path) { + String document = resource(path); + return OpenApiParser.parse(OAI_HELPER.types(), OpenAPI.class, new StringReader(document)); + } } \ No newline at end of file diff --git a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/ServerConfigTest.java b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/ServerConfigTest.java index 2e8a7a2a6f6..20c12a0ad68 100644 --- a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/ServerConfigTest.java +++ b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/ServerConfigTest.java @@ -45,7 +45,7 @@ class ServerConfigTest { @Test public void testAlternatePath() { Map document = document(); - String summary = YamlQuery.get(document, "paths./testapp/go.get.summary", String.class); + String summary = TestUtils.query(document, "paths./testapp/go.get.summary", String.class); assertThat(summary, is(TestApp.GO_SUMMARY)); } diff --git a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/ServerModelReaderTest.java b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/ServerModelReaderTest.java index f45636a45e0..79ce7c74947 100644 --- a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/ServerModelReaderTest.java +++ b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/ServerModelReaderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022 Oracle and/or its affiliates. + * Copyright (c) 2019, 2023 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import io.helidon.common.media.type.MediaTypes; import io.helidon.http.Http; import io.helidon.microprofile.tests.junit5.AddBean; -import io.helidon.microprofile.tests.junit5.Configuration; +import io.helidon.microprofile.tests.junit5.AddConfig; import io.helidon.microprofile.tests.junit5.HelidonTest; import io.helidon.microprofile.openapi.test.MyModelReader; @@ -32,7 +32,6 @@ import jakarta.json.JsonStructure; import jakarta.json.JsonValue; import jakarta.ws.rs.client.WebTarget; -import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.junit.jupiter.api.Test; @@ -46,7 +45,8 @@ * the OpenAPI model. */ @HelidonTest -@Configuration(configSources = "simple.properties") +@AddConfig(key = "mp.openapi.model.reader", value = "io.helidon.microprofile.openapi.test.MyModelReader") +@AddConfig(key = "mp.openapi.filter", value = "io.helidon.microprofile.openapi.test.MySimpleFilter") @AddBean(TestApp.class) class ServerModelReaderTest { @@ -59,12 +59,13 @@ class ServerModelReaderTest { void checkCustomModelReader() { try (Response response = webTarget.path("/openapi").request(APPLICATION_OPENAPI_JSON).get()) { assertThat(response.getStatus(), is(Http.Status.OK_200.code())); - assertThat(response.getMediaType(), is(MediaType.APPLICATION_JSON)); + assertThat(response.getMediaType().toString(), is(APPLICATION_OPENAPI_JSON)); String text = response.readEntity(String.class); JsonStructure json = readJson(text); // The model reader adds the following key/value (among others) to the model. - JsonValue v = json.getValue(String.format("/paths/%s/get/summary", escapeJsonPointer(MyModelReader.MODEL_READER_PATH))); + JsonValue v = json.getValue(String.format("/paths/%s/get/summary", + escapeJsonPointer(MyModelReader.MODEL_READER_PATH))); assertThat(v.getValueType(), is(JsonValue.ValueType.STRING)); assertThat(((JsonString) v).getString(), is(MyModelReader.SUMMARY)); } @@ -74,7 +75,7 @@ void checkCustomModelReader() { void makeSureFilteredPathIsMissing() { try (Response response = webTarget.path("/openapi").request(APPLICATION_OPENAPI_JSON).get()) { assertThat(response.getStatus(), is(Http.Status.OK_200.code())); - assertThat(response.getMediaType(), is(MediaType.APPLICATION_JSON)); + assertThat(response.getMediaType().toString(), is(APPLICATION_OPENAPI_JSON)); String text = response.readEntity(String.class); JsonStructure json = readJson(text); diff --git a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/YamlQuery.java b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/TestUtils.java similarity index 52% rename from microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/YamlQuery.java rename to microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/TestUtils.java index 56ddfe989af..d38f8f67572 100644 --- a/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/YamlQuery.java +++ b/microprofile/openapi/src/test/java/io/helidon/microprofile/openapi/TestUtils.java @@ -15,14 +15,67 @@ */ package io.helidon.microprofile.openapi; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Map; +import io.helidon.config.mp.MpConfigSources; + +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.spi.ConfigProviderResolver; +import org.eclipse.microprofile.config.spi.ConfigSource; + /** * Utility to query a tree structure using a dotted path notation. */ -class YamlQuery { +class TestUtils { + + private TestUtils() { + } + + /** + * {@link io.helidon.microprofile.openapi.OpenApiHelper} initialized with empty config. + */ + static final OpenApiHelper OAI_HELPER = new OpenApiHelper(config()); + + /** + * Get a class-path resource. + * @param path resource path + * @return resource content as a string + */ + static String resource(String path) { + try (InputStream is = TestUtils.class.getResourceAsStream(path)) { + if (is == null) { + throw new IllegalArgumentException("Resource not found: " + path); + } + return new String(is.readAllBytes(), StandardCharsets.UTF_8); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + + /** + * Create a new instance of {@link Config} with the given maps as config sources. + * + * @param configSources config sources + * @return config + */ + @SafeVarargs + static Config config(Map... configSources) { + return ConfigProviderResolver.instance() + .getBuilder() + .withSources(configSources(configSources)) + .build(); + } - private YamlQuery() { + @SafeVarargs + private static ConfigSource[] configSources(Map... configSources) { + return Arrays.stream(configSources) + .map(MpConfigSources::create) + .toArray(ConfigSource[]::new); } /** @@ -39,7 +92,7 @@ private YamlQuery() { * @return value from the lowest-level map retrieved using the last path segment, cast to the specified type */ @SuppressWarnings(value = "unchecked") - public static T get(Map map, String dottedPath, Class cl) { + public static T query(Map map, String dottedPath, Class cl) { Map originalMap = map; String[] segments = dottedPath.split("\\."); for (int i = 0; i < segments.length - 1; i++) { diff --git a/openapi/openapi-ui/src/main/java/io/helidon/openapi/OpenApiUiProvider.java b/openapi/openapi-ui/src/main/java/io/helidon/openapi/OpenApiUiProvider.java deleted file mode 100644 index 6d84521cada..00000000000 --- a/openapi/openapi-ui/src/main/java/io/helidon/openapi/OpenApiUiProvider.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.helidon.openapi; - -import io.helidon.common.config.Config; -import io.helidon.openapi.spi.OpenApiServiceProvider; - -/** - * A {@link OpenApiServiceProvider} that provides {@link OpenApiUi}. - */ -public final class OpenApiUiProvider implements OpenApiServiceProvider { - - /** - * Create a new instance. - * - * @deprecated to be used solely by {@link java.util.ServiceLoader} - */ - @Deprecated - public OpenApiUiProvider() { - } - - @Override - public String configKey() { - return "ui"; - } - - @Override - public OpenApiUi create(Config config, String name) { - return OpenApiUi.builder().config(config).build(); - } -} diff --git a/openapi/openapi-ui/src/main/java/io/helidon/openapi/OpenApiUi.java b/openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/OpenApiUi.java similarity index 98% rename from openapi/openapi-ui/src/main/java/io/helidon/openapi/OpenApiUi.java rename to openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/OpenApiUi.java index d7cea612e50..789e67a2fb5 100644 --- a/openapi/openapi-ui/src/main/java/io/helidon/openapi/OpenApiUi.java +++ b/openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/OpenApiUi.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.helidon.openapi; +package io.helidon.openapi.ui; import java.io.IOException; import java.io.UncheckedIOException; @@ -28,6 +28,7 @@ import io.helidon.common.media.type.MediaTypes; import io.helidon.http.Http; import io.helidon.http.HttpMediaType; +import io.helidon.openapi.OpenApiService; import io.helidon.webserver.http.HttpRules; import io.helidon.webserver.http.ServerRequest; import io.helidon.webserver.http.ServerResponse; diff --git a/openapi/openapi-ui/src/main/java/io/helidon/openapi/OpenApiUiConfigBlueprint.java b/openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/OpenApiUiConfigBlueprint.java similarity index 95% rename from openapi/openapi-ui/src/main/java/io/helidon/openapi/OpenApiUiConfigBlueprint.java rename to openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/OpenApiUiConfigBlueprint.java index 3cf1bdb31a9..6bf389694b9 100644 --- a/openapi/openapi-ui/src/main/java/io/helidon/openapi/OpenApiUiConfigBlueprint.java +++ b/openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/OpenApiUiConfigBlueprint.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.helidon.openapi; +package io.helidon.openapi.ui; import java.util.Map; @@ -49,6 +49,6 @@ interface OpenApiUiConfigBlueprint extends Prototype.Factory { * * @return full web context path */ - @ConfiguredOption + @ConfiguredOption(value = "/openapi/ui") String webContext(); } diff --git a/openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/OpenApiUiProvider.java b/openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/OpenApiUiProvider.java new file mode 100644 index 00000000000..43a3c127986 --- /dev/null +++ b/openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/OpenApiUiProvider.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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 io.helidon.openapi.ui; + +import io.helidon.common.config.Config; +import io.helidon.openapi.spi.OpenApiServiceProvider; + +/** + * A {@link OpenApiServiceProvider} that provides {@link OpenApiUi}. + */ +public final class OpenApiUiProvider implements OpenApiServiceProvider { + + /** + * Create a new instance. + * + * @deprecated to be used solely by {@link java.util.ServiceLoader} + */ + @Deprecated + public OpenApiUiProvider() { + } + + @Override + public String configKey() { + return "ui"; + } + + @Override + public OpenApiUi create(Config config, String name) { + return OpenApiUi.builder().config(config).build(); + } +} diff --git a/openapi/openapi-ui/src/main/java/io/helidon/openapi/package-info.java b/openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/package-info.java similarity index 95% rename from openapi/openapi-ui/src/main/java/io/helidon/openapi/package-info.java rename to openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/package-info.java index fac2fbc86a7..cd9b011798a 100644 --- a/openapi/openapi-ui/src/main/java/io/helidon/openapi/package-info.java +++ b/openapi/openapi-ui/src/main/java/io/helidon/openapi/ui/package-info.java @@ -17,4 +17,4 @@ /** * Helidon OpenAPI UI support. */ -package io.helidon.openapi; +package io.helidon.openapi.ui; diff --git a/openapi/openapi-ui/src/main/java/module-info.java b/openapi/openapi-ui/src/main/java/module-info.java index 36c8bc6d8c3..ad0bff14889 100644 --- a/openapi/openapi-ui/src/main/java/module-info.java +++ b/openapi/openapi-ui/src/main/java/module-info.java @@ -16,10 +16,10 @@ import io.helidon.common.features.api.Feature; import io.helidon.common.features.api.HelidonFlavor; import io.helidon.openapi.spi.OpenApiServiceProvider; -import io.helidon.openapi.OpenApiUiProvider; +import io.helidon.openapi.ui.OpenApiUiProvider; -@Feature(value = "OpenAPI", - description = "OpenAPI support", +@Feature(value = "OpenAPI UI", + description = "OpenAPI UI support", in = HelidonFlavor.SE ) module io.helidon.openapi.ui { diff --git a/openapi/openapi-ui/src/test/java/io/helidon/openapi/OpenApiUiTest.java b/openapi/openapi-ui/src/test/java/io/helidon/openapi/ui/OpenApiUiTest.java similarity index 61% rename from openapi/openapi-ui/src/test/java/io/helidon/openapi/OpenApiUiTest.java rename to openapi/openapi-ui/src/test/java/io/helidon/openapi/ui/OpenApiUiTest.java index 2658b23f82e..6257cefb019 100644 --- a/openapi/openapi-ui/src/test/java/io/helidon/openapi/OpenApiUiTest.java +++ b/openapi/openapi-ui/src/test/java/io/helidon/openapi/ui/OpenApiUiTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.helidon.openapi; +package io.helidon.openapi.ui; import java.util.Map; @@ -21,12 +21,12 @@ import io.helidon.common.media.type.MediaTypes; import io.helidon.http.Http; import io.helidon.http.HttpMediaType; +import io.helidon.openapi.OpenApiFeature; import io.helidon.webclient.api.HttpClientResponse; import io.helidon.webclient.api.WebClient; -import io.helidon.webserver.WebServerConfig; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpServer; -import io.helidon.webserver.testing.junit5.Socket; +import io.helidon.webserver.http.HttpRouting; +import io.helidon.webserver.testing.junit5.RoutingTest; +import io.helidon.webserver.testing.junit5.SetUpRoute; import org.junit.jupiter.api.Test; @@ -37,11 +37,9 @@ /** * Tests {@link OpenApiUi}. */ -@ServerTest +@RoutingTest class OpenApiUiTest { - private static final String GREETING_OPENAPI_PATH = "/openapi-greeting"; - private static final MediaType[] SIMULATED_BROWSER_ACCEPT = new MediaType[] { MediaTypes.TEXT_HTML, MediaTypes.APPLICATION_XHTML_XML, @@ -58,29 +56,26 @@ class OpenApiUiTest { }; private final WebClient client; - private final WebClient altClient; - OpenApiUiTest(WebClient client, @Socket("alt") WebClient altClient) { + OpenApiUiTest(WebClient client) { this.client = client; - this.altClient = altClient; } - @SetUpServer - public static void setup(WebServerConfig.Builder server) { - server.routing(routing -> routing - .addFeature(OpenApiFeature.builder() - .servicesDiscoverServices(false) - .staticFile("src/test/resources/greeting.yml") - .webContext("/openapi-greeting") - .cors(cors -> cors.enabled(false)) - .addService(OpenApiUi.create()))) - .putSocket("alt", socket -> socket - .routing(routing -> routing - .addFeature(OpenApiFeature.builder() - .servicesDiscoverServices(false) - .staticFile("src/test/resources/time.yml") - .cors(cors -> cors.enabled(false)) - .addService(OpenApiUi.create())))); + @SetUpRoute + public static void setup(HttpRouting.Builder routing) { + routing.addFeature(OpenApiFeature.builder() + .servicesDiscoverServices(false) + .staticFile("src/test/resources/greeting.yml") + .webContext("/openapi-greeting") + .cors(cors -> cors.enabled(false)) + .addService(OpenApiUi.create())) + .addFeature(OpenApiFeature.builder() + .servicesDiscoverServices(false) + .staticFile("src/test/resources/time.yml") + .cors(cors -> cors.enabled(false)) + .addService(OpenApiUi.builder() + .webContext("/my-ui") + .build())); } @Test @@ -95,7 +90,7 @@ void checkNoOpUi() { @Test void checkSimulatedBrowserAccessToMainEndpoint() { - try (HttpClientResponse response = client.get(GREETING_OPENAPI_PATH) + try (HttpClientResponse response = client.get("/openapi-greeting") .accept(SIMULATED_BROWSER_ACCEPT) .request()) { @@ -108,7 +103,7 @@ void checkSimulatedBrowserAccessToMainEndpoint() { @Test void checkAlternateUiWebContext() { - try (HttpClientResponse response = altClient.get("/my-ui") + try (HttpClientResponse response = client.get("/my-ui") .accept(MediaTypes.TEXT_PLAIN) .request()) { assertThat(response.status(), is(Http.Status.NOT_FOUND_404)); diff --git a/openapi/openapi/src/main/java/io/helidon/openapi/OpenApiManager.java b/openapi/openapi/src/main/java/io/helidon/openapi/OpenApiManager.java index cd368b118ef..041c9a6319a 100644 --- a/openapi/openapi/src/main/java/io/helidon/openapi/OpenApiManager.java +++ b/openapi/openapi/src/main/java/io/helidon/openapi/OpenApiManager.java @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * http://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 io.helidon.openapi; import io.helidon.common.config.NamedService; diff --git a/openapi/openapi/src/main/resources/META-INF/native-image/io.helidon.openapi/helidon-openapi/native-image.properties b/openapi/openapi/src/main/resources/META-INF/native-image/io.helidon.openapi/helidon-openapi/native-image.properties index d4458ccb1ee..c247eb32a4f 100644 --- a/openapi/openapi/src/main/resources/META-INF/native-image/io.helidon.openapi/helidon-openapi/native-image.properties +++ b/openapi/openapi/src/main/resources/META-INF/native-image/io.helidon.openapi/helidon-openapi/native-image.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2022 Oracle and/or its affiliates. +# Copyright (c) 2020, 2023 Oracle and/or its affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/openapi/openapi/src/test/resources/greeting.yml b/openapi/openapi/src/test/resources/greeting.yml index fc36ebd11b7..dc367eb57a3 100644 --- a/openapi/openapi/src/test/resources/greeting.yml +++ b/openapi/openapi/src/test/resources/greeting.yml @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, 2021 Oracle and/or its affiliates. +# Copyright (c) 2019, 2023 Oracle and/or its affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/openapi/openapi/src/test/resources/time-server.yml b/openapi/openapi/src/test/resources/time-server.yml index b6bbf906f8c..292b72ed125 100644 --- a/openapi/openapi/src/test/resources/time-server.yml +++ b/openapi/openapi/src/test/resources/time-server.yml @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, 2021 Oracle and/or its affiliates. +# Copyright (c) 2019, 2023 Oracle and/or its affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License.