Skip to content

Commit 84d09ac

Browse files
committed
Adopt to AOT changes in Commons.
This change adopts the newly added AOT changes from spring-projects/spring-data-commons#3282 to Cassandra repositories. - 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: spring-projects#1566
1 parent cbf2019 commit 84d09ac

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)