From d5c1365bfd933b94d58e6c02aed6d23cae8ebc8a Mon Sep 17 00:00:00 2001 From: Jeff Trent Date: Sat, 22 Apr 2023 13:39:04 -0400 Subject: [PATCH 1/4] fix for issue #6674 - named and repeating config --- .../test/AbstractConfiguredByTest.java | 5 +- .../configuredby/test/package-info.java | 2 +- .../configuredby/yaml/test/Async.java | 33 ++++++++ .../configuredby/yaml/test/AsyncConfig.java | 28 +++++++ .../yaml/test/BulkheadConfig.java | 26 ++++++ .../configuredby/yaml/test/ServerConfig.java | 26 ++++++ .../configuredby/yaml/test/package-info.java | 20 +++++ .../yaml/test/NamedConfiguredByTest.java | 83 +++++++++++++++++++ .../src/test/resources/application.yaml | 29 +++++++ 9 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/Async.java create mode 100644 pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/AsyncConfig.java create mode 100644 pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/BulkheadConfig.java create mode 100644 pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/ServerConfig.java create mode 100644 pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/package-info.java create mode 100644 pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java create mode 100644 pico/configdriven/tests/configuredby/src/test/resources/application.yaml diff --git a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/test/AbstractConfiguredByTest.java b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/test/AbstractConfiguredByTest.java index 7486f6e4ebb..8db24089a94 100644 --- a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/test/AbstractConfiguredByTest.java +++ b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/test/AbstractConfiguredByTest.java @@ -125,7 +125,10 @@ void testRegistry() { .addQualifier(DefaultQualifierAndValue.create(ConfiguredBy.class)) .build(); List> list = services.lookupAll(criteria); - List desc = list.stream().map(ServiceProvider::description).collect(Collectors.toList()); + List desc = list.stream() + .filter(it -> !it.serviceInfo().serviceTypeName().contains(".yaml.")) + .map(ServiceProvider::description) + .collect(Collectors.toList()); // order matters here since it should be based upon weight assertThat("root providers are config-driven, auto-started services unless overridden to not be driven", desc, contains("ASingletonService{root}:ACTIVE", diff --git a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/test/package-info.java b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/test/package-info.java index 883c4bb955a..c77b57f7169 100644 --- a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/test/package-info.java +++ b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/test/package-info.java @@ -15,6 +15,6 @@ */ /** - * For Testing. + * For testing. */ package io.helidon.pico.configdriven.configuredby.test; diff --git a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/Async.java b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/Async.java new file mode 100644 index 00000000000..9eb2b3356e9 --- /dev/null +++ b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/Async.java @@ -0,0 +1,33 @@ +/* + * 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.pico.configdriven.configuredby.yaml.test; + +import io.helidon.pico.configdriven.api.ConfiguredBy; + +import jakarta.inject.Inject; + +@ConfiguredBy(AsyncConfig.class) +class Async { + + final AsyncConfig cfg; + + @Inject + Async(AsyncConfig cfg) { + this.cfg = cfg; + } + +} diff --git a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/AsyncConfig.java b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/AsyncConfig.java new file mode 100644 index 00000000000..fd83af99534 --- /dev/null +++ b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/AsyncConfig.java @@ -0,0 +1,28 @@ +/* + * 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.pico.configdriven.configuredby.yaml.test; + +import java.util.Optional; + +import io.helidon.builder.config.ConfigBean; + +@ConfigBean("ft.asyncs") +interface AsyncConfig { + + Optional executor(); + +} diff --git a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/BulkheadConfig.java b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/BulkheadConfig.java new file mode 100644 index 00000000000..b43c550aed7 --- /dev/null +++ b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/BulkheadConfig.java @@ -0,0 +1,26 @@ +/* + * 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.pico.configdriven.configuredby.yaml.test; + +import io.helidon.builder.config.ConfigBean; + +@ConfigBean("ft.bulkheads") +interface BulkheadConfig { + + int queue(); + +} diff --git a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/ServerConfig.java b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/ServerConfig.java new file mode 100644 index 00000000000..ff8697c29b3 --- /dev/null +++ b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/ServerConfig.java @@ -0,0 +1,26 @@ +/* + * 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.pico.configdriven.configuredby.yaml.test; + +import io.helidon.builder.config.ConfigBean; + +@ConfigBean(value = "server", repeatable = false) +interface ServerConfig { + + int port(); + +} diff --git a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/package-info.java b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/package-info.java new file mode 100644 index 00000000000..2f3ca5c656c --- /dev/null +++ b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/package-info.java @@ -0,0 +1,20 @@ +/* + * 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. + */ + +/** + * Pico ConfiguredBy tests driven testing from the {@code application.yaml} config under test/resources. + */ +package io.helidon.pico.configdriven.configuredby.yaml.test; diff --git a/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java b/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java new file mode 100644 index 00000000000..053ba4afaa8 --- /dev/null +++ b/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java @@ -0,0 +1,83 @@ +/* + * 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.pico.configdriven.configuredby.yaml.test; + +import java.util.Optional; + +import io.helidon.builder.config.spi.ConfigBeanRegistryHolder; +import io.helidon.common.testing.junit5.OptionalMatcher; +import io.helidon.config.Config; +import io.helidon.config.ConfigSources; +import io.helidon.pico.api.Bootstrap; +import io.helidon.pico.api.PicoServices; +import io.helidon.pico.api.Services; +import io.helidon.pico.configdriven.runtime.ConfigBeanRegistry; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static io.helidon.pico.testing.PicoTestingSupport.resetAll; +import static io.helidon.pico.testing.PicoTestingSupport.testableServices; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +class NamedConfiguredByTest { + PicoServices picoServices; + Services services; + + @BeforeAll + static void initialStateChecks() { + ConfigBeanRegistry cbr = (ConfigBeanRegistry) ConfigBeanRegistryHolder.configBeanRegistry().orElseThrow(); + assertThat(cbr.ready(), is(false)); + } + + @AfterAll + static void tearDown() { + resetAll(); + } + + void resetWith(Config config) { + resetAll(); + this.picoServices = testableServices(config); + this.services = picoServices.services(); + } + + @BeforeEach + void setup() { + Optional existingBootstrap = PicoServices.globalBootstrap(); + assertThat(existingBootstrap, OptionalMatcher.optionalEmpty()); + + Config config = Config.builder() + .addSource(ConfigSources.classpath("application.yaml")) + .disableSystemPropertiesSource() + .disableEnvironmentVariablesSource() + .build(); + resetWith(config); + + this.picoServices = PicoServices.picoServices().get(); + // this line is needed! + picoServices.services(); + } + + @Test + void namedConfiguredServices() { + System.out.println("here"); + } + +} diff --git a/pico/configdriven/tests/configuredby/src/test/resources/application.yaml b/pico/configdriven/tests/configuredby/src/test/resources/application.yaml new file mode 100644 index 00000000000..8d4e82348a1 --- /dev/null +++ b/pico/configdriven/tests/configuredby/src/test/resources/application.yaml @@ -0,0 +1,29 @@ +# +# 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. +# + +pico: + permits-dynamic: true + +server: + port: 8080 +ft: + asyncs: + first: + executor: "exec" + second: + executor: "service" + bulkheads: + - queue: 10 From 21c290f82c7c6259555e6269b794b0f52c413f69 Mon Sep 17 00:00:00 2001 From: Jeff Trent Date: Sat, 22 Apr 2023 13:39:04 -0400 Subject: [PATCH 2/4] preq changes for fix related to issue #6674 --- .../processor/ConfigBeanBuilderCreator.java | 2 +- .../builder/config/spi/ConfigBeanInfo.java | 5 + .../config/spi/GeneratedConfigBean.java | 24 +++-- .../config/spi/GeneratedConfigBeanBase.java | 28 ++++- .../config/spi/HelidonConfigBeanRegistry.java | 4 +- .../config/spi/HelidonConfigResolver.java | 2 +- .../processor/tools/GenerateMethod.java | 4 + .../config/test/BasicConfigBeanTest.java | 34 ++++++ .../AbstractConfiguredServiceProvider.java | 4 +- .../DefaultPicoConfigBeanRegistry.java | 101 +++++++++--------- .../configuredby/yaml/test/Async.java | 2 +- .../configuredby/yaml/test/AsyncConfig.java | 2 +- .../yaml/test/BulkheadConfig.java | 2 +- .../configuredby/yaml/test/ServerConfig.java | 2 +- .../yaml/test/NamedConfiguredByTest.java | 8 +- 15 files changed, 156 insertions(+), 68 deletions(-) diff --git a/builder/builder-config-processor/src/main/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreator.java b/builder/builder-config-processor/src/main/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreator.java index b18c365b5d5..813d995f4d6 100644 --- a/builder/builder-config-processor/src/main/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreator.java +++ b/builder/builder-config-processor/src/main/java/io/helidon/builder/config/processor/ConfigBeanBuilderCreator.java @@ -208,7 +208,7 @@ protected void appendMetaProps(StringBuilder builder, String tag, AtomicBoolean needsCustomMapOf) { builder.append("\t\t").append(tag); - builder.append(".put(\"__meta\", Map.of(").append(ConfigBeanInfo.class.getName()); + builder.append(".put(" + ConfigBeanInfo.class.getName() + ".TAG_META, Map.of(").append(ConfigBeanInfo.class.getName()); builder.append(".class.getName(),\n\t\t\t\t").append(MetaConfigBeanInfo.class.getName()).append(".builder()\n"); appendConfigBeanInfoAttributes(builder, ctx.typeInfo(), diff --git a/builder/builder-config/src/main/java/io/helidon/builder/config/spi/ConfigBeanInfo.java b/builder/builder-config/src/main/java/io/helidon/builder/config/spi/ConfigBeanInfo.java index 90b27fef177..f4bab0b8c23 100644 --- a/builder/builder-config/src/main/java/io/helidon/builder/config/spi/ConfigBeanInfo.java +++ b/builder/builder-config/src/main/java/io/helidon/builder/config/spi/ConfigBeanInfo.java @@ -29,6 +29,11 @@ @Builder(implPrefix = "Meta") public interface ConfigBeanInfo extends ConfigBean { + /** + * The tag used to represent the meta properties. + */ + String TAG_META = "__meta"; + /** * The attribute name for {@link #value()} ()}. */ diff --git a/builder/builder-config/src/main/java/io/helidon/builder/config/spi/GeneratedConfigBean.java b/builder/builder-config/src/main/java/io/helidon/builder/config/spi/GeneratedConfigBean.java index 8667ad01a4f..5bf76381e12 100644 --- a/builder/builder-config/src/main/java/io/helidon/builder/config/spi/GeneratedConfigBean.java +++ b/builder/builder-config/src/main/java/io/helidon/builder/config/spi/GeneratedConfigBean.java @@ -16,6 +16,10 @@ package io.helidon.builder.config.spi; +import java.util.Optional; + +import io.helidon.common.config.Config; + /** * Every {@link io.helidon.builder.config.ConfigBean}-annotated type will also implement this contract. */ @@ -28,17 +32,25 @@ public interface GeneratedConfigBean extends GeneratedConfigBeanCommon { */ /** - * Set the instance id of this config bean. + * Returns the instance id assigned to this bean. + * Note that the instance id is typically assigned the {@link Config#key()} in most circumstances. * - * @param val the new instance identifier + * @return the instance id assigned to this bean */ - void __instanceId(String val); + String __instanceId(); /** - * Returns the existing instance identifier. + * Returns the {@link Config#name()} if available. * - * @return the instance identifier + * @return the config name or else empty */ - String __instanceId(); + Optional __name(); + + /** + * Returns the generated config bean meta information. + * + * @return the config bean meta information + */ + MetaConfigBeanInfo __metaInfo(); } diff --git a/builder/builder-config/src/main/java/io/helidon/builder/config/spi/GeneratedConfigBeanBase.java b/builder/builder-config/src/main/java/io/helidon/builder/config/spi/GeneratedConfigBeanBase.java index d933c40817f..07292482827 100644 --- a/builder/builder-config/src/main/java/io/helidon/builder/config/spi/GeneratedConfigBeanBase.java +++ b/builder/builder-config/src/main/java/io/helidon/builder/config/spi/GeneratedConfigBeanBase.java @@ -16,6 +16,8 @@ package io.helidon.builder.config.spi; +import java.util.Map; +import java.util.Objects; import java.util.Optional; import io.helidon.common.config.Config; @@ -23,7 +25,7 @@ /** * Minimal implementation for the {@link GeneratedConfigBeanCommon}. This is the base for generated config beans. */ -public abstract class GeneratedConfigBeanBase implements GeneratedConfigBeanCommon { +public abstract class GeneratedConfigBeanBase implements GeneratedConfigBean { private final Config config; private String instanceId; @@ -46,17 +48,37 @@ public Optional __config() { return Optional.ofNullable(config); } + @Override + public Optional __name() { + if (__config().isEmpty()) { + return Optional.empty(); + } + + return Optional.of(__config().get().name()); + } + /** - * Returns the instance id assigned to this bean. + * The meta attributes for this generated config bean. * - * @return the instance id assigned to this bean + * @return meta attributes for this config bean */ + public abstract Map> __metaProps(); + + @Override + public MetaConfigBeanInfo __metaInfo() { + Map meta = __metaProps().get(ConfigBeanInfo.TAG_META); + MetaConfigBeanInfo metaInfo = (MetaConfigBeanInfo) meta.get(ConfigBeanInfo.class.getName()); + return Objects.requireNonNull(metaInfo); + } + + @Override public String __instanceId() { return instanceId; } /** * Assigns the instance id assigned to this bean. + * Note that the instance id is typically assigned the {@link Config#key()} in most circumstances. * * @param val the new instance id for this bean */ diff --git a/builder/builder-config/src/main/java/io/helidon/builder/config/spi/HelidonConfigBeanRegistry.java b/builder/builder-config/src/main/java/io/helidon/builder/config/spi/HelidonConfigBeanRegistry.java index 00001bbfecf..7034fda9d20 100644 --- a/builder/builder-config/src/main/java/io/helidon/builder/config/spi/HelidonConfigBeanRegistry.java +++ b/builder/builder-config/src/main/java/io/helidon/builder/config/spi/HelidonConfigBeanRegistry.java @@ -28,9 +28,9 @@ public interface HelidonConfigBeanRegistry { /** * Returns all config beans indexed by its config key. * - * @param the config bean type + * @param the generated config bean type * @return all config beans */ - Map> allConfigBeans(); + Map> allConfigBeans(); } diff --git a/builder/builder-config/src/main/java/io/helidon/builder/config/spi/HelidonConfigResolver.java b/builder/builder-config/src/main/java/io/helidon/builder/config/spi/HelidonConfigResolver.java index 7f5f107bd65..bb3c9417b83 100644 --- a/builder/builder-config/src/main/java/io/helidon/builder/config/spi/HelidonConfigResolver.java +++ b/builder/builder-config/src/main/java/io/helidon/builder/config/spi/HelidonConfigResolver.java @@ -47,7 +47,7 @@ public class HelidonConfigResolver implements ConfigResolver, ConfigResolverProv /** * Tag that represents meta information about the attribute. Used in the maps for various methods herein. */ - public static final String TAG_META = "__meta"; + public static final String TAG_META = ConfigBeanInfo.TAG_META; /** * Tag that represents the component type. diff --git a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateMethod.java b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateMethod.java index d6bed58d77c..911c13d0254 100644 --- a/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateMethod.java +++ b/builder/processor-tools/src/main/java/io/helidon/builder/processor/tools/GenerateMethod.java @@ -67,6 +67,10 @@ static void internalMetaAttributes(StringBuilder builder) { builder.append("\tpublic static Map> __metaAttributes() {\n" + "\t\treturn ").append(BodyContext.TAG_META_PROPS).append(";\n" + "\t}\n\n"); + + GenerateJavadoc.internalMetaAttributes(builder); + builder.append("\tpublic Map> __metaProps() {\n" + + "\t\treturn __metaAttributes();\n\t}\n\n"); } static void nonOptionalSetter(StringBuilder builder, diff --git a/builder/tests/configbean/src/test/java/io/helidon/builder/config/test/BasicConfigBeanTest.java b/builder/tests/configbean/src/test/java/io/helidon/builder/config/test/BasicConfigBeanTest.java index 6fa62981268..be1af844a1f 100644 --- a/builder/tests/configbean/src/test/java/io/helidon/builder/config/test/BasicConfigBeanTest.java +++ b/builder/tests/configbean/src/test/java/io/helidon/builder/config/test/BasicConfigBeanTest.java @@ -19,6 +19,8 @@ import java.util.List; import java.util.Map; +import io.helidon.builder.config.spi.GeneratedConfigBean; +import io.helidon.builder.config.spi.MetaConfigBeanInfo; import io.helidon.builder.config.testsubjects.DefaultTestClientConfig; import io.helidon.builder.config.testsubjects.DefaultTestServerConfig; import io.helidon.builder.config.testsubjects.TestClientConfig; @@ -72,6 +74,18 @@ void acceptConfig() { contains("a", "b", "c")); assertThat(serverConfig.toString(), endsWith("(name=server, port=8080, cipherSuites=[a, b, c], pswd=not-null, description=Optional[test])")); + GeneratedConfigBean generatedCB = (GeneratedConfigBean) serverConfig; + assertThat(generatedCB.__name(), + optionalValue(equalTo(""))); + assertThat(generatedCB.__metaInfo(), + equalTo(MetaConfigBeanInfo.builder() + .value("test-server") + .repeatable(true) + .drivesActivation(false) + .atLeastOne(true) + .wantDefaultConfigBean(false) + .levelType(io.helidon.builder.config.ConfigBean.LevelType.ROOT) + .build())); TestClientConfig clientConfig = DefaultTestClientConfig.toBuilder(cfg).build(); assertThat(clientConfig.name(), @@ -91,6 +105,18 @@ void acceptConfig() { assertThat(clientConfig.toString(), endsWith("(name=server, port=8080, cipherSuites=[a, b, c], pswd=not-null, " + "serverPort=0, headers={headers.1=header2, headers.0=header1})")); + generatedCB = (GeneratedConfigBean) clientConfig; + assertThat(generatedCB.__name(), + optionalValue(equalTo(""))); + assertThat(generatedCB.__metaInfo(), + equalTo(MetaConfigBeanInfo.builder() + .value("test-client") + .repeatable(true) + .drivesActivation(false) + .atLeastOne(false) + .wantDefaultConfigBean(false) + .levelType(io.helidon.builder.config.ConfigBean.LevelType.ROOT) + .build())); } @Test @@ -103,6 +129,10 @@ void emptyConfig() { equalTo("default")); assertThat(serverConfig.port(), equalTo(0)); + + GeneratedConfigBean generatedCB = (GeneratedConfigBean) serverConfig; + assertThat(generatedCB.__name(), + optionalValue(equalTo(""))); } /** @@ -148,6 +178,10 @@ void noConfig() { equalTo(Map.of())); assertThat(clientConfig.cipherSuites(), equalTo(List.of())); + + GeneratedConfigBean generatedCB = (GeneratedConfigBean) clientConfig; + assertThat(generatedCB.__name(), + optionalEmpty()); } @Test diff --git a/pico/configdriven/runtime/src/main/java/io/helidon/pico/configdriven/runtime/AbstractConfiguredServiceProvider.java b/pico/configdriven/runtime/src/main/java/io/helidon/pico/configdriven/runtime/AbstractConfiguredServiceProvider.java index ee106d79082..545f2683b3c 100644 --- a/pico/configdriven/runtime/src/main/java/io/helidon/pico/configdriven/runtime/AbstractConfiguredServiceProvider.java +++ b/pico/configdriven/runtime/src/main/java/io/helidon/pico/configdriven/runtime/AbstractConfiguredServiceProvider.java @@ -307,7 +307,7 @@ public Map> configBeanAttributes() { // note that all responsibilities to resolve is delegated to the root provider @Override - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "rawtypes"}) public Optional resolve(InjectionPointInfo ipInfo, PicoServices picoServices, ServiceProvider serviceProvider, @@ -335,7 +335,7 @@ public Optional resolve(InjectionPointInfo ipInfo, return Optional.of(configBeanType()); } - return (Optional) configBean(); + return (Optional) configBean(); } /** diff --git a/pico/configdriven/runtime/src/main/java/io/helidon/pico/configdriven/runtime/DefaultPicoConfigBeanRegistry.java b/pico/configdriven/runtime/src/main/java/io/helidon/pico/configdriven/runtime/DefaultPicoConfigBeanRegistry.java index 832a896d7df..d04c84a9560 100644 --- a/pico/configdriven/runtime/src/main/java/io/helidon/pico/configdriven/runtime/DefaultPicoConfigBeanRegistry.java +++ b/pico/configdriven/runtime/src/main/java/io/helidon/pico/configdriven/runtime/DefaultPicoConfigBeanRegistry.java @@ -34,6 +34,7 @@ import io.helidon.builder.AttributeVisitor; import io.helidon.builder.config.ConfigBean; import io.helidon.builder.config.spi.ConfigBeanInfo; +import io.helidon.builder.config.spi.GeneratedConfigBean; import io.helidon.builder.config.spi.MetaConfigBeanInfo; import io.helidon.common.config.Config; import io.helidon.common.config.ConfigException; @@ -68,10 +69,10 @@ class DefaultPicoConfigBeanRegistry implements BindableConfigBeanRegistry { private static final boolean FORCE_VALIDATE_USING_CONFIG_ATTRIBUTES = true; private final AtomicBoolean initializing = new AtomicBoolean(); - private final Map, ConfigBeanInfo> configuredServiceProviderMetaConfigBeanMap = - new ConcurrentHashMap<>(); - private final Map>> configuredServiceProvidersByConfigKey = - new ConcurrentHashMap<>(); + private final Map, ConfigBeanInfo> + configuredServiceProviderMetaConfigBeanMap = new ConcurrentHashMap<>(); + private final Map>> + configuredServiceProvidersByConfigKey = new ConcurrentHashMap<>(); private CountDownLatch initialized = new CountDownLatch(1); DefaultPicoConfigBeanRegistry() { @@ -152,7 +153,8 @@ public void bind(ConfiguredServiceProvider configuredServiceProvider, + " with " + configuredByQualifier.value()); } - Object prev = configuredServiceProviderMetaConfigBeanMap.put(configuredServiceProvider, metaConfigBeanInfo); + Object prev = configuredServiceProviderMetaConfigBeanMap + .put((ConfiguredServiceProvider) configuredServiceProvider, metaConfigBeanInfo); assert (prev == null) : "duplicate service provider initialization occurred"; String configKey = validatedConfigKey(metaConfigBeanInfo); @@ -161,12 +163,12 @@ public void bind(ConfiguredServiceProvider configuredServiceProvider, if (cspList == null) { cspList = new ArrayList<>(); } - Optional> prevCsp = cspList.stream() + Optional> prevCsp = cspList.stream() .filter(it -> cspType.equals(it.configBeanType())) .findAny(); assert (prevCsp.isEmpty()) : "duplicate service provider initialization occurred"; - boolean added = cspList.add(configuredServiceProvider); + boolean added = cspList.add((ConfiguredServiceProvider) configuredServiceProvider); assert (added); return cspList; @@ -268,7 +270,7 @@ public Set configBeansByConfigKey(String key, @Override public Map configBeanMapByConfigKey(String key, String fullConfigKey) { - List> cspsUsingSameKey = + List> cspsUsingSameKey = configuredServiceProvidersByConfigKey.get(Objects.requireNonNull(key)); if (cspsUsingSameKey == null) { return Map.of(); @@ -294,8 +296,8 @@ public Set configBeansByConfigKey(String key, @Override @SuppressWarnings("unchecked") - public Map> allConfigBeans() { - Map> result = new TreeMap<>(AbstractConfiguredServiceProvider.configBeanComparator()); + public Map> allConfigBeans() { + Map> result = new TreeMap<>(AbstractConfiguredServiceProvider.configBeanComparator()); configuredServiceProvidersByConfigKey.forEach((key, value) -> value.stream() .filter(csp -> csp instanceof AbstractConfiguredServiceProvider) @@ -307,7 +309,7 @@ public Map> allConfigBeans() { if (v == null) { v = new ArrayList<>(); } - v.add((CB) value1); + v.add((GCB) value1); return v; }); }); @@ -320,10 +322,10 @@ protected boolean isInitialized() { return (0 == initialized.getCount()); } - void loadConfigBeans(io.helidon.config.Config config, - ConfiguredServiceProvider configuredServiceProvider, - ConfigBeanInfo metaConfigBeanInfo, - Map> metaAttributes) { + void loadConfigBeans(io.helidon.config.Config config, + ConfiguredServiceProvider configuredServiceProvider, + ConfigBeanInfo metaConfigBeanInfo, + Map> metaAttributes) { if (LOGGER.isLoggable(System.Logger.Level.DEBUG)) { LOGGER.log(System.Logger.Level.DEBUG, "Loading config bean(s) for " + configuredServiceProvider.serviceType() + " with config: " @@ -331,8 +333,8 @@ void loadConfigBeans(io.helidon.config.Config config, } ConfigValue> nodeList = config.asNodeList(); - Object baseConfigBean = maybeLoadBaseConfigBean(config, nodeList, configuredServiceProvider); - Map mapOfInstanceBasedConfig = maybeLoadConfigBeans(nodeList, configuredServiceProvider); + GCB baseConfigBean = maybeLoadBaseConfigBean(config, nodeList, configuredServiceProvider); + Map mapOfInstanceBasedConfig = maybeLoadConfigBeans(nodeList, configuredServiceProvider); // validate what we've loaded, to ensure it complies to the meta config info policy if (!metaConfigBeanInfo.repeatable() && !mapOfInstanceBasedConfig.isEmpty()) { @@ -357,9 +359,9 @@ void loadConfigBeans(io.helidon.config.Config config, * The base config bean must be a root config, and is only available if there is a non-numeric * key in our node list (e.g., "x.y" not "x.1.y"). */ - CB maybeLoadBaseConfigBean(io.helidon.config.Config config, - ConfigValue> nodeList, - ConfiguredServiceProvider configuredServiceProvider) { + GCB maybeLoadBaseConfigBean(io.helidon.config.Config config, + ConfigValue> nodeList, + ConfiguredServiceProvider configuredServiceProvider) { boolean hasAnyNonNumericNodes = nodeList.get().stream() .anyMatch(cfg -> toNumeric(cfg.name()).isEmpty()); if (!hasAnyNonNumericNodes) { @@ -372,16 +374,17 @@ CB maybeLoadBaseConfigBean(io.helidon.config.Config config, /** * These are any {config}.N instances, not the base w/o the N. */ - Map maybeLoadConfigBeans(ConfigValue> nodeList, - ConfiguredServiceProvider configuredServiceProvider) { - Map result = new LinkedHashMap<>(); + Map maybeLoadConfigBeans( + ConfigValue> nodeList, + ConfiguredServiceProvider configuredServiceProvider) { + Map result = new LinkedHashMap<>(); nodeList.get().stream() .filter(cfg -> toNumeric(cfg.name()).isPresent()) .map(ConfigDrivenUtils::safeDowncastOf) .forEach(cfg -> { String key = cfg.name(); - CB configBean = toConfigBean(cfg, configuredServiceProvider); + GCB configBean = toConfigBean(cfg, configuredServiceProvider); Object prev = result.put(key, configBean); assert (prev == null) : prev + " and " + configBean; }); @@ -389,13 +392,14 @@ Map maybeLoadConfigBeans(ConfigValue CB toConfigBean(io.helidon.config.Config config, - ConfiguredServiceProvider configuredServiceProvider) { - CB configBean = Objects.requireNonNull(configuredServiceProvider.toConfigBean(config), + GCB toConfigBean(io.helidon.config.Config config, + ConfiguredServiceProvider configuredServiceProvider) { + GCB configBean = (GCB) Objects.requireNonNull(configuredServiceProvider.toConfigBean(config), "unable to create default config bean for " + configuredServiceProvider); if (configuredServiceProvider instanceof AbstractConfiguredServiceProvider) { - AbstractConfiguredServiceProvider csp = (AbstractConfiguredServiceProvider) configuredServiceProvider; + AbstractConfiguredServiceProvider csp = (AbstractConfiguredServiceProvider) configuredServiceProvider; csp.configBeanInstanceId(configBean, config.key().toString()); + assert (config.name().equals(configBean.__name().orElseThrow())) : csp; } return configBean; @@ -411,11 +415,11 @@ CB toConfigBean(io.helidon.config.Config config, * @param metaAttributes the meta-attributes that captures the policy in a map like structure by attribute name * @throws PicoServiceProviderException if the provided config bean is not validated according to policy */ - void validate(Object configBean, - String key, - Config config, - AbstractConfiguredServiceProvider csp, - Map> metaAttributes) { + void validate(GCB configBean, + String key, + Config config, + AbstractConfiguredServiceProvider csp, + Map> metaAttributes) { Set problems = new LinkedHashSet<>(); String instanceId = csp.toConfigBeanInstanceId(configBean); assert (hasValue(key)); @@ -474,19 +478,19 @@ public void visit(String attrName, } @SuppressWarnings("unchecked") - void registerConfigBean(Object configBean, - String instanceId, - Config config, - ConfiguredServiceProvider configuredServiceProvider, - Map> metaAttributes) { + void registerConfigBean(GCB configBean, + String instanceId, + Config config, + ConfiguredServiceProvider configuredServiceProvider, + Map> metaAttributes) { assert (configuredServiceProvider instanceof AbstractConfiguredServiceProvider); - AbstractConfiguredServiceProvider csp = - (AbstractConfiguredServiceProvider) configuredServiceProvider; + AbstractConfiguredServiceProvider csp = + (AbstractConfiguredServiceProvider) configuredServiceProvider; if (instanceId != null) { csp.configBeanInstanceId(configBean, instanceId); } else { - instanceId = configuredServiceProvider.toConfigBeanInstanceId((CB) configBean); + instanceId = configuredServiceProvider.toConfigBeanInstanceId((GCB) configBean); } if (DEFAULT_INSTANCE_ID.equals(instanceId)) { @@ -513,7 +517,7 @@ void registerConfigBean(Object configBean, private Set configBeansByConfigKey(String key, Optional optFullConfigKey) { - List> cspsUsingSameKey = + List> cspsUsingSameKey = configuredServiceProvidersByConfigKey.get(Objects.requireNonNull(key)); if (cspsUsingSameKey == null) { return Set.of(); @@ -561,9 +565,10 @@ private void initialize(Config commonCfg) { LOGGER.log(System.Logger.Level.DEBUG, "finishing walking config tree"); } - private void processRootLevelConfigBean(io.helidon.config.Config cfg, - ConfiguredServiceProvider configuredServiceProvider, - MetaConfigBeanInfo metaConfigBeanInfo) { + private void processRootLevelConfigBean( + io.helidon.config.Config cfg, + ConfiguredServiceProvider configuredServiceProvider, + MetaConfigBeanInfo metaConfigBeanInfo) { if (metaConfigBeanInfo.levelType() != ConfigBean.LevelType.ROOT) { return; } @@ -574,14 +579,14 @@ private void processRootLevelConfigBean(io.helidon.config.Config cfg, if (config.exists()) { loadConfigBeans(config, configuredServiceProvider, metaConfigBeanInfo, metaAttributes); } else if (metaConfigBeanInfo.wantDefaultConfigBean()) { - Object cfgBean = Objects.requireNonNull(configuredServiceProvider.toConfigBean(cfg), + GeneratedConfigBean cfgBean = Objects.requireNonNull(configuredServiceProvider.toConfigBean(cfg), "unable to create default config bean for " + configuredServiceProvider); registerConfigBean(cfgBean, DEFAULT_INSTANCE_ID, config, configuredServiceProvider, metaAttributes); } } private void processNestedLevelConfigBean(io.helidon.config.Config config, - ConfiguredServiceProvider configuredServiceProvider, + ConfiguredServiceProvider configuredServiceProvider, ConfigBeanInfo metaConfigBeanInfo) { if (metaConfigBeanInfo.levelType() != ConfigBean.LevelType.NESTED) { return; @@ -597,7 +602,7 @@ private void visitAndInitialize(List configs, // we start nested, since we've already processed the root level config beans previously if (depth > 0) { String key = config.name(); - List> csps = configuredServiceProvidersByConfigKey.get(key); + List> csps = configuredServiceProvidersByConfigKey.get(key); if (csps != null && !csps.isEmpty()) { csps.forEach(configuredServiceProvider -> { ConfigBeanInfo metaConfigBeanInfo = diff --git a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/Async.java b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/Async.java index 9eb2b3356e9..f2529b808c4 100644 --- a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/Async.java +++ b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/Async.java @@ -21,7 +21,7 @@ import jakarta.inject.Inject; @ConfiguredBy(AsyncConfig.class) -class Async { +public class Async { final AsyncConfig cfg; diff --git a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/AsyncConfig.java b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/AsyncConfig.java index fd83af99534..3f951da6d17 100644 --- a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/AsyncConfig.java +++ b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/AsyncConfig.java @@ -21,7 +21,7 @@ import io.helidon.builder.config.ConfigBean; @ConfigBean("ft.asyncs") -interface AsyncConfig { +public interface AsyncConfig { Optional executor(); diff --git a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/BulkheadConfig.java b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/BulkheadConfig.java index b43c550aed7..c70a422ce01 100644 --- a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/BulkheadConfig.java +++ b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/BulkheadConfig.java @@ -19,7 +19,7 @@ import io.helidon.builder.config.ConfigBean; @ConfigBean("ft.bulkheads") -interface BulkheadConfig { +public interface BulkheadConfig { int queue(); diff --git a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/ServerConfig.java b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/ServerConfig.java index ff8697c29b3..2360d6dc502 100644 --- a/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/ServerConfig.java +++ b/pico/configdriven/tests/configuredby/src/main/java/io/helidon/pico/configdriven/configuredby/yaml/test/ServerConfig.java @@ -19,7 +19,7 @@ import io.helidon.builder.config.ConfigBean; @ConfigBean(value = "server", repeatable = false) -interface ServerConfig { +public interface ServerConfig { int port(); diff --git a/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java b/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java index 053ba4afaa8..a85eed602f5 100644 --- a/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java +++ b/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java @@ -16,9 +16,12 @@ package io.helidon.pico.configdriven.configuredby.yaml.test; +import java.util.Collection; +import java.util.Map; import java.util.Optional; import io.helidon.builder.config.spi.ConfigBeanRegistryHolder; +import io.helidon.builder.config.spi.GeneratedConfigBean; import io.helidon.common.testing.junit5.OptionalMatcher; import io.helidon.config.Config; import io.helidon.config.ConfigSources; @@ -77,7 +80,10 @@ void setup() { @Test void namedConfiguredServices() { - System.out.println("here"); + ConfigBeanRegistry cbr = (ConfigBeanRegistry) ConfigBeanRegistryHolder.configBeanRegistry().orElseThrow(); + Map> all = cbr.allConfigBeans(); + + System.out.println(all); } } From 8467b4ee7205751529c83a62a279375ff88c98bb Mon Sep 17 00:00:00 2001 From: Jeff Trent Date: Mon, 24 Apr 2023 11:56:01 -0400 Subject: [PATCH 3/4] disable test --- .../configuredby/yaml/test/NamedConfiguredByTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java b/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java index a85eed602f5..ac5c9efa4dc 100644 --- a/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java +++ b/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java @@ -33,6 +33,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static io.helidon.pico.testing.PicoTestingSupport.resetAll; @@ -78,12 +79,13 @@ void setup() { picoServices.services(); } + @Disabled("Will be addressed in #6674") @Test void namedConfiguredServices() { ConfigBeanRegistry cbr = (ConfigBeanRegistry) ConfigBeanRegistryHolder.configBeanRegistry().orElseThrow(); Map> all = cbr.allConfigBeans(); - System.out.println(all); +// System.out.println(all); } } From d6415d4870bdf2428ea998cc1962c7e384aec2a7 Mon Sep 17 00:00:00 2001 From: Jeff Trent Date: Mon, 24 Apr 2023 12:37:14 -0400 Subject: [PATCH 4/4] tweak a test --- .../configuredby/yaml/test/NamedConfiguredByTest.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java b/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java index ac5c9efa4dc..7ea7485a6d2 100644 --- a/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java +++ b/pico/configdriven/tests/configuredby/src/test/java/io/helidon/pico/configdriven/configuredby/yaml/test/NamedConfiguredByTest.java @@ -40,6 +40,7 @@ import static io.helidon.pico.testing.PicoTestingSupport.testableServices; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; class NamedConfiguredByTest { PicoServices picoServices; @@ -73,10 +74,6 @@ void setup() { .disableEnvironmentVariablesSource() .build(); resetWith(config); - - this.picoServices = PicoServices.picoServices().get(); - // this line is needed! - picoServices.services(); } @Disabled("Will be addressed in #6674") @@ -84,8 +81,8 @@ void setup() { void namedConfiguredServices() { ConfigBeanRegistry cbr = (ConfigBeanRegistry) ConfigBeanRegistryHolder.configBeanRegistry().orElseThrow(); Map> all = cbr.allConfigBeans(); - -// System.out.println(all); + assertThat(all.keySet(), + containsInAnyOrder("ft.asyncs.first", "ft.asyncs.second", "ft.bulkheads", "server")); } }