From 744a1ed497d56915088b88486b0614e2f55852e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Tue, 7 Mar 2017 21:29:21 -0500 Subject: [PATCH 1/3] Add support for CustomConversions with Cassandra This commit add the support for CustomConversions in spring-data-cassandra. To customize, bean just need to be declared and it will be auto-configured. See gh-8534 --- .../CassandraDataAutoConfiguration.java | 19 +++++++-- .../CassandraDataAutoConfigurationTests.java | 42 +++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java index 0a85a34cc7d..db8ff1626f0 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.boot.autoconfigure.data.cassandra; +import java.util.Collections; import java.util.List; import com.datastax.driver.core.Cluster; @@ -41,9 +42,11 @@ import org.springframework.data.cassandra.config.SchemaAction; import org.springframework.data.cassandra.core.CassandraAdminOperations; import org.springframework.data.cassandra.core.CassandraTemplate; import org.springframework.data.cassandra.core.convert.CassandraConverter; +import org.springframework.data.cassandra.core.convert.CassandraCustomConversions; import org.springframework.data.cassandra.core.convert.MappingCassandraConverter; import org.springframework.data.cassandra.core.mapping.CassandraMappingContext; import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver; +import org.springframework.data.convert.CustomConversions; import org.springframework.util.StringUtils; /** @@ -79,7 +82,7 @@ public class CassandraDataAutoConfiguration { @Bean @ConditionalOnMissingBean - public CassandraMappingContext cassandraMapping() throws ClassNotFoundException { + public CassandraMappingContext cassandraMapping(CustomConversions conversions) throws ClassNotFoundException { CassandraMappingContext context = new CassandraMappingContext(); List packages = EntityScanPackages.get(this.beanFactory) .getPackageNames(); @@ -93,13 +96,17 @@ public class CassandraDataAutoConfiguration { context.setUserTypeResolver(new SimpleUserTypeResolver(this.cluster, this.properties.getKeyspaceName())); } + context.setCustomConversions(conversions); return context; } @Bean @ConditionalOnMissingBean - public CassandraConverter cassandraConverter(CassandraMappingContext mapping) { - return new MappingCassandraConverter(mapping); + public CassandraConverter cassandraConverter(CassandraMappingContext mapping, + CustomConversions conversions) { + MappingCassandraConverter converter = new MappingCassandraConverter(mapping); + converter.setCustomConversions(conversions); + return converter; } @Bean @@ -123,4 +130,10 @@ public class CassandraDataAutoConfiguration { return new CassandraTemplate(session, converter); } + @Bean + @ConditionalOnMissingBean + public CustomConversions cassandraCustomConversions() { + return new CassandraCustomConversions(Collections.emptyList()); + } + } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java index 3a1670fd3f9..8d950fdf98f 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java @@ -16,6 +16,7 @@ package org.springframework.boot.autoconfigure.data.cassandra; +import java.util.Arrays; import java.util.Set; import com.datastax.driver.core.Session; @@ -26,13 +27,16 @@ import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfigurati import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.data.cassandra.city.City; import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; +import org.springframework.core.convert.converter.Converter; import org.springframework.data.cassandra.core.CassandraTemplate; +import org.springframework.data.cassandra.core.convert.CassandraCustomConversions; import org.springframework.data.cassandra.core.mapping.CassandraMappingContext; import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver; import org.springframework.test.util.ReflectionTestUtils; @@ -101,6 +105,22 @@ public class CassandraDataAutoConfigurationTests { .isInstanceOf(SimpleUserTypeResolver.class); } + @Test + public void customConversions() { + this.context = new AnnotationConfigApplicationContext(); + EnvironmentTestUtils.addEnvironment(this.context, + "spring.data.cassandra.keyspaceName:boot_test"); + this.context.register(CustomConversionConfig.class, + TestConfiguration.class, + PropertyPlaceholderAutoConfiguration.class, + CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class); + this.context.refresh(); + CassandraTemplate template = this.context.getBean(CassandraTemplate.class); + assertThat(template.getConverter().getConversionService().canConvert(Person.class, + String.class)).isTrue(); + + } + @Configuration @ComponentScan(excludeFilters = @ComponentScan.Filter(classes = { Session.class }, type = FilterType.ASSIGNABLE_TYPE)) @@ -124,4 +144,26 @@ public class CassandraDataAutoConfigurationTests { } + @Configuration + static class CustomConversionConfig { + + @Bean + public CassandraCustomConversions cassandraCustomConversions() { + return new CassandraCustomConversions(Arrays.asList(new MyConverter())); + } + + } + + private static class MyConverter implements Converter { + + @Override + public String convert(Person o) { + return null; + } + } + + private static class Person { + + } + } From 49797b11539b998fc7f8f857e05c15297e9111f6 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 19 Jun 2017 08:28:08 +0200 Subject: [PATCH 2/3] Polish "Add support for CustomConversions with Cassandra" Closes gh-8534 --- .../CassandraDataAutoConfiguration.java | 8 +++--- .../CassandraDataAutoConfigurationTests.java | 26 ++++++++++++++----- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java index db8ff1626f0..22e8ef33331 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java @@ -46,7 +46,6 @@ import org.springframework.data.cassandra.core.convert.CassandraCustomConversion import org.springframework.data.cassandra.core.convert.MappingCassandraConverter; import org.springframework.data.cassandra.core.mapping.CassandraMappingContext; import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver; -import org.springframework.data.convert.CustomConversions; import org.springframework.util.StringUtils; /** @@ -82,7 +81,8 @@ public class CassandraDataAutoConfiguration { @Bean @ConditionalOnMissingBean - public CassandraMappingContext cassandraMapping(CustomConversions conversions) throws ClassNotFoundException { + public CassandraMappingContext cassandraMapping( + CassandraCustomConversions conversions) throws ClassNotFoundException { CassandraMappingContext context = new CassandraMappingContext(); List packages = EntityScanPackages.get(this.beanFactory) .getPackageNames(); @@ -103,7 +103,7 @@ public class CassandraDataAutoConfiguration { @Bean @ConditionalOnMissingBean public CassandraConverter cassandraConverter(CassandraMappingContext mapping, - CustomConversions conversions) { + CassandraCustomConversions conversions) { MappingCassandraConverter converter = new MappingCassandraConverter(mapping); converter.setCustomConversions(conversions); return converter; @@ -132,7 +132,7 @@ public class CassandraDataAutoConfiguration { @Bean @ConditionalOnMissingBean - public CustomConversions cassandraCustomConversions() { + public CassandraCustomConversions cassandraCustomConversions() { return new CassandraCustomConversions(Collections.emptyList()); } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java index 8d950fdf98f..3801172dd04 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java @@ -16,7 +16,7 @@ package org.springframework.boot.autoconfigure.data.cassandra; -import java.util.Arrays; +import java.util.Collections; import java.util.Set; import com.datastax.driver.core.Session; @@ -27,7 +27,6 @@ import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfigurati import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.data.cassandra.city.City; import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -105,11 +104,25 @@ public class CassandraDataAutoConfigurationTests { .isInstanceOf(SimpleUserTypeResolver.class); } + @Test + public void defaultConversions() { + this.context = new AnnotationConfigApplicationContext(); + TestPropertyValues.of("spring.data.cassandra.keyspaceName:boot_test") + .applyTo(this.context); + this.context.register(TestConfiguration.class, + PropertyPlaceholderAutoConfiguration.class, + CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class); + this.context.refresh(); + CassandraTemplate template = this.context.getBean(CassandraTemplate.class); + assertThat(template.getConverter().getConversionService().canConvert(Person.class, + String.class)).isFalse(); + } + @Test public void customConversions() { this.context = new AnnotationConfigApplicationContext(); - EnvironmentTestUtils.addEnvironment(this.context, - "spring.data.cassandra.keyspaceName:boot_test"); + TestPropertyValues.of("spring.data.cassandra.keyspaceName:boot_test") + .applyTo(this.context); this.context.register(CustomConversionConfig.class, TestConfiguration.class, PropertyPlaceholderAutoConfiguration.class, @@ -148,8 +161,9 @@ public class CassandraDataAutoConfigurationTests { static class CustomConversionConfig { @Bean - public CassandraCustomConversions cassandraCustomConversions() { - return new CassandraCustomConversions(Arrays.asList(new MyConverter())); + public CassandraCustomConversions myCassandraCustomConversions() { + return new CassandraCustomConversions(Collections.singletonList( + new MyConverter())); } } From 2916cdf953e5df9dbe4f9b43876a967e164fc992 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 19 Jun 2017 08:38:04 +0200 Subject: [PATCH 3/3] Polish --- .../CassandraDataAutoConfigurationTests.java | 58 +++++++------------ 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java index 3801172dd04..bff272d4626 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java @@ -24,7 +24,6 @@ import org.junit.After; import org.junit.Test; import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; -import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.data.cassandra.city.City; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.test.util.TestPropertyValues; @@ -39,15 +38,17 @@ import org.springframework.data.cassandra.core.convert.CassandraCustomConversion import org.springframework.data.cassandra.core.mapping.CassandraMappingContext; import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver; import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.util.ObjectUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; /** - * Tests for {@link CassandraDataAutoConfiguration} + * Tests for {@link CassandraDataAutoConfiguration}. * * @author EddĂș MelĂ©ndez * @author Mark Paluch + * @author Stephane Nicoll */ public class CassandraDataAutoConfigurationTests { @@ -62,13 +63,7 @@ public class CassandraDataAutoConfigurationTests { @Test public void templateExists() { - this.context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("spring.data.cassandra.keyspaceName:boot_test") - .applyTo(this.context); - this.context.register(TestExcludeConfiguration.class, TestConfiguration.class, - PropertyPlaceholderAutoConfiguration.class, - CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class); - this.context.refresh(); + load(TestExcludeConfiguration.class); assertThat(this.context.getBeanNamesForType(CassandraTemplate.class).length) .isEqualTo(1); } @@ -76,12 +71,7 @@ public class CassandraDataAutoConfigurationTests { @Test @SuppressWarnings("unchecked") public void entityScanShouldSetInitialEntitySet() throws Exception { - this.context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("spring.data.cassandra.keyspaceName:boot_test"); - this.context.register(TestConfiguration.class, EntityScanConfig.class, - PropertyPlaceholderAutoConfiguration.class, - CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class); - this.context.refresh(); + load(EntityScanConfig.class); CassandraMappingContext mappingContext = this.context .getBean(CassandraMappingContext.class); Set> initialEntitySet = (Set>) ReflectionTestUtils @@ -91,13 +81,7 @@ public class CassandraDataAutoConfigurationTests { @Test public void userTypeResolverShouldBeSet() throws Exception { - this.context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("spring.data.cassandra.keyspaceName:boot_test") - .applyTo(this.context); - this.context.register(TestConfiguration.class, - PropertyPlaceholderAutoConfiguration.class, - CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class); - this.context.refresh(); + load(); CassandraMappingContext mappingContext = this.context .getBean(CassandraMappingContext.class); assertThat(ReflectionTestUtils.getField(mappingContext, "userTypeResolver")) @@ -106,13 +90,7 @@ public class CassandraDataAutoConfigurationTests { @Test public void defaultConversions() { - this.context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("spring.data.cassandra.keyspaceName:boot_test") - .applyTo(this.context); - this.context.register(TestConfiguration.class, - PropertyPlaceholderAutoConfiguration.class, - CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class); - this.context.refresh(); + load(); CassandraTemplate template = this.context.getBean(CassandraTemplate.class); assertThat(template.getConverter().getConversionService().canConvert(Person.class, String.class)).isFalse(); @@ -120,20 +98,26 @@ public class CassandraDataAutoConfigurationTests { @Test public void customConversions() { - this.context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("spring.data.cassandra.keyspaceName:boot_test") - .applyTo(this.context); - this.context.register(CustomConversionConfig.class, - TestConfiguration.class, - PropertyPlaceholderAutoConfiguration.class, - CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class); - this.context.refresh(); + load(CustomConversionConfig.class); CassandraTemplate template = this.context.getBean(CassandraTemplate.class); assertThat(template.getConverter().getConversionService().canConvert(Person.class, String.class)).isTrue(); } + public void load(Class... config) { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + TestPropertyValues.of("spring.data.cassandra.keyspaceName:boot_test") + .applyTo(ctx); + if (!ObjectUtils.isEmpty(config)) { + ctx.register(config); + } + ctx.register(TestConfiguration.class, CassandraAutoConfiguration.class, + CassandraDataAutoConfiguration.class); + ctx.refresh(); + this.context = ctx; + } + @Configuration @ComponentScan(excludeFilters = @ComponentScan.Filter(classes = { Session.class }, type = FilterType.ASSIGNABLE_TYPE))