From 8e0b3dd00a5960ff80b52f3f916d08f91e9961c6 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 28 Jul 2014 23:17:34 -0700 Subject: [PATCH] Rename some ConditionalOnProperty attributes Rename the newly introduced @ConditionalOnProperty `match` and `defaultMatch` attributes to `havingValue` and `matchIfMissing`. Also added a new `name` attribute as an alternative to `value` to aid readability. Closes gh-1000 --- .../aop/AopAutoConfiguration.java | 8 +- .../batch/BatchAutoConfiguration.java | 2 +- .../condition/ConditionalOnProperty.java | 120 ++++++++---------- .../condition/OnPropertyCondition.java | 101 ++++++++------- ...icsearchRepositoriesAutoConfiguration.java | 3 +- .../jpa/JpaRepositoriesAutoConfiguration.java | 2 +- .../MongoRepositoriesAutoConfiguration.java | 2 +- .../SolrRepositoriesAutoConfiguration.java | 2 +- .../IntegrationAutoConfiguration.java | 2 +- .../jmx/JmxAutoConfiguration.java | 2 +- ...legatingViewResolverAutoConfiguration.java | 2 +- .../SitePreferenceAutoConfiguration.java | 2 +- .../orm/jpa/JpaBaseConfiguration.java | 2 +- .../social/FacebookAutoConfiguration.java | 4 +- .../social/LinkedInAutoConfiguration.java | 4 +- .../social/SocialWebAutoConfiguration.java | 2 +- .../social/TwitterAutoConfiguration.java | 4 +- .../web/WebMvcAutoConfiguration.java | 4 +- .../condition/ConditionalOnPropertyTests.java | 119 +++++++++++++---- 19 files changed, 219 insertions(+), 168 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/aop/AopAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/aop/AopAutoConfiguration.java index d8447a6acf3..f59ec29bdda 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/aop/AopAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/aop/AopAutoConfiguration.java @@ -19,7 +19,6 @@ package org.springframework.boot.autoconfigure.aop; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.Advice; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @@ -40,19 +39,18 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy; */ @Configuration @ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class }) -@ConditionalOnProperty(value = "spring.aop.auto", match = "true", defaultMatch = true) +@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true) public class AopAutoConfiguration { @Configuration @EnableAspectJAutoProxy(proxyTargetClass = false) - @ConditionalOnProperty(value = "spring.aop.proxyTargetClass", match = "false", defaultMatch = true) + @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = true) public static class JdkDynamicAutoProxyConfiguration { } @Configuration @EnableAspectJAutoProxy(proxyTargetClass = true) - @ConditionalOnExpression("${spring.aop.proxyTargetClass:false}") - @ConditionalOnProperty(value = "spring.aop.proxyTargetClass", match = "true", defaultMatch = false) + @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = false) public static class CglibAutoProxyConfiguration { } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java index 278f3261b2e..5dc30d5d3ba 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java @@ -78,7 +78,7 @@ public class BatchAutoConfiguration { @Bean @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.batch.job.enabled", match = "true", defaultMatch = true) + @ConditionalOnProperty(prefix = "spring.batch.job", name = "enabled", havingValue = "true", matchIfMissing = true) public JobLauncherCommandLineRunner jobLauncherCommandLineRunner( JobLauncher jobLauncher, JobExplorer jobExplorer) { JobLauncherCommandLineRunner runner = new JobLauncherCommandLineRunner( diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnProperty.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnProperty.java index 9f00db0a57e..e7cd7c3e8c1 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnProperty.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnProperty.java @@ -25,66 +25,56 @@ import org.springframework.context.annotation.Conditional; import org.springframework.core.env.Environment; /** - * {@link Conditional} that checks if the specified properties - * have the requested matching value. By default the properties - * must be present in the {@link Environment} ant not - * equal to {@code false}. The {@link #match()} and {@link #defaultMatch()} - * attributes allow to further customize the condition. + * {@link Conditional} that checks if the specified properties have a specific value. By + * default the properties must be present in the {@link Environment} and + * not equal to {@code false}. The {@link #havingValue()} and + * {@link #matchIfMissing()} attributes allow further customizations. * - *

The {@link #match} attribute provides the value that the property - * should have. The {@link #defaultMatch()} flag specifies if the - * condition also matches if the property is not present - * at all. - * - *

The table below defines when a condition match according to the - * property value and the {@link #match()} value + *

+ * The {@link #havingValue} attribute can be used to specify the value that the property + * should have. The table below shows when a condition matches according to the property + * value and the {@link #havingValue()} attribute: * + *

* - * - * - * - * - * - * - * - * - * - * - * - * * - * - * - * - * - * + * + * + * + * + * * * - * - * - * - * - * + * + * + * + * + * * * - * - * - * - * - * + * + * + * + * + * * * - * - * - * - * - * + * + * + * + * + * * *
- * no {@code match} value{@code true}{@code false}{@code foo}
not set ({@code defaultMatch = false})nononono
not set ({@code defaultMatch = true})yesyesyesyesProperty Value{@code havingValue=""}{@code havingValue="true"}{@code havingValue="false"}{@code havingValue="foo"}
{@code true}yesyesnono{@code "true"}yesyesnono
{@code false}nonoyesno{@code "false"}nonoyesno
{@code foo}yesnonoyes{@code "foo"}yesnonoyes
* + *

+ * If the property is not contained in the {@link Environment} at all, the + * {@link #matchIfMissing()} attribute is consulted. By default missing attributes do not + * match. + * * @author Maciej Walkowiak * @author Stephane Nicoll + * @author Phillip Webb * @since 1.1.0 */ @Conditional(OnPropertyCondition.class) @@ -93,38 +83,38 @@ import org.springframework.core.env.Environment; public @interface ConditionalOnProperty { /** - * A prefix that should be applied to each property. - *

Defaults to no prefix. The prefix automatically - * ends with a dot if not specified. + * Alias for {@link #name()}. + */ + String[] value() default {}; + + /** + * A prefix that should be applied to each property. The prefix automatically ends + * with a dot if not specified. */ String prefix() default ""; /** - * One or more properties to validate against the - * {@link #match} value. If a prefix has been defined, it - * is applied to compute the full key of each property. For - * instance if the prefix is {@code app.config} and one - * value is {@code my-value}, the fully key would be + * The name of the properties to test.If a prefix has been defined, it is applied to + * compute the full key of each property. For instance if the prefix is + * {@code app.config} and one value is {@code my-value}, the fully key would be * {@code app.config.my-value} - *

Use the dashed notation to specify each property, that - * is all lower case with a "-" to separate words (e.g. - * {@code my-long-property}). - * @return the property names + *

+ * Use the dashed notation to specify each property, that is all lower case with a "-" + * to separate words (e.g. {@code my-long-property}). */ - String[] value(); + String[] name() default {}; /** - * The string representation of the expected value for the - * properties. If not specified, the property must - * not be equals to {@code false} + * The string representation of the expected value for the properties. If not + * specified, the property must not be equals to {@code false} */ - String match() default ""; + String havingValue() default ""; /** - * Specify if the condition should match if the property is not set. - * Defaults to {@code false} + * Specify if the condition should match if the property is not set. Defaults to + * {@code false} */ - boolean defaultMatch() default false; + boolean matchIfMissing() default false; /** * If relaxed names should be checked. Defaults to {@code true}. diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnPropertyCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnPropertyCondition.java index cdc8c820eb2..122e6715caa 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnPropertyCondition.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnPropertyCondition.java @@ -23,8 +23,10 @@ import java.util.Map; import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.PropertyResolver; import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** @@ -42,41 +44,35 @@ class OnPropertyCondition extends SpringBootCondition { public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { - Map annotationAttributes = metadata.getAnnotationAttributes( - ConditionalOnProperty.class.getName()); + AnnotationAttributes annotationAttributes = AnnotationAttributes.fromMap(metadata + .getAnnotationAttributes(ConditionalOnProperty.class.getName())); - String prefix = getPrefix(annotationAttributes); - String expectedValue = getExpectedValue(annotationAttributes); - String[] names = (String[]) annotationAttributes.get("value"); - boolean relaxedNames = (Boolean) annotationAttributes.get("relaxedNames"); - boolean matchDefault = (Boolean) annotationAttributes.get("defaultMatch"); - - List missingProperties = new ArrayList(); - List nonMatchingProperties = new ArrayList(); + String prefix = annotationAttributes.getString("prefix").trim(); + if (StringUtils.hasText(prefix) && !prefix.endsWith(".")) { + prefix = prefix + "."; + } + String havingValue = annotationAttributes.getString("havingValue"); + String[] names = getNames(annotationAttributes); + boolean relaxedNames = annotationAttributes.getBoolean("relaxedNames"); + boolean matchIfMissing = annotationAttributes.getBoolean("matchIfMissing"); PropertyResolver resolver = context.getEnvironment(); if (relaxedNames) { resolver = new RelaxedPropertyResolver(resolver, prefix); - prefix = ""; } + List missingProperties = new ArrayList(); + List nonMatchingProperties = new ArrayList(); for (String name : names) { - name = prefix + name; - boolean hasProperty = resolver.containsProperty(name); - if (!hasProperty) { // property not set - if (!matchDefault) { // property is mandatory - missingProperties.add(name); + String key = (relaxedNames ? name : prefix + name); + if (resolver.containsProperty(key)) { + if (!isMatch(resolver.getProperty(key), havingValue)) { + nonMatchingProperties.add(name); } } else { - String actualValue = resolver.getProperty(name); - if (expectedValue == null) { - if ("false".equalsIgnoreCase(actualValue)) { - nonMatchingProperties.add(name); - } - } - else if (!expectedValue.equalsIgnoreCase(actualValue)) { - nonMatchingProperties.add(name); + if (!matchIfMissing) { + missingProperties.add(name); } } } @@ -85,42 +81,45 @@ class OnPropertyCondition extends SpringBootCondition { return ConditionOutcome.match(); } - StringBuilder sb = new StringBuilder("@ConditionalOnProperty "); - if (!matchDefault && !missingProperties.isEmpty()) { - sb.append("missing required properties ") - .append(StringUtils.arrayToCommaDelimitedString(missingProperties.toArray())) - .append(" "); + StringBuilder message = new StringBuilder("@ConditionalOnProperty "); + if (!missingProperties.isEmpty()) { + message.append("missing required properties " + + expandNames(prefix, missingProperties) + " "); } if (!nonMatchingProperties.isEmpty()) { - String expected = expectedValue == null ? "!false" : expectedValue; - sb.append("expected '").append(expected).append("' for properties: ") - .append(StringUtils.arrayToCommaDelimitedString(nonMatchingProperties.toArray())); + String expected = havingValue == null ? "!false" : havingValue; + message.append("expected '").append(expected).append("' for properties ") + .append(expandNames(prefix, nonMatchingProperties)); } - return ConditionOutcome.noMatch(sb.toString()); + return ConditionOutcome.noMatch(message.toString()); } - /** - * Return the prefix to use or an empty String if it's not set. - *

Add a dot at the end if it is not present already. - */ - private static String getPrefix(Map annotationAttributes) { - String prefix = ((String) annotationAttributes.get("prefix")).trim(); - if (StringUtils.hasText(prefix) && !prefix.endsWith(".")) { - prefix = prefix + "."; + private String[] getNames(Map annotationAttributes) { + String[] value = (String[]) annotationAttributes.get("value"); + String[] name = (String[]) annotationAttributes.get("name"); + Assert.state(value.length > 0 || name.length > 0, + "The name or value attribute of @ConditionalOnProperty must be specified"); + Assert.state(value.length == 0 || name.length == 0, + "The name and value attributes of @ConditionalOnProperty are exclusive"); + return (value.length > 0 ? value : name); + } + + private boolean isMatch(String value, String requiredValue) { + if (StringUtils.hasLength(requiredValue)) { + return requiredValue.equalsIgnoreCase(value); } - return prefix; + return !"false".equalsIgnoreCase(value); } - /** - * Return the expected value to match against or {@code null} if no - * match value is set. - */ - private static String getExpectedValue(Map annotationAttributes) { - String match = (String) annotationAttributes.get("match"); - if (StringUtils.hasText(match)) { - return match; + private String expandNames(String prefix, List names) { + StringBuffer expanded = new StringBuffer(); + for (String name : names) { + expanded.append(expanded.length() == 0 ? "" : ", "); + expanded.append(prefix); + expanded.append(name); } - return null; + return expanded.toString(); } + } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchRepositoriesAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchRepositoriesAutoConfiguration.java index 1b0e982f078..3d5bcc63b0c 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchRepositoriesAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchRepositoriesAutoConfiguration.java @@ -38,8 +38,7 @@ import org.springframework.data.repository.core.support.RepositoryFactoryBeanSup */ @Configuration @ConditionalOnClass({ Client.class, ElasticsearchRepository.class }) -@ConditionalOnProperty(value = "spring.data.elasticsearch.repositories.enabled", - match = "true", defaultMatch = true) +@ConditionalOnProperty(prefix = "spring.data.elasticsearch.repositories", name = "enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnMissingBean(RepositoryFactoryBeanSupport.class) @Import(ElasticsearchRepositoriesAutoConfigureRegistrar.class) public class ElasticsearchRepositoriesAutoConfiguration { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/jpa/JpaRepositoriesAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/jpa/JpaRepositoriesAutoConfiguration.java index 074728ea4ea..983bea005d9 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/jpa/JpaRepositoriesAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/jpa/JpaRepositoriesAutoConfiguration.java @@ -59,7 +59,7 @@ import org.springframework.data.web.config.EnableSpringDataWebSupport; @ConditionalOnClass(JpaRepository.class) @ConditionalOnMissingBean({ RepositoryFactoryBeanSupport.class, JpaRepositoryConfigExtension.class }) -@ConditionalOnProperty(value = "spring.data.jpa.repositories.enabled", match = "true", defaultMatch = true) +@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true", matchIfMissing = true) @Import(JpaRepositoriesAutoConfigureRegistrar.class) @AutoConfigureAfter(HibernateJpaAutoConfiguration.class) public class JpaRepositoriesAutoConfiguration { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfiguration.java index c222236f19b..1a135c2df9f 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoRepositoriesAutoConfiguration.java @@ -56,7 +56,7 @@ import com.mongodb.Mongo; @ConditionalOnClass({ Mongo.class, MongoRepository.class }) @ConditionalOnMissingBean({ RepositoryFactoryBeanSupport.class, MongoRepositoryConfigurationExtension.class }) -@ConditionalOnProperty(value = "spring.data.mongo.repositories.enabled", match = "true", defaultMatch = true) +@ConditionalOnProperty(prefix = "spring.data.mongo.repositories", name = "enabled", havingValue = "true", matchIfMissing = true) @Import(MongoRepositoriesAutoConfigureRegistrar.class) @AutoConfigureAfter(MongoAutoConfiguration.class) public class MongoRepositoriesAutoConfiguration { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/solr/SolrRepositoriesAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/solr/SolrRepositoriesAutoConfiguration.java index 4aebec341db..765f2fe8699 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/solr/SolrRepositoriesAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/solr/SolrRepositoriesAutoConfiguration.java @@ -47,7 +47,7 @@ import org.springframework.data.solr.repository.config.SolrRepositoryConfigExten @ConditionalOnClass({ SolrServer.class, SolrRepository.class }) @ConditionalOnMissingBean({ RepositoryFactoryBeanSupport.class, SolrRepositoryConfigExtension.class }) -@ConditionalOnProperty(value = "spring.data.solr.repositories.enabled", match = "true", defaultMatch = true) +@ConditionalOnProperty(prefix = "spring.data.solr.repositories", name = "enabled", havingValue = "true", matchIfMissing = true) @Import(SolrRepositoriesAutoConfigureRegistrar.class) public class SolrRepositoriesAutoConfiguration { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java index 974e64d1797..c594c268b99 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java @@ -51,7 +51,7 @@ public class IntegrationAutoConfiguration { @Configuration @ConditionalOnClass(EnableIntegrationMBeanExport.class) @ConditionalOnMissingBean(value = IntegrationMBeanExporter.class, search = SearchStrategy.CURRENT) - @ConditionalOnProperty(value = "spring.jmx.enabled", match = "true", defaultMatch = true) + @ConditionalOnProperty(prefix = "spring.jmx", name = "enabled", havingValue = "true", matchIfMissing = true) @EnableIntegrationMBeanExport(defaultDomain = "${spring.jmx.default_domain:}", server = "${spring.jmx.server:mbeanServer}") protected static class IntegrationJmxConfiguration { } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java index 230212595d9..05f86311393 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java @@ -53,7 +53,7 @@ import org.springframework.util.ClassUtils; */ @Configuration @ConditionalOnClass({ MBeanExporter.class }) -@ConditionalOnProperty(value = "spring.jmx.enabled", match = "true", defaultMatch = true) +@ConditionalOnProperty(prefix = "spring.jmx", name = "enabled", havingValue = "true", matchIfMissing = true) public class JmxAutoConfiguration { @Autowired diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfiguration.java index d962c59c65a..f1a07193316 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/DeviceDelegatingViewResolverAutoConfiguration.java @@ -88,7 +88,7 @@ public class DeviceDelegatingViewResolverAutoConfiguration { @Configuration @EnableConfigurationProperties(DeviceDelegatingViewResolverProperties.class) @ConditionalOnMissingBean(name = "deviceDelegatingViewResolver") - @ConditionalOnProperty(value = "spring.mobile.devicedelegatingviewresolver.enabled", match = "true", defaultMatch = false) + @ConditionalOnProperty(prefix = "spring.mobile.devicedelegatingviewresolver", name = "enabled", havingValue = "true", matchIfMissing = false) protected static class DeviceDelegatingViewResolverConfiguration { @Configuration diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/SitePreferenceAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/SitePreferenceAutoConfiguration.java index 49e60b4f468..bad97da902e 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/SitePreferenceAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mobile/SitePreferenceAutoConfiguration.java @@ -47,7 +47,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter @ConditionalOnClass({ SitePreferenceHandlerInterceptor.class, SitePreferenceHandlerMethodArgumentResolver.class }) @AutoConfigureAfter(DeviceResolverAutoConfiguration.class) -@ConditionalOnProperty(value ="spring.mobile.sitepreference.enabled", match = "true", defaultMatch = true) +@ConditionalOnProperty(prefix = "spring.mobile.sitepreference", name = "enabled", havingValue = "true", matchIfMissing = true) public class SitePreferenceAutoConfiguration { @Configuration diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java index 0d4f94a01d1..dbcb6dd656b 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java @@ -136,7 +136,7 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware { @ConditionalOnWebApplication @ConditionalOnMissingBean({ OpenEntityManagerInViewInterceptor.class, OpenEntityManagerInViewFilter.class }) - @ConditionalOnProperty(prefix = "spring.jpa", value = "openInView", match = "true", defaultMatch = true) + @ConditionalOnProperty(prefix = "spring.jpa", name = "open-in-view", havingValue = "true", matchIfMissing = true) protected static class JpaWebConfiguration extends WebMvcConfigurerAdapter { @Override diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/FacebookAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/FacebookAutoConfiguration.java index 12316d2f8e0..0e04cb90be1 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/FacebookAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/FacebookAutoConfiguration.java @@ -50,7 +50,7 @@ import org.springframework.web.servlet.View; */ @Configuration @ConditionalOnClass({ SocialConfigurerAdapter.class, FacebookConnectionFactory.class }) -@ConditionalOnProperty(prefix = "spring.social.facebook.", value = "app-id") +@ConditionalOnProperty(prefix = "spring.social.facebook", name = "app-id") @AutoConfigureBefore(SocialWebAutoConfiguration.class) @AutoConfigureAfter(WebMvcAutoConfiguration.class) public class FacebookAutoConfiguration { @@ -75,7 +75,7 @@ public class FacebookAutoConfiguration { } @Bean(name = { "connect/facebookConnect", "connect/facebookConnected" }) - @ConditionalOnProperty(prefix = "spring.social.", value = "auto-connection-views") + @ConditionalOnProperty(prefix = "spring.social", name = "auto-connection-views") public View facebookConnectView() { return new GenericConnectionStatusView("facebook", "Facebook"); } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/LinkedInAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/LinkedInAutoConfiguration.java index f9fb652ead1..73cb7b9889f 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/LinkedInAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/LinkedInAutoConfiguration.java @@ -49,7 +49,7 @@ import org.springframework.web.servlet.View; */ @Configuration @ConditionalOnClass({ SocialConfigurerAdapter.class, LinkedInConnectionFactory.class }) -@ConditionalOnProperty(prefix = "spring.social.linkedin.", value = "app-id") +@ConditionalOnProperty(prefix = "spring.social.linkedin", name = "app-id") @AutoConfigureBefore(SocialWebAutoConfiguration.class) @AutoConfigureAfter(WebMvcAutoConfiguration.class) public class LinkedInAutoConfiguration { @@ -74,7 +74,7 @@ public class LinkedInAutoConfiguration { } @Bean(name = { "connect/linkedinConnect", "connect/linkedinConnected" }) - @ConditionalOnProperty(prefix = "spring.social.", value = "auto-connection-views") + @ConditionalOnProperty(prefix = "spring.social", name = "auto-connection-views") public View linkedInConnectView() { return new GenericConnectionStatusView("linkedin", "LinkedIn"); } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/SocialWebAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/SocialWebAutoConfiguration.java index 8c6e9e52bff..a46a2a80ec5 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/SocialWebAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/SocialWebAutoConfiguration.java @@ -99,7 +99,7 @@ public class SocialWebAutoConfiguration { @Bean @ConditionalOnMissingBean(BeanNameViewResolver.class) - @ConditionalOnProperty(prefix = "spring.social.", value = "auto-connection-views") + @ConditionalOnProperty(prefix = "spring.social", name = "auto-connection-views") public ViewResolver beanNameViewResolver() { BeanNameViewResolver viewResolver = new BeanNameViewResolver(); viewResolver.setOrder(Integer.MIN_VALUE); diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/TwitterAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/TwitterAutoConfiguration.java index fa008e891f3..dd6f394a508 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/TwitterAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/social/TwitterAutoConfiguration.java @@ -50,7 +50,7 @@ import org.springframework.web.servlet.View; */ @Configuration @ConditionalOnClass({ SocialConfigurerAdapter.class, TwitterConnectionFactory.class }) -@ConditionalOnProperty(prefix = "spring.social.twitter.", value = "app-id") +@ConditionalOnProperty(prefix = "spring.social.twitter", name = "app-id") @AutoConfigureBefore(SocialWebAutoConfiguration.class) @AutoConfigureAfter(WebMvcAutoConfiguration.class) public class TwitterAutoConfiguration { @@ -79,7 +79,7 @@ public class TwitterAutoConfiguration { } @Bean(name = { "connect/twitterConnect", "connect/twitterConnected" }) - @ConditionalOnProperty(prefix = "spring.social.", value = "auto-connection-views") + @ConditionalOnProperty(prefix = "spring.social", name = "auto-connection-views") public View twitterConnectView() { return new GenericConnectionStatusView("twitter", "Twitter"); } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java index e545dcb435d..0ea0c91f21c 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java @@ -197,14 +197,14 @@ public class WebMvcAutoConfiguration { @Bean @ConditionalOnMissingBean(LocaleResolver.class) - @ConditionalOnProperty(prefix = "spring.mvc.", value = "locale") + @ConditionalOnProperty(prefix = "spring.mvc", name = "locale") public LocaleResolver localeResolver() { return new FixedLocaleResolver( StringUtils.parseLocaleString(this.mvcProperties.getLocale())); } @Bean - @ConditionalOnProperty(prefix = "spring.mvc.", value = "date-format") + @ConditionalOnProperty(prefix = "spring.mvc", name = "date-format") public Formatter dateFormatter() { return new DateFormatter(this.mvcProperties.getDateFormat()); } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnPropertyTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnPropertyTests.java index b8381c798c3..89da1b27d7e 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnPropertyTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnPropertyTests.java @@ -17,23 +17,31 @@ package org.springframework.boot.autoconfigure.condition; import org.junit.After; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage; /** * Tests for {@link ConditionalOnProperty}. * * @author Maciej Walkowiak * @author Stephane Nicoll + * @author Phillip Webb */ public class ConditionalOnPropertyTests { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private AnnotationConfigApplicationContext context; @After @@ -45,29 +53,28 @@ public class ConditionalOnPropertyTests { @Test public void allPropertiesAreDefined() { - load(MultiplePropertiesRequiredConfiguration.class, - "property1=value1", "property2=value2"); + load(MultiplePropertiesRequiredConfiguration.class, "property1=value1", + "property2=value2"); assertTrue(this.context.containsBean("foo")); } @Test public void notAllPropertiesAreDefined() { - load(MultiplePropertiesRequiredConfiguration.class, - "property1=value1"); + load(MultiplePropertiesRequiredConfiguration.class, "property1=value1"); assertFalse(this.context.containsBean("foo")); } @Test public void propertyValueEqualsFalse() { - load(MultiplePropertiesRequiredConfiguration.class, - "property1=false", "property2=value2"); + load(MultiplePropertiesRequiredConfiguration.class, "property1=false", + "property2=value2"); assertFalse(this.context.containsBean("foo")); } @Test public void propertyValueEqualsFALSE() { - load(MultiplePropertiesRequiredConfiguration.class, - "property1=FALSE", "property2=value2"); + load(MultiplePropertiesRequiredConfiguration.class, "property1=FALSE", + "property2=value2"); assertFalse(this.context.containsBean("foo")); } @@ -87,12 +94,12 @@ public class ConditionalOnPropertyTests { @Test public void nonRelaxedName() throws Exception { - load(NonRelaxedPropertiesRequiredConfiguration.class, - "theRelaxedProperty=value1"); + load(NonRelaxedPropertiesRequiredConfiguration.class, "theRelaxedProperty=value1"); assertFalse(this.context.containsBean("foo")); } - @Test // Enabled by default + @Test + // Enabled by default public void enabledIfNotConfiguredOtherwise() { load(EnabledIfNotConfiguredOtherwiseConfig.class); assertTrue(this.context.containsBean("foo")); @@ -110,7 +117,8 @@ public class ConditionalOnPropertyTests { assertFalse(this.context.containsBean("foo")); } - @Test // Disabled by default + @Test + // Disabled by default public void disableIfNotConfiguredOtherwise() { load(DisabledIfNotConfiguredOtherwiseConfig.class); assertFalse(this.context.containsBean("foo")); @@ -184,7 +192,8 @@ public class ConditionalOnPropertyTests { @Test public void multiValuesAllSet() { - load(MultiValuesConfig.class, "simple.my-property:bar", "simple.my-another-property:bar"); + load(MultiValuesConfig.class, "simple.my-property:bar", + "simple.my-another-property:bar"); assertTrue(this.context.containsBean("foo")); } @@ -194,6 +203,28 @@ public class ConditionalOnPropertyTests { assertFalse(this.context.containsBean("foo")); } + @Test + public void usingValueAttribute() throws Exception { + load(ValueAttribute.class, "some.property"); + assertTrue(this.context.containsBean("foo")); + } + + @Test + public void nameOrValueMustBeSpecified() throws Exception { + this.thrown.expect(IllegalStateException.class); + this.thrown.expectCause(hasMessage(containsString("The name or " + + "value attribute of @ConditionalOnProperty must be specified"))); + load(NoNameOrValueAttribute.class, "some.property"); + } + + @Test + public void nameAndValueMustNotBeSpecified() throws Exception { + this.thrown.expect(IllegalStateException.class); + this.thrown.expectCause(hasMessage(containsString("The name and " + + "value attributes of @ConditionalOnProperty are exclusive"))); + load(NameAndValueAttribute.class, "some.property"); + } + private void load(Class config, String... environment) { this.context = new AnnotationConfigApplicationContext(); EnvironmentTestUtils.addEnvironment(this.context, environment); @@ -201,9 +232,8 @@ public class ConditionalOnPropertyTests { this.context.refresh(); } - @Configuration - @ConditionalOnProperty({ "property1", "property2" }) + @ConditionalOnProperty(name = { "property1", "property2" }) protected static class MultiplePropertiesRequiredConfiguration { @Bean @@ -214,7 +244,7 @@ public class ConditionalOnPropertyTests { } @Configuration - @ConditionalOnProperty(prefix = "spring.", value = "the-relaxed-property") + @ConditionalOnProperty(prefix = "spring.", name = "the-relaxed-property") protected static class RelaxedPropertiesRequiredConfiguration { @Bean @@ -225,7 +255,7 @@ public class ConditionalOnPropertyTests { } @Configuration - @ConditionalOnProperty(prefix = "spring", value = "property") + @ConditionalOnProperty(prefix = "spring", name = "property") protected static class RelaxedPropertiesRequiredConfigurationWithShortPrefix { @Bean @@ -236,7 +266,7 @@ public class ConditionalOnPropertyTests { } @Configuration - @ConditionalOnProperty(value = "the-relaxed-property", relaxedNames = false) + @ConditionalOnProperty(name = "the-relaxed-property", relaxedNames = false) protected static class NonRelaxedPropertiesRequiredConfiguration { @Bean @@ -246,8 +276,9 @@ public class ConditionalOnPropertyTests { } - @Configuration // ${simple.myProperty:true} - @ConditionalOnProperty(prefix = "simple", value = "my-property", match = "true", defaultMatch = true) + @Configuration + // i.e ${simple.myProperty:true} + @ConditionalOnProperty(prefix = "simple", name = "my-property", havingValue = "true", matchIfMissing = true) static class EnabledIfNotConfiguredOtherwiseConfig { @Bean @@ -257,8 +288,9 @@ public class ConditionalOnPropertyTests { } - @Configuration // ${simple.myProperty:false} - @ConditionalOnProperty(prefix = "simple", value = "my-property", match = "true", defaultMatch = false) + @Configuration + // i.e ${simple.myProperty:false} + @ConditionalOnProperty(prefix = "simple", name = "my-property", havingValue = "true", matchIfMissing = false) static class DisabledIfNotConfiguredOtherwiseConfig { @Bean @@ -269,7 +301,7 @@ public class ConditionalOnPropertyTests { } @Configuration - @ConditionalOnProperty(prefix = "simple", value = "my-property", match = "bar") + @ConditionalOnProperty(prefix = "simple", name = "my-property", havingValue = "bar") static class SimpleValueConfig { @Bean @@ -280,7 +312,7 @@ public class ConditionalOnPropertyTests { } @Configuration - @ConditionalOnProperty(value = "simple.myProperty", match = "bar", defaultMatch = true) + @ConditionalOnProperty(name = "simple.myProperty", havingValue = "bar", matchIfMissing = true) static class DefaultValueConfig { @Bean @@ -291,7 +323,7 @@ public class ConditionalOnPropertyTests { } @Configuration - @ConditionalOnProperty(prefix = "simple", value = "my-property", match = "bar") + @ConditionalOnProperty(prefix = "simple", name = "my-property", havingValue = "bar") static class PrefixValueConfig { @Bean @@ -302,7 +334,7 @@ public class ConditionalOnPropertyTests { } @Configuration - @ConditionalOnProperty(prefix = "simple", value = "my-property", match = "bar", relaxedNames = false) + @ConditionalOnProperty(prefix = "simple", name = "my-property", havingValue = "bar", relaxedNames = false) static class StrictNameConfig { @Bean @@ -313,7 +345,8 @@ public class ConditionalOnPropertyTests { } @Configuration - @ConditionalOnProperty(prefix = "simple", value = {"my-property", "my-another-property"}, match = "bar") + @ConditionalOnProperty(prefix = "simple", name = { "my-property", + "my-another-property" }, havingValue = "bar") static class MultiValuesConfig { @Bean @@ -323,4 +356,36 @@ public class ConditionalOnPropertyTests { } + @Configuration + @ConditionalOnProperty("some.property") + protected static class ValueAttribute { + + @Bean + public String foo() { + return "foo"; + } + + } + + @Configuration + @ConditionalOnProperty + protected static class NoNameOrValueAttribute { + + @Bean + public String foo() { + return "foo"; + } + + } + + @Configuration + @ConditionalOnProperty(value = "x", name = "y") + protected static class NameAndValueAttribute { + + @Bean + public String foo() { + return "foo"; + } + + } }