Commit 4b51b6f9 authored by Phillip Webb's avatar Phillip Webb

Support relaxed names with ConditionalOnProperty

Update ConditionalOnProperty to optionally support relaxed form names.

Fixes gh-835
parent f80d23ad
...@@ -37,9 +37,20 @@ import org.springframework.core.env.Environment; ...@@ -37,9 +37,20 @@ import org.springframework.core.env.Environment;
public @interface ConditionalOnProperty { public @interface ConditionalOnProperty {
/** /**
* One or more properties that must be present. * A prefix that should be applied to each property.
*/
String prefix() default "";
/**
* One or more properties that must be present. If you are checking relaxed names you
* should specify the property in its dashed form.
* @return the property names * @return the property names
*/ */
String[] value(); String[] value();
/**
* If relaxed names should be checked. Defaults to {@code true}.
*/
boolean relaxedNames() default true;
} }
...@@ -19,9 +19,10 @@ package org.springframework.boot.autoconfigure.condition; ...@@ -19,9 +19,10 @@ package org.springframework.boot.autoconfigure.condition;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment; import org.springframework.core.env.PropertyResolver;
import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
...@@ -29,6 +30,7 @@ import org.springframework.util.StringUtils; ...@@ -29,6 +30,7 @@ import org.springframework.util.StringUtils;
* {@link Condition} that checks if properties are defined in environment. * {@link Condition} that checks if properties are defined in environment.
* *
* @author Maciej Walkowiak * @author Maciej Walkowiak
* @author Phillip Webb
* @see ConditionalOnProperty * @see ConditionalOnProperty
* @since 1.1.0 * @since 1.1.0
*/ */
...@@ -38,17 +40,27 @@ class OnPropertyCondition extends SpringBootCondition { ...@@ -38,17 +40,27 @@ class OnPropertyCondition extends SpringBootCondition {
public ConditionOutcome getMatchOutcome(ConditionContext context, public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) { AnnotatedTypeMetadata metadata) {
String[] onProperties = (String[]) metadata.getAnnotationAttributes( String prefix = (String) metadata.getAnnotationAttributes(
ConditionalOnProperty.class.getName()).get("prefix");
String[] names = (String[]) metadata.getAnnotationAttributes(
ConditionalOnProperty.class.getName()).get("value"); ConditionalOnProperty.class.getName()).get("value");
Boolean relaxedNames = (Boolean) metadata.getAnnotationAttributes(
ConditionalOnProperty.class.getName()).get("relaxedNames");
List<String> missingProperties = new ArrayList<String>(); List<String> missingProperties = new ArrayList<String>();
Environment environment = context.getEnvironment(); PropertyResolver resolver = context.getEnvironment();
for (String property : onProperties) { if (relaxedNames) {
if (!environment.containsProperty(property) resolver = new RelaxedPropertyResolver(resolver, prefix);
|| StringUtils.endsWithIgnoreCase(environment.getProperty(property), prefix = "";
"false")) { }
missingProperties.add(property);
for (String name : names) {
name = prefix + name;
if (!resolver.containsProperty(name)
|| "false".equalsIgnoreCase(resolver.getProperty(name))) {
missingProperties.add(name);
} }
} }
...@@ -56,9 +68,9 @@ class OnPropertyCondition extends SpringBootCondition { ...@@ -56,9 +68,9 @@ class OnPropertyCondition extends SpringBootCondition {
return ConditionOutcome.match(); return ConditionOutcome.match();
} }
return ConditionOutcome return ConditionOutcome.noMatch("@ConditionalOnProperty "
.noMatch("@ConditionalOnProperty missing required properties: " + "missing required properties: "
+ StringUtils.arrayToCommaDelimitedString(missingProperties + StringUtils.arrayToCommaDelimitedString(missingProperties.toArray())
.toArray()) + " not found"); + " not found");
} }
} }
...@@ -22,7 +22,6 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext ...@@ -22,7 +22,6 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
...@@ -36,41 +35,57 @@ public class ConditionalOnPropertyTests { ...@@ -36,41 +35,57 @@ public class ConditionalOnPropertyTests {
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@Test @Test
public void testBeanIsCreatedWhenAllPropertiesAreDefined() { public void allPropertiesAreDefined() {
EnvironmentTestUtils.addEnvironment(this.context.getEnvironment(), EnvironmentTestUtils.addEnvironment(this.context.getEnvironment(),
"property1=value1", "property2=value2"); "property1=value1", "property2=value2");
setupContext(); this.context.register(MultiplePropertiesRequiredConfiguration.class);
this.context.refresh();
assertTrue(this.context.containsBean("foo")); assertTrue(this.context.containsBean("foo"));
assertEquals("foo", this.context.getBean("foo"));
} }
@Test @Test
public void testBeanIsNotCreatedWhenNotAllPropertiesAreDefined() { public void notAllPropertiesAreDefined() {
EnvironmentTestUtils.addEnvironment(this.context.getEnvironment(), EnvironmentTestUtils.addEnvironment(this.context.getEnvironment(),
"property1=value1"); "property1=value1");
setupContext(); this.context.register(MultiplePropertiesRequiredConfiguration.class);
this.context.refresh();
assertFalse(this.context.containsBean("foo")); assertFalse(this.context.containsBean("foo"));
} }
@Test @Test
public void testBeanIsNotCreatedWhenPropertyValueEqualsFalse() { public void propertyValueEqualsFalse() {
EnvironmentTestUtils.addEnvironment(this.context.getEnvironment(), EnvironmentTestUtils.addEnvironment(this.context.getEnvironment(),
"property1=false", "property2=value2"); "property1=false", "property2=value2");
setupContext(); this.context.register(MultiplePropertiesRequiredConfiguration.class);
this.context.refresh();
assertFalse(this.context.containsBean("foo")); assertFalse(this.context.containsBean("foo"));
} }
@Test @Test
public void testBeanIsNotCreatedWhenPropertyValueEqualsFALSE() { public void propertyValueEqualsFALSE() {
EnvironmentTestUtils.addEnvironment(this.context.getEnvironment(), EnvironmentTestUtils.addEnvironment(this.context.getEnvironment(),
"property1=FALSE", "property2=value2"); "property1=FALSE", "property2=value2");
setupContext(); this.context.register(MultiplePropertiesRequiredConfiguration.class);
this.context.refresh();
assertFalse(this.context.containsBean("foo")); assertFalse(this.context.containsBean("foo"));
} }
private void setupContext() { @Test
this.context.register(MultiplePropertiesRequiredConfiguration.class); public void relaxedName() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context.getEnvironment(),
"spring.theRelaxedProperty=value1");
this.context.register(RelaxedPropertiesRequiredConfiguration.class);
this.context.refresh(); this.context.refresh();
assertTrue(this.context.containsBean("foo"));
}
@Test
public void nonRelaxedName() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context.getEnvironment(),
"theRelaxedProperty=value1");
this.context.register(NonRelaxedPropertiesRequiredConfiguration.class);
this.context.refresh();
assertFalse(this.context.containsBean("foo"));
} }
@Configuration @Configuration
...@@ -84,4 +99,26 @@ public class ConditionalOnPropertyTests { ...@@ -84,4 +99,26 @@ public class ConditionalOnPropertyTests {
} }
@Configuration
@ConditionalOnProperty(prefix = "spring.", value = "the-relaxed-property")
protected static class RelaxedPropertiesRequiredConfiguration {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnProperty(value = "the-relaxed-property", relaxedNames = false)
protected static class NonRelaxedPropertiesRequiredConfiguration {
@Bean
public String foo() {
return "foo";
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment