Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra-parent</artifactId>
<version>5.0.0-SNAPSHOT</version>
<version>5.0.0-GH-1566-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data for Apache Cassandra</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-cassandra-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra-parent</artifactId>
<version>5.0.0-SNAPSHOT</version>
<version>5.0.0-GH-1566-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-cassandra/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra-parent</artifactId>
<version>5.0.0-SNAPSHOT</version>
<version>5.0.0-GH-1566-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.springframework.data.cassandra.core.mapping.Table;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.cassandra.repository.support.CassandraRepositoryFactoryBean;
import org.springframework.data.cassandra.repository.support.SimpleCassandraRepository;
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
Expand All @@ -40,6 +41,7 @@
* @author Mark Paluch
* @author Christoph Strobl
* @author Mateusz Szymczak
* @author Chris Bono
*/
public class CassandraRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {

Expand All @@ -55,6 +57,11 @@ protected String getModulePrefix() {
return "cassandra";
}

@Override
public String getRepositoryBaseClassName() {
return SimpleCassandraRepository.class.getName();
}

@Override
public String getRepositoryFactoryBeanClassName() {
return CassandraRepositoryFactoryBean.class.getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.data.cassandra.repository.ReactiveCassandraRepository;
import org.springframework.data.cassandra.repository.support.ReactiveCassandraRepositoryFactoryBean;
import org.springframework.data.cassandra.repository.support.SimpleReactiveCassandraRepository;
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
import org.springframework.data.repository.core.RepositoryMetadata;
Expand All @@ -30,6 +31,7 @@
* {@link RepositoryConfigurationExtension} for Cassandra.
*
* @author Mark Paluch
* @author Chris Bono
* @since 2.0
*/
public class ReactiveCassandraRepositoryConfigurationExtension extends CassandraRepositoryConfigurationExtension {
Expand All @@ -39,6 +41,11 @@ public String getModuleName() {
return "Reactive Cassandra";
}

@Override
public String getRepositoryBaseClassName() {
return SimpleReactiveCassandraRepository.class.getName();
}

@Override
public String getRepositoryFactoryBeanClassName() {
return ReactiveCassandraRepositoryFactoryBean.class.getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.springframework.data.repository.core.NamedQueries;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.data.repository.query.CachingValueExpressionDelegate;
import org.springframework.data.repository.query.QueryLookupStrategy;
Expand All @@ -50,13 +51,16 @@
* @author Thomas Darimont
* @author Mark Paluch
* @author John Blum
* @author Chris Bono
*/
public class CassandraRepositoryFactory extends RepositoryFactorySupport {

private final MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext;

private final CassandraOperations operations;

private CassandraRepositoryFragmentsContributor fragmentsContributor = CassandraRepositoryFragmentsContributor.DEFAULT;

/**
* Create a new {@link CassandraRepositoryFactory} with the given {@link CassandraOperations}.
*
Expand All @@ -70,6 +74,17 @@ public CassandraRepositoryFactory(CassandraOperations operations) {
this.mappingContext = operations.getConverter().getMappingContext();
}

/**
* Configures the {@link CassandraRepositoryFragmentsContributor} to be used. Defaults to
* {@link CassandraRepositoryFragmentsContributor#DEFAULT}.
*
* @param fragmentsContributor
* @since 5.0
*/
public void setFragmentsContributor(CassandraRepositoryFragmentsContributor fragmentsContributor) {
this.fragmentsContributor = fragmentsContributor;
}

@Override
protected ProjectionFactory getProjectionFactory(@Nullable ClassLoader classLoader,
@Nullable BeanFactory beanFactory) {
Expand Down Expand Up @@ -105,6 +120,23 @@ protected Optional<QueryLookupStrategy> getQueryLookupStrategy(@Nullable Key key
new CachingValueExpressionDelegate(valueExpressionDelegate), mappingContext));
}

@Override
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
return getRepositoryFragments(metadata, operations);
}

/**
* Creates {@link RepositoryFragments} based on {@link RepositoryMetadata} to add Cassandra-specific extensions.
* Built-in fragment contribution can be customized by configuring {@link CassandraRepositoryFragmentsContributor}.
*
* @param metadata repository metadata.
* @param operations the Cassandra operations manager.
* @return {@link RepositoryFragments} to be added to the repository.
* @since 5.0
*/
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata, CassandraOperations operations) {
return fragmentsContributor.contribute(metadata, getEntityInformation(metadata.getDomainType()), operations);
}

private record CassandraQueryLookupStrategy(CassandraOperations operations,
ValueExpressionDelegate valueExpressionDelegate,
Expand Down Expand Up @@ -132,4 +164,3 @@ public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata,
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
Expand All @@ -31,12 +32,17 @@
* @author John Blum
* @author Oliver Gierke
* @author Mark Paluch
* @author Chris Bono
*/
public class CassandraRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
extends RepositoryFactoryBeanSupport<T, S, ID> {

private boolean mappingContextConfigured = false;

private @Nullable CassandraOperations cassandraOperations;

private CassandraRepositoryFragmentsContributor repositoryFragmentsContributor = CassandraRepositoryFragmentsContributor.DEFAULT;

/**
* Create a new {@link CassandraRepositoryFactoryBean} for the given repository interface.
*
Expand All @@ -51,7 +57,35 @@ protected RepositoryFactorySupport createRepositoryFactory() {

Assert.state(cassandraOperations != null, "CassandraOperations must not be null");

return new CassandraRepositoryFactory(cassandraOperations);
CassandraRepositoryFactory factory = getFactoryInstance(cassandraOperations);
factory.setFragmentsContributor(repositoryFragmentsContributor);
return factory;
}

/**
* Creates and initializes a {@link CassandraRepositoryFactory} instance.
*
* @param operations the Cassandra operations
* @return new {@link CassandraRepositoryFactory} instance
*/
protected CassandraRepositoryFactory getFactoryInstance(CassandraOperations operations) {
return new CassandraRepositoryFactory(operations);
}

@Override
public CassandraRepositoryFragmentsContributor getRepositoryFragmentsContributor() {
return this.repositoryFragmentsContributor;
}

/**
* Configures the {@link CassandraRepositoryFragmentsContributor} to contribute built-in fragment functionality to the
* repository.
*
* @param repositoryFragmentsContributor must not be {@literal null}.
* @since 5.0
*/
public void setRepositoryFragmentsContributor(CassandraRepositoryFragmentsContributor repositoryFragmentsContributor) {
this.repositoryFragmentsContributor = repositoryFragmentsContributor;
}

/**
Expand All @@ -61,9 +95,15 @@ protected RepositoryFactorySupport createRepositoryFactory() {
* on Apache Cassandra.
*/
public void setCassandraTemplate(CassandraTemplate cassandraTemplate) {

this.cassandraOperations = cassandraTemplate;
setMappingContext(cassandraTemplate.getConverter().getMappingContext());
}

@Override
protected void setMappingContext(MappingContext<?, ?> mappingContext) {

super.setMappingContext(mappingContext);

this.mappingContextConfigured = true;
}

@Override
Expand All @@ -72,5 +112,9 @@ public void afterPropertiesSet() {
super.afterPropertiesSet();

Assert.notNull(cassandraOperations, "CassandraOperations must not be null");

if (!mappingContextConfigured) {
setMappingContext(cassandraOperations.getConverter().getMappingContext());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright 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.data.cassandra.repository.support;

import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.repository.query.CassandraEntityInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments;
import org.springframework.data.repository.core.support.RepositoryFragmentsContributor;
import org.springframework.util.Assert;

/**
* Cassandra-specific {@link RepositoryFragmentsContributor} contributing fragments based on the repository.
* <p>
* Implementations must define a no-args constructor.
*
* @author Chris Bono
* @since 5.0
*/
public interface CassandraRepositoryFragmentsContributor extends RepositoryFragmentsContributor {

CassandraRepositoryFragmentsContributor DEFAULT = DefaultCassandraRepositoryFragmentsContributor.INSTANCE;

/**
* Returns a composed {@code CassandraRepositoryFragmentsContributor} that first applies this contributor to its inputs,
* and then applies the {@code after} contributor concatenating effectively both results. If evaluation of either
* contributors throws an exception, it is relayed to the caller of the composed contributor.
*
* @param after the contributor to apply after this contributor is applied.
* @return a composed contributor that first applies this contributor and then applies the {@code after} contributor.
*/
default CassandraRepositoryFragmentsContributor andThen(CassandraRepositoryFragmentsContributor after) {

Assert.notNull(after, "CassandraRepositoryFragmentsContributor must not be null");

return new CassandraRepositoryFragmentsContributor() {

@Override
public RepositoryFragments contribute(RepositoryMetadata metadata,
CassandraEntityInformation<?, ?> entityInformation, CassandraOperations operations) {
return CassandraRepositoryFragmentsContributor.this.contribute(metadata, entityInformation, operations)
.append(after.contribute(metadata, entityInformation, operations));
}

@Override
public RepositoryFragments describe(RepositoryMetadata metadata) {
return CassandraRepositoryFragmentsContributor.this.describe(metadata).append(after.describe(metadata));
}
};
}

/**
* Creates {@link RepositoryFragments} based on {@link RepositoryMetadata} to add
* Cassandra-specific extensions.
*
* @param metadata repository metadata.
* @param entityInformation must not be {@literal null}.
* @param operations must not be {@literal null}.
* @return {@link RepositoryFragments} to be added to the repository.
*/
RepositoryFragments contribute(RepositoryMetadata metadata,
CassandraEntityInformation<?, ?> entityInformation, CassandraOperations operations);

/**
* Implementation of {@link CassandraRepositoryFragmentsContributor} that contributes empty fragments by default.
*
* @author Chris Bono
* @since 5.0
*/
enum DefaultCassandraRepositoryFragmentsContributor implements CassandraRepositoryFragmentsContributor {

INSTANCE;

@Override
public RepositoryFragments contribute(RepositoryMetadata metadata,
CassandraEntityInformation<?, ?> entityInformation, CassandraOperations operations) {
return RepositoryFragments.empty();
}

@Override
public RepositoryFragments describe(RepositoryMetadata metadata) {
return RepositoryFragments.empty();
}
}
}
Loading