diff --git a/api/src/main/java/javax/config/ComposedConfig.java b/api/src/main/java/javax/config/ComposedConfig.java
new file mode 100644
index 0000000..e67bc98
--- /dev/null
+++ b/api/src/main/java/javax/config/ComposedConfig.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2016-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * 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 javax.config;
+
+import javax.config.inject.ConfigProperty;
+import javax.enterprise.util.Nonbinding;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.concurrent.TimeUnit;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Specifies a configuration type as composed configuration.
+ * Composed configuration types comprise multiple, potentially hierarchical, configuration values.
+ *
+ *
Examples
+ *
+ * Composed, coherent configuration
+ *
+ * The following example defines a coherent server socket configuration.
+ *
+ *
+ * @ComposedConfig
+ * public class SocketConfig {
+ *
+ * @ConfigProperty(name = "name")
+ * private String name;
+ *
+ * @ConfigProperty(name = "protocol", defaultValue = "http")
+ * private String protocolName;
+ *
+ * @ConfigProperty(name = "port")
+ * private int port;
+ *
+ * // getters & setters
+ * }
+ *
+ *
+ * The {@code SocketConfig} configuration can be retrieved like any other configured value, by programmatic lookup, or dependency injection:
+ *
+ *
+ * public class SomeBean {
+ *
+ * @Inject
+ * @ConfigProperty(name = "server.socket")
+ * private SocketConfig socketConfig;
+ *
+ * }
+ *
+ *
+ * The example will resolve the configuration values as follows, provided by the corresponding property keys:
+ *
+ *
+ * server.socket.name
+ * server.socket.protocol
+ * server.socket.port
+ *
+ *
+ * Implicit property resolution
+ *
+ * It's possible to omit the individual {@link ConfigProperty} annotations on the fields of the composed type.
+ * In this case the composed property keys are derived from the field names:
+ *
+ *
+ *
+ * public class SomeBean {
+ *
+ * @Inject
+ * @ConfigProperty(name = "server.socket")
+ * private SocketConfig socketConfig;
+ *
+ * @ComposedConfig
+ * public static class SocketConfig {
+ *
+ * private String name;
+ * private String protocol;
+ * private int port;
+ *
+ * // getters & setters
+ * }
+ * }
+ *
+ *
+ *
+ * This example will result in the same configuration resolution as in the previous example, apart from the default value for {@code server.socket.protocol}.
+ *
+ * If the property keys differ from the field names, they can be overridden individually via the {@link ConfigProperty} annotation.
+ * The same is true for default values, as seen before.
+ *
+ * The {@link ConfigProperty} annotation can be annotated on fields as well as on methods.
+ * The latter is useful if interfaces instead of classes are defined as composed types.
+ * Per default, methods are not implicitly taken to resolve composed configuration properties.
+ * If both fields and methods are annotated within a single type, methods take precedence.
+ *
+ * See the following example for a composed interface configuration type.
+ *
+ *
+ *
+ * @ComposedConfig
+ * public interface SocketConfig {
+ *
+ * @ConfigProperty(name = "name")
+ * String name();
+ *
+ * @ConfigProperty(name = "protocol", defaultValue = "http")
+ * String protocolName();
+ *
+ * @ConfigProperty(name = "port")
+ * int getPort();
+ * }
+ *
+ *
+ * This example will result in the same configuration as before.
+ *
+ *
Hierarchical type resolution
+ *
+ * The configuration properties of composed types are resolved hierarchically.
+ * That is, properties in composed types are implicitly considered as possible composed types themselves, as well.
+ * This allows developers to define complex configuration structures without repeating annotations.
+ *
+ * The types of composed properties are therefore resolved as possible composed configuration types, if no built-in, custom, or implicit converters are defined.
+ *
+ * The hierarchical resolution works both for implicitly resolved fields and explicitly annotated members.
+ *
+ *
+ * @ComposedConfig
+ * public class ServerConfig {
+ *
+ * private String host;
+ * private SocketConfig socket;
+ *
+ * // getters & setters
+ *
+ * public static class SocketConfig {
+ * private String name;
+ * private String protocol;
+ * private int port;
+ *
+ * // getters & setters
+ * }
+ *
+ * }
+ *
+ *
+ * If a {@code ServerConfig} configuration type is retrieved, the property keys are resolved as follows:
+ *
+ *
+ * public class SomeBean {
+ *
+ * @Inject
+ * @ConfigProperty(name = "server")
+ * private ServerConfig serverConfig;
+ *
+ * }
+ *
+ *
+ * This leads to:
+ *
+ *
+ * server.host
+ * server.socket.name
+ * server.socket.protocol
+ * server.socket.port
+ *
+ *
+ * The property keys are resolved by the field names, or the names defined in {@link ConfigProperty}, respectively, and combined via dot ({@code .}).
+ *
+ * The example above is congruent with annotating {@code SocketConfig} with {@link ComposedConfig}, as well.
+ *
+ *
Collection resolution
+ *
+ * Composed configuration types also resolve collections and array types.
+ *
+ *
+ * @ComposedConfig
+ * public class MultiSocketServerConfig {
+ *
+ * private String[] hosts;
+ * private List sockets;
+ *
+ * // getters & setters
+ *
+ * public static class SocketConfig {
+ * private String name;
+ * private String protocol;
+ * private int port;
+ *
+ * // getters & setters
+ * }
+ *
+ * }
+ *
+ *
+ * If the {@code MultiSocketServerConfig} type is resolved by key {@code alternative-server}, it results in the following:
+ *
+ *
+ * server.hosts.0
+ * server.hosts.1
+ *
+ * server.sockets.0.name
+ * server.sockets.0.protocol
+ * server.sockets.1.name
+ *
+ *
+ * Element types of collections and arrays are resolved by an implicit zero-based index, which is part of the resulting, combined property key.
+ *
+ * This collection resolution works for array types, and types that are assignable to {@link java.util.Collection}.
+ * For unordered collection types, e.g. {@link java.util.Set}, the order in which the configured elements will be retrieved is non-deterministic, despite the (zero-based) indexed key names.
+ *
+ * Similar to singular sub-types, the element types within the collection or array are resolved by potentially existent converters, and resolved recursively if no built-in, custom, or implicit converters are defined.
+ *
+ * @author Sebastian Daschner
+ */
+@Retention(RUNTIME)
+@Target(TYPE)
+public @interface ComposedConfig {
+
+ /**
+ * Only valid for injection of dynamically readable values, e.g. {@code Provider}!
+ *
+ * @return {@code TimeUnit} for {@link #cacheFor()}
+ */
+ @Nonbinding
+ TimeUnit cacheTimeUnit() default TimeUnit.SECONDS;
+
+ /**
+ * Only valid for injection of dynamically readable values, e.g. {@code Provider}!
+ *
+ * @return how long should dynamic values be locally cached. Measured in {@link #cacheTimeUnit()}.
+ */
+ @Nonbinding
+ long cacheFor() default 0L;
+}
diff --git a/spec/src/main/asciidoc/composed-configuration.adoc b/spec/src/main/asciidoc/composed-configuration.adoc
new file mode 100644
index 0000000..321e5e7
--- /dev/null
+++ b/spec/src/main/asciidoc/composed-configuration.adoc
@@ -0,0 +1,375 @@
+//
+// Copyright (c) 2016-2018 Contributors to the Eclipse Foundation
+//
+// See the NOTICE file(s) distributed with this work for additional
+// information regarding copyright ownership.
+//
+// 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.
+// Contributors:
+// Sebastian Daschner
+
+[[composed-configuration]]
+== Composed Configuration
+
+Developers can specify composed configuration types in order to define multiple, coherent configuration values, and access them conveniently and consistently.
+Composed configuration types, which are annotated with `@ComposedConfig`, comprise multiple, potentially hierarchical, configuration values.
+
+=== Usage
+
+See the following example that defines a coherent server socket configuration.
+
+[source,java]
+----
+@ComposedConfig
+public class SocketConfig {
+
+ @ConfigProperty(name = "name")
+ private String name;
+
+ @ConfigProperty(name = "protocol", defaultValue = "http")
+ private String protocolName;
+
+ @ConfigProperty(name = "port")
+ private int port;
+
+ // getters & setters
+}
+----
+
+The `SocketConfig` configuration can be retrieved like any other configured value, by programmatic lookup, or dependency injection:
+
+[source,java]
+----
+public class SomeBean {
+
+ @Inject
+ @ConfigProperty(name = "server.socket")
+ private SocketConfig socketConfig;
+
+}
+----
+
+The example will resolve the configuration values as follows, provided by the corresponding property keys:
+
+[source,text]
+----
+socketConfig.getName() -> server.socket.name
+socketConfig.getProtocolName() -> server.socket.protocol (or "http" if undefined)
+socketConfig.getPort() -> server.socket.port
+----
+
+
+==== Implicit Property Resolution
+
+It's possible to omit the individual `@ConfigProperty` annotations on the fields of the composed type.
+In this case the composed property keys are derived from the field names:
+
+[source,java]
+----
+public class SomeBean {
+
+ @Inject
+ @ConfigProperty(name = "server.socket")
+ private SocketConfig socketConfig;
+
+ @ComposedConfig
+ public static class SocketConfig {
+
+ private String name;
+ private String protocol;
+ private int port;
+
+ // getters & setters
+ }
+}
+----
+
+This example will result in the same configuration resolution as in the previous example, apart from the default value (`http`) for `server.socket.protocol`.
+
+If the property keys differ from the field names, they can be overridden individually via the `@ConfigProperty` annotation.
+The same is true for default values, as seen before.
+
+The `@ConfigProperty` annotation can be annotated on fields as well as on methods.
+The latter is useful if interfaces instead of classes are defined as composed types.
+Per default, methods are not implicitly taken to resolve composed configuration properties.
+If both fields and methods are annotated within a single type, methods take precedence.
+
+See the following example for a composed interface configuration type.
+
+[source,java]
+----
+@ComposedConfig
+public interface SocketConfig {
+
+ @ConfigProperty(name = "name")
+ String name();
+
+ @ConfigProperty(name = "protocol", defaultValue = "http")
+ String protocolName();
+
+ @ConfigProperty(name = "port")
+ int getPort();
+}
+----
+
+Again, this example will result in the same configuration as before.
+
+
+==== Hierarchical Type Resolution
+
+The configuration properties of composed types are resolved hierarchically.
+That is, properties in composed types are implicitly considered as possible composed types themselves, as well.
+This allows developers to define complex configuration structures without repeating annotations.
+
+The types of composed properties are therefore resolved as possible composed configuration types, if no built-in, custom, or implicit converters are defined.
+
+The hierarchical resolution works both for implicitly resolved fields and explicitly annotated members.
+
+[source,java]
+----
+@ComposedConfig
+public class ServerConfig {
+
+ private String host;
+ private SocketConfig socket;
+
+ // getters & setters
+
+ public static class SocketConfig {
+ private String name;
+ private String protocol;
+ private int port;
+
+ // getters & setters
+ }
+
+}
+----
+
+If a `ServerConfig` configuration type is retrieved, the property keys are resolved as follows:
+
+[source,java]
+----
+public class SomeBean {
+
+ @Inject
+ @ConfigProperty(name = "server")
+ private ServerConfig serverConfig;
+
+}
+----
+
+This leads to:
+
+[source,text]
+----
+serverConfig.getHost() -> server.host
+serverConfig.getSocket().getName() -> server.socket.name
+serverConfig.getSocket().getProtocol() -> server.socket.protocol
+serverConfig.getSocket().getPort() -> server.socket.port
+----
+
+The property keys are resolved by the field names, or the names defined in `@ConfigProperty`, respectively, and combined via dot (`.`).
+
+The example above is congruent with annotating `SocketConfig` with `@ComposedConfig`, as well.
+
+
+==== Collection Resolution
+
+Composed configuration types also resolve collections and array types.
+
+[source,java]
+----
+@ComposedConfig
+public class MultiSocketServerConfig {
+
+ private String[] hosts;
+ private List sockets;
+
+ // getters & setters
+
+ public static class SocketConfig {
+ private String name;
+ private String protocol;
+ private int port;
+
+ // getters & setters
+ }
+
+}
+----
+
+If the `MultiSocketServerConfig` type is resolved by key `alternative-server`, it results in the following:
+
+[source,text]
+----
+serverConfig.getHosts()[0] -> server.hosts.0
+serverConfig.getHosts()[1] -> server.hosts.1
+...
+serverConfig.getSockets().get(0).getName() -> server.sockets.0.name
+serverConfig.getSockets().get(0).getProtocol() -> server.sockets.0.protocol
+serverConfig.getSockets().get(1).getName() -> server.sockets.1.name
+...
+----
+
+Element types of collections and arrays are resolved by an implicit zero-based index, which is part of the resulting, combined property key.
+
+This collection resolution works for array types, and types that are assignable to `java.util.Collection`.
+For unordered collection types, e.g. `java.util.Set`, the order in which the configured elements will be retrieved is non-deterministic, despite the (zero-based) indexed key names.
+
+Similar to singular sub-types, the element types within the collection or array are resolved by potentially existent converters, and resolved recursively if no built-in, custom, or implicit converters are defined.
+
+[[resolution]]
+=== Resolution
+
+The following examines how the resolution for composed configuration values works.
+This information is particularly interesting for implementors.
+
+1. The `Config` implementation detects whether the type of a retrieved configuration value is a composed configuration.
+This is handled equally, whether the configuration is retrieved programmatically, or via dependency injection.
+The configuration value type is considered a composed type if the type definition is annotated with `@ComposedConfig`.
+
+2. The retrieval of a composed value MUST be performed by a single config source at a time, in order of their defined priority.
+Due to the potential hierarchical nature of composed configuration, the individual sources must define coherent configuration compositions.
+Defining multiple parts of composed values in multiple config sources is not supported.
+The config sources will override the whole composition of a composed configuration value individually.
+
+3. The individual, potentially hierarchical properties are resolved by the implementation by inspecting the composed configuration type definition.
+The following order MUST be followed, while subsequent, colliding definitions might override the resolved field names.
+ - every non-static, non-final field that is not annotated with `@ConfigProperty`, with its declared field name as key suffix and field type as configured property type
+ - every non-static, non-final field that is annotated with `@ConfigProperty`, with the specified name as key suffix, optional default value and field type as configured property type
+ - every non-static, non-void method that is annotated with `@ConfigProperty`, with the specified name as key suffix, optional default value and method return type as configured property type
+
+4. The resolved properties are looked-up via the config source following the same mechanism as for any other configuration values, except the constraints mentioned in steps 5. and 6.
+The configured keys used lookup the configuration values are concatenated as follows:
+ - the keys of all config properties in the hierarchy of the composed configuration value (see step 5.), individually joined by a dot (`.`)
+ - the key suffix derived from the defined property
+For example, a composed configuration `serverConfig` with lookup key `server`, and property `socket` with identical implicit property key (`socket`), and property `name` with identical implicit property key (`name`) will be resolved as property key `server.socket.name`.
+
+5. Properties within the composed type are themselves resolved and inspected for composed types.
+Unlike general configuration lookup, configured property types are considered as composed types, if no built-in, custom, or implicit converter is defined for them.
+If no build-in, custom, or implicit converter could be resolved by the implementation, following the corresponding priorities, the configured type is considered a composed configuration and resolution is performed recursively, starting from step 3.
+To ensure configuration consistency, implementations MUST resolve hierarchical sub-types using a single config source throughout the whole hierarchy for a single (root) composed configuration.
+Unlike conventional configuration lookup, configured properties contained in composed types do not cause an error in case single configured properties are undefined (i.e. the computed property key doesn't lead to a configured value) in the config source,
+In case a configured property is not defined, the value of the corresponding field is the default primitive value (e.g. `0` for `int`, `false` for `boolean`), `null` for reference types, `Optional.EMPTY` for `java.util.Optional` types, an empty array, or an empty collection of the corresponding collection type, respectively, depending on the property type.
+In order to notify users of JSR 382 about configuration mismatches implementations SHOULD emit a warning if none of the resolved properties could be resolved within a (root) composed configuration value.
+
+6. Properties within the composed type are themselves resolved and inspected for collection types.
+Following types are considered collection types:
+ - array types
+ - types assignable to `java.util.Collection`
+The configured type comprised in the collection type are resolved recursively within the same config source.
+Configured types are resolved as configuration values using built-in, custom, or implicit converters with their defined priority, or considered as composed types, if no built-in, custom, or implicit converter is defined for them.
+The property keys of configured collection types are computed as follows:
+ - the property key of the collection type itself is computed following the rules described in step 4.
+ - every element of the collection is indexed with a zero-based integer index, which is concatenated separated by a dot (`.`).
+For example, a collection type configuration `socketNames` of type `List` with property key `socket-names`, within a composed configuration type `server` with identical property key will be resolved as property keys `server.socket-names.0`, `server.socket-names.1`, etc.
+Types within the collection that are themselves composed types compute their properties starting from the property key of the collection type and following the rules described in step 4.
+Collection types that are not explicitly ordered compute the property keys following the same rules with non-deterministic ordering of the elements.
+To ensure configuration consistency, implementations MUST resolve collection sub-types using a single config source throughout the whole hierarchy for a single (root) composed configuration.
+
+
+=== Relationship to CDI Beans
+
+In order to define multiple, coherent configuration values conveniently, it's possible to inject conventional CDI scoped beans that themselves define configuration properties, without regarding composed configuration values.
+An example looks as follows:
+
+[source,java]
+----
+public class SomeBean {
+
+ @Inject
+ private SocketConfig socketConfig;
+
+}
+----
+
+The `SomeBean` injects the dependent-scoped bean which comprised the coherent configuration values.
+
+[source,java]
+----
+public class SocketConfig {
+
+ @Inject
+ @ConfigProperty(name = "server.socket.name")
+ private String name;
+
+ @Inject
+ @ConfigProperty(name = "server.socket.protocol", defaultValue = "http")
+ private String protocolName;
+
+ @Inject
+ @ConfigProperty(name = "server.socket.port")
+ private int port;
+
+ // accessor methods
+}
+----
+
+This usage doesn't require composed configuration values.
+
+Developers might want to prefer to use composed configuration values in the following cases:
+ - complex hierarchies of configuration values must be realized
+ - collection types are used within the composed configuration hierarchy
+ - leaner syntax is preferred (possibility to omit `@Inject` and `@ConfigProperty` annotations
+ - duplication of configuration property key prefixes (e.g. `server.socket` should be avoided
+ - interface types should be used to define composed configuration types
+ - composed configuration types are defined by a third-party, or being reused, and thus can't or shouldn't be annotated with JSR 382 annotations
+
+
+=== Hierarchical Configuration File Formats
+
+Config sources that are backed by file format with a hierarchical structure, such as XML, JSON, or YAML, SHOULD resolve the individual properties following the same rules as described in steps 4. and 6. of <> in order to end up with the same hierarchical semantics of the property keys.
+
+The following example illustrates this recommendation for a hypothetical config source that resolves YAML configuration files.
+
+Given the following YAML configuration structure:
+
+[source,yaml]
+----
+server:
+ name: pet-1
+ hosts:
+ - "foo.example.com"
+ - "bar.example.com"
+ sockets:
+ - name: http-default
+ protocol: http
+ port: 80
+ - name: https-default
+ protocol: https
+ port: 443
+----
+
+The YAML structure SHOULD result in configuration properties that are congruent with the following properties file definition:
+
+[source,text]
+----
+server.name=pet-1
+server.hosts.0=foo.example.com
+server.hosts.1=bar.example.com
+
+server.sockets.0.name=http-default
+server.sockets.0.protocol=http
+server.sockets.0.port=80
+
+server.sockets.1.name=https-default
+server.sockets.1.protocol=https
+server.sockets.1.port=443
+----
+
+
+=== Decisions & Considerations (for EG members, to be removed)
+- No prefix attribute added on `@ComposedConfig`, since it arguable doesn't provide much benefits. The injection point has to specify some property name anyway. Discussed on 2018-09-06.
+- Starting with supporting to annotate `@ComposedConfig` on types only, i.e. no qualifier and no annotation on the injection point. Discussed on 2018-09-06.
+- The programmatic `ConfigAccessor` API doesn't require a specific method (such as `composed()`), since the resolution currently requires the composed type to be annotated with `@ComposedConfig`.
diff --git a/spec/src/main/asciidoc/javaconfig-spec.asciidoc b/spec/src/main/asciidoc/javaconfig-spec.asciidoc
index 49cb0a2..0075d05 100644
--- a/spec/src/main/asciidoc/javaconfig-spec.asciidoc
+++ b/spec/src/main/asciidoc/javaconfig-spec.asciidoc
@@ -48,3 +48,4 @@ include::converters.asciidoc[]
include::configaccessor.asciidoc[]
+include::composed-configuration.asciidoc[]