Skip to content

Commit

Permalink
ConfigValue API.
Browse files Browse the repository at this point in the history
Signed-off-by: Roberto Cortez <[email protected]>
  • Loading branch information
radcortez committed Jun 12, 2020
1 parent c0d3203 commit 535aca9
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 2 deletions.
22 changes: 21 additions & 1 deletion api/src/main/java/org/eclipse/microprofile/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@
*/
@org.osgi.annotation.versioning.ProviderType
public interface Config {

/**
* Return the resolved property value with the specified type for the
* specified property name from the underlying {@linkplain ConfigSource configuration sources}.
Expand All @@ -111,6 +110,27 @@ public interface Config {
*/
<T> T getValue(String propertyName, Class<T> propertyType);

/**
* Return the {@link ConfigValue} for the specified property name from the underlying
* {@linkplain ConfigSource configuration source}. The lookup of the configuration is performed immediatily,
* meaning that calls to {@link ConfigValue} will always yeld the same results.
* <p>
*
* 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>
*
* A {@link ConfigValue} is always returned even if a property name cannot be found. In this case, every method in
* {@link ConfigValue} returns {@code null} except for {@link ConfigValue#getName()}, which includes the original
* property name being looked up.
*
* @param propertyName
* The configuration property name
* @return the resolved property value as a {@link ConfigValue}
*/
ConfigValue getConfigValue(String propertyName);

/**
* Return the resolved property values with the specified type for the
* specified property name from the underlying {@linkplain ConfigSource configuration sources}.
Expand Down
64 changes: 64 additions & 0 deletions api/src/main/java/org/eclipse/microprofile/config/ConfigValue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2020 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 org.eclipse.microprofile.config;

/**
* The ConfigValue holds additional information after the lookup of a configuration property and is itself immutable.
* <p>
*
* Holds information about the configuration property name, configuration value, the
* {@link org.eclipse.microprofile.config.spi.ConfigSource} name from where the configuration property was loaded and
* the ordinal of the {@link org.eclipse.microprofile.config.spi.ConfigSource}.
* <p>
*
* This is used together with {@link Config} to expose the configuration property lookup metadata.
*
* @author <a href="mailto:[email protected]">Roberto Cortez</a>
*/
public interface ConfigValue {
/**
* The name of the property.
*
* @return the name of the property.
*/
String getName();

/**
* The value of the property lookup.
*
* @return the raw value of the property lookup or {@code null} if the property could not be found.
*/
String getValue();

/**
* The {@link org.eclipse.microprofile.config.spi.ConfigSource} name that loaded the property lookup.
*
* @return the ConfigSource name that loaded the property lookup or {@code null} if the property could not be found.
*/
String getSourceName();

/**
* The {@link org.eclipse.microprofile.config.spi.ConfigSource} ordinal that loaded the property lookup.
*
* @return the ConfigSource ordinal that loaded the property lookup or {@code 0} if the property could not be
* found.
*/
int getSourceOrdinal();
}
12 changes: 11 additions & 1 deletion spec/src/main/asciidoc/configexamples.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ public class ConfigUsageSample {
Config config = ConfigProvider.getConfig();
String serverUrl = config.getValue("acme.myprj.some.url", String.class);
callToServer(serverUrl);
// or
ConfigValue configServerUrl = config.getConfigValue("acme.myprj.some.url");
callToServer(configServerUrl.getValue());
}
}
----
Expand Down Expand Up @@ -81,6 +84,13 @@ public class InjectedConfigUsageSample {
@ConfigProperty(name="myprj.some.url")
private String someUrl;
// You can also inject a configuration using the ConfigValue metadata object. The
// configured value will not lead to a DeploymentException if the value is missing.
// A default value can also be specified like any other configuration.
@Inject
@ConfigProperty(name="myprj.another.url")
private ConfigValue anotherUrl;
//The following code injects an Optional value of myprj.some.port property.
//Contrary to natively injecting the configured value, this will not lead to a
//DeploymentException if the value is missing.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* Copyright (c) 2020 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 org.eclipse.microprofile.config.tck;

import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.config.ConfigValue;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.config.spi.ConfigSource;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.testng.Arquillian;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.testng.annotations.Test;

import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;

public class ConfigValueTest extends Arquillian {
@Deployment
public static Archive deployment() {
JavaArchive testJar = ShrinkWrap
.create(JavaArchive.class, "ConfigValueTest.jar")
.addClasses(ConfigValueBean.class)
.addAsServiceProvider(ConfigSource.class, ConfigValueConfigSource.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
.as(JavaArchive.class);

return ShrinkWrap
.create(WebArchive.class, "ConfigValueTest.war")
.addAsLibrary(testJar);
}

@Test
void configValue() {
ConfigValue configValue = ConfigProvider.getConfig().getConfigValue("my.prop");
assertNotNull(configValue);
assertEquals("my.prop", configValue.getName());
assertEquals("1234", configValue.getValue());
assertEquals("ConfigValueConfigSource", configValue.getSourceName());
assertEquals(1000, configValue.getSourceOrdinal());
}

@Test
public void configValueEmpty() {
ConfigValue configValue = ConfigProvider.getConfig().getConfigValue("not.found");
assertNotNull(configValue);
assertEquals("not.found", configValue.getName());
assertNull(configValue.getValue());
assertNull(configValue.getSourceName());
assertEquals(0, configValue.getSourceOrdinal());
}

@Inject
private ConfigValueBean configValueBean;

@Test
public void configValueInjection() {
final ConfigValue configValue = configValueBean.getConfigValue();
assertNotNull(configValue);
assertEquals("my.prop", configValue.getName());
assertEquals("1234", configValue.getValue());
assertEquals(ConfigValueConfigSource.class.getSimpleName(), configValue.getSourceName());
assertEquals(1000, configValue.getSourceOrdinal());

final ConfigValue configValueDefault = configValueBean.getConfigValueDefault();
assertNotNull(configValueDefault);
assertEquals("my.prop", configValue.getName());
assertEquals("default", configValueDefault.getValue());
assertNull(configValueDefault.getSourceName());
}

public static class ConfigValueConfigSource implements ConfigSource {
private Map<String, String> properties;

public ConfigValueConfigSource() {
properties = new HashMap<>();
properties.put("my.prop", "1234");
}

@Override
public Set<String> getPropertyNames() {
return properties.keySet();
}

@Override
public String getValue(final String propertyName) {
return properties.get(propertyName);
}

@Override
public String getName() {
return this.getClass().getSimpleName();
}

@Override
public int getOrdinal() {
return 1000;
}
}

@Dependent
public static class ConfigValueBean {
@Inject
@ConfigProperty(name = "my.prop")
private ConfigValue configValue;

@Inject
@ConfigProperty(name = "my.prop.default", defaultValue = "default")
private ConfigValue configValueDefault;

ConfigValue getConfigValue() {
return configValue;
}

ConfigValue getConfigValueDefault() {
return configValueDefault;
}
}
}

0 comments on commit 535aca9

Please sign in to comment.