Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions owner/src/main/java/org/aeonbits/owner/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ public interface Config extends Serializable {
String value();
}

/**
* Indicates a mandatory property. If no property is found a {@link MissingMandatoryPropertyException}
* exception is thrown.
*/
@Retention(RUNTIME)
@Target(METHOD)
@Documented
@interface Mandatory {
}

/**
* The key used for lookup for the property. If not present, the key will be generated based on the unqualified
* method name.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.aeonbits.owner;

public class MissingMandatoryPropertyException extends RuntimeException {
private static final long serialVersionUID = 1L;

MissingMandatoryPropertyException(String message) {
super(message);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import java.util.LinkedList;
import java.util.List;

import org.aeonbits.owner.Config.Mandatory;

import static org.aeonbits.owner.Config.DisableableFeature.PARAMETER_FORMATTING;
import static org.aeonbits.owner.Config.DisableableFeature.VARIABLE_EXPANSION;
import static org.aeonbits.owner.Converters.SpecialValue.NULL;
Expand Down Expand Up @@ -81,8 +83,10 @@ private Object resolveProperty(Method method, Object... args) {
String unexpandedKey = key(method);
value = propertiesManager.getProperty(unexpandedKey);
}
if (value == null)
if (value == null) {
throwIfMandatoryProperty(method, key);
return null;
}
// Before processing the value, we decrypt it if necessary.
// It is a security hole store the decrypted value, so every time we need it it should be decrypted.
value = this.propertiesManager.decryptIfNecessary( method, value );
Expand All @@ -92,6 +96,14 @@ private Object resolveProperty(Method method, Object... args) {
return result;
}

private void throwIfMandatoryProperty(Method method, String key) {
Mandatory mandatory = method.getAnnotation(Mandatory.class);
if (mandatory != null) {
String message = String.format("Missing mandatory property: '%s'", key);
throw new MissingMandatoryPropertyException(message);
}
}

private String preProcess(Method method, String value) {
List<Preprocessor> preprocessors = resolvePreprocessors(method);
String result = value;
Expand Down
31 changes: 30 additions & 1 deletion owner/src/test/java/org/aeonbits/owner/ConfigTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

package org.aeonbits.owner;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
Expand All @@ -26,7 +28,10 @@
@RunWith(MockitoJUnitRunner.class)
public class ConfigTest {

@Mock
@Rule
public ExpectedException expected = ExpectedException.none();

@Mock
private ScheduledExecutorService scheduler;

public interface SampleConfig extends Config {
Expand Down Expand Up @@ -85,6 +90,30 @@ public void testDefaultStringValue() {
assertEquals("Hello Mr. Luigi!", config.helloMr("Luigi"));
}

static interface WithMandatoryPropertyConfig extends Config {
@Mandatory
String missingMandatoryProperty();

@Mandatory
@DefaultValue("I'm here")
String mandatory();
}

@Test
public void shouldThrowWhenMissingMandatoryProperty() {
expected.expect(MissingMandatoryPropertyException.class);
expected.expectMessage("Missing mandatory property: 'missingMandatoryProperty'");

WithMandatoryPropertyConfig config = ConfigFactory.create(WithMandatoryPropertyConfig.class);
config.missingMandatoryProperty();
}

@Test
public void testMandatoryStringValue() {
WithMandatoryPropertyConfig config = ConfigFactory.create(WithMandatoryPropertyConfig.class);
assertEquals("I'm here", config.mandatory());
}

@Test
public void testDefaultPropertyOverridden() {
SampleConfig config = ConfigFactory.create(SampleConfig.class);
Expand Down