Skip to content

Commit

Permalink
Empty value handling - rebase from eclipse#541
Browse files Browse the repository at this point in the history
Signed-off-by: Emily Jiang <emijiang6@googlemail.com>
  • Loading branch information
Emily-Jiang committed Sep 11, 2020
1 parent 50bc9d9 commit 573a98b
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 18 deletions.
31 changes: 20 additions & 11 deletions api/src/main/java/org/eclipse/microprofile/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@
* Additional reviews and feedback by Tomas Langer.
*/
package org.eclipse.microprofile.config;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.lang.reflect.Array;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

import org.eclipse.microprofile.config.spi.ConfigSource;
import org.eclipse.microprofile.config.spi.Converter;


/**
* Resolves the property value by searching through all configured {@link ConfigSource ConfigSources}. If the same
* property is specified in multiple {@link ConfigSource ConfigSources}, the value in the {@link ConfigSource} with the
Expand Down Expand Up @@ -99,15 +100,22 @@ public interface Config {
* The configuration value is not guaranteed to be cached by the implementation, and may be expensive
* to compute; therefore, if the returned value is intended to be frequently used, callers should consider storing
* rather than recomputing it.
* <p>
* The result of this method is identical to the result of calling {@code getOptionalValue(propertyName, propertyType).get()}.
* In particular, if the value element of the given property name does not exist, a {@link NoSuchElementException} is thrown.
* This method never returns {@code null}.
*
* @param <T> The property type
* @param propertyName The configuration property name
* @param propertyType The type into which the resolved property value should get converted
* @return the resolved property value as an instance of the requested type
* @throws java.lang.IllegalArgumentException if the property cannot be converted to the specified type
* @throws java.util.NoSuchElementException if the property isn't present in the configuration
* @param <T>
* The property type
* @param propertyName
* The configuration property name
* @param propertyType
* The type into which the resolved property value should get converted
* @return the resolved property value as an instance of the requested type (not {@code null})
* @throws IllegalArgumentException if the property cannot be converted to the specified type
* @throws NoSuchElementException if the property does not exist
*/
<T> T getValue(String propertyName, Class<T> propertyType);
<T> T getValue(String propertyName, Class<T> propertyType) throws IllegalArgumentException, NoSuchElementException;

/**
* Return the {@link ConfigValue} for the specified property name from the underlying
Expand Down Expand Up @@ -162,9 +170,10 @@ default <T> List<T> getValues(String propertyName, Class<T> propertyType) {
* @param propertyName The configuration property name
* @param propertyType The type into which the resolved property value should be converted
* @return The resolved property value as an {@code Optional} wrapping the requested type
* @throws java.lang.IllegalArgumentException if the property cannot be converted to the specified type
*
* @throws IllegalArgumentException if the property cannot be converted to the specified type
*/
<T> Optional<T> getOptionalValue(String propertyName, Class<T> propertyType);
<T> Optional<T> getOptionalValue(String propertyName, Class<T> propertyType) throws IllegalArgumentException;

/**
* Return the resolved property values with the specified type for the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,29 @@
* All <em>built in</em> Converters have a priority value of {@code 1}. <em>Implicit</em> converters are only created
* when no other converter was found; therefore, they do not have a priority.
*
* <h3 id="empty">Empty values</h3>
*
* For all converters, the empty string {@code ""} <em>must</em> be considered an empty value. Some converters <em>may</em>
* consider other values to be empty as well.
* <p>
* When a conversion results in an empty value, most converters should normally return {@code null}. All of the built-in
* converters <em>must</em> return {@code null} for an empty value, <em>except</em> for the built-in converters for
* {@code OptionalInt}, {@code OptionalLong}, and {@code OptionalDouble}, which <em>must</em> return their corresponding
* {@code empty()} value for an empty input.
* <p>
* Implementations <em>may</em> (but are not required to) implement {@code Config.getOptionalValue()} using a
* {@code Converter}. If so, this converter <em>must</em> return {@code Optional.empty()} for an empty input.
*
* <h3>Array conversion</h3>
*
* <p>
* A conforming implementation must support the automatic creation of an <em>implicit</em> converter for array types.
* This converter uses a comma ({@code U+002C ','}) as a delimiter. To allow a comma to be embedded within individual
* array element values, it may be escaped using a backslash ({@code U+005C '\'}) character. Any escaped comma
* character will be included as a plain comma within the single element (the backslash is discarded by the converter).
* This converter uses a comma ({@code U+002C ','}) as a delimiter. To allow a comma to be embedded within individual
* array element values, it may be escaped using a backslash ({@code U+005C '\'}) character. Any escaped comma character
* will be included as a plain comma within the single element (the backslash is discarded by the converter).
* <p>
* Empty elements <em>must</em> not be included in the final array. An array which would consist of only empty values
* <em>must</em> be considered empty; the array converter <em>must</em> return {@code null} in this case.
*
* @author <a href="mailto:rsmeral@apache.org">Ron Smeral</a>
* @author <a href="mailto:struberg@apache.org">Mark Struberg</a>
Expand Down
2 changes: 1 addition & 1 deletion spec/src/main/asciidoc/architecture.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ All this must be possible without the need to re-package the whole application b

MicroProfile Config provides a way to achieve this goal by aggregating configuration from many different <<configsource,ConfigSources>> and presents a single merged view to the user.
This allows the application to bundle default configuration within the application.
It also allows to override the defaults from outside, e.g. via an environment variable a Java system property or via a container like Docker.
It also allows to override or clear the defaults from outside, e.g. via an environment variable a Java system property or via a container like Docker.
MicroProfile Config also allows to implement and register own configuration sources in a portable way, e.g. for reading configuration values from a shared database in an application cluster.


Expand Down
2 changes: 1 addition & 1 deletion spec/src/main/asciidoc/configexamples.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public class InjectedConfigUsageSample {
@Inject
private Config config;
//The property myprj.some.url must exist in one of the configsources, otherwise a
//The property myprj.some.url must exist with a non empty value, otherwise a
//DeploymentException will be thrown.
@Inject
@ConfigProperty(name="myprj.some.url")
Expand Down
2 changes: 1 addition & 1 deletion spec/src/main/asciidoc/configsources.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ A higher `ordinal` means that the values taken from this `ConfigSource` will ove
This allows a configuration to be customized from outside a binary, assuming that external `ConfigSource` s have higher `ordinal` values than the ones whose values originate within the release binaries.

It can also be used to implement a drop-in configuration approach.
Simply create a jar containing a `ConfigSource` with a higher ordinal and override configuration values in it.
Simply create a jar containing a `ConfigSource` with a higher ordinal and override or clear configuration values in it.
If the jar is present on the classpath then it will override configuration values from <<ConfigSource,ConfigSources>> with lower `ordinal` values.

=== Manually defining the Ordinal of a built-in ConfigSource
Expand Down
3 changes: 2 additions & 1 deletion spec/src/main/asciidoc/converters.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ The converters for these types must throw an NPE if given a null value to conver

=== Adding custom Converters

A custom `Converter` must implement the generic interface `org.eclipse.microprofile.config.spi.Converter`.
A custom `Converter` must implement the generic interface `org.eclipse.microprofile.config.spi.Converter` and conform to
the API requirements of that interface.
The Type parameter of the interface is the target type the String is converted to. If your converter targets a wrapper of a primitive type (e.g. `java.lang.Integer`), the converter applies to both the wrapper type and the primitive type (e.g `int`)
You have to register your implementation in a file `/META-INF/services/org.eclipse.microprofile.config.spi.Converter` with the fully qualified class name of the custom implementation.

Expand Down

0 comments on commit 573a98b

Please sign in to comment.