From e1bc721406085c69f0bea5ee6911d30f9c503238 Mon Sep 17 00:00:00 2001 From: Tomas Langer Date: Sun, 16 Jun 2024 17:55:50 +0200 Subject: [PATCH 1/3] Fixed configuration metadata of protocol configs. Updated generated documentation to latest state of code. --- .../config/io_helidon_webserver_ListenerConfig.adoc | 11 ++++++++++- .../config/io_helidon_webserver_WebServer.adoc | 11 ++++++++++- .../config/io_helidon_webserver_cors_CorsConfig.adoc | 2 +- .../config/io_helidon_webserver_cors_CorsFeature.adoc | 2 +- .../config/io_helidon_webserver_grpc_GrpcConfig.adoc | 10 ++++++++-- .../io_helidon_webserver_http1_Http1Config.adoc | 8 +++++++- .../io_helidon_webserver_http2_Http2Config.adoc | 8 +++++++- .../io_helidon_webserver_websocket_WsConfig.adoc | 8 +++++++- .../helidon/webserver/grpc/GrpcConfigBlueprint.java | 5 +++-- .../helidon/webserver/http2/Http2ConfigBlueprint.java | 5 +++-- .../helidon/webserver/http1/Http1ConfigBlueprint.java | 5 +++-- .../webserver/websocket/WsConfigBlueprint.java | 5 +++-- 12 files changed, 63 insertions(+), 17 deletions(-) diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_ListenerConfig.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_ListenerConfig.adoc index 5ab27735bf5..a77b8f500ba 100644 --- a/docs/src/main/asciidoc/config/io_helidon_webserver_ListenerConfig.adoc +++ b/docs/src/main/asciidoc/config/io_helidon_webserver_ListenerConfig.adoc @@ -110,7 +110,16 @@ Type: link:{javadoc-base-url}/io.helidon.webserver/io/helidon/webserver/Listener If configured to `0` (the default), server starts on a random port. Port to listen on (for the default socket) -|`protocols` |io.helidon.webserver.spi.ProtocolConfig[] (service provider interface) |{nbsp} |Configuration of protocols. This may be either protocol selectors, or protocol upgraders from HTTP/1.1. +|`protocols` |io.helidon.webserver.spi.ProtocolConfig[] (service provider interface) + +Such as: + + - xref:{rootdir}/config/io_helidon_webserver_http2_Http2Config.adoc[http_2 (Http2Config)] + - xref:{rootdir}/config/io_helidon_webserver_grpc_GrpcConfig.adoc[grpc (GrpcConfig)] + - xref:{rootdir}/config/io_helidon_webserver_websocket_WsConfig.adoc[websocket (WsConfig)] + - xref:{rootdir}/config/io_helidon_webserver_http1_Http1Config.adoc[http_1_1 (Http1Config)] + + |{nbsp} |Configuration of protocols. This may be either protocol selectors, or protocol upgraders from HTTP/1.1. As the order is not important (providers are ordered by weight by default), we can use a configuration as an object, such as:
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_WebServer.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_WebServer.adoc
index cd8f542191c..666d8727631 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_WebServer.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_WebServer.adoc
@@ -126,7 +126,16 @@ Such as:
  If configured to `0` (the default), server starts on a random port.
 
  Port to listen on (for the default socket)
-|`protocols` |io.helidon.webserver.spi.ProtocolConfig[] (service provider interface) |{nbsp} |Configuration of protocols. This may be either protocol selectors, or protocol upgraders from HTTP/1.1.
+|`protocols` |io.helidon.webserver.spi.ProtocolConfig[] (service provider interface)
+
+Such as:
+
+ - xref:{rootdir}/config/io_helidon_webserver_http2_Http2Config.adoc[http_2 (Http2Config)]
+ - xref:{rootdir}/config/io_helidon_webserver_grpc_GrpcConfig.adoc[grpc (GrpcConfig)]
+ - xref:{rootdir}/config/io_helidon_webserver_websocket_WsConfig.adoc[websocket (WsConfig)]
+ - xref:{rootdir}/config/io_helidon_webserver_http1_Http1Config.adoc[http_1_1 (Http1Config)]
+
+ |{nbsp} |Configuration of protocols. This may be either protocol selectors, or protocol upgraders from HTTP/1.1.
  As the order is not important (providers are ordered by weight by default), we can use a configuration as an object,
  such as:
  
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_cors_CorsConfig.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_cors_CorsConfig.adoc
index 9531104cc8b..c57c843420d 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_cors_CorsConfig.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_cors_CorsConfig.adoc
@@ -66,7 +66,7 @@ This type provides the following service implementations:
 |`sockets` |string[] |{nbsp} |List of sockets to register this feature on. If empty, it would get registered on all sockets.
 
  Socket names to register on, defaults to empty (all available sockets)
-|`weight` |double |`950.0` |Weight of the CORS feature. As it is used by other features, the default is quite high:
+|`weight` |double |`850.0` |Weight of the CORS feature. As it is used by other features, the default is quite high:
  CorsFeature.WEIGHT.
 
  Weight of the feature
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_cors_CorsFeature.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_cors_CorsFeature.adoc
index 9531104cc8b..c57c843420d 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_cors_CorsFeature.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_cors_CorsFeature.adoc
@@ -66,7 +66,7 @@ This type provides the following service implementations:
 |`sockets` |string[] |{nbsp} |List of sockets to register this feature on. If empty, it would get registered on all sockets.
 
  Socket names to register on, defaults to empty (all available sockets)
-|`weight` |double |`950.0` |Weight of the CORS feature. As it is used by other features, the default is quite high:
+|`weight` |double |`850.0` |Weight of the CORS feature. As it is used by other features, the default is quite high:
  CorsFeature.WEIGHT.
 
  Weight of the feature
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_grpc_GrpcConfig.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_grpc_GrpcConfig.adoc
index 5df77b1b502..87d5f506f09 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_grpc_GrpcConfig.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_grpc_GrpcConfig.adoc
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 
-    Copyright (c) 2023 Oracle and/or its affiliates.
+    Copyright (c) 2023, 2024 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.
@@ -30,10 +30,16 @@ include::{rootdir}/includes/attributes.adoc[]
 Type: link:{javadoc-base-url}/io.helidon.webserver.grpc/io/helidon/webserver/grpc/GrpcConfig.html[io.helidon.webserver.grpc.GrpcConfig]
 
 
+[source,text]
+.Config key
+----
+grpc
+----
+
 
 This type provides the following service implementations:
 
-- `io.helidon.webserver.spi.ProtocolConfig`
+- `io.helidon.webserver.spi.ProtocolConfigProvider`
 
 
 == Configuration options
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_http1_Http1Config.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_http1_Http1Config.adoc
index 7a8b58ea104..a72c8fbf80c 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_http1_Http1Config.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_http1_Http1Config.adoc
@@ -30,10 +30,16 @@ include::{rootdir}/includes/attributes.adoc[]
 Type: link:{javadoc-base-url}/io.helidon.webserver.http1/io/helidon/webserver/http1/Http1Config.html[io.helidon.webserver.http1.Http1Config]
 
 
+[source,text]
+.Config key
+----
+http_1_1
+----
+
 
 This type provides the following service implementations:
 
-- `io.helidon.webserver.spi.ProtocolConfig`
+- `io.helidon.webserver.spi.ProtocolConfigProvider`
 
 
 == Configuration options
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_http2_Http2Config.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_http2_Http2Config.adoc
index c6324a3b995..099e63003e3 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_http2_Http2Config.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_http2_Http2Config.adoc
@@ -30,10 +30,16 @@ include::{rootdir}/includes/attributes.adoc[]
 Type: link:{javadoc-base-url}/io.helidon.webserver.http2/io/helidon/webserver/http2/Http2Config.html[io.helidon.webserver.http2.Http2Config]
 
 
+[source,text]
+.Config key
+----
+http_2
+----
+
 
 This type provides the following service implementations:
 
-- `io.helidon.webserver.spi.ProtocolConfig`
+- `io.helidon.webserver.spi.ProtocolConfigProvider`
 
 
 == Configuration options
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_websocket_WsConfig.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_websocket_WsConfig.adoc
index 884ee43c457..304bd316def 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_websocket_WsConfig.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_websocket_WsConfig.adoc
@@ -30,10 +30,16 @@ include::{rootdir}/includes/attributes.adoc[]
 Type: link:{javadoc-base-url}/io.helidon.webserver.websocket/io/helidon/webserver/websocket/WsConfig.html[io.helidon.webserver.websocket.WsConfig]
 
 
+[source,text]
+.Config key
+----
+websocket
+----
+
 
 This type provides the following service implementations:
 
-- `io.helidon.webserver.spi.ProtocolConfig`
+- `io.helidon.webserver.spi.ProtocolConfigProvider`
 
 
 == Configuration options
diff --git a/webserver/grpc/src/main/java/io/helidon/webserver/grpc/GrpcConfigBlueprint.java b/webserver/grpc/src/main/java/io/helidon/webserver/grpc/GrpcConfigBlueprint.java
index 286a8111bee..0593ee88fad 100644
--- a/webserver/grpc/src/main/java/io/helidon/webserver/grpc/GrpcConfigBlueprint.java
+++ b/webserver/grpc/src/main/java/io/helidon/webserver/grpc/GrpcConfigBlueprint.java
@@ -18,10 +18,11 @@
 
 import io.helidon.builder.api.Prototype;
 import io.helidon.webserver.spi.ProtocolConfig;
+import io.helidon.webserver.spi.ProtocolConfigProvider;
 
 @Prototype.Blueprint
-@Prototype.Configured
-@Prototype.Provides(ProtocolConfig.class)
+@Prototype.Configured(root = false, value = GrpcProtocolProvider.CONFIG_NAME)
+@Prototype.Provides(ProtocolConfigProvider.class)
 interface GrpcConfigBlueprint extends ProtocolConfig {
     /**
      * Protocol configuration type.
diff --git a/webserver/http2/src/main/java/io/helidon/webserver/http2/Http2ConfigBlueprint.java b/webserver/http2/src/main/java/io/helidon/webserver/http2/Http2ConfigBlueprint.java
index b06301dbbdc..d1fe59ed0c0 100644
--- a/webserver/http2/src/main/java/io/helidon/webserver/http2/Http2ConfigBlueprint.java
+++ b/webserver/http2/src/main/java/io/helidon/webserver/http2/Http2ConfigBlueprint.java
@@ -22,13 +22,14 @@
 import io.helidon.builder.api.Prototype;
 import io.helidon.http.RequestedUriDiscoveryContext;
 import io.helidon.webserver.spi.ProtocolConfig;
+import io.helidon.webserver.spi.ProtocolConfigProvider;
 
 /**
  * HTTP/2 server configuration.
  */
 @Prototype.Blueprint(decorator = Http2ConfigBlueprint.Http2ConfigDecorator.class)
-@Prototype.Configured
-@Prototype.Provides(ProtocolConfig.class)
+@Prototype.Configured(root = false, value = Http2ConnectionProvider.CONFIG_NAME)
+@Prototype.Provides(ProtocolConfigProvider.class)
 interface Http2ConfigBlueprint extends ProtocolConfig {
     /**
      * The size of the largest frame payload that the sender is willing to receive in bytes.
diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/http1/Http1ConfigBlueprint.java b/webserver/webserver/src/main/java/io/helidon/webserver/http1/Http1ConfigBlueprint.java
index 93f38aa76bb..f7673a98a2a 100644
--- a/webserver/webserver/src/main/java/io/helidon/webserver/http1/Http1ConfigBlueprint.java
+++ b/webserver/webserver/src/main/java/io/helidon/webserver/http1/Http1ConfigBlueprint.java
@@ -22,13 +22,14 @@
 import io.helidon.builder.api.Prototype;
 import io.helidon.http.RequestedUriDiscoveryContext;
 import io.helidon.webserver.spi.ProtocolConfig;
+import io.helidon.webserver.spi.ProtocolConfigProvider;
 
 /**
  * HTTP/1.1 server configuration.
  */
 @Prototype.Blueprint(decorator = Http1BuilderDecorator.class)
-@Prototype.Configured
-@Prototype.Provides(ProtocolConfig.class)
+@Prototype.Configured(root = false, value = Http1ConnectionProvider.CONFIG_NAME)
+@Prototype.Provides(ProtocolConfigProvider.class)
 interface Http1ConfigBlueprint extends ProtocolConfig {
     /**
      * Name of this configuration, in most cases the same as {@link #type()}.
diff --git a/webserver/websocket/src/main/java/io/helidon/webserver/websocket/WsConfigBlueprint.java b/webserver/websocket/src/main/java/io/helidon/webserver/websocket/WsConfigBlueprint.java
index a354775fc37..29594b146e4 100644
--- a/webserver/websocket/src/main/java/io/helidon/webserver/websocket/WsConfigBlueprint.java
+++ b/webserver/websocket/src/main/java/io/helidon/webserver/websocket/WsConfigBlueprint.java
@@ -21,13 +21,14 @@
 import io.helidon.builder.api.Option;
 import io.helidon.builder.api.Prototype;
 import io.helidon.webserver.spi.ProtocolConfig;
+import io.helidon.webserver.spi.ProtocolConfigProvider;
 
 /**
  * WebSocket protocol configuration.
  */
 @Prototype.Blueprint
-@Prototype.Configured
-@Prototype.Provides(ProtocolConfig.class)
+@Prototype.Configured(root = false, value = WsUpgradeProvider.CONFIG_NAME)
+@Prototype.Provides(ProtocolConfigProvider.class)
 interface WsConfigBlueprint extends ProtocolConfig {
     /**
      * WebSocket origins.

From a4d4b28a5a2e102530661c9294b847d52d0b5de6 Mon Sep 17 00:00:00 2001
From: Tomas Langer 
Date: Sun, 16 Jun 2024 18:37:05 +0200
Subject: [PATCH 2/3] Fixed additional providers blueprints to add config key.
 Added validation of @Provides with @Configured - it must provide a
 configuration key now.

---
 .../java/io/helidon/builder/codegen/Types.java    |  1 +
 .../helidon/builder/codegen/ValidationTask.java   | 15 ++++++++++++++-
 .../io/helidon/builder/codegen/TypesTest.java     |  1 +
 ..._helidon_webserver_observe_ObserveFeature.adoc |  8 ++++----
 ...n_webserver_observe_config_ConfigObserver.adoc |  6 ++++++
 ...lidon_webserver_observe_info_InfoObserver.adoc |  6 ++++++
 ...helidon_webserver_observe_log_LogObserver.adoc |  6 ++++++
 ...webserver_observe_tracing_TracingObserver.adoc |  6 ++++++
 .../config/ConfigObserverConfigBlueprint.java     |  4 ++--
 .../observe/info/InfoObserverConfigBlueprint.java |  4 ++--
 .../observe/log/LogObserverConfigBlueprint.java   |  4 ++--
 webserver/observe/tracing/pom.xml                 |  5 +++++
 .../tracing/TracingObserverConfigBlueprint.java   |  5 +++--
 13 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/builder/codegen/src/main/java/io/helidon/builder/codegen/Types.java b/builder/codegen/src/main/java/io/helidon/builder/codegen/Types.java
index 8a274abb2cb..3fb26ec7436 100644
--- a/builder/codegen/src/main/java/io/helidon/builder/codegen/Types.java
+++ b/builder/codegen/src/main/java/io/helidon/builder/codegen/Types.java
@@ -43,6 +43,7 @@ final class Types {
     static final TypeName PROTOTYPE_ANNOTATED = TypeName.create("io.helidon.builder.api.Prototype.Annotated");
     static final TypeName PROTOTYPE_FACTORY = TypeName.create("io.helidon.builder.api.Prototype.Factory");
     static final TypeName PROTOTYPE_CONFIGURED = TypeName.create("io.helidon.builder.api.Prototype.Configured");
+    static final TypeName PROTOTYPE_PROVIDES = TypeName.create("io.helidon.builder.api.Prototype.Provides");
     static final TypeName PROTOTYPE_BUILDER = TypeName.create("io.helidon.builder.api.Prototype.Builder");
     static final TypeName PROTOTYPE_CONFIGURED_BUILDER = TypeName.create("io.helidon.builder.api.Prototype.ConfiguredBuilder");
     static final TypeName PROTOTYPE_CUSTOM_METHODS = TypeName.create("io.helidon.builder.api.Prototype.CustomMethods");
diff --git a/builder/codegen/src/main/java/io/helidon/builder/codegen/ValidationTask.java b/builder/codegen/src/main/java/io/helidon/builder/codegen/ValidationTask.java
index f0aa71335cb..752b83458bb 100644
--- a/builder/codegen/src/main/java/io/helidon/builder/codegen/ValidationTask.java
+++ b/builder/codegen/src/main/java/io/helidon/builder/codegen/ValidationTask.java
@@ -23,6 +23,7 @@
 import io.helidon.codegen.ElementInfoPredicates;
 import io.helidon.common.Errors;
 import io.helidon.common.types.AccessModifier;
+import io.helidon.common.types.Annotation;
 import io.helidon.common.types.TypeInfo;
 import io.helidon.common.types.TypeName;
 import io.helidon.common.types.TypedElementInfo;
@@ -166,7 +167,19 @@ static class ValidateBlueprint extends ValidationTask {
         public void validate(Errors.Collector errors) {
             // must be package local
             if (blueprint.accessModifier() == AccessModifier.PUBLIC) {
-                errors.fatal(blueprint.typeName().fqName() + " is defined as public, it must be package local");
+                errors.fatal(blueprint.typeName(), blueprint.typeName().fqName() + " is defined as public, it must be package local");
+            }
+
+            // if configured & provides, must have config key
+            if (blueprint.hasAnnotation(Types.PROTOTYPE_CONFIGURED)
+                && blueprint.hasAnnotation(Types.PROTOTYPE_PROVIDES)) {
+                Annotation configured = blueprint.annotation(Types.PROTOTYPE_CONFIGURED);
+                String value = configured.stringValue().orElse("");
+                if (value.isEmpty()) {
+                    // we have a @Configured and @Provides - this should have a configuration key!
+                    errors.fatal(blueprint.typeName(), blueprint.typeName().fqName() + " is marked as @Configured and @Provides, yet it does not"
+                                         + " define a configuration key");
+                }
             }
         }
 
diff --git a/builder/tests/codegen/src/test/java/io/helidon/builder/codegen/TypesTest.java b/builder/tests/codegen/src/test/java/io/helidon/builder/codegen/TypesTest.java
index f5c1d35db9c..f0d2714df0c 100644
--- a/builder/tests/codegen/src/test/java/io/helidon/builder/codegen/TypesTest.java
+++ b/builder/tests/codegen/src/test/java/io/helidon/builder/codegen/TypesTest.java
@@ -94,6 +94,7 @@ void testTypes() {
         checkField(toCheck, checked, fields, "PROTOTYPE_ANNOTATED", Prototype.Annotated.class);
         checkField(toCheck, checked, fields, "PROTOTYPE_FACTORY", Prototype.Factory.class);
         checkField(toCheck, checked, fields, "PROTOTYPE_CONFIGURED", Prototype.Configured.class);
+        checkField(toCheck, checked, fields, "PROTOTYPE_PROVIDES", Prototype.Provides.class);
         checkField(toCheck, checked, fields, "PROTOTYPE_BUILDER", Prototype.Builder.class);
         checkField(toCheck, checked, fields, "PROTOTYPE_CONFIGURED_BUILDER", Prototype.ConfiguredBuilder.class);
         checkField(toCheck, checked, fields, "PROTOTYPE_CUSTOM_METHODS", Prototype.CustomMethods.class);
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_observe_ObserveFeature.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_observe_ObserveFeature.adoc
index 16f38a02e30..2559f02848a 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_observe_ObserveFeature.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_observe_ObserveFeature.adoc
@@ -70,10 +70,10 @@ This type provides the following service implementations:
 
 Such as:
 
- - xref:{rootdir}/config/io_helidon_webserver_observe_log_LogObserver.adoc[LogObserver]
- - xref:{rootdir}/config/io_helidon_webserver_observe_tracing_TracingObserver.adoc[TracingObserver]
- - xref:{rootdir}/config/io_helidon_webserver_observe_config_ConfigObserver.adoc[ConfigObserver]
- - xref:{rootdir}/config/io_helidon_webserver_observe_info_InfoObserver.adoc[InfoObserver]
+ - xref:{rootdir}/config/io_helidon_webserver_observe_log_LogObserver.adoc[log (LogObserver)]
+ - xref:{rootdir}/config/io_helidon_webserver_observe_tracing_TracingObserver.adoc[tracing (TracingObserver)]
+ - xref:{rootdir}/config/io_helidon_webserver_observe_config_ConfigObserver.adoc[config (ConfigObserver)]
+ - xref:{rootdir}/config/io_helidon_webserver_observe_info_InfoObserver.adoc[info (InfoObserver)]
  - xref:{rootdir}/config/io_helidon_webserver_observe_metrics_MetricsObserver.adoc[metrics (MetricsObserver)]
  - xref:{rootdir}/config/io_helidon_webserver_observe_health_HealthObserver.adoc[health (HealthObserver)]
 
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_observe_config_ConfigObserver.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_observe_config_ConfigObserver.adoc
index 43eb920fc73..ed70f806692 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_observe_config_ConfigObserver.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_observe_config_ConfigObserver.adoc
@@ -30,6 +30,12 @@ include::{rootdir}/includes/attributes.adoc[]
 Type: link:{javadoc-base-url}/io.helidon.webserver.observe.config/io/helidon/webserver/observe/config/ConfigObserver.html[io.helidon.webserver.observe.config.ConfigObserver]
 
 
+[source,text]
+.Config key
+----
+config
+----
+
 
 This type provides the following service implementations:
 
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_observe_info_InfoObserver.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_observe_info_InfoObserver.adoc
index 4016a71d1af..e56c148a15a 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_observe_info_InfoObserver.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_observe_info_InfoObserver.adoc
@@ -30,6 +30,12 @@ include::{rootdir}/includes/attributes.adoc[]
 Type: link:{javadoc-base-url}/io.helidon.webserver.observe.info/io/helidon/webserver/observe/info/InfoObserver.html[io.helidon.webserver.observe.info.InfoObserver]
 
 
+[source,text]
+.Config key
+----
+info
+----
+
 
 This type provides the following service implementations:
 
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_observe_log_LogObserver.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_observe_log_LogObserver.adoc
index 69402e92a7e..ff1d897bf07 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_observe_log_LogObserver.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_observe_log_LogObserver.adoc
@@ -30,6 +30,12 @@ include::{rootdir}/includes/attributes.adoc[]
 Type: link:{javadoc-base-url}/io.helidon.webserver.observe.log/io/helidon/webserver/observe/log/LogObserver.html[io.helidon.webserver.observe.log.LogObserver]
 
 
+[source,text]
+.Config key
+----
+log
+----
+
 
 This type provides the following service implementations:
 
diff --git a/docs/src/main/asciidoc/config/io_helidon_webserver_observe_tracing_TracingObserver.adoc b/docs/src/main/asciidoc/config/io_helidon_webserver_observe_tracing_TracingObserver.adoc
index fc0e267850e..feea2ca6abc 100644
--- a/docs/src/main/asciidoc/config/io_helidon_webserver_observe_tracing_TracingObserver.adoc
+++ b/docs/src/main/asciidoc/config/io_helidon_webserver_observe_tracing_TracingObserver.adoc
@@ -30,6 +30,12 @@ include::{rootdir}/includes/attributes.adoc[]
 Type: link:{javadoc-base-url}/io.helidon.webserver.observe.tracing/io/helidon/webserver/observe/tracing/TracingObserver.html[io.helidon.webserver.observe.tracing.TracingObserver]
 
 
+[source,text]
+.Config key
+----
+tracing
+----
+
 
 This type provides the following service implementations:
 
diff --git a/webserver/observe/config/src/main/java/io/helidon/webserver/observe/config/ConfigObserverConfigBlueprint.java b/webserver/observe/config/src/main/java/io/helidon/webserver/observe/config/ConfigObserverConfigBlueprint.java
index 4c1f15c3bf1..32bf09fba46 100644
--- a/webserver/observe/config/src/main/java/io/helidon/webserver/observe/config/ConfigObserverConfigBlueprint.java
+++ b/webserver/observe/config/src/main/java/io/helidon/webserver/observe/config/ConfigObserverConfigBlueprint.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Oracle and/or its affiliates.
+ * Copyright (c) 2023, 2024 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.
@@ -24,7 +24,7 @@
 import io.helidon.webserver.observe.spi.ObserveProvider;
 
 @Prototype.Blueprint
-@Prototype.Configured
+@Prototype.Configured(root = false, value = "config")
 @Prototype.Provides(ObserveProvider.class)
 interface ConfigObserverConfigBlueprint extends ObserverConfigBase, Prototype.Factory {
     @Option.Configured
diff --git a/webserver/observe/info/src/main/java/io/helidon/webserver/observe/info/InfoObserverConfigBlueprint.java b/webserver/observe/info/src/main/java/io/helidon/webserver/observe/info/InfoObserverConfigBlueprint.java
index f6f8a2f4e70..7f66920251d 100644
--- a/webserver/observe/info/src/main/java/io/helidon/webserver/observe/info/InfoObserverConfigBlueprint.java
+++ b/webserver/observe/info/src/main/java/io/helidon/webserver/observe/info/InfoObserverConfigBlueprint.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Oracle and/or its affiliates.
+ * Copyright (c) 2023, 2024 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.
@@ -27,7 +27,7 @@
  * Info Observer configuration.
  */
 @Prototype.Blueprint
-@Prototype.Configured
+@Prototype.Configured(root = false, value = "info")
 @Prototype.Provides(ObserveProvider.class)
 interface InfoObserverConfigBlueprint extends ObserverConfigBase, Prototype.Factory {
     @Option.Configured
diff --git a/webserver/observe/log/src/main/java/io/helidon/webserver/observe/log/LogObserverConfigBlueprint.java b/webserver/observe/log/src/main/java/io/helidon/webserver/observe/log/LogObserverConfigBlueprint.java
index b91a384eab1..fbb689e849d 100644
--- a/webserver/observe/log/src/main/java/io/helidon/webserver/observe/log/LogObserverConfigBlueprint.java
+++ b/webserver/observe/log/src/main/java/io/helidon/webserver/observe/log/LogObserverConfigBlueprint.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Oracle and/or its affiliates.
+ * Copyright (c) 2023, 2024 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.
@@ -25,7 +25,7 @@
  * Log Observer configuration.
  */
 @Prototype.Blueprint
-@Prototype.Configured
+@Prototype.Configured(root = false, value = "log")
 @Prototype.Provides(ObserveProvider.class)
 interface LogObserverConfigBlueprint extends ObserverConfigBase, Prototype.Factory {
     @Option.Configured
diff --git a/webserver/observe/tracing/pom.xml b/webserver/observe/tracing/pom.xml
index 355ea4a973e..283e5266bce 100644
--- a/webserver/observe/tracing/pom.xml
+++ b/webserver/observe/tracing/pom.xml
@@ -50,6 +50,11 @@
             helidon-common-features-api
             true
         
+        
+            io.helidon.config
+            helidon-config-metadata
+            true
+        
         
             io.helidon.webserver.testing.junit5
             helidon-webserver-testing-junit5
diff --git a/webserver/observe/tracing/src/main/java/io/helidon/webserver/observe/tracing/TracingObserverConfigBlueprint.java b/webserver/observe/tracing/src/main/java/io/helidon/webserver/observe/tracing/TracingObserverConfigBlueprint.java
index b2f1c5cef64..b7d3a3ba084 100644
--- a/webserver/observe/tracing/src/main/java/io/helidon/webserver/observe/tracing/TracingObserverConfigBlueprint.java
+++ b/webserver/observe/tracing/src/main/java/io/helidon/webserver/observe/tracing/TracingObserverConfigBlueprint.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Oracle and/or its affiliates.
+ * Copyright (c) 2023, 2024 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.
@@ -33,7 +33,7 @@
  * @see io.helidon.webserver.observe.tracing.TracingObserver#builder()
  */
 @Prototype.Blueprint(decorator = TracingObserverSupport.TracingObserverDecorator.class)
-@Prototype.Configured
+@Prototype.Configured(root = false, value = "tracing")
 @Prototype.Provides(ObserveProvider.class)
 interface TracingObserverConfigBlueprint extends ObserverConfigBase, Prototype.Factory {
     @Option.Default("tracing")
@@ -60,6 +60,7 @@ interface TracingObserverConfigBlueprint extends ObserverConfigBase, Prototype.F
      *
      * By default we disable both the SE-style paths ({@code /observe/health}) and the MP-style paths ({@code /health}).
      */
+
     /**
      * Path specific configuration of tracing.
      *

From 593674a713e783541569f2523b47f77ecc8fb574 Mon Sep 17 00:00:00 2001
From: Tomas Langer 
Date: Sun, 16 Jun 2024 23:01:41 +0200
Subject: [PATCH 3/3] Checkstyle fix Validation errors now contain source type
 for better error messages.

---
 .../helidon/builder/codegen/ValidationTask.java   | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/builder/codegen/src/main/java/io/helidon/builder/codegen/ValidationTask.java b/builder/codegen/src/main/java/io/helidon/builder/codegen/ValidationTask.java
index 752b83458bb..f9ff370e4a1 100644
--- a/builder/codegen/src/main/java/io/helidon/builder/codegen/ValidationTask.java
+++ b/builder/codegen/src/main/java/io/helidon/builder/codegen/ValidationTask.java
@@ -42,7 +42,7 @@ private static void validateImplements(Errors.Collector errors,
         if (validatedType.interfaceTypeInfo()
                 .stream()
                 .noneMatch(it -> it.typeName().equals(implementedInterface))) {
-            errors.fatal(message);
+            errors.fatal(validatedType.typeName(), message);
         }
     }
 
@@ -71,7 +71,7 @@ private static void validateFactoryMethod(Errors.Collector errors,
                 })
                 .findFirst()
                 .isEmpty()) {
-            errors.fatal(validatedType.typeName().fqName(), message);
+            errors.fatal(validatedType.typeName(), message);
         }
     }
 
@@ -167,7 +167,8 @@ static class ValidateBlueprint extends ValidationTask {
         public void validate(Errors.Collector errors) {
             // must be package local
             if (blueprint.accessModifier() == AccessModifier.PUBLIC) {
-                errors.fatal(blueprint.typeName(), blueprint.typeName().fqName() + " is defined as public, it must be package local");
+                errors.fatal(blueprint.typeName(), blueprint.typeName().fqName()
+                        + " is defined as public, it must be package local");
             }
 
             // if configured & provides, must have config key
@@ -177,7 +178,8 @@ public void validate(Errors.Collector errors) {
                 String value = configured.stringValue().orElse("");
                 if (value.isEmpty()) {
                     // we have a @Configured and @Provides - this should have a configuration key!
-                    errors.fatal(blueprint.typeName(), blueprint.typeName().fqName() + " is marked as @Configured and @Provides, yet it does not"
+                    errors.fatal(blueprint.typeName(), blueprint.typeName().fqName()
+                            + " is marked as @Configured and @Provides, yet it does not"
                                          + " define a configuration key");
                 }
             }
@@ -289,8 +291,9 @@ void validate(Errors.Collector errors) {
             if (typeInfo.findAnnotation(annotation)
                     .stream()
                     .noneMatch(it -> it.value().map(expectedValue::equals).orElse(false))) {
-                errors.fatal("Type " + typeInfo.typeName()
-                        .fqName() + " must be annotated with " + annotation.fqName() + "(" + expectedValue + ")");
+                errors.fatal(typeInfo.typeName(),
+                             "Type " + typeInfo.typeName().fqName()
+                                     + " must be annotated with " + annotation.fqName() + "(" + expectedValue + ")");
             }
         }
     }