Create spring-boot-data-cassandra module
This commit is contained in:
committed by
Phillip Webb
parent
7fbf1ce778
commit
f3dd5dae72
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlSession;
|
||||
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.cassandra.CassandraContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.cassandra.autoconfigure.CassandraAutoConfiguration;
|
||||
import org.springframework.boot.data.cassandra.domain.city.City;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.cassandra.config.SchemaAction;
|
||||
import org.springframework.data.cassandra.config.SessionFactoryFactoryBean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link CassandraDataAutoConfiguration} that require a Cassandra instance.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class CassandraDataAutoConfigurationIntegrationTests {
|
||||
|
||||
@Container
|
||||
static final CassandraContainer cassandra = TestImage.container(CassandraContainer.class);
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class))
|
||||
.withPropertyValues(
|
||||
"spring.cassandra.contact-points:" + cassandra.getHost() + ":" + cassandra.getFirstMappedPort(),
|
||||
"spring.cassandra.local-datacenter=datacenter1", "spring.cassandra.connection.connect-timeout=60s",
|
||||
"spring.cassandra.connection.init-query-timeout=60s", "spring.cassandra.request.timeout=60s")
|
||||
.withInitializer((context) -> AutoConfigurationPackages.register((BeanDefinitionRegistry) context,
|
||||
City.class.getPackage().getName()));
|
||||
|
||||
@Test
|
||||
void hasDefaultSchemaActionSet() {
|
||||
this.contextRunner.run((context) -> assertThat(context.getBean(SessionFactoryFactoryBean.class))
|
||||
.hasFieldOrPropertyWithValue("schemaAction", SchemaAction.NONE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasRecreateSchemaActionSet() {
|
||||
this.contextRunner.withUserConfiguration(KeyspaceTestConfiguration.class)
|
||||
.withPropertyValues("spring.cassandra.schemaAction=recreate_drop_unused")
|
||||
.run((context) -> assertThat(context.getBean(SessionFactoryFactoryBean.class))
|
||||
.hasFieldOrPropertyWithValue("schemaAction", SchemaAction.RECREATE_DROP_UNUSED));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class KeyspaceTestConfiguration {
|
||||
|
||||
@Bean
|
||||
CqlSession cqlSession(CqlSessionBuilder cqlSessionBuilder) {
|
||||
try (CqlSession session = cqlSessionBuilder.build()) {
|
||||
session.execute("CREATE KEYSPACE IF NOT EXISTS boot_test"
|
||||
+ " WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };");
|
||||
}
|
||||
return cqlSessionBuilder.withKeyspace("boot_test").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlSession;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScanPackages;
|
||||
import org.springframework.boot.cassandra.autoconfigure.CassandraAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.cassandra.CassandraManagedTypes;
|
||||
import org.springframework.data.cassandra.SessionFactory;
|
||||
import org.springframework.data.cassandra.config.CassandraEntityClassScanner;
|
||||
import org.springframework.data.cassandra.config.SchemaAction;
|
||||
import org.springframework.data.cassandra.config.SessionFactoryFactoryBean;
|
||||
import org.springframework.data.cassandra.core.CassandraAdminOperations;
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
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.cql.CqlOperations;
|
||||
import org.springframework.data.cassandra.core.cql.CqlTemplate;
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Cassandra support.
|
||||
*
|
||||
* @author Julien Dubois
|
||||
* @author Eddú Meléndez
|
||||
* @author Mark Paluch
|
||||
* @author Madhura Bhave
|
||||
* @author Christoph Strobl
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@AutoConfiguration(after = CassandraAutoConfiguration.class)
|
||||
@ConditionalOnClass({ CqlSession.class, CassandraAdminOperations.class })
|
||||
@ConditionalOnBean(CqlSession.class)
|
||||
public class CassandraDataAutoConfiguration {
|
||||
|
||||
private final CqlSession session;
|
||||
|
||||
public CassandraDataAutoConfiguration(@Lazy CqlSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public static CassandraManagedTypes cassandraManagedTypes(BeanFactory beanFactory) throws ClassNotFoundException {
|
||||
List<String> packages = EntityScanPackages.get(beanFactory).getPackageNames();
|
||||
if (packages.isEmpty() && AutoConfigurationPackages.has(beanFactory)) {
|
||||
packages = AutoConfigurationPackages.get(beanFactory);
|
||||
}
|
||||
if (!packages.isEmpty()) {
|
||||
return CassandraManagedTypes.fromIterable(CassandraEntityClassScanner.scan(packages));
|
||||
}
|
||||
return CassandraManagedTypes.empty();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public CassandraMappingContext cassandraMappingContext(CassandraManagedTypes cassandraManagedTypes,
|
||||
CassandraCustomConversions conversions) {
|
||||
CassandraMappingContext context = new CassandraMappingContext();
|
||||
context.setManagedTypes(cassandraManagedTypes);
|
||||
context.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
|
||||
return context;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public CassandraConverter cassandraConverter(CassandraMappingContext mapping,
|
||||
CassandraCustomConversions conversions) {
|
||||
MappingCassandraConverter converter = new MappingCassandraConverter(mapping);
|
||||
converter.setCodecRegistry(() -> this.session.getContext().getCodecRegistry());
|
||||
converter.setCustomConversions(conversions);
|
||||
converter.setUserTypeResolver(new SimpleUserTypeResolver(this.session));
|
||||
return converter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(SessionFactory.class)
|
||||
public SessionFactoryFactoryBean cassandraSessionFactory(Environment environment, CassandraConverter converter) {
|
||||
SessionFactoryFactoryBean session = new SessionFactoryFactoryBean();
|
||||
session.setSession(this.session);
|
||||
session.setConverter(converter);
|
||||
Binder binder = Binder.get(environment);
|
||||
binder.bind("spring.cassandra.schema-action", SchemaAction.class).ifBound(session::setSchemaAction);
|
||||
return session;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CqlOperations.class)
|
||||
public CqlTemplate cqlTemplate(SessionFactory sessionFactory) {
|
||||
return new CqlTemplate(sessionFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CassandraOperations.class)
|
||||
public CassandraTemplate cassandraTemplate(CqlTemplate cqlTemplate, CassandraConverter converter) {
|
||||
return new CassandraTemplate(cqlTemplate, converter);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public CassandraCustomConversions cassandraCustomConversions() {
|
||||
return new CassandraCustomConversions(Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlSession;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.cassandra.ReactiveSession;
|
||||
import org.springframework.data.cassandra.ReactiveSessionFactory;
|
||||
import org.springframework.data.cassandra.core.ReactiveCassandraOperations;
|
||||
import org.springframework.data.cassandra.core.ReactiveCassandraTemplate;
|
||||
import org.springframework.data.cassandra.core.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.core.cql.ReactiveCqlOperations;
|
||||
import org.springframework.data.cassandra.core.cql.ReactiveCqlTemplate;
|
||||
import org.springframework.data.cassandra.core.cql.session.DefaultBridgedReactiveSession;
|
||||
import org.springframework.data.cassandra.core.cql.session.DefaultReactiveSessionFactory;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's reactive Cassandra
|
||||
* support.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Mark Paluch
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@AutoConfiguration(after = CassandraDataAutoConfiguration.class)
|
||||
@ConditionalOnClass({ CqlSession.class, ReactiveCassandraTemplate.class, Flux.class })
|
||||
@ConditionalOnBean(CqlSession.class)
|
||||
public class CassandraReactiveDataAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ReactiveSession reactiveCassandraSession(CqlSession session) {
|
||||
return new DefaultBridgedReactiveSession(session);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ReactiveSessionFactory reactiveCassandraSessionFactory(ReactiveSession reactiveCassandraSession) {
|
||||
return new DefaultReactiveSessionFactory(reactiveCassandraSession);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ReactiveCqlOperations.class)
|
||||
public ReactiveCqlTemplate reactiveCqlTemplate(ReactiveSessionFactory reactiveCassandraSessionFactory) {
|
||||
return new ReactiveCqlTemplate(reactiveCassandraSessionFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ReactiveCassandraOperations.class)
|
||||
public ReactiveCassandraTemplate reactiveCassandraTemplate(ReactiveCqlTemplate reactiveCqlTemplate,
|
||||
CassandraConverter converter) {
|
||||
return new ReactiveCassandraTemplate(reactiveCqlTemplate, converter);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
|
||||
import org.springframework.boot.autoconfigure.data.RepositoryType;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.cassandra.ReactiveSession;
|
||||
import org.springframework.data.cassandra.repository.ReactiveCassandraRepository;
|
||||
import org.springframework.data.cassandra.repository.config.EnableReactiveCassandraRepositories;
|
||||
import org.springframework.data.cassandra.repository.support.ReactiveCassandraRepositoryFactoryBean;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Cassandra Reactive
|
||||
* Repositories.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Mark Paluch
|
||||
* @since 4.0.0
|
||||
* @see EnableReactiveCassandraRepositories
|
||||
*/
|
||||
@AutoConfiguration(after = CassandraReactiveDataAutoConfiguration.class)
|
||||
@ConditionalOnClass({ ReactiveSession.class, ReactiveCassandraRepository.class })
|
||||
@ConditionalOnRepositoryType(store = "cassandra", type = RepositoryType.REACTIVE)
|
||||
@ConditionalOnMissingBean(ReactiveCassandraRepositoryFactoryBean.class)
|
||||
@Import(CassandraReactiveRepositoriesRegistrar.class)
|
||||
public class CassandraReactiveRepositoriesAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.data.cassandra.repository.config.EnableReactiveCassandraRepositories;
|
||||
import org.springframework.data.cassandra.repository.config.ReactiveCassandraRepositoryConfigurationExtension;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
|
||||
/**
|
||||
* {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Cassandra
|
||||
* Reactive Repositories.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
class CassandraReactiveRepositoriesRegistrar extends AbstractRepositoryConfigurationSourceSupport {
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotation() {
|
||||
return EnableReactiveCassandraRepositories.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getConfiguration() {
|
||||
return EnableReactiveCassandraRepositoriesConfiguration.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() {
|
||||
return new ReactiveCassandraRepositoryConfigurationExtension();
|
||||
}
|
||||
|
||||
@EnableReactiveCassandraRepositories
|
||||
private static final class EnableReactiveCassandraRepositoriesConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlSession;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
|
||||
import org.springframework.boot.autoconfigure.data.RepositoryType;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.cassandra.repository.CassandraRepository;
|
||||
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
|
||||
import org.springframework.data.cassandra.repository.support.CassandraRepositoryFactoryBean;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Cassandra
|
||||
* Repositories.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @since 4.0.0
|
||||
* @see EnableCassandraRepositories
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass({ CqlSession.class, CassandraRepository.class })
|
||||
@ConditionalOnRepositoryType(store = "cassandra", type = RepositoryType.IMPERATIVE)
|
||||
@ConditionalOnMissingBean(CassandraRepositoryFactoryBean.class)
|
||||
@Import(CassandraRepositoriesRegistrar.class)
|
||||
public class CassandraRepositoriesAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.data.cassandra.repository.config.CassandraRepositoryConfigurationExtension;
|
||||
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
|
||||
/**
|
||||
* {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Cassandra
|
||||
* Repositories.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
class CassandraRepositoriesRegistrar extends AbstractRepositoryConfigurationSourceSupport {
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotation() {
|
||||
return EnableCassandraRepositories.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getConfiguration() {
|
||||
return EnableCassandraRepositoriesConfiguration.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() {
|
||||
return new CassandraRepositoryConfigurationExtension();
|
||||
}
|
||||
|
||||
@EnableCassandraRepositories
|
||||
private static final class EnableCassandraRepositoriesConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-configuration for Spring Data Cassandra.
|
||||
*/
|
||||
package org.springframework.boot.data.cassandra.autoconfigure;
|
||||
@@ -0,0 +1,263 @@
|
||||
{
|
||||
"groups": [],
|
||||
"properties": [
|
||||
{
|
||||
"name": "spring.data.cassandra.compression",
|
||||
"defaultValue": "none",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.compression",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.config",
|
||||
"type": "org.springframework.core.io.Resource",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.config",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.connection.connect-timeout",
|
||||
"defaultValue": "5s",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.connection.connect-timeout",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.connection.init-query-timeout",
|
||||
"defaultValue": "5s",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.connection.init-query-timeout",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.contact-points",
|
||||
"defaultValue": [
|
||||
"127.0.0.1:9042"
|
||||
],
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.contact-points",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.controlconnection.timeout",
|
||||
"defaultValue": "5s",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.controlconnection.timeout",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.jmx-enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to enable JMX reporting. Default to false as Cassandra JMX reporting is not compatible with Dropwizard Metrics.",
|
||||
"deprecation": {
|
||||
"reason": "Cassandra no longer provides JMX metrics.",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.keyspace-name",
|
||||
"type": "java.lang.String",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.keyspace-name",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.load-balancing-policy",
|
||||
"type": "java.lang.Class",
|
||||
"description": "Class name of the load balancing policy. The class must have a default constructor.",
|
||||
"deprecation": {
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.local-datacenter",
|
||||
"type": "java.lang.String",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.local-datacenter",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.password",
|
||||
"type": "java.lang.String",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.password",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.pool.heartbeat-interval",
|
||||
"defaultValue": "30s",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.pool.heartbeat-interval",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.pool.idle-timeout",
|
||||
"defaultValue": "5s",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.pool.idle-timeout",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.pool.max-queue-size",
|
||||
"type": "java.lang.Integer",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.request.throttler.max-queue-size",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.pool.pool-timeout",
|
||||
"type": "java.time.Duration",
|
||||
"description": "Pool timeout when trying to acquire a connection from a host's pool.",
|
||||
"deprecation": {
|
||||
"reason": "No longer available.",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.port",
|
||||
"type": "java.lang.Integer",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.port",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.reconnection-policy",
|
||||
"type": "java.lang.Class",
|
||||
"description": "Class name of the reconnection policy. The class must have a default constructor.",
|
||||
"deprecation": {
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.repositories.type",
|
||||
"type": "org.springframework.boot.autoconfigure.data.RepositoryType",
|
||||
"description": "Type of Cassandra repositories to enable.",
|
||||
"defaultValue": "auto"
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.request.consistency",
|
||||
"type": "com.datastax.oss.driver.api.core.DefaultConsistencyLevel",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.request.consistency",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.request.page-size",
|
||||
"defaultValue": 5000,
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.request.page-size",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.request.serial-consistency",
|
||||
"type": "com.datastax.oss.driver.api.core.DefaultConsistencyLevel",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.request.serial-consistency",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.request.throttler.drain-interval",
|
||||
"type": "java.time.Duration",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.request.throttler.drain-interval",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.request.throttler.max-concurrent-requests",
|
||||
"type": "java.lang.Integer",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.request.throttler.max-concurrent-requests",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.request.throttler.max-queue-size",
|
||||
"type": "java.lang.Integer",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.request.throttler.max-queue-size",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.request.throttler.max-requests-per-second",
|
||||
"type": "java.lang.Integer",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.request.throttler.max-requests-per-second",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.request.throttler.type",
|
||||
"defaultValue": "none",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.request.throttler.type",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.request.timeout",
|
||||
"defaultValue": "2s",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.request.timeout",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.retry-policy",
|
||||
"type": "java.lang.Class",
|
||||
"description": "Class name of the retry policy. The class must have a default constructor.",
|
||||
"deprecation": {
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.schema-action",
|
||||
"type": "java.lang.String",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.schema-action",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.session-name",
|
||||
"type": "java.lang.String",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.session-name",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.ssl",
|
||||
"type": "java.lang.Boolean",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.ssl.enabled",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.data.cassandra.username",
|
||||
"type": "java.lang.String",
|
||||
"deprecation": {
|
||||
"replacement": "spring.cassandra.username",
|
||||
"level": "error"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
org.springframework.boot.data.cassandra.autoconfigure.CassandraDataAutoConfiguration
|
||||
org.springframework.boot.data.cassandra.autoconfigure.CassandraReactiveDataAutoConfiguration
|
||||
org.springframework.boot.data.cassandra.autoconfigure.CassandraReactiveRepositoriesAutoConfiguration
|
||||
org.springframework.boot.data.cassandra.autoconfigure.CassandraRepositoriesAutoConfiguration
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlSession;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.cassandra.autoconfigure.CassandraAutoConfiguration;
|
||||
import org.springframework.boot.data.cassandra.domain.city.City;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
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.cql.CqlTemplate;
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link CassandraDataAutoConfiguration}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Mark Paluch
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class CassandraDataAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withPropertyValues("spring.cassandra.keyspaceName=boot_test")
|
||||
.withUserConfiguration(CassandraMockConfiguration.class)
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void cqlTemplateExists() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CqlTemplate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void templateExists() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CassandraTemplate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void templateUsesCqlTemplate() {
|
||||
this.contextRunner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(CassandraTemplate.class);
|
||||
assertThat(context.getBean(CassandraTemplate.class).getCqlOperations())
|
||||
.isSameAs(context.getBean(CqlTemplate.class));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void entityScanShouldSetManagedTypes() {
|
||||
this.contextRunner.withUserConfiguration(EntityScanConfig.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(CassandraMappingContext.class);
|
||||
CassandraMappingContext mappingContext = context.getBean(CassandraMappingContext.class);
|
||||
assertThat(mappingContext.getManagedTypes()).singleElement()
|
||||
.satisfies((typeInformation) -> assertThat(typeInformation.getType()).isEqualTo(City.class));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void userTypeResolverShouldBeSet() {
|
||||
this.contextRunner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(CassandraConverter.class);
|
||||
assertThat(context.getBean(CassandraConverter.class)).extracting("userTypeResolver")
|
||||
.isInstanceOf(SimpleUserTypeResolver.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void codecRegistryShouldBeSet() {
|
||||
this.contextRunner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(CassandraConverter.class);
|
||||
assertThat(context.getBean(CassandraConverter.class).getCodecRegistry())
|
||||
.isSameAs(context.getBean(CassandraMockConfiguration.class).codecRegistry);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConversions() {
|
||||
this.contextRunner.run((context) -> {
|
||||
CassandraTemplate template = context.getBean(CassandraTemplate.class);
|
||||
assertThat(template.getConverter().getConversionService().canConvert(Person.class, String.class)).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void customConversions() {
|
||||
this.contextRunner.withUserConfiguration(CustomConversionConfig.class).run((context) -> {
|
||||
CassandraTemplate template = context.getBean(CassandraTemplate.class);
|
||||
assertThat(template.getConverter().getConversionService().canConvert(Person.class, String.class)).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void clusterDoesNotExist() {
|
||||
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
CassandraDataAutoConfiguration.class)) {
|
||||
assertThat(context.getBeansOfType(CqlSession.class)).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EntityScan("org.springframework.boot.data.cassandra.domain.city")
|
||||
static class EntityScanConfig {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomConversionConfig {
|
||||
|
||||
@Bean
|
||||
CassandraCustomConversions myCassandraCustomConversions() {
|
||||
return new CassandraCustomConversions(Collections.singletonList(new MyConverter()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class MyConverter implements Converter<Person, String> {
|
||||
|
||||
@Override
|
||||
public String convert(Person o) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class Person {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlSession;
|
||||
import com.datastax.oss.driver.api.core.context.DriverContext;
|
||||
import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Test configuration that mocks access to Cassandra.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class CassandraMockConfiguration {
|
||||
|
||||
final CodecRegistry codecRegistry = mock(CodecRegistry.class);
|
||||
|
||||
@Bean
|
||||
CqlSession cqlSession() {
|
||||
DriverContext context = mock(DriverContext.class);
|
||||
given(context.getCodecRegistry()).willReturn(this.codecRegistry);
|
||||
CqlSession cqlSession = mock(CqlSession.class);
|
||||
given(cqlSession.getContext()).willReturn(context);
|
||||
return cqlSession;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.cassandra.autoconfigure.CassandraAutoConfiguration;
|
||||
import org.springframework.boot.data.cassandra.domain.city.City;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.cassandra.core.ReactiveCassandraTemplate;
|
||||
import org.springframework.data.cassandra.core.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.core.cql.ReactiveCqlTemplate;
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link CassandraReactiveDataAutoConfiguration}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class CassandraReactiveDataAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withPropertyValues("spring.cassandra.keyspaceName=boot_test")
|
||||
.withUserConfiguration(CassandraMockConfiguration.class)
|
||||
.withConfiguration(AutoConfigurations.of(CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
|
||||
CassandraReactiveDataAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void reactiveCqlTemplateExists() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ReactiveCqlTemplate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void templateExists() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ReactiveCassandraTemplate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void templateUsesReactiveCqlTemplate() {
|
||||
this.contextRunner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ReactiveCassandraTemplate.class);
|
||||
assertThat(context.getBean(ReactiveCassandraTemplate.class).getReactiveCqlOperations())
|
||||
.isSameAs(context.getBean(ReactiveCqlTemplate.class));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void entityScanShouldSetManagedTypes() {
|
||||
this.contextRunner.withUserConfiguration(EntityScanConfig.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(CassandraMappingContext.class);
|
||||
CassandraMappingContext mappingContext = context.getBean(CassandraMappingContext.class);
|
||||
assertThat(mappingContext.getManagedTypes()).singleElement()
|
||||
.satisfies((typeInformation) -> assertThat(typeInformation.getType()).isEqualTo(City.class));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void userTypeResolverShouldBeSet() {
|
||||
this.contextRunner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(CassandraConverter.class);
|
||||
assertThat(context.getBean(CassandraConverter.class)).extracting("userTypeResolver")
|
||||
.isInstanceOf(SimpleUserTypeResolver.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EntityScan("org.springframework.boot.data.cassandra.domain.city")
|
||||
static class EntityScanConfig {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.cassandra.autoconfigure.CassandraAutoConfiguration;
|
||||
import org.springframework.boot.data.cassandra.domain.city.City;
|
||||
import org.springframework.boot.data.cassandra.domain.city.ReactiveCityRepository;
|
||||
import org.springframework.boot.data.cassandra.domain.empty.EmptyDataPackage;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.repository.config.EnableReactiveCassandraRepositories;
|
||||
import org.springframework.data.domain.ManagedTypes;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link CassandraReactiveRepositoriesAutoConfiguration}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Mark Paluch
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class CassandraReactiveRepositoriesAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
|
||||
AutoConfigurations.of(CassandraAutoConfiguration.class, CassandraRepositoriesAutoConfiguration.class,
|
||||
CassandraDataAutoConfiguration.class, CassandraReactiveDataAutoConfiguration.class,
|
||||
CassandraReactiveRepositoriesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void testDefaultRepositoryConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(DefaultConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(ReactiveCityRepository.class);
|
||||
assertThat(context).hasSingleBean(CqlSessionBuilder.class);
|
||||
assertThat(getManagedTypes(context).toList()).hasSize(1);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoRepositoryConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(CqlSessionBuilder.class);
|
||||
assertThat(getManagedTypes(context).toList()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
|
||||
this.contextRunner.withUserConfiguration(CustomizedConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(ReactiveCityRepository.class);
|
||||
assertThat(getManagedTypes(context).toList()).hasSize(1).containsOnly(City.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void enablingImperativeRepositoriesDisablesReactiveRepositories() {
|
||||
this.contextRunner.withUserConfiguration(DefaultConfiguration.class)
|
||||
.withPropertyValues("spring.data.cassandra.repositories.type=imperative")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveCityRepository.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void enablingNoRepositoriesDisablesReactiveRepositories() {
|
||||
this.contextRunner.withUserConfiguration(DefaultConfiguration.class)
|
||||
.withPropertyValues("spring.data.cassandra.repositories.type=none")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveCityRepository.class));
|
||||
}
|
||||
|
||||
private ManagedTypes getManagedTypes(ApplicationContext context) {
|
||||
CassandraMappingContext mappingContext = context.getBean(CassandraMappingContext.class);
|
||||
return (ManagedTypes) ReflectionTestUtils.getField(mappingContext, "managedTypes");
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(EmptyDataPackage.class)
|
||||
@Import(CassandraMockConfiguration.class)
|
||||
static class EmptyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(City.class)
|
||||
@Import(CassandraMockConfiguration.class)
|
||||
static class DefaultConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(City.class)
|
||||
@EnableReactiveCassandraRepositories(basePackageClasses = ReactiveCityRepository.class)
|
||||
@Import(CassandraMockConfiguration.class)
|
||||
static class CustomizedConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.autoconfigure;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.cassandra.autoconfigure.CassandraAutoConfiguration;
|
||||
import org.springframework.boot.data.cassandra.domain.city.City;
|
||||
import org.springframework.boot.data.cassandra.domain.city.CityRepository;
|
||||
import org.springframework.boot.data.cassandra.domain.empty.EmptyDataPackage;
|
||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
|
||||
import org.springframework.data.domain.ManagedTypes;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link CassandraRepositoriesAutoConfiguration}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Mark Paluch
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class CassandraRepositoriesAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
|
||||
AutoConfigurations.of(CassandraAutoConfiguration.class, CassandraRepositoriesAutoConfiguration.class,
|
||||
CassandraDataAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void testDefaultRepositoryConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(DefaultConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(CityRepository.class);
|
||||
assertThat(context).hasSingleBean(CqlSessionBuilder.class);
|
||||
assertThat(getManagedTypes(context).toList()).hasSize(1);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoRepositoryConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(CqlSessionBuilder.class);
|
||||
assertThat(getManagedTypes(context).toList()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
|
||||
this.contextRunner.withUserConfiguration(CustomizedConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(CityRepository.class);
|
||||
assertThat(getManagedTypes(context).toList()).hasSize(1).containsOnly(City.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void enablingReactiveRepositoriesDisablesImperativeRepositories() {
|
||||
this.contextRunner.withUserConfiguration(DefaultConfiguration.class)
|
||||
.withPropertyValues("spring.data.cassandra.repositories.type=reactive")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CityRepository.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void enablingNoRepositoriesDisablesImperativeRepositories() {
|
||||
this.contextRunner.withUserConfiguration(DefaultConfiguration.class)
|
||||
.withPropertyValues("spring.data.cassandra.repositories.type=none")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CityRepository.class));
|
||||
}
|
||||
|
||||
private ManagedTypes getManagedTypes(AssertableApplicationContext context) {
|
||||
CassandraMappingContext mappingContext = context.getBean(CassandraMappingContext.class);
|
||||
return (ManagedTypes) ReflectionTestUtils.getField(mappingContext, "managedTypes");
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(EmptyDataPackage.class)
|
||||
@Import(CassandraMockConfiguration.class)
|
||||
static class EmptyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(City.class)
|
||||
@Import(CassandraMockConfiguration.class)
|
||||
static class DefaultConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(City.class)
|
||||
@EnableCassandraRepositories(basePackageClasses = CityRepository.class)
|
||||
@Import(CassandraMockConfiguration.class)
|
||||
static class CustomizedConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.domain.city;
|
||||
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraType;
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraType.Name;
|
||||
import org.springframework.data.cassandra.core.mapping.Column;
|
||||
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
|
||||
import org.springframework.data.cassandra.core.mapping.Table;
|
||||
|
||||
@Table
|
||||
public class City {
|
||||
|
||||
@PrimaryKey
|
||||
@CassandraType(type = Name.BIGINT)
|
||||
private Long id;
|
||||
|
||||
@Column
|
||||
private String name;
|
||||
|
||||
@Column
|
||||
private String state;
|
||||
|
||||
@Column
|
||||
private String country;
|
||||
|
||||
@Column
|
||||
private String map;
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return this.country;
|
||||
}
|
||||
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public String getMap() {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
public void setMap(String map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.domain.city;
|
||||
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
public interface CityRepository extends Repository<City, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.domain.city;
|
||||
|
||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
|
||||
public interface ReactiveCityRepository extends ReactiveCrudRepository<City, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2012-2025 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
|
||||
*
|
||||
* https://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.data.cassandra.domain.empty;
|
||||
|
||||
public class EmptyDataPackage {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user