pull/5158/head
Phillip Webb 9 years ago
parent 2ae1435916
commit 7942d9f787

@ -82,7 +82,8 @@ public class InfoContributorAutoConfiguration {
@ConditionalOnSingleCandidate(BuildProperties.class) @ConditionalOnSingleCandidate(BuildProperties.class)
@Order(DEFAULT_ORDER) @Order(DEFAULT_ORDER)
public InfoContributor buildInfoContributor(BuildProperties buildProperties) { public InfoContributor buildInfoContributor(BuildProperties buildProperties) {
return new BuildInfoContributor(buildProperties, this.properties.getBuild().getMode()); return new BuildInfoContributor(buildProperties,
this.properties.getBuild().getMode());
} }
} }

@ -23,7 +23,6 @@ import org.springframework.boot.info.BuildProperties;
import org.springframework.core.env.PropertiesPropertySource; import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
/** /**
* An {@link InfoContributor} that exposes {@link BuildProperties}. * An {@link InfoContributor} that exposes {@link BuildProperties}.
* *

@ -62,9 +62,12 @@ public class GitInfoContributor extends InfoPropertiesInfoContributor<GitPropert
* are converted to {@link Date} instances. * are converted to {@link Date} instances.
* @param content the content to expose * @param content the content to expose
*/ */
@Override
protected void postProcessContent(Map<String, Object> content) { protected void postProcessContent(Map<String, Object> content) {
replaceValue(getNestedMap(content, "commit"), "time", getProperties().getCommitTime()); replaceValue(getNestedMap(content, "commit"), "time",
replaceValue(getNestedMap(content, "build"), "time", getProperties().getDate("build.time")); getProperties().getCommitTime());
replaceValue(getNestedMap(content, "build"), "time",
getProperties().getDate("build.time"));
} }
} }

@ -32,7 +32,8 @@ import org.springframework.util.StringUtils;
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 1.4.0 * @since 1.4.0
*/ */
public abstract class InfoPropertiesInfoContributor<T extends InfoProperties> implements InfoContributor { public abstract class InfoPropertiesInfoContributor<T extends InfoProperties>
implements InfoContributor {
private final T properties; private final T properties;
@ -103,9 +104,7 @@ public abstract class InfoPropertiesInfoContributor<T extends InfoProperties> im
if (this.mode.equals(Mode.FULL)) { if (this.mode.equals(Mode.FULL)) {
return this.properties.toPropertySource(); return this.properties.toPropertySource();
} }
else { return toSimplePropertySource();
return toSimplePropertySource();
}
} }
/** /**
@ -141,16 +140,13 @@ public abstract class InfoPropertiesInfoContributor<T extends InfoProperties> im
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected Map<String, Object> getNestedMap(Map<String, Object> map, String key) { protected Map<String, Object> getNestedMap(Map<String, Object> map, String key) {
Object o = map.get(key); Object value = map.get(key);
if (o == null) { if (value == null) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
else { return (Map<String, Object>) value;
return (Map<String, Object>) o;
}
} }
/** /**
* Defines how properties should be exposed. * Defines how properties should be exposed.
*/ */

@ -269,9 +269,10 @@ public class EndpointAutoConfigurationTests {
if (location.exists()) { if (location.exists()) {
Properties gitInfoProperties = PropertiesLoaderUtils Properties gitInfoProperties = PropertiesLoaderUtils
.loadProperties(location); .loadProperties(location);
PropertiesPropertySource gitPropertySource = PropertiesPropertySource gitPropertySource = new PropertiesPropertySource(
new PropertiesPropertySource("git", gitInfoProperties); "git", gitInfoProperties);
this.content = new PropertySourcesBinder(gitPropertySource).extractAll("git"); this.content = new PropertySourcesBinder(gitPropertySource)
.extractAll("git");
} }
} }

@ -85,8 +85,8 @@ public class InfoContributorAutoConfigurationTests {
Map<String, InfoContributor> beans = this.context Map<String, InfoContributor> beans = this.context
.getBeansOfType(InfoContributor.class); .getBeansOfType(InfoContributor.class);
assertThat(beans).containsKeys("gitInfoContributor"); assertThat(beans).containsKeys("gitInfoContributor");
Map<String, Object> content = Map<String, Object> content = invokeContributor(
invokeContributor(this.context.getBean("gitInfoContributor", InfoContributor.class)); this.context.getBean("gitInfoContributor", InfoContributor.class));
Object git = content.get("git"); Object git = content.get("git");
assertThat(git).isInstanceOf(Map.class); assertThat(git).isInstanceOf(Map.class);
Map<String, Object> gitInfo = (Map<String, Object>) git; Map<String, Object> gitInfo = (Map<String, Object>) git;
@ -97,8 +97,8 @@ public class InfoContributorAutoConfigurationTests {
@Test @Test
public void gitPropertiesFullMode() { public void gitPropertiesFullMode() {
load(GitPropertiesConfiguration.class, "management.info.git.mode=full"); load(GitPropertiesConfiguration.class, "management.info.git.mode=full");
Map<String, Object> content = Map<String, Object> content = invokeContributor(
invokeContributor(this.context.getBean("gitInfoContributor", InfoContributor.class)); this.context.getBean("gitInfoContributor", InfoContributor.class));
Object git = content.get("git"); Object git = content.get("git");
assertThat(git).isInstanceOf(Map.class); assertThat(git).isInstanceOf(Map.class);
Map<String, Object> gitInfo = (Map<String, Object>) git; Map<String, Object> gitInfo = (Map<String, Object>) git;
@ -120,8 +120,8 @@ public class InfoContributorAutoConfigurationTests {
Map<String, InfoContributor> beans = this.context Map<String, InfoContributor> beans = this.context
.getBeansOfType(InfoContributor.class); .getBeansOfType(InfoContributor.class);
assertThat(beans).containsKeys("buildInfoContributor"); assertThat(beans).containsKeys("buildInfoContributor");
Map<String, Object> content = Map<String, Object> content = invokeContributor(
invokeContributor(this.context.getBean("buildInfoContributor", InfoContributor.class)); this.context.getBean("buildInfoContributor", InfoContributor.class));
Object build = content.get("build"); Object build = content.get("build");
assertThat(build).isInstanceOf(Map.class); assertThat(build).isInstanceOf(Map.class);
Map<String, Object> gitInfo = (Map<String, Object>) build; Map<String, Object> gitInfo = (Map<String, Object>) build;
@ -132,8 +132,8 @@ public class InfoContributorAutoConfigurationTests {
@Test @Test
public void buildPropertiesFullMode() { public void buildPropertiesFullMode() {
load(BuildPropertiesConfiguration.class, "management.info.build.mode=full"); load(BuildPropertiesConfiguration.class, "management.info.build.mode=full");
Map<String, Object> content = Map<String, Object> content = invokeContributor(
invokeContributor(this.context.getBean("buildInfoContributor", InfoContributor.class)); this.context.getBean("buildInfoContributor", InfoContributor.class));
Object build = content.get("build"); Object build = content.get("build");
assertThat(build).isInstanceOf(Map.class); assertThat(build).isInstanceOf(Map.class);
Map<String, Object> gitInfo = (Map<String, Object>) build; Map<String, Object> gitInfo = (Map<String, Object>) build;

@ -62,24 +62,24 @@ public class SpringApplicationHierarchyTests {
@EnableAutoConfiguration(exclude = { ElasticsearchDataAutoConfiguration.class, @EnableAutoConfiguration(exclude = { ElasticsearchDataAutoConfiguration.class,
ElasticsearchRepositoriesAutoConfiguration.class, ElasticsearchRepositoriesAutoConfiguration.class,
CassandraAutoConfiguration.class, CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
CassandraDataAutoConfiguration.class,
RedisAutoConfiguration.class, RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class}, excludeName = { RedisRepositoriesAutoConfiguration.class }, excludeName = {
"org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" }) "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" })
public static class Child { public static class Child {
} }
@EnableAutoConfiguration(exclude = { JolokiaAutoConfiguration.class, @EnableAutoConfiguration(exclude = { JolokiaAutoConfiguration.class,
EndpointMBeanExportAutoConfiguration.class, EndpointMBeanExportAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class, ElasticsearchDataAutoConfiguration.class,
ElasticsearchRepositoriesAutoConfiguration.class, ElasticsearchRepositoriesAutoConfiguration.class,
CassandraAutoConfiguration.class, CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
CassandraDataAutoConfiguration.class,
RedisAutoConfiguration.class, RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class }, excludeName = { RedisRepositoriesAutoConfiguration.class }, excludeName = {
"org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" }) "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" })
public static class Parent { public static class Parent {
} }
} }

@ -39,7 +39,8 @@ public class GitInfoContributorTests {
Properties properties = new Properties(); Properties properties = new Properties();
properties.put("branch", "master"); properties.put("branch", "master");
properties.put("commit.time", "2016-03-04T14:36:33+0100"); properties.put("commit.time", "2016-03-04T14:36:33+0100");
GitInfoContributor contributor = new GitInfoContributor(new GitProperties(properties)); GitInfoContributor contributor = new GitInfoContributor(
new GitProperties(properties));
Map<String, Object> content = contributor.generateContent(); Map<String, Object> content = contributor.generateContent();
assertThat(content.get("commit")).isInstanceOf(Map.class); assertThat(content.get("commit")).isInstanceOf(Map.class);
Map<String, Object> commit = (Map<String, Object>) content.get("commit"); Map<String, Object> commit = (Map<String, Object>) content.get("commit");
@ -54,7 +55,8 @@ public class GitInfoContributorTests {
Properties properties = new Properties(); Properties properties = new Properties();
properties.put("branch", "master"); properties.put("branch", "master");
properties.put("commit.id", "8e29a0b0d423d2665c6ee5171947c101a5c15681"); properties.put("commit.id", "8e29a0b0d423d2665c6ee5171947c101a5c15681");
GitInfoContributor contributor = new GitInfoContributor(new GitProperties(properties)); GitInfoContributor contributor = new GitInfoContributor(
new GitProperties(properties));
Map<String, Object> content = contributor.generateContent(); Map<String, Object> content = contributor.generateContent();
assertThat(content.get("commit")).isInstanceOf(Map.class); assertThat(content.get("commit")).isInstanceOf(Map.class);
Map<String, Object> commit = (Map<String, Object>) content.get("commit"); Map<String, Object> commit = (Map<String, Object>) content.get("commit");

@ -29,8 +29,6 @@ import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties.Retry;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties.Template;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -161,29 +159,33 @@ public class RabbitAutoConfiguration {
if (messageConverter != null) { if (messageConverter != null) {
rabbitTemplate.setMessageConverter(messageConverter); rabbitTemplate.setMessageConverter(messageConverter);
} }
Template template = this.properties.getTemplate(); RabbitProperties.Template templateProperties = this.properties.getTemplate();
Retry retry = template.getRetry(); RabbitProperties.Retry retryProperties = templateProperties.getRetry();
if (retry.isEnabled()) { if (retryProperties.isEnabled()) {
RetryTemplate retryTemplate = new RetryTemplate(); rabbitTemplate.setRetryTemplate(createRetryTemplate(retryProperties));
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(retry.getMaxAttempts());
retryTemplate.setRetryPolicy(retryPolicy);
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(retry.getInitialInterval());
backOffPolicy.setMultiplier(retry.getMultiplier());
backOffPolicy.setMaxInterval(retry.getMaxInterval());
retryTemplate.setBackOffPolicy(backOffPolicy);
rabbitTemplate.setRetryTemplate(retryTemplate);
} }
if (template.getReceiveTimeout() != null) { if (templateProperties.getReceiveTimeout() != null) {
rabbitTemplate.setReceiveTimeout(template.getReceiveTimeout()); rabbitTemplate.setReceiveTimeout(templateProperties.getReceiveTimeout());
} }
if (template.getReplyTimeout() != null) { if (templateProperties.getReplyTimeout() != null) {
rabbitTemplate.setReplyTimeout(template.getReplyTimeout()); rabbitTemplate.setReplyTimeout(templateProperties.getReplyTimeout());
} }
return rabbitTemplate; return rabbitTemplate;
} }
private RetryTemplate createRetryTemplate(RabbitProperties.Retry properties) {
RetryTemplate template = new RetryTemplate();
SimpleRetryPolicy policy = new SimpleRetryPolicy();
policy.setMaxAttempts(properties.getMaxAttempts());
template.setRetryPolicy(policy);
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(properties.getInitialInterval());
backOffPolicy.setMultiplier(properties.getMultiplier());
backOffPolicy.setMaxInterval(properties.getMaxInterval());
template.setBackOffPolicy(backOffPolicy);
return template;
}
@Bean @Bean
@ConditionalOnSingleCandidate(ConnectionFactory.class) @ConditionalOnSingleCandidate(ConnectionFactory.class)
@ConditionalOnProperty(prefix = "spring.rabbitmq", name = "dynamic", matchIfMissing = true) @ConditionalOnProperty(prefix = "spring.rabbitmq", name = "dynamic", matchIfMissing = true)
@ -192,7 +194,6 @@ public class RabbitAutoConfiguration {
return new RabbitAdmin(connectionFactory); return new RabbitAdmin(connectionFactory);
} }
} }
@Configuration @Configuration

@ -512,8 +512,7 @@ public class RabbitProperties {
private int maxAttempts = 3; private int maxAttempts = 3;
/** /**
* Interval between the first and second attempt to publish or deliver * Interval between the first and second attempt to publish or deliver a message.
* a message.
*/ */
private long initialInterval = 1000L; private long initialInterval = 1000L;

@ -92,14 +92,14 @@ public final class SimpleRabbitListenerContainerFactoryConfigurer {
} }
ListenerRetry retryConfig = listenerConfig.getRetry(); ListenerRetry retryConfig = listenerConfig.getRetry();
if (retryConfig.isEnabled()) { if (retryConfig.isEnabled()) {
RetryInterceptorBuilder<?> builder = (retryConfig.isStateless() ? RetryInterceptorBuilder<?> builder = (retryConfig.isStateless()
RetryInterceptorBuilder.stateless() : RetryInterceptorBuilder.stateful()); ? RetryInterceptorBuilder.stateless()
factory.setAdviceChain(builder : RetryInterceptorBuilder.stateful());
.maxAttempts(retryConfig.getMaxAttempts()) builder.maxAttempts(retryConfig.getMaxAttempts());
.backOffOptions(retryConfig.getInitialInterval(), builder.backOffOptions(retryConfig.getInitialInterval(),
retryConfig.getMultiplier(), retryConfig.getMaxInterval()) retryConfig.getMultiplier(), retryConfig.getMaxInterval());
.recoverer(new RejectAndDontRequeueRecoverer()) builder.recoverer(new RejectAndDontRequeueRecoverer());
.build()); factory.setAdviceChain(builder.build());
} }
} }

@ -65,7 +65,7 @@ import org.springframework.util.Assert;
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver") @ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")
@EnableConfigurationProperties(CacheProperties.class) @EnableConfigurationProperties(CacheProperties.class)
@AutoConfigureBefore(HibernateJpaAutoConfiguration.class) @AutoConfigureBefore(HibernateJpaAutoConfiguration.class)
@AutoConfigureAfter({CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class, @AutoConfigureAfter({ CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class,
RedisAutoConfiguration.class }) RedisAutoConfiguration.class })
@Import({ CacheManagerCustomizers.class, CacheConfigurationImportSelector.class }) @Import({ CacheManagerCustomizers.class, CacheConfigurationImportSelector.class })
public class CacheAutoConfiguration { public class CacheAutoConfiguration {

@ -30,9 +30,6 @@ import org.springframework.util.Assert;
*/ */
final class CacheConfigurations { final class CacheConfigurations {
private CacheConfigurations() {
}
private static final Map<CacheType, Class<?>> MAPPINGS; private static final Map<CacheType, Class<?>> MAPPINGS;
static { static {
@ -51,6 +48,9 @@ final class CacheConfigurations {
MAPPINGS = Collections.unmodifiableMap(mappings); MAPPINGS = Collections.unmodifiableMap(mappings);
} }
private CacheConfigurations() {
}
public static String getConfigurationClass(CacheType cacheType) { public static String getConfigurationClass(CacheType cacheType) {
Class<?> configurationClass = MAPPINGS.get(cacheType); Class<?> configurationClass = MAPPINGS.get(cacheType);
Assert.state(configurationClass != null, "Unknown cache type " + cacheType); Assert.state(configurationClass != null, "Unknown cache type " + cacheType);

@ -37,7 +37,7 @@ import org.springframework.context.annotation.Configuration;
* @since 1.4.0 * @since 1.4.0
*/ */
@Configuration @Configuration
@ConditionalOnClass({Bucket.class, CouchbaseCacheManager.class}) @ConditionalOnClass({ Bucket.class, CouchbaseCacheManager.class })
@ConditionalOnMissingBean(CacheManager.class) @ConditionalOnMissingBean(CacheManager.class)
@ConditionalOnSingleCandidate(Bucket.class) @ConditionalOnSingleCandidate(Bucket.class)
@Conditional(CacheCondition.class) @Conditional(CacheCondition.class)
@ -60,8 +60,8 @@ public class CouchbaseCacheConfiguration {
public CouchbaseCacheManager cacheManager() { public CouchbaseCacheManager cacheManager() {
List<String> cacheNames = this.cacheProperties.getCacheNames(); List<String> cacheNames = this.cacheProperties.getCacheNames();
CouchbaseCacheManager cacheManager = new CouchbaseCacheManager( CouchbaseCacheManager cacheManager = new CouchbaseCacheManager(
CacheBuilder.newInstance(this.bucket) CacheBuilder.newInstance(this.bucket).withExpirationInMillis(
.withExpirationInMillis(this.cacheProperties.getCouchbase().getExpiration()), this.cacheProperties.getCouchbase().getExpiration()),
cacheNames.toArray(new String[cacheNames.size()])); cacheNames.toArray(new String[cacheNames.size()]));
return this.customizers.customize(cacheManager); return this.customizers.customize(cacheManager);
} }

@ -45,12 +45,11 @@ import org.springframework.data.couchbase.config.CouchbaseConfigurer;
* @since 1.4.0 * @since 1.4.0
*/ */
@Configuration @Configuration
@ConditionalOnClass({CouchbaseBucket.class, Cluster.class}) @ConditionalOnClass({ CouchbaseBucket.class, Cluster.class })
@Conditional(CouchbaseAutoConfiguration.CouchbaseCondition.class) @Conditional(CouchbaseAutoConfiguration.CouchbaseCondition.class)
@EnableConfigurationProperties(CouchbaseProperties.class) @EnableConfigurationProperties(CouchbaseProperties.class)
public class CouchbaseAutoConfiguration { public class CouchbaseAutoConfiguration {
@Configuration @Configuration
@ConditionalOnMissingBean(CouchbaseConfigurer.class) @ConditionalOnMissingBean(CouchbaseConfigurer.class)
public static class CouchbaseConfiguration { public static class CouchbaseConfiguration {
@ -77,8 +76,10 @@ public class CouchbaseAutoConfiguration {
@Bean @Bean
@Primary @Primary
public ClusterInfo couchbaseClusterInfo() throws Exception { public ClusterInfo couchbaseClusterInfo() throws Exception {
return couchbaseCluster().clusterManager(this.properties.getBucket().getName(), return couchbaseCluster()
this.properties.getBucket().getPassword()).info(); .clusterManager(this.properties.getBucket().getName(),
this.properties.getBucket().getPassword())
.info();
} }
@Bean @Bean
@ -96,13 +97,12 @@ public class CouchbaseAutoConfiguration {
protected CouchbaseEnvironment createEnvironment(CouchbaseProperties properties) { protected CouchbaseEnvironment createEnvironment(CouchbaseProperties properties) {
CouchbaseProperties.Endpoints endpoints = properties.getEnv().getEndpoints(); CouchbaseProperties.Endpoints endpoints = properties.getEnv().getEndpoints();
CouchbaseProperties.Timeouts timeouts = properties.getEnv().getTimeouts(); CouchbaseProperties.Timeouts timeouts = properties.getEnv().getTimeouts();
DefaultCouchbaseEnvironment.Builder builder = DefaultCouchbaseEnvironment.builder() DefaultCouchbaseEnvironment.Builder builder = DefaultCouchbaseEnvironment
.connectTimeout(timeouts.getConnect()) .builder().connectTimeout(timeouts.getConnect())
.kvEndpoints(endpoints.getKeyValue()) .kvEndpoints(endpoints.getKeyValue())
.kvTimeout(timeouts.getKeyValue()) .kvTimeout(timeouts.getKeyValue())
.queryEndpoints(endpoints.getQuery()) .queryEndpoints(endpoints.getQuery())
.queryTimeout(timeouts.getQuery()) .queryTimeout(timeouts.getQuery()).viewEndpoints(endpoints.getView())
.viewEndpoints(endpoints.getView())
.viewTimeout(timeouts.getView()); .viewTimeout(timeouts.getView());
CouchbaseProperties.Ssl ssl = properties.getEnv().getSsl(); CouchbaseProperties.Ssl ssl = properties.getEnv().getSsl();
if (ssl.getEnabled()) { if (ssl.getEnabled()) {
@ -121,8 +121,8 @@ public class CouchbaseAutoConfiguration {
/** /**
* Determine if Couchbase should be configured. This happens if either the * Determine if Couchbase should be configured. This happens if either the
* user-configuration defines a {@link CouchbaseConfigurer} or if at least * user-configuration defines a {@link CouchbaseConfigurer} or if at least the
* the "bootstrapHosts" property is specified. * "bootstrapHosts" property is specified.
*/ */
static class CouchbaseCondition extends AnyNestedCondition { static class CouchbaseCondition extends AnyNestedCondition {

@ -57,7 +57,6 @@ public class CouchbaseProperties {
return this.env; return this.env;
} }
public static class Bucket { public static class Bucket {
/** /**
@ -175,7 +174,8 @@ public class CouchbaseProperties {
private String keyStorePassword; private String keyStorePassword;
public Boolean getEnabled() { public Boolean getEnabled() {
return (this.enabled != null ? this.enabled : StringUtils.hasText(this.keyStore)); return (this.enabled != null ? this.enabled
: StringUtils.hasText(this.keyStore));
} }
public void setEnabled(Boolean enabled) { public void setEnabled(Boolean enabled) {

@ -25,8 +25,8 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.config.CouchbaseConfigurer; import org.springframework.data.couchbase.config.CouchbaseConfigurer;
/** /**
* Adapt the core Couchbase configuration to an expected {@link CouchbaseConfigurer} * Adapt the core Couchbase configuration to an expected {@link CouchbaseConfigurer} if
* if necessary. * necessary.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
@ -44,8 +44,10 @@ class CouchbaseConfigurerAdapterConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public CouchbaseConfigurer springBootCouchbaseConfigurer() throws Exception { public CouchbaseConfigurer springBootCouchbaseConfigurer() throws Exception {
return new SpringBootCouchbaseConfigurer(this.configuration.couchbaseEnvironment(), return new SpringBootCouchbaseConfigurer(
this.configuration.couchbaseCluster(), this.configuration.couchbaseClusterInfo(), this.configuration.couchbaseEnvironment(),
this.configuration.couchbaseCluster(),
this.configuration.couchbaseClusterInfo(),
this.configuration.couchbaseClient()); this.configuration.couchbaseClient());
} }

@ -40,7 +40,7 @@ import org.springframework.data.couchbase.repository.CouchbaseRepository;
* @since 1.4.0 * @since 1.4.0
*/ */
@Configuration @Configuration
@ConditionalOnClass({Bucket.class, CouchbaseRepository.class}) @ConditionalOnClass({ Bucket.class, CouchbaseRepository.class })
@AutoConfigureAfter(CouchbaseAutoConfiguration.class) @AutoConfigureAfter(CouchbaseAutoConfiguration.class)
@EnableConfigurationProperties(CouchbaseDataProperties.class) @EnableConfigurationProperties(CouchbaseDataProperties.class)
@Import({ CouchbaseConfigurerAdapterConfiguration.class, @Import({ CouchbaseConfigurerAdapterConfiguration.class,

@ -29,7 +29,6 @@ import org.springframework.data.repository.config.RepositoryConfigurationExtensi
* Repositories. * Repositories.
* *
* @author Eddú Meléndez * @author Eddú Meléndez
* @since 1.4.0
*/ */
class CouchbaseRepositoriesRegistrar class CouchbaseRepositoriesRegistrar
extends AbstractRepositoryConfigurationSourceSupport { extends AbstractRepositoryConfigurationSourceSupport {

@ -68,9 +68,7 @@ class SpringBootCouchbaseDataConfiguration extends AbstractCouchbaseDataConfigur
if (this.properties.isAutoIndex()) { if (this.properties.isAutoIndex()) {
return new IndexManager(true, true, true); return new IndexManager(true, true, true);
} }
else { return new IndexManager(false, false, false);
return new IndexManager(false, false, false);
}
} }
} }

@ -43,4 +43,5 @@ import org.springframework.data.redis.repository.support.RedisRepositoryFactoryB
@Import(RedisRepositoriesAutoConfigureRegistrar.class) @Import(RedisRepositoriesAutoConfigureRegistrar.class)
@AutoConfigureAfter(RedisAutoConfiguration.class) @AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisRepositoriesAutoConfiguration { public class RedisRepositoriesAutoConfiguration {
} }

@ -50,6 +50,7 @@ class RedisRepositoriesAutoConfigureRegistrar
@EnableRedisRepositories @EnableRedisRepositories
private static class EnableRedisRepositoriesConfiguration { private static class EnableRedisRepositoriesConfiguration {
} }
} }

@ -63,7 +63,8 @@ public class H2ConsoleAutoConfiguration {
public ServletRegistrationBean h2Console() { public ServletRegistrationBean h2Console() {
String path = this.properties.getPath(); String path = this.properties.getPath();
String urlMapping = (path.endsWith("/") ? path + "*" : path + "/*"); String urlMapping = (path.endsWith("/") ? path + "*" : path + "/*");
ServletRegistrationBean registration = new ServletRegistrationBean(new WebServlet(), urlMapping); ServletRegistrationBean registration = new ServletRegistrationBean(
new WebServlet(), urlMapping);
H2ConsoleProperties.Settings settings = this.properties.getSettings(); H2ConsoleProperties.Settings settings = this.properties.getSettings();
if (settings.isTrace()) { if (settings.isTrace()) {
registration.addInitParameter("trace", ""); registration.addInitParameter("trace", "");

@ -66,7 +66,8 @@ public class ProjectInfoAutoConfiguration {
@ConditionalOnMissingBean @ConditionalOnMissingBean
@Bean @Bean
public BuildProperties buildProperties() throws Exception { public BuildProperties buildProperties() throws Exception {
return new BuildProperties(loadFrom(this.properties.getBuild().getLocation(), "build")); return new BuildProperties(
loadFrom(this.properties.getBuild().getLocation(), "build"));
} }
protected Properties loadFrom(Resource location, String prefix) throws IOException { protected Properties loadFrom(Resource location, String prefix) throws IOException {
@ -88,8 +89,10 @@ public class ProjectInfoAutoConfiguration {
@Override @Override
public ConditionOutcome getMatchOutcome(ConditionContext context, public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) { AnnotatedTypeMetadata metadata) {
ResourceLoader loader = context.getResourceLoader() == null ResourceLoader loader = context.getResourceLoader();
? this.defaultResourceLoader : context.getResourceLoader(); if (loader == null) {
loader = this.defaultResourceLoader;
}
PropertyResolver propertyResolver = context.getEnvironment(); PropertyResolver propertyResolver = context.getEnvironment();
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver( RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
propertyResolver, "spring.info.git."); propertyResolver, "spring.info.git.");

@ -53,7 +53,6 @@ public class ProjectInfoProperties {
getGit().setLocation(defaultGitLocation); getGit().setLocation(defaultGitLocation);
} }
/** /**
* Build specific info properties. * Build specific info properties.
*/ */
@ -62,7 +61,8 @@ public class ProjectInfoProperties {
/** /**
* Location of the generated build.properties file. * Location of the generated build.properties file.
*/ */
private Resource location = new ClassPathResource("META-INF/boot/build.properties"); private Resource location = new ClassPathResource(
"META-INF/boot/build.properties");
public Resource getLocation() { public Resource getLocation() {
return this.location; return this.location;

@ -65,7 +65,8 @@ public class JmsAutoConfiguration {
public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) { public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {
JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory); JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
jmsTemplate.setPubSubDomain(this.properties.isPubSubDomain()); jmsTemplate.setPubSubDomain(this.properties.isPubSubDomain());
DestinationResolver destinationResolver = this.destinationResolver.getIfUnique(); DestinationResolver destinationResolver = this.destinationResolver
.getIfUnique();
if (destinationResolver != null) { if (destinationResolver != null) {
jmsTemplate.setDestinationResolver(destinationResolver); jmsTemplate.setDestinationResolver(destinationResolver);
} }

@ -55,7 +55,8 @@ class ActiveMQConnectionFactoryConfiguration {
@Bean(destroyMethod = "stop") @Bean(destroyMethod = "stop")
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false) @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false)
@ConfigurationProperties("spring.activemq.pool.configuration") @ConfigurationProperties("spring.activemq.pool.configuration")
public PooledConnectionFactory pooledJmsConnectionFactory(ActiveMQProperties properties) { public PooledConnectionFactory pooledJmsConnectionFactory(
ActiveMQProperties properties) {
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory( PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(
new ActiveMQConnectionFactoryFactory(properties) new ActiveMQConnectionFactoryFactory(properties)
.createConnectionFactory(ActiveMQConnectionFactory.class)); .createConnectionFactory(ActiveMQConnectionFactory.class));

@ -67,6 +67,26 @@ public class ActiveMQProperties {
this.inMemory = inMemory; this.inMemory = inMemory;
} }
/**
* Get if pooling is enabled.
* @return if pooling is enabled
* @deprecated since 1.4 in favor of "spring.activemq.pool.enabled"
*/
@Deprecated
public boolean isPooled() {
return getPool().isEnabled();
}
/**
* Set if pooling is enabled.
* @param pooled the pooling enabled value
* @deprecated since 1.4 in favor of "spring.activemq.pool.enabled"
*/
@Deprecated
public void setPooled(boolean pooled) {
getPool().setEnabled(pooled);
}
public String getUser() { public String getUser() {
return this.user; return this.user;
} }
@ -91,7 +111,7 @@ public class ActiveMQProperties {
this.pool = pool; this.pool = pool;
} }
protected static class Pool { public static class Pool {
/** /**
* Whether a PooledConnectionFactory should be created instead of a regular * Whether a PooledConnectionFactory should be created instead of a regular
@ -147,4 +167,5 @@ public class ActiveMQProperties {
} }
} }
} }

@ -45,7 +45,7 @@ import org.springframework.context.annotation.Primary;
class ActiveMQXAConnectionFactoryConfiguration { class ActiveMQXAConnectionFactoryConfiguration {
@Primary @Primary
@Bean(name = {"jmsConnectionFactory", "xaJmsConnectionFactory"}) @Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" })
public ConnectionFactory jmsConnectionFactory(ActiveMQProperties properties, public ConnectionFactory jmsConnectionFactory(ActiveMQProperties properties,
XAConnectionFactoryWrapper wrapper) throws Exception { XAConnectionFactoryWrapper wrapper) throws Exception {
ActiveMQXAConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory( ActiveMQXAConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory(

@ -158,11 +158,14 @@ public class RabbitAutoConfigurationTests {
DirectFieldAccessor dfa = new DirectFieldAccessor(rabbitTemplate); DirectFieldAccessor dfa = new DirectFieldAccessor(rabbitTemplate);
assertThat(dfa.getPropertyValue("receiveTimeout")).isEqualTo(123L); assertThat(dfa.getPropertyValue("receiveTimeout")).isEqualTo(123L);
assertThat(dfa.getPropertyValue("replyTimeout")).isEqualTo(456L); assertThat(dfa.getPropertyValue("replyTimeout")).isEqualTo(456L);
RetryTemplate retryTemplate = (RetryTemplate) dfa.getPropertyValue("retryTemplate"); RetryTemplate retryTemplate = (RetryTemplate) dfa
.getPropertyValue("retryTemplate");
assertThat(retryTemplate).isNotNull(); assertThat(retryTemplate).isNotNull();
dfa = new DirectFieldAccessor(retryTemplate); dfa = new DirectFieldAccessor(retryTemplate);
SimpleRetryPolicy retryPolicy = (SimpleRetryPolicy) dfa.getPropertyValue("retryPolicy"); SimpleRetryPolicy retryPolicy = (SimpleRetryPolicy) dfa
ExponentialBackOffPolicy backOffPolicy = (ExponentialBackOffPolicy) dfa.getPropertyValue("backOffPolicy"); .getPropertyValue("retryPolicy");
ExponentialBackOffPolicy backOffPolicy = (ExponentialBackOffPolicy) dfa
.getPropertyValue("backOffPolicy");
assertThat(retryPolicy.getMaxAttempts()).isEqualTo(4); assertThat(retryPolicy.getMaxAttempts()).isEqualTo(4);
assertThat(backOffPolicy.getInitialInterval()).isEqualTo(2000); assertThat(backOffPolicy.getInitialInterval()).isEqualTo(2000);
assertThat(backOffPolicy.getMultiplier()).isEqualTo(1.5); assertThat(backOffPolicy.getMultiplier()).isEqualTo(1.5);
@ -182,8 +185,7 @@ public class RabbitAutoConfigurationTests {
@Test @Test
public void testConnectionFactoryCacheSettings() { public void testConnectionFactoryCacheSettings() {
load(TestConfiguration.class, load(TestConfiguration.class, "spring.rabbitmq.cache.channel.size=23",
"spring.rabbitmq.cache.channel.size=23",
"spring.rabbitmq.cache.channel.checkoutTimeout=1000", "spring.rabbitmq.cache.channel.checkoutTimeout=1000",
"spring.rabbitmq.cache.connection.mode=CONNECTION", "spring.rabbitmq.cache.connection.mode=CONNECTION",
"spring.rabbitmq.cache.connection.size=2"); "spring.rabbitmq.cache.connection.size=2");
@ -273,16 +275,20 @@ public class RabbitAutoConfigurationTests {
assertThat(dfa.getPropertyValue("txSize")).isEqualTo(20); assertThat(dfa.getPropertyValue("txSize")).isEqualTo(20);
assertThat(dfa.getPropertyValue("messageConverter")) assertThat(dfa.getPropertyValue("messageConverter"))
.isSameAs(this.context.getBean("myMessageConverter")); .isSameAs(this.context.getBean("myMessageConverter"));
assertThat(dfa.getPropertyValue("defaultRequeueRejected")).isEqualTo(Boolean.FALSE); assertThat(dfa.getPropertyValue("defaultRequeueRejected"))
.isEqualTo(Boolean.FALSE);
Advice[] adviceChain = (Advice[]) dfa.getPropertyValue("adviceChain"); Advice[] adviceChain = (Advice[]) dfa.getPropertyValue("adviceChain");
assertThat(adviceChain).isNotNull(); assertThat(adviceChain).isNotNull();
assertThat(adviceChain.length).isEqualTo(1); assertThat(adviceChain.length).isEqualTo(1);
dfa = new DirectFieldAccessor(adviceChain[0]); dfa = new DirectFieldAccessor(adviceChain[0]);
RetryTemplate retryTemplate = (RetryTemplate) dfa.getPropertyValue("retryOperations"); RetryTemplate retryTemplate = (RetryTemplate) dfa
.getPropertyValue("retryOperations");
assertThat(retryTemplate).isNotNull(); assertThat(retryTemplate).isNotNull();
dfa = new DirectFieldAccessor(retryTemplate); dfa = new DirectFieldAccessor(retryTemplate);
SimpleRetryPolicy retryPolicy = (SimpleRetryPolicy) dfa.getPropertyValue("retryPolicy"); SimpleRetryPolicy retryPolicy = (SimpleRetryPolicy) dfa
ExponentialBackOffPolicy backOffPolicy = (ExponentialBackOffPolicy) dfa.getPropertyValue("backOffPolicy"); .getPropertyValue("retryPolicy");
ExponentialBackOffPolicy backOffPolicy = (ExponentialBackOffPolicy) dfa
.getPropertyValue("backOffPolicy");
assertThat(retryPolicy.getMaxAttempts()).isEqualTo(4); assertThat(retryPolicy.getMaxAttempts()).isEqualTo(4);
assertThat(backOffPolicy.getInitialInterval()).isEqualTo(2000); assertThat(backOffPolicy.getInitialInterval()).isEqualTo(2000);
assertThat(backOffPolicy.getMultiplier()).isEqualTo(1.5); assertThat(backOffPolicy.getMultiplier()).isEqualTo(1.5);
@ -427,10 +433,12 @@ public class RabbitAutoConfigurationTests {
@Configuration @Configuration
@EnableRabbit @EnableRabbit
protected static class EnableRabbitConfiguration { protected static class EnableRabbitConfiguration {
} }
@Configuration @Configuration
protected static class NoEnableRabbitConfiguration { protected static class NoEnableRabbitConfiguration {
} }
} }

@ -214,7 +214,8 @@ public class CacheAutoConfigurationTests {
@Test @Test
public void couchbaseCacheExplicit() { public void couchbaseCacheExplicit() {
load(CouchbaseCacheConfiguration.class, "spring.cache.type=couchbase"); load(CouchbaseCacheConfiguration.class, "spring.cache.type=couchbase");
CouchbaseCacheManager cacheManager = validateCacheManager(CouchbaseCacheManager.class); CouchbaseCacheManager cacheManager = validateCacheManager(
CouchbaseCacheManager.class);
assertThat(cacheManager.getCacheNames()).isEmpty(); assertThat(cacheManager.getCacheNames()).isEmpty();
} }
@ -228,24 +229,29 @@ public class CacheAutoConfigurationTests {
public void couchbaseCacheExplicitWithCaches() { public void couchbaseCacheExplicitWithCaches() {
load(CouchbaseCacheConfiguration.class, "spring.cache.type=couchbase", load(CouchbaseCacheConfiguration.class, "spring.cache.type=couchbase",
"spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar"); "spring.cache.cacheNames[0]=foo", "spring.cache.cacheNames[1]=bar");
CouchbaseCacheManager cacheManager = validateCacheManager(CouchbaseCacheManager.class); CouchbaseCacheManager cacheManager = validateCacheManager(
CouchbaseCacheManager.class);
assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar");
Cache cache = cacheManager.getCache("foo"); Cache cache = cacheManager.getCache("foo");
assertThat(cache).isInstanceOf(CouchbaseCache.class); assertThat(cache).isInstanceOf(CouchbaseCache.class);
assertThat(((CouchbaseCache) cache).getTtl()).isEqualTo(0); assertThat(((CouchbaseCache) cache).getTtl()).isEqualTo(0);
assertThat(((CouchbaseCache) cache).getNativeCache()).isEqualTo(this.context.getBean("bucket")); assertThat(((CouchbaseCache) cache).getNativeCache())
.isEqualTo(this.context.getBean("bucket"));
} }
@Test @Test
public void couchbaseCacheExplicitWithTtl() { public void couchbaseCacheExplicitWithTtl() {
load(CouchbaseCacheConfiguration.class, "spring.cache.type=couchbase", load(CouchbaseCacheConfiguration.class, "spring.cache.type=couchbase",
"spring.cache.cacheNames=foo,bar", "spring.cache.couchbase.expiration=2000"); "spring.cache.cacheNames=foo,bar",
CouchbaseCacheManager cacheManager = validateCacheManager(CouchbaseCacheManager.class); "spring.cache.couchbase.expiration=2000");
CouchbaseCacheManager cacheManager = validateCacheManager(
CouchbaseCacheManager.class);
assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar"); assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar");
Cache cache = cacheManager.getCache("foo"); Cache cache = cacheManager.getCache("foo");
assertThat(cache).isInstanceOf(CouchbaseCache.class); assertThat(cache).isInstanceOf(CouchbaseCache.class);
assertThat(((CouchbaseCache) cache).getTtl()).isEqualTo(2000); assertThat(((CouchbaseCache) cache).getTtl()).isEqualTo(2000);
assertThat(((CouchbaseCache) cache).getNativeCache()).isEqualTo(this.context.getBean("bucket")); assertThat(((CouchbaseCache) cache).getNativeCache())
.isEqualTo(this.context.getBean("bucket"));
} }
@Test @Test
@ -789,7 +795,8 @@ public class CacheAutoConfigurationTests {
} }
@Configuration @Configuration
@Import({ CouchbaseCacheConfiguration.class, CacheManagerCustomizersConfiguration.class }) @Import({ CouchbaseCacheConfiguration.class,
CacheManagerCustomizersConfiguration.class })
static class CouchbaseCacheAndCustomizersConfiguration { static class CouchbaseCacheAndCustomizersConfiguration {
} }

@ -23,6 +23,8 @@ import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/** /**
* Base class for {@link CouchbaseAutoConfiguration} tests.
*
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
public abstract class AbstractCouchbaseAutoConfigurationTests { public abstract class AbstractCouchbaseAutoConfigurationTests {

@ -59,7 +59,6 @@ public class CouchbaseAutoConfigurationIntegrationTests
assertThat(this.context.getBeansOfType(Bucket.class)).hasSize(2); assertThat(this.context.getBeansOfType(Bucket.class)).hasSize(2);
} }
@Configuration @Configuration
static class CustomConfiguration { static class CustomConfiguration {

@ -33,7 +33,8 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Eddú Meléndez * @author Eddú Meléndez
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
public class CouchbaseAutoConfigurationTests extends AbstractCouchbaseAutoConfigurationTests { public class CouchbaseAutoConfigurationTests
extends AbstractCouchbaseAutoConfigurationTests {
@Rule @Rule
public ExpectedException thrown = ExpectedException.none(); public ExpectedException thrown = ExpectedException.none();
@ -47,8 +48,7 @@ public class CouchbaseAutoConfigurationTests extends AbstractCouchbaseAutoConfig
@Test @Test
public void bootstrapHostsNotRequiredIfCouchbaseConfigurerIsSet() { public void bootstrapHostsNotRequiredIfCouchbaseConfigurerIsSet() {
load(CouchbaseTestConfigurer.class); load(CouchbaseTestConfigurer.class);
assertThat(this.context.getBeansOfType(CouchbaseTestConfigurer.class)) assertThat(this.context.getBeansOfType(CouchbaseTestConfigurer.class)).hasSize(1);
.hasSize(1);
// No beans are going to be created // No beans are going to be created
assertNoCouchbaseBeans(); assertNoCouchbaseBeans();
} }
@ -56,8 +56,7 @@ public class CouchbaseAutoConfigurationTests extends AbstractCouchbaseAutoConfig
@Test @Test
public void bootstrapHostsIgnoredIfCouchbaseConfigurerIsSet() { public void bootstrapHostsIgnoredIfCouchbaseConfigurerIsSet() {
load(CouchbaseTestConfigurer.class, "spring.couchbase.bootstrapHosts=localhost"); load(CouchbaseTestConfigurer.class, "spring.couchbase.bootstrapHosts=localhost");
assertThat(this.context.getBeansOfType(CouchbaseTestConfigurer.class)) assertThat(this.context.getBeansOfType(CouchbaseTestConfigurer.class)).hasSize(1);
.hasSize(1);
assertNoCouchbaseBeans(); assertNoCouchbaseBeans();
} }
@ -114,11 +113,12 @@ public class CouchbaseAutoConfigurationTests extends AbstractCouchbaseAutoConfig
assertThat(env.sslKeystorePassword()).isNull(); assertThat(env.sslKeystorePassword()).isNull();
} }
private DefaultCouchbaseEnvironment customizeEnv(String... environment) throws Exception { private DefaultCouchbaseEnvironment customizeEnv(String... environment)
throws Exception {
load(CouchbaseTestConfigurer.class, environment); load(CouchbaseTestConfigurer.class, environment);
CouchbaseProperties properties = this.context.getBean(CouchbaseProperties.class); CouchbaseProperties properties = this.context.getBean(CouchbaseProperties.class);
return (DefaultCouchbaseEnvironment) new CouchbaseAutoConfiguration.CouchbaseConfiguration(properties) return (DefaultCouchbaseEnvironment) new CouchbaseAutoConfiguration.CouchbaseConfiguration(
.couchbaseEnvironment(); properties).couchbaseEnvironment();
} }
} }

@ -25,14 +25,14 @@ import com.couchbase.client.java.env.CouchbaseEnvironment;
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment; import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.junit.Assume; import org.junit.AssumptionViolatedException;
import org.junit.rules.TestRule; import org.junit.rules.TestRule;
import org.junit.runner.Description; import org.junit.runner.Description;
import org.junit.runners.model.Statement; import org.junit.runners.model.Statement;
/** /**
* {@link TestRule} for working with an optional Couchbase server. Expects * {@link TestRule} for working with an optional Couchbase server. Expects a default
* a default {@link Bucket} with no password to be available on localhost. * {@link Bucket} with no password to be available on localhost.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
@ -40,19 +40,20 @@ public class CouchbaseTestServer implements TestRule {
private static final Log logger = LogFactory.getLog(CouchbaseTestServer.class); private static final Log logger = LogFactory.getLog(CouchbaseTestServer.class);
private CouchbaseEnvironment env; private CouchbaseEnvironment environment;
private Cluster cluster; private Cluster cluster;
@Override @Override
public Statement apply(Statement base, Description description) { public Statement apply(Statement base, Description description) {
try { try {
this.env = DefaultCouchbaseEnvironment.create(); this.environment = DefaultCouchbaseEnvironment.create();
this.cluster = CouchbaseCluster.create(this.env, "localhost"); this.cluster = CouchbaseCluster.create(this.environment,
"localhost");
testConnection(this.cluster); testConnection(this.cluster);
return new CouchbaseStatement(base, this.env, this.cluster); return new CouchbaseStatement(base, this.environment, this.cluster);
} }
catch (Exception e) { catch (Exception ex) {
logger.info("No couchbase server available"); logger.info("No couchbase server available");
return new SkipStatement(); return new SkipStatement();
} }
@ -64,10 +65,10 @@ public class CouchbaseTestServer implements TestRule {
} }
/** /**
* @return the couchbase env if any * @return the Couchbase environment if any
*/ */
public CouchbaseEnvironment getEnv() { public CouchbaseEnvironment getCouchbaseEnvironment() {
return this.env; return this.environment;
} }
/** /**
@ -77,16 +78,18 @@ public class CouchbaseTestServer implements TestRule {
return this.cluster; return this.cluster;
} }
private static class CouchbaseStatement extends Statement { private static class CouchbaseStatement extends Statement {
private final Statement base; private final Statement base;
private final CouchbaseEnvironment env;
private final CouchbaseEnvironment environment;
private final Cluster cluster; private final Cluster cluster;
CouchbaseStatement(Statement base, CouchbaseEnvironment env, Cluster cluster) { CouchbaseStatement(Statement base, CouchbaseEnvironment environment,
Cluster cluster) {
this.base = base; this.base = base;
this.env = env; this.environment = environment;
this.cluster = cluster; this.cluster = cluster;
} }
@ -98,10 +101,11 @@ public class CouchbaseTestServer implements TestRule {
finally { finally {
try { try {
this.cluster.disconnect(); this.cluster.disconnect();
this.env.shutdownAsync(); this.environment.shutdownAsync();
} }
catch (Exception ex) { catch (Exception ex) {
logger.warn("Exception while trying to cleanup couchbase resource", ex); logger.warn("Exception while trying to cleanup couchbase resource",
ex);
} }
} }
} }
@ -111,8 +115,8 @@ public class CouchbaseTestServer implements TestRule {
@Override @Override
public void evaluate() throws Throwable { public void evaluate() throws Throwable {
Assume.assumeTrue("Skipping test due to Couchbase " throw new AssumptionViolatedException(
+ "not being available", false); "Skipping test due to Couchbase not being available");
} }
} }

@ -65,14 +65,15 @@ public class CouchbaseDataAutoConfigurationTests {
@Test @Test
public void customConfiguration() { public void customConfiguration() {
load(CustomCouchbaseConfiguration.class); load(CustomCouchbaseConfiguration.class);
CouchbaseTemplate couchbaseTemplate = this.context.getBean(CouchbaseTemplate.class); CouchbaseTemplate couchbaseTemplate = this.context
assertThat(couchbaseTemplate.getDefaultConsistency()).isEqualTo(Consistency.STRONGLY_CONSISTENT); .getBean(CouchbaseTemplate.class);
assertThat(couchbaseTemplate.getDefaultConsistency())
.isEqualTo(Consistency.STRONGLY_CONSISTENT);
} }
@Test @Test
public void validatorIsPresent() { public void validatorIsPresent() {
load(ValidatorConfiguration.class); load(ValidatorConfiguration.class);
ValidatingCouchbaseEventListener listener = this.context ValidatingCouchbaseEventListener listener = this.context
.getBean(ValidatingCouchbaseEventListener.class); .getBean(ValidatingCouchbaseEventListener.class);
assertThat(new DirectFieldAccessor(listener).getPropertyValue("validator")) assertThat(new DirectFieldAccessor(listener).getPropertyValue("validator"))
@ -90,8 +91,7 @@ public class CouchbaseDataAutoConfigurationTests {
@Test @Test
public void enableAutoIndex() { public void enableAutoIndex() {
load(CouchbaseTestConfigurer.class, load(CouchbaseTestConfigurer.class, "spring.data.couchbase.auto-index=true");
"spring.data.couchbase.auto-index=true");
IndexManager indexManager = this.context.getBean(IndexManager.class); IndexManager indexManager = this.context.getBean(IndexManager.class);
assertThat(indexManager.isIgnoreViews()).isFalse(); assertThat(indexManager.isIgnoreViews()).isFalse();
assertThat(indexManager.isIgnoreN1qlPrimary()).isFalse(); assertThat(indexManager.isIgnoreN1qlPrimary()).isFalse();
@ -115,13 +115,11 @@ public class CouchbaseDataAutoConfigurationTests {
context.register(config); context.register(config);
} }
context.register(PropertyPlaceholderAutoConfiguration.class, context.register(PropertyPlaceholderAutoConfiguration.class,
CouchbaseAutoConfiguration.class, CouchbaseAutoConfiguration.class, CouchbaseDataAutoConfiguration.class);
CouchbaseDataAutoConfiguration.class);
context.refresh(); context.refresh();
this.context = context; this.context = context;
} }
@Configuration @Configuration
@Import(CouchbaseTestConfigurer.class) @Import(CouchbaseTestConfigurer.class)
static class ValidatorConfiguration { static class ValidatorConfiguration {
@ -145,6 +143,7 @@ public class CouchbaseDataAutoConfigurationTests {
protected Consistency getDefaultConsistency() { protected Consistency getDefaultConsistency() {
return Consistency.STRONGLY_CONSISTENT; return Consistency.STRONGLY_CONSISTENT;
} }
} }
} }

@ -82,8 +82,7 @@ public class CouchbaseRepositoriesAutoConfigurationTests {
context.register(config); context.register(config);
} }
context.register(PropertyPlaceholderAutoConfiguration.class, context.register(PropertyPlaceholderAutoConfiguration.class,
CouchbaseAutoConfiguration.class, CouchbaseAutoConfiguration.class, CouchbaseDataAutoConfiguration.class,
CouchbaseDataAutoConfiguration.class,
CouchbaseRepositoriesAutoConfiguration.class); CouchbaseRepositoriesAutoConfiguration.class);
context.refresh(); context.refresh();
this.context = context; this.context = context;

@ -43,8 +43,7 @@ public class RedisRepositoriesAutoConfigurationTests {
@Rule @Rule
public RedisTestServer redis = new RedisTestServer(); public RedisTestServer redis = new RedisTestServer();
private AnnotationConfigApplicationContext context private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
= new AnnotationConfigApplicationContext();
@After @After
public void close() { public void close() {
@ -53,8 +52,8 @@ public class RedisRepositoriesAutoConfigurationTests {
@Test @Test
public void testDefaultRepositoryConfiguration() { public void testDefaultRepositoryConfiguration() {
this.context.register(TestConfiguration.class, this.context.register(TestConfiguration.class, RedisAutoConfiguration.class,
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
assertThat(this.context.getBean(CityRepository.class)).isNotNull(); assertThat(this.context.getBean(CityRepository.class)).isNotNull();
@ -62,8 +61,7 @@ public class RedisRepositoriesAutoConfigurationTests {
@Test @Test
public void testNoRepositoryConfiguration() { public void testNoRepositoryConfiguration() {
this.context.register(EmptyConfiguration.class, this.context.register(EmptyConfiguration.class, RedisAutoConfiguration.class,
RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
@ -72,8 +70,7 @@ public class RedisRepositoriesAutoConfigurationTests {
@Test @Test
public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() { public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
this.context.register(CustomizedConfiguration.class, this.context.register(CustomizedConfiguration.class, RedisAutoConfiguration.class,
RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); this.context.refresh();

@ -70,12 +70,12 @@ public class H2ConsoleAutoConfigurationTests {
"spring.h2.console.enabled:true"); "spring.h2.console.enabled:true");
this.context.refresh(); this.context.refresh();
assertThat(this.context.getBeansOfType(ServletRegistrationBean.class)).hasSize(1); assertThat(this.context.getBeansOfType(ServletRegistrationBean.class)).hasSize(1);
assertThat(this.context.getBean(ServletRegistrationBean.class).getUrlMappings()) ServletRegistrationBean registrationBean = this.context
.contains("/h2-console/*"); .getBean(ServletRegistrationBean.class);
assertThat(this.context.getBean(ServletRegistrationBean.class).getInitParameters()). assertThat(registrationBean.getUrlMappings()).contains("/h2-console/*");
doesNotContainKey("trace"); assertThat(registrationBean.getInitParameters()).doesNotContainKey("trace");
assertThat(this.context.getBean(ServletRegistrationBean.class).getInitParameters()). assertThat(registrationBean.getInitParameters())
doesNotContainKey("webAllowOthers"); .doesNotContainKey("webAllowOthers");
} }
@Test @Test
@ -114,17 +114,16 @@ public class H2ConsoleAutoConfigurationTests {
public void customInitParameters() { public void customInitParameters() {
this.context.register(H2ConsoleAutoConfiguration.class); this.context.register(H2ConsoleAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(this.context, EnvironmentTestUtils.addEnvironment(this.context,
"spring.h2.console.enabled:true", "spring.h2.console.enabled:true", "spring.h2.console.settings.trace=true",
"spring.h2.console.settings.trace=true",
"spring.h2.console.settings.webAllowOthers=true"); "spring.h2.console.settings.webAllowOthers=true");
this.context.refresh(); this.context.refresh();
assertThat(this.context.getBeansOfType(ServletRegistrationBean.class)).hasSize(1); assertThat(this.context.getBeansOfType(ServletRegistrationBean.class)).hasSize(1);
assertThat(this.context.getBean(ServletRegistrationBean.class).getUrlMappings()) ServletRegistrationBean registrationBean = this.context
.contains("/h2-console/*"); .getBean(ServletRegistrationBean.class);
assertThat(this.context.getBean(ServletRegistrationBean.class).getInitParameters()). assertThat(registrationBean.getUrlMappings()).contains("/h2-console/*");
containsEntry("trace", ""); assertThat(registrationBean.getInitParameters()).containsEntry("trace", "");
assertThat(this.context.getBean(ServletRegistrationBean.class).getInitParameters()). assertThat(registrationBean.getInitParameters()).containsEntry("webAllowOthers",
containsEntry("webAllowOthers", ""); "");
} }
} }

@ -51,7 +51,8 @@ public class ProjectInfoAutoConfigurationTests {
@Test @Test
public void gitPropertiesUnavailableIfResourceNotAvailable() { public void gitPropertiesUnavailableIfResourceNotAvailable() {
load(); load();
Map<String, GitProperties> beans = this.context.getBeansOfType(GitProperties.class); Map<String, GitProperties> beans = this.context
.getBeansOfType(GitProperties.class);
assertThat(beans).hasSize(0); assertThat(beans).hasSize(0);
} }
@ -61,7 +62,8 @@ public class ProjectInfoAutoConfigurationTests {
"spring.git.properties=classpath:/org/springframework/boot/autoconfigure/info/git-no-data.properties"); "spring.git.properties=classpath:/org/springframework/boot/autoconfigure/info/git-no-data.properties");
GitProperties gitProperties = this.context.getBean(GitProperties.class); GitProperties gitProperties = this.context.getBean(GitProperties.class);
assertThat(gitProperties.getBranch()).isNull(); assertThat(gitProperties.getBranch()).isNull();
assertThat(gitProperties.getCommitId()).isEqualTo("f95038ec09e29d8f91982fd1cbcc0f3b131b1d0a"); assertThat(gitProperties.getCommitId())
.isEqualTo("f95038ec09e29d8f91982fd1cbcc0f3b131b1d0a");
assertThat(gitProperties.getCommitTime().getTime()).isEqualTo(1456995720000L); assertThat(gitProperties.getCommitTime().getTime()).isEqualTo(1456995720000L);
} }
@ -70,7 +72,8 @@ public class ProjectInfoAutoConfigurationTests {
load("spring.git.properties=classpath:/org/springframework/boot/autoconfigure/info/git-epoch.properties"); load("spring.git.properties=classpath:/org/springframework/boot/autoconfigure/info/git-epoch.properties");
GitProperties gitProperties = this.context.getBean(GitProperties.class); GitProperties gitProperties = this.context.getBean(GitProperties.class);
assertThat(gitProperties.getBranch()).isEqualTo("master"); assertThat(gitProperties.getBranch()).isEqualTo("master");
assertThat(gitProperties.getCommitId()).isEqualTo("5009933788f5f8c687719de6a697074ff80b1b69"); assertThat(gitProperties.getCommitId())
.isEqualTo("5009933788f5f8c687719de6a697074ff80b1b69");
assertThat(gitProperties.getCommitTime().getTime()).isEqualTo(1457103850000L); assertThat(gitProperties.getCommitTime().getTime()).isEqualTo(1457103850000L);
} }
@ -114,7 +117,8 @@ public class ProjectInfoAutoConfigurationTests {
@Test @Test
public void buildPropertiesCustomInvalidLocation() { public void buildPropertiesCustomInvalidLocation() {
load("spring.info.build.location=classpath:/org/acme/no-build.properties"); load("spring.info.build.location=classpath:/org/acme/no-build.properties");
Map<String, BuildProperties> beans = this.context.getBeansOfType(BuildProperties.class); Map<String, BuildProperties> beans = this.context
.getBeansOfType(BuildProperties.class);
assertThat(beans).hasSize(0); assertThat(beans).hasSize(0);
} }
@ -122,7 +126,8 @@ public class ProjectInfoAutoConfigurationTests {
public void buildPropertiesFallbackWithBuildInfoBean() { public void buildPropertiesFallbackWithBuildInfoBean() {
load(CustomInfoPropertiesConfiguration.class); load(CustomInfoPropertiesConfiguration.class);
BuildProperties buildProperties = this.context.getBean(BuildProperties.class); BuildProperties buildProperties = this.context.getBean(BuildProperties.class);
assertThat(buildProperties).isSameAs(this.context.getBean("customBuildProperties")); assertThat(buildProperties)
.isSameAs(this.context.getBean("customBuildProperties"));
} }
private void load(String... environment) { private void load(String... environment) {

@ -21,7 +21,6 @@ import javax.jms.JMSException;
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.pool.PooledConnectionFactory; import org.apache.activemq.pool.PooledConnectionFactory;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration; import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
@ -64,21 +63,22 @@ public class ActiveMQAutoConfigurationTests {
@Test @Test
public void customPooledConnectionFactoryConfiguration() { public void customPooledConnectionFactoryConfiguration() {
load(EmptyConfiguration.class, load(EmptyConfiguration.class, "spring.activemq.pool.enabled:true",
"spring.activemq.pool.enabled:true", "spring.activemq.pool.maxConnections:256",
"spring.activemq.pool.maxConnections:256", "spring.activemq.pool.idleTimeout:512",
"spring.activemq.pool.idleTimeout:512", "spring.activemq.pool.expiryTimeout:4096",
"spring.activemq.pool.expiryTimeout:4096", "spring.activemq.pool.configuration.maximumActiveSessionPerConnection:1024",
"spring.activemq.pool.configuration.maximumActiveSessionPerConnection:1024", "spring.activemq.pool.configuration.timeBetweenExpirationCheckMillis:2048");
"spring.activemq.pool.configuration.timeBetweenExpirationCheckMillis:2048"); ConnectionFactory connectionFactory = this.context
ConnectionFactory connectionFactory = this.context.getBean(ConnectionFactory.class); .getBean(ConnectionFactory.class);
assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class); assertThat(connectionFactory).isInstanceOf(PooledConnectionFactory.class);
PooledConnectionFactory pooledConnectionFactory = (PooledConnectionFactory) connectionFactory; PooledConnectionFactory pooledConnectionFactory = (PooledConnectionFactory) connectionFactory;
assertThat(pooledConnectionFactory.getMaxConnections()).isEqualTo(256); assertThat(pooledConnectionFactory.getMaxConnections()).isEqualTo(256);
assertThat(pooledConnectionFactory.getIdleTimeout()).isEqualTo(512); assertThat(pooledConnectionFactory.getIdleTimeout()).isEqualTo(512);
assertThat(pooledConnectionFactory.getMaximumActiveSessionPerConnection()).isEqualTo(1024); assertThat(pooledConnectionFactory.getMaximumActiveSessionPerConnection())
assertThat(pooledConnectionFactory.getTimeBetweenExpirationCheckMillis()).isEqualTo(2048); .isEqualTo(1024);
assertThat(pooledConnectionFactory.getTimeBetweenExpirationCheckMillis())
.isEqualTo(2048);
assertThat(pooledConnectionFactory.getExpiryTimeout()).isEqualTo(4096); assertThat(pooledConnectionFactory.getExpiryTimeout()).isEqualTo(4096);
} }
@ -119,6 +119,7 @@ public class ActiveMQAutoConfigurationTests {
public ConnectionFactory connectionFactory() { public ConnectionFactory connectionFactory() {
return mock(ConnectionFactory.class); return mock(ConnectionFactory.class);
} }
} }
} }

@ -21,7 +21,7 @@ import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Tests for {@link ActiveMQProperties} and ActiveMQConnectionFactoryFactory. * Tests for {@link ActiveMQProperties} and {@link ActiveMQConnectionFactoryFactory}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Aurélien Leboulanger * @author Aurélien Leboulanger

@ -3231,6 +3231,7 @@ SSL support:
Check the `spring.couchbase.env.*` properties for more details. Check the `spring.couchbase.env.*` properties for more details.
[[boot-features-spring-data-couchbase-repositories]] [[boot-features-spring-data-couchbase-repositories]]
==== Spring Data Couchbase repositories ==== Spring Data Couchbase repositories
Spring Data includes repository support for Couchbase. For complete details of Spring Spring Data includes repository support for Couchbase. For complete details of Spring
@ -3266,6 +3267,7 @@ If you add a `@Bean` of your own of type `CouchbaseTemplate` named `couchbaseTem
will replace the default. will replace the default.
[[boot-features-caching]] [[boot-features-caching]]
== Caching == Caching
The Spring Framework provides support for transparently adding caching to an application. The Spring Framework provides support for transparently adding caching to an application.
@ -3947,6 +3949,8 @@ You can modify this behavior in two ways; set the `defaultRequeueRejected` prope
will be attempted; or, throw an `AmqpRejectAndDontRequeueException` to signal the message should be rejected. will be attempted; or, throw an `AmqpRejectAndDontRequeueException` to signal the message should be rejected.
This is the mechanism used when retries are enabled and the maximum delivery attempts is reached. This is the mechanism used when retries are enabled and the maximum delivery attempts is reached.
[[boot-features-email]] [[boot-features-email]]
== Sending email == Sending email
The Spring Framework provides an easy abstraction for sending email using the The Spring Framework provides an easy abstraction for sending email using the

@ -20,6 +20,7 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
@ -34,7 +35,8 @@ import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
/** /**
* Generate a {@code build.properties} file based the content of the current {@link MavenProject}. * Generate a {@code build.properties} file based the content of the current
* {@link MavenProject}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 1.4.0 * @since 1.4.0
@ -64,27 +66,30 @@ public class BuildInfoMojo extends AbstractMojo {
@Override @Override
public void execute() throws MojoExecutionException, MojoFailureException { public void execute() throws MojoExecutionException, MojoFailureException {
Properties properties = createBuildInfo(); Properties properties = createBuildInfo();
FileOutputStream fos = null;
try { try {
createFileIfNecessary(this.outputFile); createFileIfNecessary(this.outputFile);
fos = new FileOutputStream(this.outputFile); FileOutputStream outputStream = new FileOutputStream(this.outputFile);
properties.store(fos, "Properties"); try {
properties.store(outputStream, "Properties");
}
finally {
closeQuietly(outputStream);
}
} }
catch (FileNotFoundException e) { catch (FileNotFoundException ex) {
throw new MojoExecutionException(e.getMessage(), e); throw new MojoExecutionException(ex.getMessage(), ex);
} }
catch (IOException e) { catch (IOException e) {
throw new MojoExecutionException(e.getMessage(), e); throw new MojoExecutionException(e.getMessage(), e);
} }
finally { }
try {
if (fos != null) { private void closeQuietly(OutputStream outputStream) {
fos.close(); try {
} outputStream.close();
} }
catch (IOException e) { catch (IOException ex) {
getLog().error("Error closing FileOutputStream: " + fos); getLog().error("Error closing FileOutputStream: " + outputStream);
}
} }
} }
@ -108,7 +113,8 @@ public class BuildInfoMojo extends AbstractMojo {
return sdf.format(date); return sdf.format(date);
} }
private void createFileIfNecessary(File file) throws MojoExecutionException, IOException { private void createFileIfNecessary(File file)
throws MojoExecutionException, IOException {
if (file.exists()) { if (file.exists()) {
return; return;
} }

@ -84,7 +84,6 @@ public final class Verify {
return properties; return properties;
} }
public static class ArchiveVerifier { public static class ArchiveVerifier {
private final ZipFile zipFile; private final ZipFile zipFile;

@ -81,8 +81,7 @@ public class PropertySourcesBinder {
} }
/** /**
* Extract the keys using the specified {@code prefix}. The * Extract the keys using the specified {@code prefix}. The prefix won't be included.
* prefix won't be included.
* <p> * <p>
* Any key that starts with the {@code prefix} will be included * Any key that starts with the {@code prefix} will be included
* @param prefix the prefix to use * @param prefix the prefix to use
@ -119,7 +118,8 @@ public class PropertySourcesBinder {
} }
} }
private static PropertySources createPropertySources(PropertySource<?> propertySource) { private static PropertySources createPropertySources(
PropertySource<?> propertySource) {
MutablePropertySources propertySources = new MutablePropertySources(); MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addLast(propertySource); propertySources.addLast(propertySource);
return propertySources; return propertySources;

@ -90,7 +90,8 @@ public @interface ConfigurationProperties {
* defined in the environment. * defined in the environment.
* @return the path (or paths) of resources to bind to * @return the path (or paths) of resources to bind to
* @see #merge() * @see #merge()
* @deprecated configure the environment with those additional locations instead * @deprecated since 1.4 in favor of configuring the environment directly with
* additional locations
*/ */
@Deprecated @Deprecated
String[] locations() default {}; String[] locations() default {};
@ -100,7 +101,8 @@ public @interface ConfigurationProperties {
* merged with the default configuration. * merged with the default configuration.
* @return the flag value (default true) * @return the flag value (default true)
* @see #locations() * @see #locations()
* @deprecated as {@link #locations()} is deprecated as well * @deprecated since 1.4 along with {@link #locations()} in favor of configuring the
* environment directly with additional locations
*/ */
@Deprecated @Deprecated
boolean merge() default true; boolean merge() default true;

@ -16,6 +16,7 @@
package org.springframework.boot.context.web; package org.springframework.boot.context.web;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -24,18 +25,19 @@ import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
/** /**
* Annotation at the field or method/constructor parameter level * Annotation at the field or method/constructor parameter level that injects the HTTP
* that injects the HTTP port that got allocated at runtime. * port that got allocated at runtime. Privdes a convenient alternative for
* <p> * <code>&#064;Value(&quot;${local.server.port}&quot;)</code>.
* Convenient meta-annotation replacing {@code @LocalServerPort}.
* *
* @author Anand Shah * @author Anand Shah
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 1.4.0 * @since 1.4.0
*/ */
@Value("${local.server.port}") @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE}) ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented
@Value("${local.server.port}")
public @interface LocalServerPort { public @interface LocalServerPort {
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -31,6 +31,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@ -57,12 +58,14 @@ public class ServerPortInfoApplicationContextInitializer
public void initialize(ConfigurableApplicationContext applicationContext) { public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.addApplicationListener( applicationContext.addApplicationListener(
new ApplicationListener<EmbeddedServletContainerInitializedEvent>() { new ApplicationListener<EmbeddedServletContainerInitializedEvent>() {
@Override @Override
public void onApplicationEvent( public void onApplicationEvent(
EmbeddedServletContainerInitializedEvent event) { EmbeddedServletContainerInitializedEvent event) {
ServerPortInfoApplicationContextInitializer.this ServerPortInfoApplicationContextInitializer.this
.onApplicationEvent(event); .onApplicationEvent(event);
} }
}); });
} }
@ -83,26 +86,24 @@ public class ServerPortInfoApplicationContextInitializer
private void setPortProperty(ApplicationContext context, String propertyName, private void setPortProperty(ApplicationContext context, String propertyName,
int port) { int port) {
if (context instanceof ConfigurableApplicationContext) { if (context instanceof ConfigurableApplicationContext) {
ConfigurableEnvironment environment = ((ConfigurableApplicationContext) context) setPortProperty(((ConfigurableApplicationContext) context).getEnvironment(),
.getEnvironment(); propertyName, port);
MutablePropertySources sources = environment.getPropertySources();
Map<String, Object> map;
if (!sources.contains("server.ports")) {
map = new HashMap<String, Object>();
MapPropertySource source = new MapPropertySource("server.ports", map);
sources.addFirst(source);
}
else {
@SuppressWarnings("unchecked")
Map<String, Object> value = (Map<String, Object>) sources
.get("server.ports").getSource();
map = value;
}
map.put(propertyName, port);
} }
if (context.getParent() != null) { if (context.getParent() != null) {
setPortProperty(context.getParent(), propertyName, port); setPortProperty(context.getParent(), propertyName, port);
} }
} }
@SuppressWarnings("unchecked")
private void setPortProperty(ConfigurableEnvironment environment, String propertyName,
int port) {
MutablePropertySources sources = environment.getPropertySources();
PropertySource<?> source = sources.get("server.ports");
if (source == null) {
source = new MapPropertySource("server.ports", new HashMap<String, Object>());
sources.addFirst(source);
}
((Map<String, Object>) source.getSource()).put(propertyName, port);
}
} }

@ -72,8 +72,8 @@ public class BuildProperties extends InfoProperties {
/** /**
* Return the timestamp of the build or {@code null}. * Return the timestamp of the build or {@code null}.
* <p> * <p>
* If the original value could not be parsed properly, it is still available with * If the original value could not be parsed properly, it is still available with the
* the {@code time} key. * {@code time} key.
* @return the build time * @return the build time
* @see #get(String) * @see #get(String)
*/ */

@ -54,16 +54,18 @@ public class GitProperties extends InfoProperties {
* @return the short commit id * @return the short commit id
*/ */
public String getShortCommitId() { public String getShortCommitId() {
String commitId = getCommitId(); String id = getCommitId();
return commitId == null ? null if (id == null) {
: (commitId.length() > 7 ? commitId.substring(0, 7) : commitId); return null;
}
return (id.length() > 7 ? id.substring(0, 7) : id);
} }
/** /**
* Return the timestamp of the commit or {@code null}. * Return the timestamp of the commit or {@code null}.
* <p> * <p>
* If the original value could not be parsed properly, it is still available with * If the original value could not be parsed properly, it is still available with the
* the {@code commit.time} key. * {@code commit.time} key.
* @return the commit time * @return the commit time
* @see #get(String) * @see #get(String)
*/ */
@ -72,12 +74,12 @@ public class GitProperties extends InfoProperties {
} }
private static Properties processEntries(Properties properties) { private static Properties processEntries(Properties properties) {
coerceDate(properties, "commit.time"); coercePropertyToEpoch(properties, "commit.time");
coerceDate(properties, "build.time"); coercePropertyToEpoch(properties, "build.time");
return properties; return properties;
} }
private static void coerceDate(Properties properties, String key) { private static void coercePropertyToEpoch(Properties properties, String key) {
String value = properties.getProperty(key); String value = properties.getProperty(key);
if (value != null) { if (value != null) {
properties.setProperty(key, coerceToEpoch(value)); properties.setProperty(key, coerceToEpoch(value));
@ -85,9 +87,9 @@ public class GitProperties extends InfoProperties {
} }
/** /**
* Attempt to convert the specified value to epoch time. Git properties * Attempt to convert the specified value to epoch time. Git properties information
* information are known to be specified either as epoch time in seconds * are known to be specified either as epoch time in seconds or using a specific date
* or using a specific date format. * format.
* @param s the value to coerce to * @param s the value to coerce to
* @return the epoch time in milliseconds or the original value if it couldn't be * @return the epoch time in milliseconds or the original value if it couldn't be
* converted * converted
@ -110,7 +112,7 @@ public class GitProperties extends InfoProperties {
try { try {
return Long.parseLong(s) * 1000; return Long.parseLong(s) * 1000;
} }
catch (NumberFormatException e) { catch (NumberFormatException ex) {
return null; return null;
} }
} }

@ -17,8 +17,8 @@
package org.springframework.boot.info; package org.springframework.boot.info;
import java.util.Date; import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import org.springframework.core.env.PropertiesPropertySource; import org.springframework.core.env.PropertiesPropertySource;
@ -26,8 +26,8 @@ import org.springframework.core.env.PropertySource;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Base class for components exposing unstructured data with dedicated methods for * Base class for components exposing unstructured data with dedicated methods for well
* well known keys. * known keys.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 1.4.0 * @since 1.4.0
@ -55,10 +55,8 @@ public class InfoProperties implements Iterable<InfoProperties.Entry> {
} }
/** /**
* Return the value of the specified property as a {@link Date} or {@code null} * Return the value of the specified property as a {@link Date} or {@code null} if the
* <p> * value is not a valid {@link Long} representation of an epoch time.
* Return {@code null} if the value is not a valid {@link Long} representing an
* epoch time.
* @param key the id of the property * @param key the id of the property
* @return the property value * @return the property value
*/ */
@ -66,10 +64,9 @@ public class InfoProperties implements Iterable<InfoProperties.Entry> {
String s = get(key); String s = get(key);
if (s != null) { if (s != null) {
try { try {
long epoch = Long.parseLong(s); return new Date(Long.parseLong(s));
return new Date(epoch);
} }
catch (NumberFormatException e) { catch (NumberFormatException ex) {
// Not valid epoch time // Not valid epoch time
} }
} }
@ -86,15 +83,42 @@ public class InfoProperties implements Iterable<InfoProperties.Entry> {
* @return a {@link PropertySource} * @return a {@link PropertySource}
*/ */
public PropertySource<?> toPropertySource() { public PropertySource<?> toPropertySource() {
return new PropertiesPropertySource(getClass().getSimpleName(), copy(this.entries)); return new PropertiesPropertySource(getClass().getSimpleName(),
copy(this.entries));
} }
private static Properties copy(Properties properties) { private Properties copy(Properties properties) {
Properties copy = new Properties(); Properties copy = new Properties();
copy.putAll(properties); copy.putAll(properties);
return copy; return copy;
} }
private final class PropertiesIterator implements Iterator<Entry> {
private final Iterator<Map.Entry<Object, Object>> iterator;
private PropertiesIterator(Properties properties) {
this.iterator = properties.entrySet().iterator();
}
@Override
public boolean hasNext() {
return this.iterator.hasNext();
}
@Override
public Entry next() {
Map.Entry<Object, Object> entry = this.iterator.next();
return new Entry((String) entry.getKey(), (String) entry.getValue());
}
@Override
public void remove() {
throw new UnsupportedOperationException("InfoProperties are immutable.");
}
}
/** /**
* Property entry. * Property entry.
*/ */
@ -119,33 +143,4 @@ public class InfoProperties implements Iterable<InfoProperties.Entry> {
} }
private final class PropertiesIterator implements Iterator<Entry> {
private final Properties properties;
private final Enumeration<Object> keys;
private PropertiesIterator(Properties properties) {
this.properties = properties;
this.keys = this.properties.keys();
}
@Override
public boolean hasNext() {
return this.keys.hasMoreElements();
}
@Override
public Entry next() {
String key = (String) this.keys.nextElement();
return new Entry(key, this.properties.getProperty(key));
}
@Override
public void remove() {
throw new UnsupportedOperationException("InfoProperties are immutable.");
}
}
} }

@ -47,10 +47,9 @@ import org.springframework.util.StringUtils;
/** /**
* An {@link ApplicationListener} that configures the {@link LoggingSystem}. If the * An {@link ApplicationListener} that configures the {@link LoggingSystem}. If the
* environment contains a {@code logging.config} property it will be used to * environment contains a {@code logging.config} property it will be used to bootstrap the
* bootstrap the logging system, otherwise a default configuration is used. Regardless, * logging system, otherwise a default configuration is used. Regardless, logging levels
* logging levels will be customized if the environment contains {@code logging.level.*} * will be customized if the environment contains {@code logging.level.*} entries.
* entries.
* <p> * <p>
* By default, log output is only written to the console. If a log file is required the * By default, log output is only written to the console. If a log file is required the
* {@code logging.path} and {@code logging.file} properties can be used. * {@code logging.path} and {@code logging.file} properties can be used.
@ -295,7 +294,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
private boolean isSet(ConfigurableEnvironment environment, String property) { private boolean isSet(ConfigurableEnvironment environment, String property) {
String value = environment.getProperty(property); String value = environment.getProperty(property);
return !(value == null || value.equals("false")); return (value != null && !value.equals("false"));
} }
private void initializeSystem(ConfigurableEnvironment environment, private void initializeSystem(ConfigurableEnvironment environment,

@ -37,7 +37,8 @@ public class PropertySourcesBinderTests {
@Test @Test
public void extractAllWithPrefix() { public void extractAllWithPrefix() {
EnvironmentTestUtils.addEnvironment(this.env, "foo.first=1", "foo.second=2"); EnvironmentTestUtils.addEnvironment(this.env, "foo.first=1", "foo.second=2");
Map<String, Object> content = new PropertySourcesBinder(this.env).extractAll("foo"); Map<String, Object> content = new PropertySourcesBinder(this.env)
.extractAll("foo");
assertThat(content.get("first")).isEqualTo("1"); assertThat(content.get("first")).isEqualTo("1");
assertThat(content.get("second")).isEqualTo("2"); assertThat(content.get("second")).isEqualTo("2");
assertThat(content).hasSize(2); assertThat(content).hasSize(2);
@ -46,7 +47,8 @@ public class PropertySourcesBinderTests {
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void extractNoPrefix() { public void extractNoPrefix() {
EnvironmentTestUtils.addEnvironment(this.env, "foo.ctx.first=1", "foo.ctx.second=2"); EnvironmentTestUtils.addEnvironment(this.env, "foo.ctx.first=1",
"foo.ctx.second=2");
Map<String, Object> content = new PropertySourcesBinder(this.env).extractAll(""); Map<String, Object> content = new PropertySourcesBinder(this.env).extractAll("");
assertThat(content.get("foo")).isInstanceOf(Map.class); assertThat(content.get("foo")).isInstanceOf(Map.class);
Map<String, Object> foo = (Map<String, Object>) content.get("foo"); Map<String, Object> foo = (Map<String, Object>) content.get("foo");
@ -67,8 +69,9 @@ public class PropertySourcesBinderTests {
assertThat(bean.getCounter()).isEqualTo(42); assertThat(bean.getCounter()).isEqualTo(42);
} }
@SuppressWarnings("unused")
private static class TestBean { private static class TestBean {
private String name; private String name;
private Integer counter; private Integer counter;

@ -0,0 +1,55 @@
/*
* Copyright 2012-2016 the original author or authors.
*
* 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.springframework.boot.context.web;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link LocalServerPort}.
*
* @author Anand Shah
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
@TestPropertySource(properties = "local.server.port=8181")
public class LocalServerPortTests {
@Value("${local.server.port}")
private String fromValue;
@LocalServerPort
private String fromAnnotation;
@Test
public void testLocalServerPortAnnotation() {
assertThat(this.fromAnnotation).isNotNull().isEqualTo(this.fromValue);
}
@Configuration
static class Config {
}
}

@ -31,8 +31,8 @@ public class BuildPropertiesTests {
@Test @Test
public void basicInfo() { public void basicInfo() {
BuildProperties properties = new BuildProperties(createProperties( BuildProperties properties = new BuildProperties(createProperties("com.example",
"com.example", "demo", "0.0.1", "2016-03-04T14:36:33+0100")); "demo", "0.0.1", "2016-03-04T14:36:33+0100"));
assertThat(properties.getGroup()).isEqualTo("com.example"); assertThat(properties.getGroup()).isEqualTo("com.example");
assertThat(properties.getArtifact()).isEqualTo("demo"); assertThat(properties.getArtifact()).isEqualTo("demo");
assertThat(properties.getVersion()).isEqualTo("0.0.1"); assertThat(properties.getVersion()).isEqualTo("0.0.1");

@ -81,7 +81,8 @@ public class GitPropertiesTests {
assertThat(properties.getShortCommitId()).isEqualTo("abc"); assertThat(properties.getShortCommitId()).isEqualTo("abc");
} }
private static Properties createProperties(String branch, String commitId, String commitTime) { private static Properties createProperties(String branch, String commitId,
String commitTime) {
Properties properties = new Properties(); Properties properties = new Properties();
properties.put("branch", branch); properties.put("branch", branch);
properties.put("commit.id", commitId); properties.put("commit.id", commitId);

@ -86,6 +86,7 @@ public class InfoPropertiesTests {
MyInfoProperties(Properties entries) { MyInfoProperties(Properties entries) {
super(entries); super(entries);
} }
} }
} }

@ -37,7 +37,6 @@ public @interface ClassPathExclusions {
* path. Matching is performed against an entry's {@link File#getName() file name}. * path. Matching is performed against an entry's {@link File#getName() file name}.
* For example, to exclude Hibernate Validator from the classpath, * For example, to exclude Hibernate Validator from the classpath,
* {@code "hibernate-validator-*.jar"} can be used. * {@code "hibernate-validator-*.jar"} can be used.
*
* @return the exclusion patterns * @return the exclusion patterns
*/ */
String[] value(); String[] value();

@ -47,36 +47,15 @@ import org.springframework.util.StringUtils;
*/ */
public class FilteredClassPathRunner extends BlockJUnit4ClassRunner { public class FilteredClassPathRunner extends BlockJUnit4ClassRunner {
public FilteredClassPathRunner(Class<?> klass) throws InitializationError { public FilteredClassPathRunner(Class<?> testClass) throws InitializationError {
super(klass); super(testClass);
} }
@Override @Override
protected TestClass createTestClass(Class<?> testClass) { protected TestClass createTestClass(Class<?> testClass) {
try { try {
final ClassLoader classLoader = createTestClassLoader(testClass); ClassLoader classLoader = createTestClassLoader(testClass);
return new TestClass(classLoader.loadClass(testClass.getName())) { return new FilteredTestClass(classLoader, testClass.getName());
@SuppressWarnings("unchecked")
@Override
public List<FrameworkMethod> getAnnotatedMethods(
Class<? extends Annotation> annotationClass) {
List<FrameworkMethod> methods = new ArrayList<FrameworkMethod>();
try {
for (FrameworkMethod frameworkMethod : super.getAnnotatedMethods(
(Class<? extends Annotation>) classLoader
.loadClass(annotationClass.getName()))) {
methods.add(new CustomTcclFrameworkMethod(classLoader,
frameworkMethod.getMethod()));
}
return methods;
}
catch (ClassNotFoundException ex) {
throw new RuntimeException(ex);
}
}
};
} }
catch (Exception ex) { catch (Exception ex) {
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
@ -136,6 +115,9 @@ public class FilteredClassPathRunner extends BlockJUnit4ClassRunner {
return filteredUrls.toArray(new URL[filteredUrls.size()]); return filteredUrls.toArray(new URL[filteredUrls.size()]);
} }
/**
* Filter for class path entries.
*/
private static final class ClassPathEntryFilter { private static final class ClassPathEntryFilter {
private final List<String> exclusions; private final List<String> exclusions;
@ -163,25 +145,75 @@ public class FilteredClassPathRunner extends BlockJUnit4ClassRunner {
} }
} }
private static final class CustomTcclFrameworkMethod extends FrameworkMethod { /**
* Filtered version of JUnit's {@link TestClass}.
*/
private static final class FilteredTestClass extends TestClass {
private final ClassLoader classLoader;
FilteredTestClass(ClassLoader classLoader, String testClassName)
throws ClassNotFoundException {
super(classLoader.loadClass(testClassName));
this.classLoader = classLoader;
}
@Override
public List<FrameworkMethod> getAnnotatedMethods(
Class<? extends Annotation> annotationClass) {
try {
return getAnnotatedMethods(annotationClass.getName());
}
catch (ClassNotFoundException ex) {
throw new RuntimeException(ex);
}
}
@SuppressWarnings("unchecked")
private List<FrameworkMethod> getAnnotatedMethods(String annotationClassName)
throws ClassNotFoundException {
Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) this.classLoader
.loadClass(annotationClassName);
List<FrameworkMethod> methods = super.getAnnotatedMethods(annotationClass);
return wrapFrameworkMethods(methods);
}
private List<FrameworkMethod> wrapFrameworkMethods(
List<FrameworkMethod> methods) {
List<FrameworkMethod> wrapped = new ArrayList<FrameworkMethod>(
methods.size());
for (FrameworkMethod frameworkMethod : methods) {
wrapped.add(new FilteredFrameworkMethod(this.classLoader,
frameworkMethod.getMethod()));
}
return wrapped;
}
}
/**
* Filtered version of JUnit's {@link FrameworkMethod}.
*/
private static final class FilteredFrameworkMethod extends FrameworkMethod {
private final ClassLoader customTccl; private final ClassLoader classLoader;
private CustomTcclFrameworkMethod(ClassLoader customTccl, Method method) { private FilteredFrameworkMethod(ClassLoader classLoader, Method method) {
super(method); super(method);
this.customTccl = customTccl; this.classLoader = classLoader;
} }
@Override @Override
public Object invokeExplosively(Object target, Object... params) public Object invokeExplosively(Object target, Object... params)
throws Throwable { throws Throwable {
ClassLoader originalTccl = Thread.currentThread().getContextClassLoader(); ClassLoader originalClassLoader = Thread.currentThread()
Thread.currentThread().setContextClassLoader(this.customTccl); .getContextClassLoader();
Thread.currentThread().setContextClassLoader(this.classLoader);
try { try {
return super.invokeExplosively(target, params); return super.invokeExplosively(target, params);
} }
finally { finally {
Thread.currentThread().setContextClassLoader(originalTccl); Thread.currentThread().setContextClassLoader(originalClassLoader);
} }
} }

@ -30,18 +30,18 @@ import static org.assertj.core.api.Assertions.assertThat;
@ClassPathExclusions("hibernate-validator-*.jar") @ClassPathExclusions("hibernate-validator-*.jar")
public class FilteredClassPathRunnerTests { public class FilteredClassPathRunnerTests {
private static final String EXCLUDED_RESOURCE = "META-INF/services/"
+ "javax.validation.spi.ValidationProvider";
@Test @Test
public void entriesAreFilteredFromTestClassClassLoader() { public void entriesAreFilteredFromTestClassClassLoader() {
assertThat(getClass().getClassLoader() assertThat(getClass().getClassLoader().getResource(EXCLUDED_RESOURCE)).isNull();
.getResource("META-INF/services/javax.validation.spi.ValidationProvider"))
.isNull();
} }
@Test @Test
public void entriesAreFilteredFromThreadContextClassLoader() { public void entriesAreFilteredFromThreadContextClassLoader() {
assertThat(Thread.currentThread().getContextClassLoader() assertThat(Thread.currentThread().getContextClassLoader()
.getResource("META-INF/services/javax.validation.spi.ValidationProvider")) .getResource(EXCLUDED_RESOURCE)).isNull();
.isNull();
} }
} }

Loading…
Cancel
Save