Skip to content

Commit 9986abd

Browse files
committed
Adopt to AOT changes in Commons.
Adds repository base class to configuration extensions. Introduces repository fragments contributor and updates the repository factories and factory beans w/ to use the default implementations. Also makes the CassandraRepositoryFactoryBean consistent with its reactive counterpart by only setting the mapping context from the CassandraOperations in afterPropertiesSet iff the mapping context was not specified by the user. See: #1566 Related tickets: spring-projects/spring-data-commons#3282
1 parent cbf2019 commit 9986abd

10 files changed

+559
-6
lines changed

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoryConfigurationExtension.java

+7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.springframework.data.cassandra.core.mapping.Table;
2626
import org.springframework.data.cassandra.repository.CassandraRepository;
2727
import org.springframework.data.cassandra.repository.support.CassandraRepositoryFactoryBean;
28+
import org.springframework.data.cassandra.repository.support.SimpleCassandraRepository;
2829
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
2930
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
3031
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
@@ -40,6 +41,7 @@
4041
* @author Mark Paluch
4142
* @author Christoph Strobl
4243
* @author Mateusz Szymczak
44+
* @author Chris Bono
4345
*/
4446
public class CassandraRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
4547

@@ -55,6 +57,11 @@ protected String getModulePrefix() {
5557
return "cassandra";
5658
}
5759

60+
@Override
61+
public String getRepositoryBaseClassName() {
62+
return SimpleCassandraRepository.class.getName();
63+
}
64+
5865
@Override
5966
public String getRepositoryFactoryBeanClassName() {
6067
return CassandraRepositoryFactoryBean.class.getName();

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/ReactiveCassandraRepositoryConfigurationExtension.java

+7
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
2222
import org.springframework.data.cassandra.repository.ReactiveCassandraRepository;
2323
import org.springframework.data.cassandra.repository.support.ReactiveCassandraRepositoryFactoryBean;
24+
import org.springframework.data.cassandra.repository.support.SimpleReactiveCassandraRepository;
2425
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
2526
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
2627
import org.springframework.data.repository.core.RepositoryMetadata;
@@ -30,6 +31,7 @@
3031
* {@link RepositoryConfigurationExtension} for Cassandra.
3132
*
3233
* @author Mark Paluch
34+
* @author Chris Bono
3335
* @since 2.0
3436
*/
3537
public class ReactiveCassandraRepositoryConfigurationExtension extends CassandraRepositoryConfigurationExtension {
@@ -39,6 +41,11 @@ public String getModuleName() {
3941
return "Reactive Cassandra";
4042
}
4143

44+
@Override
45+
public String getRepositoryBaseClassName() {
46+
return SimpleReactiveCassandraRepository.class.getName();
47+
}
48+
4249
@Override
4350
public String getRepositoryFactoryBeanClassName() {
4451
return ReactiveCassandraRepositoryFactoryBean.class.getName();

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactory.java

+32-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.data.repository.core.NamedQueries;
3535
import org.springframework.data.repository.core.RepositoryInformation;
3636
import org.springframework.data.repository.core.RepositoryMetadata;
37+
import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments;
3738
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
3839
import org.springframework.data.repository.query.CachingValueExpressionDelegate;
3940
import org.springframework.data.repository.query.QueryLookupStrategy;
@@ -50,13 +51,16 @@
5051
* @author Thomas Darimont
5152
* @author Mark Paluch
5253
* @author John Blum
54+
* @author Chris Bono
5355
*/
5456
public class CassandraRepositoryFactory extends RepositoryFactorySupport {
5557

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

5860
private final CassandraOperations operations;
5961

62+
private CassandraRepositoryFragmentsContributor fragmentsContributor = CassandraRepositoryFragmentsContributor.DEFAULT;
63+
6064
/**
6165
* Create a new {@link CassandraRepositoryFactory} with the given {@link CassandraOperations}.
6266
*
@@ -70,6 +74,17 @@ public CassandraRepositoryFactory(CassandraOperations operations) {
7074
this.mappingContext = operations.getConverter().getMappingContext();
7175
}
7276

77+
/**
78+
* Configures the {@link CassandraRepositoryFragmentsContributor} to be used. Defaults to
79+
* {@link CassandraRepositoryFragmentsContributor#DEFAULT}.
80+
*
81+
* @param fragmentsContributor
82+
* @since 5.0
83+
*/
84+
public void setFragmentsContributor(CassandraRepositoryFragmentsContributor fragmentsContributor) {
85+
this.fragmentsContributor = fragmentsContributor;
86+
}
87+
7388
@Override
7489
protected ProjectionFactory getProjectionFactory(@Nullable ClassLoader classLoader,
7590
@Nullable BeanFactory beanFactory) {
@@ -105,6 +120,23 @@ protected Optional<QueryLookupStrategy> getQueryLookupStrategy(@Nullable Key key
105120
new CachingValueExpressionDelegate(valueExpressionDelegate), mappingContext));
106121
}
107122

123+
@Override
124+
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
125+
return getRepositoryFragments(metadata, operations);
126+
}
127+
128+
/**
129+
* Creates {@link RepositoryFragments} based on {@link RepositoryMetadata} to add Cassandra-specific extensions.
130+
* Built-in fragment contribution can be customized by configuring {@link CassandraRepositoryFragmentsContributor}.
131+
*
132+
* @param metadata repository metadata.
133+
* @param operations the Cassandra operations manager.
134+
* @return {@link RepositoryFragments} to be added to the repository.
135+
* @since 5.0
136+
*/
137+
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata, CassandraOperations operations) {
138+
return fragmentsContributor.contribute(metadata, getEntityInformation(metadata.getDomainType()), operations);
139+
}
108140

109141
private record CassandraQueryLookupStrategy(CassandraOperations operations,
110142
ValueExpressionDelegate valueExpressionDelegate,
@@ -132,4 +164,3 @@ public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata,
132164
}
133165

134166
}
135-

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactoryBean.java

+47-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.springframework.data.cassandra.core.CassandraOperations;
2020
import org.springframework.data.cassandra.core.CassandraTemplate;
2121
import org.springframework.data.cassandra.repository.CassandraRepository;
22+
import org.springframework.data.mapping.context.MappingContext;
2223
import org.springframework.data.repository.Repository;
2324
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
2425
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
@@ -31,12 +32,17 @@
3132
* @author John Blum
3233
* @author Oliver Gierke
3334
* @author Mark Paluch
35+
* @author Chris Bono
3436
*/
3537
public class CassandraRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
3638
extends RepositoryFactoryBeanSupport<T, S, ID> {
3739

40+
private boolean mappingContextConfigured = false;
41+
3842
private @Nullable CassandraOperations cassandraOperations;
3943

44+
private CassandraRepositoryFragmentsContributor repositoryFragmentsContributor = CassandraRepositoryFragmentsContributor.DEFAULT;
45+
4046
/**
4147
* Create a new {@link CassandraRepositoryFactoryBean} for the given repository interface.
4248
*
@@ -51,7 +57,35 @@ protected RepositoryFactorySupport createRepositoryFactory() {
5157

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

54-
return new CassandraRepositoryFactory(cassandraOperations);
60+
CassandraRepositoryFactory factory = getFactoryInstance(cassandraOperations);
61+
factory.setFragmentsContributor(repositoryFragmentsContributor);
62+
return factory;
63+
}
64+
65+
/**
66+
* Creates and initializes a {@link CassandraRepositoryFactory} instance.
67+
*
68+
* @param operations the Cassandra operations
69+
* @return new {@link CassandraRepositoryFactory} instance
70+
*/
71+
protected CassandraRepositoryFactory getFactoryInstance(CassandraOperations operations) {
72+
return new CassandraRepositoryFactory(operations);
73+
}
74+
75+
@Override
76+
public CassandraRepositoryFragmentsContributor getRepositoryFragmentsContributor() {
77+
return this.repositoryFragmentsContributor;
78+
}
79+
80+
/**
81+
* Configures the {@link CassandraRepositoryFragmentsContributor} to contribute built-in fragment functionality to the
82+
* repository.
83+
*
84+
* @param repositoryFragmentsContributor must not be {@literal null}.
85+
* @since 5.0
86+
*/
87+
public void setRepositoryFragmentsContributor(CassandraRepositoryFragmentsContributor repositoryFragmentsContributor) {
88+
this.repositoryFragmentsContributor = repositoryFragmentsContributor;
5589
}
5690

5791
/**
@@ -61,9 +95,15 @@ protected RepositoryFactorySupport createRepositoryFactory() {
6195
* on Apache Cassandra.
6296
*/
6397
public void setCassandraTemplate(CassandraTemplate cassandraTemplate) {
64-
6598
this.cassandraOperations = cassandraTemplate;
66-
setMappingContext(cassandraTemplate.getConverter().getMappingContext());
99+
}
100+
101+
@Override
102+
protected void setMappingContext(MappingContext<?, ?> mappingContext) {
103+
104+
super.setMappingContext(mappingContext);
105+
106+
this.mappingContextConfigured = true;
67107
}
68108

69109
@Override
@@ -72,5 +112,9 @@ public void afterPropertiesSet() {
72112
super.afterPropertiesSet();
73113

74114
Assert.notNull(cassandraOperations, "CassandraOperations must not be null");
115+
116+
if (!mappingContextConfigured) {
117+
setMappingContext(cassandraOperations.getConverter().getMappingContext());
118+
}
75119
}
76120
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.cassandra.repository.support;
17+
18+
import org.springframework.data.cassandra.core.CassandraOperations;
19+
import org.springframework.data.cassandra.repository.query.CassandraEntityInformation;
20+
import org.springframework.data.repository.core.RepositoryMetadata;
21+
import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments;
22+
import org.springframework.data.repository.core.support.RepositoryFragmentsContributor;
23+
import org.springframework.util.Assert;
24+
25+
/**
26+
* Cassandra-specific {@link RepositoryFragmentsContributor} contributing fragments based on the repository.
27+
* <p>
28+
* Implementations must define a no-args constructor.
29+
*
30+
* @author Chris Bono
31+
* @since 5.0
32+
*/
33+
public interface CassandraRepositoryFragmentsContributor extends RepositoryFragmentsContributor {
34+
35+
CassandraRepositoryFragmentsContributor DEFAULT = DefaultCassandraRepositoryFragmentsContributor.INSTANCE;
36+
37+
/**
38+
* Returns a composed {@code CassandraRepositoryFragmentsContributor} that first applies this contributor to its inputs,
39+
* and then applies the {@code after} contributor concatenating effectively both results. If evaluation of either
40+
* contributors throws an exception, it is relayed to the caller of the composed contributor.
41+
*
42+
* @param after the contributor to apply after this contributor is applied.
43+
* @return a composed contributor that first applies this contributor and then applies the {@code after} contributor.
44+
*/
45+
default CassandraRepositoryFragmentsContributor andThen(CassandraRepositoryFragmentsContributor after) {
46+
47+
Assert.notNull(after, "CassandraRepositoryFragmentsContributor must not be null");
48+
49+
return new CassandraRepositoryFragmentsContributor() {
50+
51+
@Override
52+
public RepositoryFragments contribute(RepositoryMetadata metadata,
53+
CassandraEntityInformation<?, ?> entityInformation, CassandraOperations operations) {
54+
return CassandraRepositoryFragmentsContributor.this.contribute(metadata, entityInformation, operations)
55+
.append(after.contribute(metadata, entityInformation, operations));
56+
}
57+
58+
@Override
59+
public RepositoryFragments describe(RepositoryMetadata metadata) {
60+
return CassandraRepositoryFragmentsContributor.this.describe(metadata).append(after.describe(metadata));
61+
}
62+
};
63+
}
64+
65+
/**
66+
* Creates {@link RepositoryFragments} based on {@link RepositoryMetadata} to add
67+
* Cassandra-specific extensions.
68+
*
69+
* @param metadata repository metadata.
70+
* @param entityInformation must not be {@literal null}.
71+
* @param operations must not be {@literal null}.
72+
* @return {@link RepositoryFragments} to be added to the repository.
73+
*/
74+
RepositoryFragments contribute(RepositoryMetadata metadata,
75+
CassandraEntityInformation<?, ?> entityInformation, CassandraOperations operations);
76+
77+
/**
78+
* Implementation of {@link CassandraRepositoryFragmentsContributor} that contributes empty fragments by default.
79+
*
80+
* @author Chris Bono
81+
* @since 5.0
82+
*/
83+
enum DefaultCassandraRepositoryFragmentsContributor implements CassandraRepositoryFragmentsContributor {
84+
85+
INSTANCE;
86+
87+
@Override
88+
public RepositoryFragments contribute(RepositoryMetadata metadata,
89+
CassandraEntityInformation<?, ?> entityInformation, CassandraOperations operations) {
90+
return RepositoryFragments.empty();
91+
}
92+
93+
@Override
94+
public RepositoryFragments describe(RepositoryMetadata metadata) {
95+
return RepositoryFragments.empty();
96+
}
97+
}
98+
}

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/ReactiveCassandraRepositoryFactory.java

+33
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.data.repository.core.RepositoryInformation;
3535
import org.springframework.data.repository.core.RepositoryMetadata;
3636
import org.springframework.data.repository.core.support.ReactiveRepositoryFactorySupport;
37+
import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments;
3738
import org.springframework.data.repository.query.CachingValueExpressionDelegate;
3839
import org.springframework.data.repository.query.QueryLookupStrategy;
3940
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
@@ -46,6 +47,7 @@
4647
*
4748
* @author Mark Paluch
4849
* @author Marcin Grzejszczak
50+
* @author Chris Bono
4951
* @since 2.0
5052
*/
5153
public class ReactiveCassandraRepositoryFactory extends ReactiveRepositoryFactorySupport {
@@ -54,6 +56,8 @@ public class ReactiveCassandraRepositoryFactory extends ReactiveRepositoryFactor
5456

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

59+
private ReactiveCassandraRepositoryFragmentsContributor fragmentsContributor = ReactiveCassandraRepositoryFragmentsContributor.DEFAULT;
60+
5761
/**
5862
* Create a new {@link ReactiveCassandraRepositoryFactory} with the given {@link ReactiveCassandraOperations}.
5963
*
@@ -67,6 +71,17 @@ public ReactiveCassandraRepositoryFactory(ReactiveCassandraOperations cassandraO
6771
this.mappingContext = cassandraOperations.getConverter().getMappingContext();
6872
}
6973

74+
/**
75+
* Configures the {@link ReactiveCassandraRepositoryFragmentsContributor} to be used. Defaults to
76+
* {@link ReactiveCassandraRepositoryFragmentsContributor#DEFAULT}.
77+
*
78+
* @param fragmentsContributor
79+
* @since 5.0
80+
*/
81+
public void setFragmentsContributor(ReactiveCassandraRepositoryFragmentsContributor fragmentsContributor) {
82+
this.fragmentsContributor = fragmentsContributor;
83+
}
84+
7085
@Override
7186
protected ProjectionFactory getProjectionFactory(@Nullable ClassLoader classLoader,
7287
@Nullable BeanFactory beanFactory) {
@@ -101,6 +116,24 @@ public <T, ID> CassandraEntityInformation<T, ID> getEntityInformation(Class<T> d
101116
return new MappingCassandraEntityInformation<>((CassandraPersistentEntity<T>) entity, operations.getConverter());
102117
}
103118

119+
@Override
120+
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
121+
return getRepositoryFragments(metadata, operations);
122+
}
123+
124+
/**
125+
* Creates {@link RepositoryFragments} based on {@link RepositoryMetadata} to add Cassandra-specific extensions.
126+
* Built-in fragment contribution can be customized by configuring {@link CassandraRepositoryFragmentsContributor}.
127+
*
128+
* @param metadata repository metadata.
129+
* @param operations the Cassandra operations manager.
130+
* @return {@link RepositoryFragments} to be added to the repository.
131+
* @since 5.0
132+
*/
133+
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata, ReactiveCassandraOperations operations) {
134+
return fragmentsContributor.contribute(metadata, getEntityInformation(metadata.getDomainType()), operations);
135+
}
136+
104137
/**
105138
* {@link QueryLookupStrategy} to create
106139
* {@link org.springframework.data.cassandra.repository.query.PartTreeCassandraQuery} instances.

0 commit comments

Comments
 (0)