Skip to content

Commit 8d713fb

Browse files
committed
Polish "Auto-configure CqlTemplate and ReactiveCqlTemplate"
See gh-44291
1 parent e8661f6 commit 8d713fb

File tree

5 files changed

+87
-99
lines changed

5 files changed

+87
-99
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -116,18 +116,18 @@ public SessionFactoryFactoryBean cassandraSessionFactory(Environment environment
116116
return session;
117117
}
118118

119-
@Bean
120-
@ConditionalOnMissingBean(CassandraOperations.class)
121-
public CassandraTemplate cassandraTemplate(SessionFactory sessionFactory, CassandraConverter converter) {
122-
return new CassandraTemplate(sessionFactory, converter);
123-
}
124-
125119
@Bean
126120
@ConditionalOnMissingBean(CqlOperations.class)
127121
public CqlTemplate cqlTemplate(SessionFactory sessionFactory) {
128122
return new CqlTemplate(sessionFactory);
129123
}
130124

125+
@Bean
126+
@ConditionalOnMissingBean(CassandraOperations.class)
127+
public CassandraTemplate cassandraTemplate(CqlTemplate cqlTemplate, CassandraConverter converter) {
128+
return new CassandraTemplate(cqlTemplate, converter);
129+
}
130+
131131
@Bean
132132
@ConditionalOnMissingBean
133133
public CassandraCustomConversions cassandraCustomConversions() {

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraReactiveDataAutoConfiguration.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,17 @@ public ReactiveSessionFactory reactiveCassandraSessionFactory(ReactiveSession re
6060
return new DefaultReactiveSessionFactory(reactiveCassandraSession);
6161
}
6262

63-
@Bean
64-
@ConditionalOnMissingBean(ReactiveCassandraOperations.class)
65-
public ReactiveCassandraTemplate reactiveCassandraTemplate(ReactiveSession reactiveCassandraSession,
66-
CassandraConverter converter) {
67-
return new ReactiveCassandraTemplate(reactiveCassandraSession, converter);
68-
}
69-
7063
@Bean
7164
@ConditionalOnMissingBean(ReactiveCqlOperations.class)
7265
public ReactiveCqlTemplate reactiveCqlTemplate(ReactiveSessionFactory reactiveCassandraSessionFactory) {
7366
return new ReactiveCqlTemplate(reactiveCassandraSessionFactory);
7467
}
7568

69+
@Bean
70+
@ConditionalOnMissingBean(ReactiveCassandraOperations.class)
71+
public ReactiveCassandraTemplate reactiveCassandraTemplate(ReactiveCqlTemplate reactiveCqlTemplate,
72+
CassandraConverter converter) {
73+
return new ReactiveCassandraTemplate(reactiveCqlTemplate, converter);
74+
}
75+
7676
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java

+44-46
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919
import java.util.Collections;
2020

2121
import com.datastax.oss.driver.api.core.CqlSession;
22-
import org.junit.jupiter.api.AfterEach;
2322
import org.junit.jupiter.api.Test;
2423

24+
import org.springframework.boot.autoconfigure.AutoConfigurations;
2525
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
2626
import org.springframework.boot.autoconfigure.data.cassandra.city.City;
2727
import org.springframework.boot.autoconfigure.domain.EntityScan;
28-
import org.springframework.boot.test.util.TestPropertyValues;
28+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
2929
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3030
import org.springframework.context.annotation.Bean;
3131
import org.springframework.context.annotation.Configuration;
@@ -36,9 +36,6 @@
3636
import org.springframework.data.cassandra.core.cql.CqlTemplate;
3737
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
3838
import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver;
39-
import org.springframework.data.domain.ManagedTypes;
40-
import org.springframework.test.util.ReflectionTestUtils;
41-
import org.springframework.util.ObjectUtils;
4239

4340
import static org.assertj.core.api.Assertions.assertThat;
4441

@@ -51,80 +48,81 @@
5148
*/
5249
class CassandraDataAutoConfigurationTests {
5350

54-
private AnnotationConfigApplicationContext context;
51+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
52+
.withPropertyValues("spring.cassandra.keyspaceName=boot_test")
53+
.withUserConfiguration(CassandraMockConfiguration.class)
54+
.withConfiguration(
55+
AutoConfigurations.of(CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class));
5556

56-
@AfterEach
57-
void close() {
58-
if (this.context != null) {
59-
this.context.close();
60-
}
57+
@Test
58+
void cqlTemplateExists() {
59+
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CqlTemplate.class));
6160
}
6261

6362
@Test
6463
void templateExists() {
65-
load(CassandraMockConfiguration.class);
66-
assertThat(this.context.getBeanNamesForType(CassandraTemplate.class)).hasSize(1);
64+
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CassandraTemplate.class));
6765
}
6866

6967
@Test
70-
void cqlTemplateExists() {
71-
load(CassandraMockConfiguration.class);
72-
assertThat(this.context.getBeanNamesForType(CqlTemplate.class)).hasSize(1);
68+
void templateUsesCqlTemplate() {
69+
this.contextRunner.run((context) -> {
70+
assertThat(context).hasSingleBean(CassandraTemplate.class);
71+
assertThat(context.getBean(CassandraTemplate.class).getCqlOperations())
72+
.isSameAs(context.getBean(CqlTemplate.class));
73+
});
7374
}
7475

7576
@Test
7677
void entityScanShouldSetManagedTypes() {
77-
load(EntityScanConfig.class);
78-
CassandraMappingContext mappingContext = this.context.getBean(CassandraMappingContext.class);
79-
ManagedTypes managedTypes = (ManagedTypes) ReflectionTestUtils.getField(mappingContext, "managedTypes");
80-
assertThat(managedTypes.toList()).containsOnly(City.class);
78+
this.contextRunner.withUserConfiguration(EntityScanConfig.class).run((context) -> {
79+
assertThat(context).hasSingleBean(CassandraMappingContext.class);
80+
CassandraMappingContext mappingContext = context.getBean(CassandraMappingContext.class);
81+
assertThat(mappingContext.getManagedTypes()).singleElement()
82+
.satisfies((typeInformation) -> assertThat(typeInformation.getType()).isEqualTo(City.class));
83+
});
8184
}
8285

8386
@Test
8487
void userTypeResolverShouldBeSet() {
85-
load();
86-
CassandraConverter cassandraConverter = this.context.getBean(CassandraConverter.class);
87-
assertThat(cassandraConverter).extracting("userTypeResolver").isInstanceOf(SimpleUserTypeResolver.class);
88+
this.contextRunner.run((context) -> {
89+
assertThat(context).hasSingleBean(CassandraConverter.class);
90+
assertThat(context.getBean(CassandraConverter.class)).extracting("userTypeResolver")
91+
.isInstanceOf(SimpleUserTypeResolver.class);
92+
});
8893
}
8994

9095
@Test
9196
void codecRegistryShouldBeSet() {
92-
load();
93-
CassandraConverter cassandraConverter = this.context.getBean(CassandraConverter.class);
94-
assertThat(cassandraConverter.getCodecRegistry())
95-
.isSameAs(this.context.getBean(CassandraMockConfiguration.class).codecRegistry);
97+
this.contextRunner.run((context) -> {
98+
assertThat(context).hasSingleBean(CassandraConverter.class);
99+
assertThat(context.getBean(CassandraConverter.class).getCodecRegistry())
100+
.isSameAs(context.getBean(CassandraMockConfiguration.class).codecRegistry);
101+
});
96102
}
97103

98104
@Test
99105
void defaultConversions() {
100-
load();
101-
CassandraTemplate template = this.context.getBean(CassandraTemplate.class);
102-
assertThat(template.getConverter().getConversionService().canConvert(Person.class, String.class)).isFalse();
106+
this.contextRunner.run((context) -> {
107+
CassandraTemplate template = context.getBean(CassandraTemplate.class);
108+
assertThat(template.getConverter().getConversionService().canConvert(Person.class, String.class)).isFalse();
109+
});
103110
}
104111

105112
@Test
106113
void customConversions() {
107-
load(CustomConversionConfig.class);
108-
CassandraTemplate template = this.context.getBean(CassandraTemplate.class);
109-
assertThat(template.getConverter().getConversionService().canConvert(Person.class, String.class)).isTrue();
114+
this.contextRunner.withUserConfiguration(CustomConversionConfig.class).run((context) -> {
115+
CassandraTemplate template = context.getBean(CassandraTemplate.class);
116+
assertThat(template.getConverter().getConversionService().canConvert(Person.class, String.class)).isTrue();
117+
});
110118
}
111119

112120
@Test
113121
void clusterDoesNotExist() {
114-
this.context = new AnnotationConfigApplicationContext(CassandraDataAutoConfiguration.class);
115-
assertThat(this.context.getBeansOfType(CqlSession.class)).isEmpty();
116-
}
117-
118-
void load(Class<?>... config) {
119-
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
120-
TestPropertyValues.of("spring.cassandra.keyspaceName:boot_test").applyTo(ctx);
121-
if (!ObjectUtils.isEmpty(config)) {
122-
ctx.register(config);
122+
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
123+
CassandraDataAutoConfiguration.class)) {
124+
assertThat(context.getBeansOfType(CqlSession.class)).isEmpty();
123125
}
124-
ctx.register(CassandraMockConfiguration.class, CassandraAutoConfiguration.class,
125-
CassandraDataAutoConfiguration.class);
126-
ctx.refresh();
127-
this.context = ctx;
128126
}
129127

130128
@Configuration(proxyBeanMethods = false)

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraReactiveDataAutoConfigurationTests.java

+29-39
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,19 @@
1616

1717
package org.springframework.boot.autoconfigure.data.cassandra;
1818

19-
import org.junit.jupiter.api.AfterEach;
2019
import org.junit.jupiter.api.Test;
2120

21+
import org.springframework.boot.autoconfigure.AutoConfigurations;
2222
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
2323
import org.springframework.boot.autoconfigure.data.cassandra.city.City;
2424
import org.springframework.boot.autoconfigure.domain.EntityScan;
25-
import org.springframework.boot.test.util.TestPropertyValues;
26-
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
25+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
2726
import org.springframework.context.annotation.Configuration;
2827
import org.springframework.data.cassandra.core.ReactiveCassandraTemplate;
2928
import org.springframework.data.cassandra.core.convert.CassandraConverter;
3029
import org.springframework.data.cassandra.core.cql.ReactiveCqlTemplate;
3130
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
3231
import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver;
33-
import org.springframework.data.domain.ManagedTypes;
34-
import org.springframework.test.util.ReflectionTestUtils;
3532

3633
import static org.assertj.core.api.Assertions.assertThat;
3734

@@ -44,56 +41,49 @@
4441
*/
4542
class CassandraReactiveDataAutoConfigurationTests {
4643

47-
private AnnotationConfigApplicationContext context;
44+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
45+
.withPropertyValues("spring.cassandra.keyspaceName=boot_test")
46+
.withUserConfiguration(CassandraMockConfiguration.class)
47+
.withConfiguration(AutoConfigurations.of(CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
48+
CassandraReactiveDataAutoConfiguration.class));
4849

49-
@AfterEach
50-
void close() {
51-
if (this.context != null) {
52-
this.context.close();
53-
}
50+
@Test
51+
void reactiveCqlTemplateExists() {
52+
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ReactiveCqlTemplate.class));
5453
}
5554

5655
@Test
5756
void templateExists() {
58-
load("spring.cassandra.keyspaceName:boot_test");
59-
assertThat(this.context.getBeanNamesForType(ReactiveCassandraTemplate.class)).hasSize(1);
57+
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ReactiveCassandraTemplate.class));
6058
}
6159

6260
@Test
63-
void reactiveCqlTemplateExists() {
64-
load("spring.cassandra.keyspaceName:boot_test");
65-
assertThat(this.context.getBeanNamesForType(ReactiveCqlTemplate.class)).hasSize(1);
61+
void templateUsesReactiveCqlTemplate() {
62+
this.contextRunner.run((context) -> {
63+
assertThat(context).hasSingleBean(ReactiveCassandraTemplate.class);
64+
assertThat(context.getBean(ReactiveCassandraTemplate.class).getReactiveCqlOperations())
65+
.isSameAs(context.getBean(ReactiveCqlTemplate.class));
66+
});
6667
}
6768

6869
@Test
6970
void entityScanShouldSetManagedTypes() {
70-
load(EntityScanConfig.class, "spring.cassandra.keyspaceName:boot_test");
71-
CassandraMappingContext mappingContext = this.context.getBean(CassandraMappingContext.class);
72-
ManagedTypes managedTypes = (ManagedTypes) ReflectionTestUtils.getField(mappingContext, "managedTypes");
73-
assertThat(managedTypes.toList()).containsOnly(City.class);
71+
this.contextRunner.withUserConfiguration(EntityScanConfig.class).run((context) -> {
72+
assertThat(context).hasSingleBean(CassandraMappingContext.class);
73+
CassandraMappingContext mappingContext = context.getBean(CassandraMappingContext.class);
74+
assertThat(mappingContext.getManagedTypes()).singleElement()
75+
.satisfies((typeInformation) -> assertThat(typeInformation.getType()).isEqualTo(City.class));
76+
});
7477
}
7578

7679
@Test
7780
void userTypeResolverShouldBeSet() {
78-
load("spring.cassandra.keyspaceName:boot_test");
79-
CassandraConverter cassandraConverter = this.context.getBean(CassandraConverter.class);
80-
assertThat(cassandraConverter).extracting("userTypeResolver").isInstanceOf(SimpleUserTypeResolver.class);
81-
}
82-
83-
private void load(String... environment) {
84-
load(null, environment);
85-
}
86-
87-
private void load(Class<?> config, String... environment) {
88-
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
89-
TestPropertyValues.of(environment).applyTo(ctx);
90-
if (config != null) {
91-
ctx.register(config);
92-
}
93-
ctx.register(CassandraMockConfiguration.class, CassandraAutoConfiguration.class,
94-
CassandraDataAutoConfiguration.class, CassandraReactiveDataAutoConfiguration.class);
95-
ctx.refresh();
96-
this.context = ctx;
81+
this.contextRunner.run((context) -> {
82+
assertThat(context).hasSingleBean(CassandraConverter.class);
83+
assertThat(context).hasSingleBean(CassandraConverter.class);
84+
assertThat(context.getBean(CassandraConverter.class)).extracting("userTypeResolver")
85+
.isInstanceOf(SimpleUserTypeResolver.class);
86+
});
9787
}
9888

9989
@Configuration(proxyBeanMethods = false)

spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/data/nosql.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ There is a `spring-boot-starter-data-cassandra` starter for collecting the depen
440440
[[data.nosql.cassandra.connecting]]
441441
=== Connecting to Cassandra
442442

443-
You can inject an auto-configured javadoc:org.springframework.data.cassandra.core.CassandraTemplate[] or a Cassandra `CqlSession` instance as you would with any other Spring Bean.
443+
You can inject an auto-configured javadoc:org.springframework.data.cassandra.core.cql.CqlTemplate[], javadoc:org.springframework.data.cassandra.core.CassandraTemplate[], or a Cassandra `CqlSession` instance as you would with any other Spring Bean.
444444
The `spring.cassandra.*` properties can be used to customize the connection.
445445
Generally, you provide `keyspace-name` and `contact-points` as well the local datacenter name, as shown in the following example:
446446

0 commit comments

Comments
 (0)