Migrate to JSpecify annotations for nullability constraints.

Closes #1549
This commit is contained in:
Mark Paluch
2025-03-12 12:11:02 +01:00
parent ec59c4544d
commit 0dd856cb84
362 changed files with 1370 additions and 1085 deletions

View File

@@ -227,6 +227,11 @@
<artifactId>kotlinx-coroutines-reactor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>io.mockk</groupId>

View File

@@ -28,7 +28,7 @@ import com.datastax.oss.driver.api.core.metadata.EndPoint;
*/
public class CassandraAuthenticationException extends PermissionDeniedDataAccessException {
@Serial private static final long serialVersionUID = 8556304586797273927L;
private static final @Serial long serialVersionUID = 8556304586797273927L;
private final EndPoint host;

View File

@@ -31,7 +31,7 @@ import com.datastax.oss.driver.api.core.metadata.Node;
*/
public class CassandraConnectionFailureException extends DataAccessResourceFailureException {
@Serial private static final long serialVersionUID = 6299912054261646552L;
private static final @Serial long serialVersionUID = 6299912054261646552L;
private final Map<Node, Throwable> messagesByHost;

View File

@@ -26,7 +26,7 @@ import org.springframework.dao.TransientDataAccessException;
*/
public class CassandraInsufficientReplicasAvailableException extends TransientDataAccessException {
@Serial private static final long serialVersionUID = 6415130674604814905L;
private static final @Serial long serialVersionUID = 6415130674604814905L;
private int numberRequired;
private int numberAlive;

View File

@@ -26,7 +26,7 @@ import org.springframework.dao.DataAccessException;
*/
public class CassandraInternalException extends DataAccessException {
@Serial private static final long serialVersionUID = 433061676465346338L;
private static final @Serial long serialVersionUID = 433061676465346338L;
/**
* Constructor for {@link CassandraInternalException}.

View File

@@ -27,7 +27,7 @@ import org.springframework.dao.InvalidDataAccessApiUsageException;
*/
public class CassandraInvalidConfigurationInQueryException extends InvalidDataAccessApiUsageException {
@Serial private static final long serialVersionUID = 4594321191806182918L;
private static final @Serial long serialVersionUID = 4594321191806182918L;
/**
* Constructor for {@link CassandraInvalidConfigurationInQueryException}.

View File

@@ -26,7 +26,7 @@ import org.springframework.dao.InvalidDataAccessApiUsageException;
*/
public class CassandraInvalidQueryException extends InvalidDataAccessApiUsageException {
@Serial private static final long serialVersionUID = 4594321191806182918L;
private static final @Serial long serialVersionUID = 4594321191806182918L;
/**
* Constructor for {@link CassandraInvalidQueryException}.

View File

@@ -24,7 +24,7 @@ import java.io.Serial;
*/
public class CassandraKeyspaceExistsException extends CassandraSchemaElementExistsException {
@Serial private static final long serialVersionUID = 6032967419751410352L;
private static final @Serial long serialVersionUID = 6032967419751410352L;
/**
* Constructor for {@link CassandraKeyspaceExistsException}.
@@ -37,6 +37,7 @@ public class CassandraKeyspaceExistsException extends CassandraSchemaElementExis
super(keyspaceName, ElementType.KEYSPACE, msg, cause);
}
@SuppressWarnings("NullAway")
public String getKeyspaceName() {
return getElementName();
}

View File

@@ -80,4 +80,5 @@ public final class CassandraManagedTypes implements ManagedTypes {
public void forEach(Consumer<Class<?>> action) {
delegate.forEach(action);
}
}

View File

@@ -26,7 +26,7 @@ import org.springframework.dao.InvalidDataAccessApiUsageException;
*/
public class CassandraQuerySyntaxException extends InvalidDataAccessApiUsageException {
@Serial private static final long serialVersionUID = 4398474399882434154L;
private static final @Serial long serialVersionUID = 4398474399882434154L;
/**
* Constructor for {@link CassandraQuerySyntaxException}.

View File

@@ -27,7 +27,7 @@ import org.springframework.dao.QueryTimeoutException;
*/
public class CassandraReadTimeoutException extends QueryTimeoutException {
@Serial private static final long serialVersionUID = -787022307935203387L;
private static final @Serial long serialVersionUID = -787022307935203387L;
private final boolean wasDataPresent;

View File

@@ -17,8 +17,8 @@ package org.springframework.data.cassandra;
import java.io.Serial;
import org.jspecify.annotations.Nullable;
import org.springframework.dao.NonTransientDataAccessException;
import org.springframework.lang.Nullable;
/**
* Spring data access exception for when Cassandra schema element being created already exists.
@@ -28,15 +28,15 @@ import org.springframework.lang.Nullable;
*/
public class CassandraSchemaElementExistsException extends NonTransientDataAccessException {
@Serial private static final long serialVersionUID = 7798361273692300162L;
private static final @Serial long serialVersionUID = 7798361273692300162L;
@Deprecated
public enum ElementType {
KEYSPACE, TABLE, COLUMN, INDEX
}
private String elementName;
private ElementType elementType;
private @Nullable String elementName;
private @Nullable ElementType elementType;
/**
* Constructor for {@link CassandraSchemaElementExistsException}.
@@ -65,14 +65,13 @@ public class CassandraSchemaElementExistsException extends NonTransientDataAcces
}
@Deprecated
@Nullable
public String getElementName() {
public @Nullable String getElementName() {
return elementName;
}
@Deprecated
@Nullable
public ElementType getElementType() {
public @Nullable ElementType getElementType() {
return elementType;
}
}

View File

@@ -24,7 +24,7 @@ import java.io.Serial;
*/
public class CassandraTableExistsException extends CassandraSchemaElementExistsException {
@Serial private static final long serialVersionUID = 6032967419751410352L;
private static final @Serial long serialVersionUID = 6032967419751410352L;
/**
* Constructor for {@link CassandraTableExistsException}.
@@ -37,6 +37,7 @@ public class CassandraTableExistsException extends CassandraSchemaElementExistsE
super(tableName, ElementType.TABLE, msg, cause);
}
@SuppressWarnings("NullAway")
public String getTableName() {
return getElementName();
}

View File

@@ -26,7 +26,7 @@ import org.springframework.dao.TransientDataAccessException;
*/
public class CassandraTraceRetrievalException extends TransientDataAccessException {
@Serial private static final long serialVersionUID = -3163557220324700239L;
private static final @Serial long serialVersionUID = -3163557220324700239L;
/**
* Constructor for {@link CassandraTraceRetrievalException}.

View File

@@ -26,7 +26,7 @@ import org.springframework.dao.TransientDataAccessException;
*/
public class CassandraTruncateException extends TransientDataAccessException {
@Serial private static final long serialVersionUID = 5730642491362430311L;
private static final @Serial long serialVersionUID = 5730642491362430311L;
/**
* Constructor for {@link CassandraTruncateException}.

View File

@@ -26,7 +26,7 @@ import org.springframework.dao.TypeMismatchDataAccessException;
*/
public class CassandraTypeMismatchException extends TypeMismatchDataAccessException {
@Serial private static final long serialVersionUID = -7420058975444905629L;
private static final @Serial long serialVersionUID = -7420058975444905629L;
/**
* Constructor for {@link CassandraTypeMismatchException}.

View File

@@ -26,7 +26,7 @@ import org.springframework.dao.PermissionDeniedDataAccessException;
*/
public class CassandraUnauthorizedException extends PermissionDeniedDataAccessException {
@Serial private static final long serialVersionUID = 4618185356687726647L;
private static final @Serial long serialVersionUID = 4618185356687726647L;
/**
* Constructor for {@link CassandraUnauthorizedException}.

View File

@@ -27,7 +27,7 @@ import org.springframework.dao.UncategorizedDataAccessException;
*/
public class CassandraUncategorizedException extends UncategorizedDataAccessException {
@Serial private static final long serialVersionUID = 1029525121238025444L;
private static final @Serial long serialVersionUID = 1029525121238025444L;
/**
* Constructor for {@link CassandraUncategorizedException}.

View File

@@ -17,8 +17,8 @@ package org.springframework.data.cassandra;
import java.io.Serial;
import org.jspecify.annotations.Nullable;
import org.springframework.dao.QueryTimeoutException;
import org.springframework.lang.Nullable;
/**
* Spring data access exception for a Cassandra write timeout.
@@ -28,7 +28,7 @@ import org.springframework.lang.Nullable;
*/
public class CassandraWriteTimeoutException extends QueryTimeoutException {
@Serial private static final long serialVersionUID = -4374826375213670718L;
private static final @Serial long serialVersionUID = -4374826375213670718L;
private @Nullable String writeType;
@@ -45,8 +45,7 @@ public class CassandraWriteTimeoutException extends QueryTimeoutException {
this.writeType = writeType;
}
@Nullable
public String getWriteType() {
public @Nullable String getWriteType() {
return writeType;
}
}

View File

@@ -15,9 +15,9 @@
*/
package org.springframework.data.cassandra.aot;
import org.jspecify.annotations.Nullable;
import org.springframework.data.aot.ManagedTypesBeanRegistrationAotProcessor;
import org.springframework.data.cassandra.CassandraManagedTypes;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**

View File

@@ -18,6 +18,7 @@ package org.springframework.data.cassandra.aot;
import java.util.Arrays;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.framework.Advised;
import org.springframework.aot.hint.MemberCategory;
@@ -32,7 +33,6 @@ import org.springframework.data.cassandra.observability.CassandraObservationSupp
import org.springframework.data.cassandra.repository.support.SimpleCassandraRepository;
import org.springframework.data.cassandra.repository.support.SimpleReactiveCassandraRepository;
import org.springframework.data.util.ReactiveWrappers;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import com.datastax.oss.driver.api.core.CqlSession;
@@ -106,4 +106,5 @@ class CassandraRuntimeHints implements RuntimeHintsRegistrar {
}
}
}
}

View File

@@ -1,7 +1,5 @@
/**
* Ahead of Time processing utilities for Spring Data Cassandra.
*/
@NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.data.cassandra.aot;
import org.springframework.lang.NonNullApi;

View File

@@ -19,6 +19,7 @@ import java.util.Arrays;
import java.util.Optional;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -38,7 +39,6 @@ import org.springframework.data.cassandra.core.mapping.Table;
import org.springframework.data.cassandra.core.mapping.UserTypeResolver;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.lang.Nullable;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.CqlSession;
@@ -255,8 +255,7 @@ public abstract class AbstractCassandraConfiguration extends AbstractSessionConf
* @return the {@link KeyspacePopulator} or {@code null} if none configured.
* @see org.springframework.data.cassandra.core.cql.session.init.ResourceKeyspacePopulator
*/
@Nullable
protected KeyspacePopulator keyspaceCleaner() {
protected @Nullable KeyspacePopulator keyspaceCleaner() {
return null;
}
@@ -266,8 +265,7 @@ public abstract class AbstractCassandraConfiguration extends AbstractSessionConf
* @return the {@link KeyspacePopulator} or {@code null} if none configured.
* @see org.springframework.data.cassandra.core.cql.session.init.ResourceKeyspacePopulator
*/
@Nullable
protected KeyspacePopulator keyspacePopulator() {
protected @Nullable KeyspacePopulator keyspacePopulator() {
return null;
}
@@ -293,4 +291,5 @@ public abstract class AbstractCassandraConfiguration extends AbstractSessionConf
protected UserTypeResolver userTypeResolver(CqlSession cqlSession) {
return new SimpleUserTypeResolver(cqlSession, CqlIdentifier.fromCql(getKeyspaceName()));
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.cassandra.config;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.annotation.Bean;
@@ -27,7 +28,6 @@ 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;
import org.springframework.lang.Nullable;
/**
* Extension to {@link AbstractCassandraConfiguration} providing Spring Data Cassandra configuration for Spring Data's
@@ -63,7 +63,7 @@ public abstract class AbstractReactiveCassandraConfiguration extends AbstractCas
*/
@Bean
public ReactiveSessionFactory reactiveCassandraSessionFactory() {
return new DefaultReactiveSessionFactory(beanFactory.getBean(ReactiveSession.class));
return new DefaultReactiveSessionFactory(getBean(ReactiveSession.class));
}
/**
@@ -75,8 +75,7 @@ public abstract class AbstractReactiveCassandraConfiguration extends AbstractCas
*/
@Bean
public ReactiveCassandraTemplate reactiveCassandraTemplate() {
return new ReactiveCassandraTemplate(beanFactory.getBean(ReactiveSessionFactory.class),
beanFactory.getBean(CassandraConverter.class));
return new ReactiveCassandraTemplate(getBean(ReactiveSessionFactory.class), getBean(CassandraConverter.class));
}
/**
@@ -87,7 +86,7 @@ public abstract class AbstractReactiveCassandraConfiguration extends AbstractCas
*/
@Bean
public ReactiveCqlTemplate reactiveCqlTemplate() {
return new ReactiveCqlTemplate(beanFactory.getBean(ReactiveSessionFactory.class));
return new ReactiveCqlTemplate(getBean(ReactiveSessionFactory.class));
}
@Override
@@ -95,4 +94,14 @@ public abstract class AbstractReactiveCassandraConfiguration extends AbstractCas
this.beanFactory = beanFactory;
super.setBeanFactory(beanFactory);
}
private <T> T getBean(Class<T> requiredType) {
if (beanFactory == null) {
throw new IllegalStateException("BeanFactory must not be null");
}
return beanFactory.getBean(requiredType);
}
}

View File

@@ -22,6 +22,8 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
@@ -34,8 +36,6 @@ import org.springframework.data.cassandra.core.cql.CqlTemplate;
import org.springframework.data.cassandra.core.cql.keyspace.CreateKeyspaceSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.DropKeyspaceSpecification;
import org.springframework.data.cassandra.core.cql.session.DefaultSessionFactory;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -99,7 +99,7 @@ public abstract class AbstractSessionConfiguration implements BeanFactoryAware {
* @see org.springframework.beans.factory.BeanFactory#getBean(Class)
* @see #getBeanFactory()
*/
protected <T> T requireBeanOfType(@NonNull Class<T> beanType) {
protected <T> T requireBeanOfType(Class<T> beanType) {
return getBeanFactory().getBean(beanType);
}
@@ -110,9 +110,8 @@ public abstract class AbstractSessionConfiguration implements BeanFactoryAware {
* @deprecated since 3.0, use {@link #getSessionName()} instead.
* @since 1.5
*/
@Nullable
@Deprecated
protected String getClusterName() {
protected @Nullable String getClusterName() {
return null;
}
@@ -130,8 +129,7 @@ public abstract class AbstractSessionConfiguration implements BeanFactoryAware {
*
* @return the local data center name. Can be {@literal null} when using an Astra connection bundle.
*/
@Nullable
protected String getLocalDataCenter() {
protected @Nullable String getLocalDataCenter() {
return "datacenter1";
}
@@ -141,8 +139,7 @@ public abstract class AbstractSessionConfiguration implements BeanFactoryAware {
* @return the session name; may be {@literal null}.
* @since 3.0
*/
@Nullable
protected String getSessionName() {
protected @Nullable String getSessionName() {
return null;
}
@@ -151,8 +148,7 @@ public abstract class AbstractSessionConfiguration implements BeanFactoryAware {
*
* @return the {@link CompressionType}, may be {@literal null}.
*/
@Nullable
protected CompressionType getCompressionType() {
protected @Nullable CompressionType getCompressionType() {
return null;
}
@@ -236,8 +232,7 @@ public abstract class AbstractSessionConfiguration implements BeanFactoryAware {
* @return the {@link DriverConfigLoaderBuilderConfigurer}; may be {@literal null}.
* @since 3.1.2
*/
@Nullable
protected DriverConfigLoaderBuilderConfigurer getDriverConfigLoaderBuilderConfigurer() {
protected @Nullable DriverConfigLoaderBuilderConfigurer getDriverConfigLoaderBuilderConfigurer() {
return null;
}
@@ -250,8 +245,7 @@ public abstract class AbstractSessionConfiguration implements BeanFactoryAware {
* @see <a href="https://docs.datastax.com/en/developer/java-driver/4.9/manual/core/configuration/">Driver
* Configuration</a>
*/
@Nullable
protected Resource getDriverConfigurationResource() {
protected @Nullable Resource getDriverConfigurationResource() {
return null;
}
@@ -395,4 +389,5 @@ public abstract class AbstractSessionConfiguration implements BeanFactoryAware {
}
}
}

View File

@@ -1,81 +0,0 @@
/*
* Copyright 2013-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.config;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
/**
* Utilities to lookup {@link BeanDefinition bean definitions} for a {@link ListableBeanFactory} and to conditionally
* register {@link BeanDefinition bean definitions}.
*
* @author Matthew Adams
* @author Mark Paluch
*/
class BeanDefinitionUtils {
/**
* Returns all {@link BeanDefinitionHolder}s with the given type.
*
* @param registry The {@link BeanDefinitionRegistry}, often the very same instance as the {@code factor} parameter.
* @param factory The {@link ListableBeanFactory}, often the very same instance as the {@code registry} parameter.
* @param type The required {@link BeanDefinition}'s type.
* @param includeNonSingletons Whether to include beans with scope other than {@code singleton}
* @param allowEagerInit Whether to allow eager initialization of beans.
* @return The {@link BeanDefinitionHolder}s -- never returns null.
* @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, Class, boolean, boolean)
*/
static BeanDefinitionHolder[] getBeanDefinitionsOfType(BeanDefinitionRegistry registry, ListableBeanFactory factory,
Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(factory, type, includeNonSingletons,
allowEagerInit);
if (names.length == 0) {
return new BeanDefinitionHolder[] {};
}
BeanDefinitionHolder[] array = new BeanDefinitionHolder[names.length];
for (int i = 0; i < names.length; i++) {
String name = names[i];
BeanDefinition beanDefinition = null;
while (beanDefinition == null) {
try {
beanDefinition = registry.getBeanDefinition(name);
} catch (NoSuchBeanDefinitionException x) {
if (FactoryBean.class.isAssignableFrom(type)) { // try unmanged BeanFactory-prefixed name
name = name.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
} else {
throw x;
}
}
}
array[i] = new BeanDefinitionHolder(beanDefinition, name);
}
return array;
}
}

View File

@@ -17,6 +17,7 @@ package org.springframework.data.cassandra.config;
import static org.springframework.data.config.ParsingUtils.*;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -28,7 +29,6 @@ import org.springframework.data.auditing.config.IsNewAwareAuditingHandlerBeanDef
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.core.mapping.event.AuditingEntityCallback;
import org.springframework.data.cassandra.core.mapping.event.ReactiveAuditingEntityCallback;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
@@ -42,7 +42,7 @@ import org.w3c.dom.Element;
*/
public class CassandraAuditingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
private static boolean PROJECT_REACTOR_AVAILABLE = ClassUtils.isPresent("reactor.core.publisher.Mono",
private static final boolean PROJECT_REACTOR_AVAILABLE = ClassUtils.isPresent("reactor.core.publisher.Mono",
CassandraAuditingRegistrar.class.getClassLoader());
@Override
@@ -56,6 +56,7 @@ public class CassandraAuditingBeanDefinitionParser extends AbstractSingleBeanDef
}
@Override
@SuppressWarnings("NullAway")
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String mappingContextRef = element.getAttribute("mapping-context-ref");
@@ -96,4 +97,5 @@ public class CassandraAuditingBeanDefinitionParser extends AbstractSingleBeanDef
registry.registerBeanDefinition(ReactiveAuditingEntityCallback.class.getName(), builder.getBeanDefinition());
}
}

View File

@@ -78,4 +78,5 @@ class CassandraAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport
registerInfrastructureBeanWithId(listenerBeanDefinitionBuilder.getBeanDefinition(),
AuditingEntityCallback.class.getName(), registry);
}
}

View File

@@ -15,12 +15,12 @@
*/
package org.springframework.data.cassandra.config;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.cassandra.SessionFactory;
import org.springframework.data.cassandra.core.cql.CqlTemplate;
import org.springframework.data.cassandra.core.cql.session.DefaultSessionFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlSession;
@@ -39,6 +39,9 @@ public class CassandraCqlTemplateFactoryBean implements FactoryBean<CqlTemplate>
@Override
public CqlTemplate getObject() {
Assert.state(this.template != null, "CqlTemplate has not been initialized");
return template;
}
@@ -89,4 +92,5 @@ public class CassandraCqlTemplateFactoryBean implements FactoryBean<CqlTemplate>
this.sessionFactory = sessionFactory;
}
}

View File

@@ -58,4 +58,5 @@ class CassandraCqlTemplateParser extends AbstractSingleBeanDefinitionParser {
builder.getRawBeanDefinition().setSource(element);
}
}

View File

@@ -23,10 +23,10 @@ import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.mapping.PrimaryKeyClass;
import org.springframework.data.cassandra.core.mapping.Table;
import org.springframework.data.util.TypeScanner;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -199,7 +199,8 @@ public class CassandraEntityClassScanner {
if (this.beanClassLoader != null) {
scanner = TypeScanner.typeScanner(this.beanClassLoader);
} else {
scanner = TypeScanner.typeScanner(ClassUtils.getDefaultClassLoader());
ClassLoader cl = ClassUtils.getDefaultClassLoader();
scanner = TypeScanner.typeScanner(cl != null ? cl : getClass().getClassLoader());
}
return scanner.forTypesAnnotatedWith(getEntityAnnotations()).scanPackages(getEntityBasePackages()).collectAsSet();
@@ -214,4 +215,5 @@ public class CassandraEntityClassScanner {
protected Class<? extends Annotation>[] getEntityAnnotations() {
return new Class[] { Table.class, PrimaryKeyClass.class };
}
}

View File

@@ -21,6 +21,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
@@ -35,6 +37,7 @@ import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
@@ -65,7 +68,7 @@ class CassandraMappingContextParser extends AbstractSingleBeanDefinitionParser {
builder.getRawBeanDefinition().setSource(element);
}
private void parseMapping(Element element, BeanDefinitionBuilder builder, ClassLoader classLoader) {
private void parseMapping(Element element, BeanDefinitionBuilder builder, @Nullable ClassLoader classLoader) {
String packages = element.getAttribute("entity-base-packages");
@@ -186,4 +189,5 @@ class CassandraMappingContextParser extends AbstractSingleBeanDefinitionParser {
return propertyMappings;
}
}

View File

@@ -56,4 +56,5 @@ class CassandraMappingConverterParser extends AbstractSingleBeanDefinitionParser
builder.addConstructorArgReference(mappingRef);
builder.getRawBeanDefinition().setSource(element);
}
}

View File

@@ -39,4 +39,5 @@ public class CassandraNamespaceHandler extends NamespaceHandlerSupport {
registerBeanDefinitionParser("mapping", new CassandraMappingContextParser());
registerBeanDefinitionParser("initialize-keyspace", new InitializeKeyspaceBeanDefinitionParser());
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.cassandra.config;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.cassandra.SessionFactory;
@@ -23,7 +24,6 @@ import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.cql.CqlOperations;
import org.springframework.data.cassandra.core.cql.session.DefaultSessionFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlSession;
@@ -57,10 +57,14 @@ public class CassandraTemplateFactoryBean implements FactoryBean<CassandraTempla
@Override
public CassandraTemplate getObject() throws Exception {
Assert.state(converter != null, "CassandraConverter is not initialized");
if (cqlOperations != null) {
return new CassandraTemplate(cqlOperations, converter);
}
Assert.state(sessionFactory != null, "Either CqlSessionFactory or CqlOperations must be set");
return new CassandraTemplate(sessionFactory, converter);
}
@@ -127,4 +131,5 @@ public class CassandraTemplateFactoryBean implements FactoryBean<CassandraTempla
this.converter = converter;
}
}

View File

@@ -66,4 +66,5 @@ class CassandraTemplateParser extends AbstractSingleBeanDefinitionParser {
builder.getRawBeanDefinition().setSource(element);
}
}

View File

@@ -31,4 +31,5 @@ public class CqlNamespaceHandler extends NamespaceHandlerSupport {
registerBeanDefinitionParser("session", new CqlSessionParser());
registerBeanDefinitionParser("template", new CassandraCqlTemplateParser());
}
}

View File

@@ -30,6 +30,7 @@ import java.util.stream.Stream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
@@ -49,7 +50,6 @@ import org.springframework.data.cassandra.core.cql.keyspace.CreateKeyspaceSpecif
import org.springframework.data.cassandra.core.cql.keyspace.DropKeyspaceSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.KeyspaceActionSpecification;
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
@@ -220,8 +220,7 @@ public class CqlSessionFactoryBean
/**
* @return the configured {@link CassandraConverter}.
*/
@Nullable
public CassandraConverter getConverter() {
public @Nullable CassandraConverter getConverter() {
return this.converter;
}
@@ -294,8 +293,7 @@ public class CqlSessionFactoryBean
* @return the name of the Cassandra Keyspace to connect to as a String.
* @see #setKeyspaceName(String)
*/
@Nullable
protected String getKeyspaceName() {
protected @Nullable String getKeyspaceName() {
return this.keyspaceName;
}
@@ -638,6 +636,9 @@ public class CqlSessionFactoryBean
*/
protected void createTables(boolean drop, boolean dropUnused, boolean ifNotExists) {
Assert.state(this.session != null, "CqlSession must be initialized");
Assert.state(this.converter != null, "CassandraConverter must be initialized");
CassandraAdminTemplate adminTemplate = new CassandraAdminTemplate(this.session, this.converter);
performSchemaActions(drop, dropUnused, ifNotExists, adminTemplate);
@@ -664,7 +665,7 @@ public class CqlSessionFactoryBean
}
@Override
public CqlSession getObject() {
public @Nullable CqlSession getObject() {
return this.session;
}
@@ -673,13 +674,13 @@ public class CqlSessionFactoryBean
return CqlSession.class;
}
@Nullable
@Override
public DataAccessException translateExceptionIfPossible(RuntimeException e) {
public @Nullable DataAccessException translateExceptionIfPossible(RuntimeException e) {
return EXCEPTION_TRANSLATOR.translateExceptionIfPossible(e);
}
@Override
@SuppressWarnings("NullAway")
public void destroy() {
if (this.session != null) {
@@ -689,12 +690,17 @@ public class CqlSessionFactoryBean
};
Runnable systemSchemaActionRunnable = () -> {
executeSpecificationsAndScripts(this.keyspaceDrops, this.keyspaceShutdownScripts, this.systemSession);
if (this.systemSession != null) {
executeSpecificationsAndScripts(this.keyspaceDrops, this.keyspaceShutdownScripts, this.systemSession);
}
};
if (this.suspendLifecycleSchemaRefresh) {
SchemaUtils.withSuspendedAsyncSchemaRefresh(this.session, schemaActionRunnable);
if (this.systemSession != null) {
SchemaUtils.withSuspendedAsyncSchemaRefresh(this.systemSession, systemSchemaActionRunnable);
}
} else {
schemaActionRunnable.run();
systemSchemaActionRunnable.run();
@@ -709,14 +715,18 @@ public class CqlSessionFactoryBean
* Close the regular session object.
*/
protected void closeSession() {
this.session.close();
if (this.session != null) {
this.session.close();
}
}
/**
* Close the system session object.
*/
protected void closeSystemSession() {
this.systemSession.close();
if (this.systemSession != null) {
this.systemSession.close();
}
}
/**
@@ -860,5 +870,7 @@ public class CqlSessionFactoryBean
public int getPort() {
return port;
}
}
}

View File

@@ -25,4 +25,5 @@ public interface DefaultBeanNames extends DefaultCqlBeanNames {
String CONVERTER = "cassandraConverter";
String CONTEXT = "cassandraMappingContext";
String USER_TYPE_RESOLVER = "userTypeResolver";
}

View File

@@ -30,4 +30,5 @@ public interface DefaultCqlBeanNames {
String SESSION = "cassandraSession";
String SESSION_FACTORY = "cassandraSessionFactory";
String TEMPLATE = "cqlTemplate";
}

View File

@@ -67,4 +67,5 @@ public @interface EnableCassandraAuditing {
* @return
*/
String dateTimeProviderRef() default "";
}

View File

@@ -67,4 +67,5 @@ public @interface EnableReactiveCassandraAuditing {
* @return
*/
String dateTimeProviderRef() default "";
}

View File

@@ -19,6 +19,7 @@ import static org.springframework.data.cassandra.config.ParsingUtils.*;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.TypedStringValue;
@@ -30,7 +31,6 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.cassandra.core.cql.session.init.CompositeKeyspacePopulator;
import org.springframework.data.cassandra.core.cql.session.init.ResourceKeyspacePopulator;
import org.springframework.data.cassandra.core.cql.session.init.SessionFactoryInitializer;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
@@ -137,4 +137,5 @@ class InitializeKeyspaceBeanDefinitionParser extends AbstractBeanDefinitionParse
return null;
}
}

View File

@@ -260,5 +260,7 @@ class KeyspaceActionSpecificationFactory {
return new KeyspaceActionSpecificationFactory(name, new ArrayList<>(replications), replicationStrategy,
replicationFactor, durableWrites);
}
}
}

View File

@@ -19,13 +19,13 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.cassandra.config.KeyspaceActionSpecificationFactory.KeyspaceActionSpecificationFactoryBuilder;
import org.springframework.data.cassandra.core.cql.keyspace.DataCenterReplication;
import org.springframework.data.cassandra.core.cql.keyspace.KeyspaceActionSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.KeyspaceOption.ReplicationStrategy;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -101,7 +101,7 @@ public class KeyspaceActionSpecificationFactoryBean implements FactoryBean<Keysp
}
@Override
public KeyspaceActions getObject() {
public @Nullable KeyspaceActions getObject() {
return actions;
}
@@ -118,8 +118,7 @@ public class KeyspaceActionSpecificationFactoryBean implements FactoryBean<Keysp
/**
* @return Returns the name.
*/
@Nullable
public String getName() {
public @Nullable String getName() {
return name;
}
@@ -147,7 +146,6 @@ public class KeyspaceActionSpecificationFactoryBean implements FactoryBean<Keysp
/**
* @return Returns the action.
*/
@Nullable
public KeyspaceAction getAction() {
return action;
}
@@ -176,7 +174,6 @@ public class KeyspaceActionSpecificationFactoryBean implements FactoryBean<Keysp
/**
* @return Returns the replicationStrategy.
*/
@Nullable
public ReplicationStrategy getReplicationStrategy() {
return replicationStrategy;
}
@@ -229,4 +226,5 @@ public class KeyspaceActionSpecificationFactoryBean implements FactoryBean<Keysp
public void setReplicationFactor(int replicationFactor) {
this.replicationFactor = replicationFactor;
}
}

View File

@@ -18,8 +18,8 @@ package org.springframework.data.cassandra.config;
import java.util.Arrays;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.cql.keyspace.KeyspaceActionSpecification;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
@@ -68,4 +68,5 @@ public final class KeyspaceActions {
public String toString() {
return "KeyspaceActions(actions=" + this.getActions() + ")";
}
}

View File

@@ -15,11 +15,11 @@
*/
package org.springframework.data.cassandra.config;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Attr;
@@ -217,7 +217,7 @@ abstract class ParsingUtils {
* @return a raw {@link BeanDefinition} built by the given {@link BeanDefinitionBuilder}.
* @throws IllegalArgumentException if {@link BeanDefinitionBuilder} is null.
*/
public static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, Object source) {
public static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, @Nullable Object source) {
Assert.notNull(builder, "BeanDefinitionBuilder must not be null");

View File

@@ -46,4 +46,5 @@ public class PersistentEntitiesFactoryBean implements FactoryBean<PersistentEnti
public Class<?> getObjectType() {
return PersistentEntities.class;
}
}

View File

@@ -48,4 +48,5 @@ public enum SchemaAction {
* Drop <em>all</em> tables in the keyspace, then create each table as necessary.
*/
RECREATE_DROP_UNUSED
}

View File

@@ -101,4 +101,5 @@ class SchemaUtils {
return CompletableFuture.completedFuture(null);
}
}

View File

@@ -56,4 +56,5 @@ class SessionFactoryBeanDefinitionParser extends AbstractSingleBeanDefinitionPar
InitializeKeyspaceBeanDefinitionParser.parseKeyspacePopulator(element, builder);
builder.getRawBeanDefinition().setSource(element);
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.cassandra.config;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.data.cassandra.SessionFactory;
import org.springframework.data.cassandra.core.CassandraAdminOperations;
@@ -26,7 +27,6 @@ import org.springframework.data.cassandra.core.cql.session.DefaultSessionFactory
import org.springframework.data.cassandra.core.cql.session.init.KeyspacePopulator;
import org.springframework.data.cassandra.core.cql.session.init.SessionFactoryInitializer;
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlSession;
@@ -47,9 +47,9 @@ public class SessionFactoryFactoryBean extends AbstractFactoryBean<SessionFactor
protected static final boolean DEFAULT_DROP_TABLES = false;
protected static final boolean DEFAULT_DROP_UNUSED_TABLES = false;
private CassandraConverter converter;
private @Nullable CassandraConverter converter;
private CqlSession session;
private @Nullable CqlSession session;
private @Nullable KeyspacePopulator keyspaceCleaner;
private @Nullable KeyspacePopulator keyspacePopulator;
@@ -166,6 +166,9 @@ public class SessionFactoryFactoryBean extends AbstractFactoryBean<SessionFactor
@Override
protected SessionFactory createInstance() {
Assert.state(this.session != null, "CqlSession must be initialized");
return new DefaultSessionFactory(this.session);
}
@@ -190,9 +193,8 @@ public class SessionFactoryFactoryBean extends AbstractFactoryBean<SessionFactor
}
}
@Nullable
@Override
public Class<?> getObjectType() {
public @Nullable Class<?> getObjectType() {
return SessionFactory.class;
}

View File

@@ -1,7 +1,7 @@
/**
* Spring Data Cassandra {@link org.springframework.beans.factory.FactoryBean factory beans} and configuration.
*/
@NonNullApi
@org.jspecify.annotations.NullMarked
package org.springframework.data.cassandra.config;
import org.springframework.lang.NonNullApi;

View File

@@ -19,6 +19,8 @@ import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.springframework.dao.DataAccessException;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.cql.AsyncCqlOperations;
@@ -97,7 +99,7 @@ public interface AsyncCassandraOperations {
* @return the converted object or {@literal null}.
* @throws DataAccessException if there is any problem executing the query.
*/
<T> CompletableFuture<T> selectOne(String cql, Class<T> entityClass) throws DataAccessException;
<T> CompletableFuture<@Nullable T> selectOne(String cql, Class<T> entityClass) throws DataAccessException;
// -------------------------------------------------------------------------
// Methods dealing with com.datastax.oss.driver.api.core.cql.Statement
@@ -157,7 +159,7 @@ public interface AsyncCassandraOperations {
* @return the converted object or {@literal null}.
* @throws DataAccessException if there is any problem executing the query.
*/
<T> CompletableFuture<T> selectOne(Statement<?> statement, Class<T> entityClass) throws DataAccessException;
<T> CompletableFuture<@Nullable T> selectOne(Statement<?> statement, Class<T> entityClass) throws DataAccessException;
// -------------------------------------------------------------------------
// Methods dealing with org.springframework.data.cassandra.core.query.Query
@@ -205,7 +207,7 @@ public interface AsyncCassandraOperations {
* @return the converted object or {@literal null}.
* @throws DataAccessException if there is any problem executing the query.
*/
<T> CompletableFuture<T> selectOne(Query query, Class<T> entityClass) throws DataAccessException;
<T> CompletableFuture<@Nullable T> selectOne(Query query, Class<T> entityClass) throws DataAccessException;
/**
* Update the queried entities and return {@literal true} if the update was applied.
@@ -286,7 +288,7 @@ public interface AsyncCassandraOperations {
* @return the converted object or {@literal null}.
* @throws DataAccessException if there is any problem executing the query.
*/
<T> CompletableFuture<T> selectOneById(Object id, Class<T> entityClass) throws DataAccessException;
<T> CompletableFuture<@Nullable T> selectOneById(Object id, Class<T> entityClass) throws DataAccessException;
/**
* Insert the given entity and return the entity if the insert was applied.
@@ -295,7 +297,7 @@ public interface AsyncCassandraOperations {
* @return the inserted entity.
* @throws DataAccessException if there is any problem executing the query.
*/
<T> CompletableFuture<T> insert(T entity) throws DataAccessException;
<T> CompletableFuture<@Nullable T> insert(T entity) throws DataAccessException;
/**
* Insert the given entity applying {@link WriteOptions} and return the entity if the insert was applied.

View File

@@ -27,7 +27,7 @@ import java.util.stream.StreamSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -61,7 +61,6 @@ import org.springframework.data.projection.EntityProjection;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.util.Streamable;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -500,11 +499,11 @@ public class AsyncCassandraTemplate
SimpleStatement statement = countStatement.build();
CompletableFuture<Long> result = doExecute(statement, it -> {
CompletableFuture<@Nullable Long> result = doExecute(statement, it -> {
SingleColumnRowMapper<Long> mapper = SingleColumnRowMapper.newInstance(Long.class);
SingleColumnRowMapper<@Nullable Long> mapper = SingleColumnRowMapper.newInstance(Long.class);
Row row = DataAccessUtils.nullableSingleResult(Streamable.of(it.currentPage()).toList());
Row row = DataAccessUtils.requiredUniqueResult(Streamable.of(it.currentPage()).toList());
return mapper.mapRow(row, 0);
});
@@ -827,7 +826,8 @@ public class AsyncCassandraTemplate
return doExecute(statement, Function.identity());
}
private <T> CompletableFuture<T> doExecute(Statement<?> statement, Function<AsyncResultSet, T> mappingFunction) {
private <T extends @Nullable Object> CompletableFuture<T> doExecute(Statement<?> statement,
Function<AsyncResultSet, T> mappingFunction) {
if (PreparedStatementDelegate.canPrepare(isUsePreparedStatements(), statement, log)) {
@@ -861,6 +861,7 @@ public class AsyncCassandraTemplate
return accessor.getPageSize();
}
}
class GetConfiguredPageSize implements AsyncSessionCallback<Integer>, CqlProvider {
@Override
public CompletableFuture<Integer> doInSession(CqlSession session) {
@@ -876,7 +877,6 @@ public class AsyncCassandraTemplate
return getAsyncCqlOperations().execute(new GetConfiguredPageSize()).join();
}
@SuppressWarnings("unchecked")
private <T> Function<Row, T> getMapper(Class<?> entityType, Class<T> targetType, CqlIdentifier tableName) {
EntityProjection<T, ?> projection = entityOperations.introspectProjection(targetType, entityType);

View File

@@ -161,7 +161,6 @@ public class CassandraAdminTemplate extends CassandraTemplate implements Cassand
Assert.notNull(keyspace, "Keyspace name must not be null");
Assert.notNull(tableName, "Table name must not be null");
// noinspection ConstantConditions
return getCqlOperations().execute((SessionCallback<Optional<TableMetadata>>) session -> {
return session.getMetadata().getKeyspace(keyspace).flatMap(it -> it.getTable(tableName));
});
@@ -170,7 +169,6 @@ public class CassandraAdminTemplate extends CassandraTemplate implements Cassand
@Override
public KeyspaceMetadata getKeyspaceMetadata() {
// noinspection ConstantConditions
return getCqlOperations().execute((SessionCallback<KeyspaceMetadata>) session -> {
return session.getKeyspace().flatMap(it -> session.getMetadata().getKeyspace(it)).orElseThrow(() -> {

View File

@@ -19,6 +19,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.dao.DataAccessException;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.cql.CqlOperations;
@@ -28,7 +29,6 @@ import org.springframework.data.cassandra.core.query.CassandraPageRequest;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.data.cassandra.core.query.Update;
import org.springframework.data.domain.Slice;
import org.springframework.lang.Nullable;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.cql.BatchType;
@@ -133,8 +133,7 @@ public interface CassandraOperations extends FluentCassandraOperations {
* @return the converted object or {@literal null}.
* @throws DataAccessException if there is any problem executing the query.
*/
@Nullable
<T> T selectOne(String cql, Class<T> entityClass) throws DataAccessException;
<T> @Nullable T selectOne(String cql, Class<T> entityClass) throws DataAccessException;
// -------------------------------------------------------------------------
// Methods dealing with com.datastax.oss.driver.api.core.cql.Statement
@@ -195,8 +194,7 @@ public interface CassandraOperations extends FluentCassandraOperations {
* @return the converted object or {@literal null}.
* @throws DataAccessException if there is any problem executing the query.
*/
@Nullable
<T> T selectOne(Statement<?> statement, Class<T> entityClass) throws DataAccessException;
<T> @Nullable T selectOne(Statement<?> statement, Class<T> entityClass) throws DataAccessException;
// -------------------------------------------------------------------------
// Methods dealing with org.springframework.data.cassandra.core.query.Query
@@ -248,8 +246,7 @@ public interface CassandraOperations extends FluentCassandraOperations {
* @throws DataAccessException if there is any problem executing the query.
* @since 2.0
*/
@Nullable
<T> T selectOne(Query query, Class<T> entityClass) throws DataAccessException;
<T> @Nullable T selectOne(Query query, Class<T> entityClass) throws DataAccessException;
/**
* Update the queried entities and return {@literal true} if the update was applied.
@@ -329,8 +326,7 @@ public interface CassandraOperations extends FluentCassandraOperations {
* @return the converted object or {@literal null}.
* @throws DataAccessException if there is any problem executing the query.
*/
@Nullable
<T> T selectOneById(Object id, Class<T> entityClass) throws DataAccessException;
<T> @Nullable T selectOneById(Object id, Class<T> entityClass) throws DataAccessException;
/**
* Insert the given entity and return the entity if the insert was applied.

View File

@@ -159,6 +159,7 @@ public class CassandraPersistentEntitySchemaCreator {
* @param ifNotExists {@literal true} to create types using {@code IF NOT EXISTS}.
* @return {@link List} of {@link CreateUserTypeSpecification}.
*/
@SuppressWarnings("NullAway")
protected List<CreateUserTypeSpecification> createUserTypeSpecifications(boolean ifNotExists) {
List<? extends CassandraPersistentEntity<?>> entities = new ArrayList<>(

View File

@@ -23,6 +23,7 @@ import java.util.stream.Stream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
@@ -57,7 +58,6 @@ import org.springframework.data.mapping.callback.EntityCallbacks;
import org.springframework.data.projection.EntityProjection;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -318,7 +318,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
}
@Override
public <T> T selectOne(String cql, Class<T> entityClass) {
public <T> @Nullable T selectOne(String cql, Class<T> entityClass) {
Assert.hasText(cql, "CQL must not be empty");
Assert.notNull(entityClass, "Entity type must not be null");
@@ -360,7 +360,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
}
@Override
public <T> T selectOne(Statement<?> statement, Class<T> entityClass) {
public <T> @Nullable T selectOne(Statement<?> statement, Class<T> entityClass) {
List<T> result = select(statement, entityClass);
return result.isEmpty() ? null : result.get(0);
@@ -421,7 +421,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
}
@Override
public <T> T selectOne(Query query, Class<T> entityClass) throws DataAccessException {
public <T> @Nullable T selectOne(Query query, Class<T> entityClass) throws DataAccessException {
List<T> result = select(query, entityClass);
@@ -472,7 +472,6 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
return doExecute(updateStatement.build()).wasApplied();
}
@Nullable
WriteResult doUpdate(Query query, org.springframework.data.cassandra.core.query.Update update, Class<?> entityClass,
CqlIdentifier tableName) {
@@ -493,7 +492,6 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
return result != null && result.wasApplied();
}
@Nullable
WriteResult doDelete(Query query, Class<?> entityClass, CqlIdentifier tableName) {
StatementBuilder<Delete> delete = getStatementFactory().delete(query, getRequiredPersistentEntity(entityClass),
@@ -535,7 +533,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
StatementBuilder<Select> countStatement = getStatementFactory().count(query,
getRequiredPersistentEntity(entityClass), tableName);
return doQueryForObject(countStatement.build(), Long.class);
return doQueryForRequiredObject(countStatement.build(), Long.class);
}
@Override
@@ -568,7 +566,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
}
@Override
public <T> T selectOneById(Object id, Class<T> entityClass) {
public <T> @Nullable T selectOneById(Object id, Class<T> entityClass) {
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
@@ -702,7 +700,6 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
return source.isVersionedEntity()
? doDeleteVersioned(source.appendVersionCondition(builder).build(), entity, source, tableName)
: doDelete(builder.build(), entity, tableName);
}
private WriteResult doDeleteVersioned(SimpleStatement statement, Object entity, AdaptibleEntity<Object> source,
@@ -845,8 +842,8 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
return getCqlOperations().query(statement, rowMapper);
}
private <T> T doQueryForObject(Statement<?> statement, Class<T> resultType) {
return DataAccessUtils.nullableSingleResult(doQuery(statement, SingleColumnRowMapper.newInstance(resultType)));
private <T> T doQueryForRequiredObject(Statement<?> statement, Class<T> resultType) {
return DataAccessUtils.requiredSingleResult(doQuery(statement, SingleColumnRowMapper.newInstance(resultType)));
}
private <T> Stream<T> doQueryForStream(Statement<?> statement, RowMapper<T> rowMapper) {
@@ -890,9 +887,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
return statement.getPageSize();
}
if (getCqlOperations() instanceof CassandraAccessor) {
CassandraAccessor accessor = (CassandraAccessor) getCqlOperations();
if (getCqlOperations() instanceof CassandraAccessor accessor) {
if (accessor.getFetchSize() != -1) {
return accessor.getFetchSize();
@@ -925,9 +920,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
T result = getConverter().project(projection, row);
if (result != null) {
maybeEmitEvent(() -> new AfterConvertEvent<>(row, result, tableName));
}
maybeEmitEvent(() -> new AfterConvertEvent<>(row, result, tableName));
return result;
};
@@ -998,5 +991,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
public String getCql() {
return statement.getQuery();
}
}
}

View File

@@ -20,11 +20,11 @@ import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.cql.ExecutionProfileResolver;
import org.springframework.data.cassandra.core.cql.WriteOptions;
import org.springframework.data.cassandra.core.query.CriteriaDefinition;
import org.springframework.data.cassandra.core.query.Filter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

View File

@@ -17,8 +17,8 @@ package org.springframework.data.cassandra.core;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.lang.Nullable;
/**
* Delegate class to encapsulate lifecycle event configuration and publishing. Event creation is deferred within an
@@ -50,6 +50,7 @@ class EntityLifecycleEventDelegate {
*
* @param eventSupplier the supplier for application events.
*/
@SuppressWarnings("NullAway")
public void publishEvent(Supplier<?> eventSupplier) {
if (canPublishEvent()) {

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.cassandra.core;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.cql.util.StatementBuilder;
@@ -27,7 +28,6 @@ import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.data.projection.EntityProjection;
import org.springframework.data.projection.EntityProjectionIntrospector;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -182,7 +182,8 @@ class EntityOperations {
* @param currentVersionNumber previous version number.
* @return the altered {@link Update} containing the {@code IF} condition for optimistic locking.
*/
StatementBuilder<Update> appendVersionCondition(StatementBuilder<Update> update, Number currentVersionNumber);
StatementBuilder<Update> appendVersionCondition(StatementBuilder<Update> update,
@Nullable Number currentVersionNumber);
/**
* Appends a {@code IF} condition to an {@link Delete} statement for optimistic locking to perform the delete only
@@ -262,8 +263,7 @@ class EntityOperations {
}
@Override
@Nullable
public Object getVersion() {
public @Nullable Object getVersion() {
return this.propertyAccessor.getProperty(this.entity.getRequiredVersionProperty());
}
}
@@ -294,7 +294,7 @@ class EntityOperations {
@Override
public StatementBuilder<Update> appendVersionCondition(StatementBuilder<Update> update,
Number currentVersionNumber) {
@Nullable Number currentVersionNumber) {
return update.bind((statement, factory) -> {
return statement.if_(Condition.column(getVersionColumnName()).isEqualTo(factory.create(currentVersionNumber)));
@@ -336,8 +336,7 @@ class EntityOperations {
}
@Override
@Nullable
public Number getVersion() {
public @Nullable Number getVersion() {
CassandraPersistentProperty versionProperty = this.entity.getRequiredVersionProperty();
@@ -350,7 +349,8 @@ class EntityOperations {
}
private CqlIdentifier getVersionColumnName() {
return this.entity.getRequiredVersionProperty().getColumnName();
return this.entity.getRequiredVersionProperty().getRequiredColumnName();
}
}
}

View File

@@ -23,13 +23,13 @@ import java.util.NoSuchElementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.cql.RowMapper;
import org.springframework.data.cassandra.core.query.CassandraPageRequest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.lang.Nullable;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.cql.AsyncResultSet;

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.cassandra.core;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -53,10 +53,10 @@ class ExecutableDeleteOperationSupport implements ExecutableDeleteOperation {
private final Query query;
@Nullable private final CqlIdentifier tableName;
private final @Nullable CqlIdentifier tableName;
public ExecutableDeleteSupport(CassandraTemplate template, Class<?> domainType, Query query,
CqlIdentifier tableName) {
@Nullable CqlIdentifier tableName) {
this.template = template;
this.domainType = domainType;
this.query = query;
@@ -86,5 +86,7 @@ class ExecutableDeleteOperationSupport implements ExecutableDeleteOperation {
private CqlIdentifier getTableName() {
return this.tableName != null ? this.tableName : this.template.getTableName(this.domainType);
}
}
}

View File

@@ -16,7 +16,7 @@
package org.springframework.data.cassandra.core;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -52,10 +52,10 @@ class ExecutableInsertOperationSupport implements ExecutableInsertOperation {
private final InsertOptions insertOptions;
@Nullable private final CqlIdentifier tableName;
private final @Nullable CqlIdentifier tableName;
public ExecutableInsertSupport(CassandraTemplate template, Class<T> domainType, InsertOptions insertOptions,
CqlIdentifier tableName) {
@Nullable CqlIdentifier tableName) {
this.template = template;
this.domainType = domainType;
this.insertOptions = insertOptions;
@@ -89,5 +89,7 @@ class ExecutableInsertOperationSupport implements ExecutableInsertOperation {
private CqlIdentifier getTableName() {
return this.tableName != null ? this.tableName : this.template.getTableName(this.domainType);
}
}
}

View File

@@ -19,8 +19,8 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;

View File

@@ -18,9 +18,9 @@ package org.springframework.data.cassandra.core;
import java.util.List;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -63,7 +63,7 @@ class ExecutableSelectOperationSupport implements ExecutableSelectOperation {
private final @Nullable CqlIdentifier tableName;
public ExecutableSelectSupport(CassandraTemplate template, Class<?> domainType, Class<T> returnType, Query query,
CqlIdentifier tableName) {
@Nullable CqlIdentifier tableName) {
this.template = template;
this.domainType = domainType;
this.returnType = returnType;
@@ -106,7 +106,7 @@ class ExecutableSelectOperationSupport implements ExecutableSelectOperation {
}
@Override
public T firstValue() {
public @Nullable T firstValue() {
List<T> result = this.template.doSelect(this.query.limit(1), this.domainType, getTableName(), this.returnType);
@@ -114,7 +114,7 @@ class ExecutableSelectOperationSupport implements ExecutableSelectOperation {
}
@Override
public T oneValue() {
public @Nullable T oneValue() {
List<T> result = this.template.doSelect(this.query.limit(2), this.domainType, getTableName(), this.returnType);
@@ -143,5 +143,7 @@ class ExecutableSelectOperationSupport implements ExecutableSelectOperation {
private CqlIdentifier getTableName() {
return this.tableName != null ? this.tableName : this.template.getTableName(this.domainType);
}
}
}

View File

@@ -15,9 +15,9 @@
*/
package org.springframework.data.cassandra.core;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.data.cassandra.core.query.Update;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -58,7 +58,7 @@ class ExecutableUpdateOperationSupport implements ExecutableUpdateOperation {
private final @Nullable CqlIdentifier tableName;
public ExecutableUpdateSupport(CassandraTemplate template, Class<?> domainType, Query query,
CqlIdentifier tableName) {
@Nullable CqlIdentifier tableName) {
this.template = template;
this.domainType = domainType;
this.query = query;
@@ -92,5 +92,7 @@ class ExecutableUpdateOperationSupport implements ExecutableUpdateOperation {
private CqlIdentifier getTableName() {
return this.tableName != null ? this.tableName : this.template.getTableName(this.domainType);
}
}
}

View File

@@ -20,9 +20,9 @@ import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.cql.ExecutionProfileResolver;
import org.springframework.data.cassandra.core.cql.WriteOptions;
import org.springframework.lang.Nullable;
import com.datastax.oss.driver.api.core.ConsistencyLevel;
import com.datastax.oss.driver.api.core.CqlIdentifier;

View File

@@ -22,8 +22,8 @@ import java.util.function.Predicate;
import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.cql.QueryExtractorDelegate;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.function.SingletonSupplier;

View File

@@ -26,6 +26,7 @@ import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import org.springframework.beans.BeansException;
@@ -65,7 +66,6 @@ import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
import org.springframework.data.projection.EntityProjection;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;

View File

@@ -17,8 +17,8 @@ package org.springframework.data.cassandra.core;
import reactor.core.publisher.Mono;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -58,7 +58,7 @@ class ReactiveDeleteOperationSupport implements ReactiveDeleteOperation {
private final @Nullable CqlIdentifier tableName;
public ReactiveDeleteSupport(ReactiveCassandraTemplate template, Class<?> domainType, Query query,
CqlIdentifier tableName) {
@Nullable CqlIdentifier tableName) {
this.template = template;
this.domainType = domainType;
this.query = query;
@@ -88,5 +88,7 @@ class ReactiveDeleteOperationSupport implements ReactiveDeleteOperation {
private CqlIdentifier getTableName() {
return this.tableName != null ? this.tableName : this.template.getTableName(this.domainType);
}
}
}

View File

@@ -17,7 +17,7 @@ package org.springframework.data.cassandra.core;
import reactor.core.publisher.Mono;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -55,7 +55,7 @@ class ReactiveInsertOperationSupport implements ReactiveInsertOperation {
private final @Nullable CqlIdentifier tableName;
public ReactiveInsertSupport(ReactiveCassandraTemplate template, Class<T> domainType, InsertOptions insertOptions,
CqlIdentifier tableName) {
@Nullable CqlIdentifier tableName) {
this.template = template;
this.domainType = domainType;
this.insertOptions = insertOptions;
@@ -89,5 +89,7 @@ class ReactiveInsertOperationSupport implements ReactiveInsertOperation {
private CqlIdentifier getTableName() {
return this.tableName != null ? this.tableName : this.template.getTableName(this.domainType);
}
}
}

View File

@@ -18,9 +18,9 @@ package org.springframework.data.cassandra.core;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.jspecify.annotations.Nullable;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -62,7 +62,7 @@ class ReactiveSelectOperationSupport implements ReactiveSelectOperation {
private final @Nullable CqlIdentifier tableName;
public ReactiveSelectSupport(ReactiveCassandraTemplate template, Class<?> domainType, Class<T> returnType,
Query query, CqlIdentifier tableName) {
Query query, @Nullable CqlIdentifier tableName) {
this.template = template;
this.domainType = domainType;
this.returnType = returnType;
@@ -139,5 +139,7 @@ class ReactiveSelectOperationSupport implements ReactiveSelectOperation {
private CqlIdentifier getTableName() {
return this.tableName != null ? this.tableName : this.template.getTableName(this.domainType);
}
}
}

View File

@@ -17,9 +17,9 @@ package org.springframework.data.cassandra.core;
import reactor.core.publisher.Mono;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.data.cassandra.core.query.Update;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -60,7 +60,7 @@ class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation {
private final @Nullable CqlIdentifier tableName;
public ReactiveUpdateSupport(ReactiveCassandraTemplate template, Class<?> domainType, Query query,
CqlIdentifier tableName) {
@Nullable CqlIdentifier tableName) {
this.template = template;
this.domainType = domainType;
this.query = query;

View File

@@ -27,6 +27,8 @@ import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.convert.QueryMapper;
import org.springframework.data.cassandra.core.convert.UpdateMapper;
@@ -67,8 +69,6 @@ import org.springframework.data.projection.EntityProjection;
import org.springframework.data.projection.ProjectionInformation;
import org.springframework.data.util.Predicates;
import org.springframework.data.util.ProxyUtils;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -611,6 +611,7 @@ public class StatementFactory {
* @return {@link Columns} with columns to be included.
* @since 2.2
*/
@SuppressWarnings("NullAway")
Columns computeColumnsForProjection(EntityProjection<?, ?> projection, Columns columns,
CassandraPersistentEntity<?> domainType, Class<?> returnType) {
@@ -682,8 +683,7 @@ public class StatementFactory {
return select;
}
@Nullable
private CqlIdentifier getKeyspace(CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
private @Nullable CqlIdentifier getKeyspace(CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
return keyspaceProvider.getKeyspace(entity, tableName);
}
@@ -1213,15 +1213,14 @@ public class StatementFactory {
this.selector = selector;
}
@NonNull
@Override
public com.datastax.oss.driver.api.querybuilder.select.Selector as(@NonNull CqlIdentifier alias) {
public com.datastax.oss.driver.api.querybuilder.select.@NonNull Selector as(@NonNull CqlIdentifier alias) {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public CqlIdentifier getAlias() {
public @Nullable CqlIdentifier getAlias() {
return null;
}
@@ -1296,9 +1295,8 @@ public class StatementFactory {
* Derive the keyspace from the given {@link CassandraPersistentEntity}.
*/
ENTITY_KEYSPACE {
@Nullable
@Override
public CqlIdentifier getKeyspace(CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
public @Nullable CqlIdentifier getKeyspace(CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
return entity.getKeyspace();
}
},
@@ -1307,9 +1305,8 @@ public class StatementFactory {
* Use the session's keyspace.
*/
EMPTY_KEYSPACE {
@Nullable
@Override
public CqlIdentifier getKeyspace(CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
public @Nullable CqlIdentifier getKeyspace(CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
return null;
}
}

View File

@@ -20,11 +20,11 @@ import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.cql.ExecutionProfileResolver;
import org.springframework.data.cassandra.core.cql.WriteOptions;
import org.springframework.data.cassandra.core.query.CriteriaDefinition;
import org.springframework.data.cassandra.core.query.Filter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

View File

@@ -64,7 +64,6 @@ public abstract class AbstractCassandraConverter implements CassandraConverter,
this.instantiators = instantiators;
}
@Override
public ConversionService getConversionService() {
return this.conversionService;
@@ -99,4 +98,5 @@ public abstract class AbstractCassandraConverter implements CassandraConverter,
getCustomConversions().registerConvertersIn((GenericConversionService) conversionService);
}
}
}

View File

@@ -52,4 +52,5 @@ public interface CassandraColumnType extends ColumnType {
default boolean isUserDefinedType() {
return getDataType() instanceof UserDefinedType;
}
}

View File

@@ -15,12 +15,13 @@
*/
package org.springframework.data.cassandra.core.convert;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
import org.springframework.data.convert.ValueConversionContext;
import org.springframework.data.mapping.model.PropertyValueProvider;
import org.springframework.data.mapping.model.SpELContext;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import com.datastax.oss.driver.api.core.cql.Row;
@@ -36,7 +37,7 @@ public class CassandraConversionContext implements ValueConversionContext<Cassan
private final CassandraPersistentProperty persistentProperty;
private final CassandraConverter cassandraConverter;
@Nullable private final SpELContext spELContext;
private final @Nullable SpELContext spELContext;
public CassandraConversionContext(PropertyValueProvider<CassandraPersistentProperty> accessor,
CassandraPersistentProperty persistentProperty, CassandraConverter CassandraConverter) {
@@ -58,25 +59,29 @@ public class CassandraConversionContext implements ValueConversionContext<Cassan
return persistentProperty;
}
@Nullable
public Object getValue(String propertyPath) {
public @Nullable Object getValue(String propertyPath) {
return accessor.getPropertyValue(persistentProperty.getOwner().getRequiredPersistentProperty(propertyPath));
}
@Override
@SuppressWarnings("unchecked")
public <T> T write(@Nullable Object value, TypeInformation<T> target) {
public <T> @Nullable T write(@Nullable Object value, TypeInformation<T> target) {
if (value == null) {
return null;
}
return (T) cassandraConverter.convertToColumnType(value, target);
}
@Override
public <T> T read(@Nullable Object value, TypeInformation<T> target) {
public <T> @Nullable T read(@Nullable Object value, TypeInformation<T> target) {
return value instanceof Row row ? cassandraConverter.read(target.getType(), row)
: ValueConversionContext.super.read(value, target);
}
@Nullable
public SpELContext getSpELContext() {
public @Nullable SpELContext getSpELContext() {
return spELContext;
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.cassandra.core.convert;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
@@ -24,7 +25,6 @@ import org.springframework.data.convert.EntityConverter;
import org.springframework.data.projection.EntityProjection;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.cql.Row;

View File

@@ -26,6 +26,8 @@ import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.data.cassandra.core.cql.converter.RowToListConverter;
@@ -105,7 +107,7 @@ public abstract class CassandraConverters {
INSTANCE;
@Override
public Date convert(Row row) {
public @Nullable Date convert(Row row) {
Instant instant = row.getInstant(0);
@@ -124,7 +126,7 @@ public abstract class CassandraConverters {
INSTANCE;
@Override
public Instant convert(Row row) {
public @Nullable Instant convert(Row row) {
return row.getInstant(0);
}
}
@@ -140,7 +142,7 @@ public abstract class CassandraConverters {
INSTANCE;
@Override
public InetAddress convert(Row row) {
public @Nullable InetAddress convert(Row row) {
return row.getInetAddress(0);
}
}
@@ -180,7 +182,7 @@ public abstract class CassandraConverters {
}
@Override
public T convert(Row source) {
public @Nullable T convert(Row source) {
Object object = source.getObject(0);
@@ -200,7 +202,7 @@ public abstract class CassandraConverters {
INSTANCE;
@Override
public String convert(Row row) {
public @Nullable String convert(Row row) {
return row.getString(0);
}
}
@@ -216,7 +218,7 @@ public abstract class CassandraConverters {
INSTANCE;
@Override
public UUID convert(Row row) {
public @Nullable UUID convert(Row row) {
return row.getUuid(0);
}
}
@@ -232,7 +234,7 @@ public abstract class CassandraConverters {
INSTANCE;
@Override
public LocalDate convert(Row row) {
public @Nullable LocalDate convert(Row row) {
return row.getLocalDate(0);
}
}

View File

@@ -287,4 +287,5 @@ public class CassandraCustomConversions extends org.springframework.data.convert
return propertyValueConversions == internalValueConversion;
}
}
}

View File

@@ -29,7 +29,6 @@ import java.util.List;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.lang.NonNull;
/**
* Helper class to register JodaTime specific {@link Converter} implementations in case the library is present on the
@@ -118,7 +117,6 @@ public abstract class CassandraJsr310Converters {
INSTANCE;
@NonNull
@Override
public Date convert(Instant source) {
return Date.from(source);
@@ -140,4 +138,5 @@ public abstract class CassandraJsr310Converters {
return source.atZone(systemDefault()).toInstant();
}
}
}

View File

@@ -43,4 +43,5 @@ public interface CassandraValueProvider extends PropertyValueProvider<CassandraP
* @since 3.0
*/
Object getSource();
}

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.cassandra.core.convert;
import org.jspecify.annotations.Nullable;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import com.datastax.oss.driver.api.core.data.TupleValue;
import com.datastax.oss.driver.api.core.data.UdtValue;

View File

@@ -15,10 +15,10 @@
*/
package org.springframework.data.cassandra.core.convert;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.core.mapping.CassandraType;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**

View File

@@ -40,4 +40,5 @@ public class CustomConversions extends CassandraCustomConversions {
private CustomConversions(List<?> converters) {
super(converters);
}
}

View File

@@ -78,4 +78,5 @@ class DefaultCassandraColumnType extends DefaultColumnType implements CassandraC
return builder.toString();
}
}

View File

@@ -20,8 +20,8 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
/**
* Default {@link ColumnType} implementation.
@@ -70,15 +70,13 @@ class DefaultColumnType implements ColumnType {
return typeInformation.isMap();
}
@Nullable
@Override
public ColumnType getComponentType() {
public @Nullable ColumnType getComponentType() {
return !parameters.isEmpty() ? parameters.get(0) : null;
}
@Nullable
@Override
public ColumnType getMapValueType() {
public @Nullable ColumnType getMapValueType() {
return parameters.size() > 1 ? parameters.get(1) : null;
}
@@ -92,4 +90,5 @@ class DefaultColumnType implements ColumnType {
return String.format("%s<%s>", getType().getName(),
parameters.stream().map(Object::toString).collect(Collectors.toList()));
}
}

View File

@@ -28,6 +28,8 @@ import java.util.stream.StreamSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.dao.InvalidDataAccessApiUsageException;
@@ -47,7 +49,6 @@ import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -234,8 +235,7 @@ class DefaultColumnTypeResolver implements ColumnTypeResolver {
return customConversions.get().getCustomWriteTarget(typeInformation.getType());
}
@Nullable
private DataType tryResolve(Class<?> type) {
private @Nullable DataType tryResolve(Class<?> type) {
if (TupleValue.class.isAssignableFrom(type)) {
return null;
@@ -266,6 +266,11 @@ class DefaultColumnTypeResolver implements ColumnTypeResolver {
Name type = annotation.type();
return doGetColumnType(annotation, type);
}
private CassandraColumnType doGetColumnType(CassandraType annotation, Name type) {
switch (type) {
case MAP:
assertTypeArguments(annotation.typeArguments().length, 2);
@@ -289,7 +294,8 @@ class DefaultColumnTypeResolver implements ColumnTypeResolver {
case TUPLE:
DataType[] dataTypes = Arrays.stream(annotation.typeArguments()).map(CassandraSimpleTypeHolder::getDataTypeFor)
DataType[] dataTypes = Arrays.stream(annotation.typeArguments())
.map(dataTypeName -> doGetColumnType(annotation, dataTypeName).getDataType())
.toArray(DataType[]::new);
return ColumnType.tupleOf(DataTypes.tupleOf(dataTypes));

View File

@@ -55,4 +55,5 @@ class FrozenIndicator {
FrozenIndicator getFrozen(int parameterIndex) {
return parameterIndex < this.nested.size() ? this.nested.get(parameterIndex) : NOT_FROZEN;
}
}

View File

@@ -26,6 +26,8 @@ import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.data.cassandra.core.cql.keyspace.CreateIndexSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.SpecificationBuilder;
@@ -38,7 +40,6 @@ import org.springframework.data.cassandra.core.mapping.SASI.StandardAnalyzed;
import org.springframework.data.cassandra.core.mapping.SaiIndexed;
import org.springframework.data.domain.Vector;
import org.springframework.data.mapping.MappingException;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -86,7 +87,7 @@ class IndexSpecificationFactory {
if (property.isAnnotationPresent(Indexed.class)) {
CreateIndexSpecification index = createIndexSpecification(keyspace, property.findAnnotation(Indexed.class),
CreateIndexSpecification index = createIndexSpecification(keyspace, property.getRequiredAnnotation(Indexed.class),
property);
if (property.isMapLike()) {
@@ -264,6 +265,7 @@ class IndexSpecificationFactory {
index.withOption("tokenization_skip_stop_words", "" + standardAnalyzed.skipStopWords());
}
}
}
enum NonTokenizingAnalyzedConfigurer implements CreateIndexConfigurer<NonTokenizingAnalyzed> {
@@ -285,5 +287,7 @@ class IndexSpecificationFactory {
index.withOption("normalize_uppercase", "true");
}
}
}
}

View File

@@ -28,7 +28,7 @@ import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.context.ApplicationContext;
@@ -44,6 +44,8 @@ import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.cassandra.core.mapping.*;
import org.springframework.data.cassandra.core.mapping.Embedded.OnEmpty;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.convert.PropertyValueConverter;
import org.springframework.data.convert.ValueConversionContext;
import org.springframework.data.mapping.InstanceCreatorMetadata;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.Parameter;
@@ -66,7 +68,7 @@ import org.springframework.data.util.Lazy;
import org.springframework.data.util.Predicates;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.lang.Nullable;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -134,7 +136,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
*
* @param mappingContext must not be {@literal null}.
*/
@SuppressWarnings({ "deprecation" })
@SuppressWarnings({ "deprecation", "NullAway" })
public MappingCassandraConverter(CassandraMappingContext mappingContext) {
super(newConversionService());
@@ -173,6 +175,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
* @return the {@link ConversionContext}.
* @see ConversionContext
*/
@SuppressWarnings("NullAway")
protected ConversionContext getConversionContext() {
return new ConversionContext(getCustomConversions(), this::doReadRow, this::doReadTupleValue, this::doReadUdtValue,
@@ -297,8 +300,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
* @return the configured {@link UserTypeResolver}.
* @since 3.0
*/
@SuppressWarnings("NullAway")
public UserTypeResolver getUserTypeResolver() {
return this.userTypeResolver != null ? this.userTypeResolver : getMappingContext().getUserTypeResolver();
}
@@ -345,7 +348,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings({ "unchecked", "NullAway" })
public <R> R project(EntityProjection<R, ?> projection, Row row) {
if (!projection.isProjection()) {
@@ -516,7 +519,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
* @param typeHint the {@link TypeInformation} to be used to unmarshall this {@link Row}.
* @return the converted object, will never be {@literal null}.
*/
@SuppressWarnings("unchecked")
@SuppressWarnings({ "unchecked", "NullAway" })
protected <S> S doReadEntity(ConversionContext context, CassandraValueProvider valueProvider,
TypeInformation<? extends S> typeHint) {
@@ -621,7 +624,6 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
@Override
public Object convertToColumnType(Object value, ColumnType columnType) {
// noinspection ConstantConditions
return value.getClass().isArray() ? value : getWriteValue(value, columnType);
}
@@ -639,7 +641,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
@Override
@SuppressWarnings("unchecked")
public void write(Object source, Object sink, CassandraPersistentEntity<?> entity) {
public void write(Object source, Object sink, @Nullable CassandraPersistentEntity<?> entity) {
Assert.notNull(source, "Value must not be null");
@@ -650,7 +652,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
if (sink instanceof Where) {
writeWhereFromObject(source, (Where) sink, entity);
} else if (sink instanceof Map) {
writeInternal(newConvertingPropertyAccessor(source, entity), (Map<CqlIdentifier, Object>) sink, entity);
writeInternal(newConvertingPropertyAccessor(source, entity), (Map<CqlIdentifier, @Nullable Object>) sink, entity);
} else if (sink instanceof TupleValue) {
writeTupleValue(newConvertingPropertyAccessor(source, entity), (TupleValue) sink, entity);
} else if (sink instanceof UdtValue) {
@@ -660,7 +662,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
}
}
private void writeInternal(ConvertingPropertyAccessor<?> accessor, Map<CqlIdentifier, Object> sink,
private void writeInternal(ConvertingPropertyAccessor<?> accessor, Map<CqlIdentifier, @Nullable Object> sink,
CassandraPersistentEntity<?> entity) {
for (CassandraPersistentProperty property : entity) {
@@ -761,8 +763,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
sink.put(idProperty.getRequiredColumnName(), getPotentiallyConvertedSimpleValue(id, targetType));
}
@Nullable
private Object extractId(Object source, CassandraPersistentEntity<?> entity) {
private @Nullable Object extractId(Object source, CassandraPersistentEntity<?> entity) {
if (ClassUtils.isAssignableValue(entity.getType(), source)) {
return getId(source, entity);
@@ -862,7 +863,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
@Override
@SuppressWarnings("unchecked")
public Object getId(Object object, CassandraPersistentEntity<?> entity) {
public @Nullable Object getId(Object object, CassandraPersistentEntity<?> entity) {
Assert.notNull(object, "Object instance must not be null");
Assert.notNull(entity, "CassandraPersistentEntity must not be null");
@@ -918,22 +919,25 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
* @param propertyAccessor the property accessor
* @return the return value, may be {@literal null}.
*/
@Nullable
@SuppressWarnings("unchecked")
private <T> T getWriteValue(CassandraPersistentProperty property, ConvertingPropertyAccessor<?> propertyAccessor) {
@SuppressWarnings({ "unchecked" })
private <T> @Nullable T getWriteValue(CassandraPersistentProperty property,
ConvertingPropertyAccessor<?> propertyAccessor) {
ColumnType cassandraTypeDescriptor = cassandraTypeResolver.resolve(property);
Object value = propertyAccessor.getProperty(property, cassandraTypeDescriptor.getType());
if (getCustomConversions().hasValueConverter(property)) {
return (T) getCustomConversions().getPropertyValueConversions().getValueConverter(property).write(value,
new CassandraConversionContext(new PropertyValueProvider<>() {
@Nullable
@Override
public <T> T getPropertyValue(CassandraPersistentProperty property) {
return (T) propertyAccessor.getProperty(property);
}
}, property, this, spELContext));
CassandraConversionContext ccc = new CassandraConversionContext(new PropertyValueProvider<>() {
@Override
public <T> @Nullable T getPropertyValue(CassandraPersistentProperty property) {
return (T) propertyAccessor.getProperty(property);
}
}, property, this, spELContext);
PropertyValueConverter<Object, Object, ValueConversionContext<CassandraPersistentProperty>> pvc = getCustomConversions()
.getRequiredValueConverter(property);
return (T) (value != null ? pvc.write(value, ccc) : pvc.writeNull(ccc));
}
return (T) getWriteValue(value, cassandraTypeDescriptor);
@@ -947,9 +951,9 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
* @param columnType the type information.
* @return the return value, may be {@literal null}.
*/
@Nullable
@SuppressWarnings("unchecked")
private Object getWriteValue(@Nullable Object value, ColumnType columnType) {
@Contract("null, _ -> null; !null, _ -> !null")
private @Nullable Object getWriteValue(@Nullable Object value, ColumnType columnType) {
if (value == null) {
return null;
@@ -1026,7 +1030,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
private Object writeCollectionInternal(Collection<Object> source, ColumnType type) {
Collection<Object> converted = CollectionFactory.createCollection(getCollectionType(type), source.size());
Collection<@Nullable Object> converted = CollectionFactory.createCollection(getCollectionType(type), source.size());
ColumnType componentType = type.getRequiredComponentType();
for (Object element : source) {
@@ -1044,7 +1048,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
private Object writeMapInternal(Map<Object, Object> source, ColumnType type) {
Map<Object, Object> converted = CollectionFactory.createMap(type.getType(), source.size());
Map<@Nullable Object, @Nullable Object> converted = CollectionFactory.createMap(type.getType(), source.size());
ColumnType keyType = type.getRequiredComponentType();
ColumnType valueType = type.getRequiredMapValueType();
@@ -1074,8 +1078,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
* @param requestedTargetType must not be {@literal null}.
* @see org.springframework.data.cassandra.core.mapping.CassandraType
*/
@Nullable
private Object getPotentiallyConvertedSimpleValue(@Nullable Object value, @Nullable Class<?> requestedTargetType) {
private @Nullable Object getPotentiallyConvertedSimpleValue(@Nullable Object value,
@Nullable Class<?> requestedTargetType) {
if (value == null) {
return null;
@@ -1106,7 +1110,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
*
* @since 3.2
*/
protected Object getPotentiallyConvertedSimpleRead(Object value, TypeInformation<?> target) {
protected @Nullable Object getPotentiallyConvertedSimpleRead(Object value, TypeInformation<?> target) {
return getPotentiallyConvertedSimpleRead(value, target.getType());
}
@@ -1119,14 +1123,14 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
* @return the converted value.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private Object getPotentiallyConvertedSimpleRead(@Nullable Object value, @Nullable Class<?> target) {
private @Nullable Object getPotentiallyConvertedSimpleRead(@Nullable Object value, @Nullable Class<?> target) {
if (value == null || target == null || ClassUtils.isAssignableValue(target, value)) {
return value;
}
if (getCustomConversions().hasCustomReadTarget(value.getClass(), target)) {
return doConvert(value, target);
return getConversionService().convert(value, target);
}
if (Enum.class.isAssignableFrom(target)) {
@@ -1139,11 +1143,6 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return Enum.valueOf((Class<Enum>) target, value.toString());
}
return doConvert(value, target);
}
@SuppressWarnings("ConstantConditions")
private <T> T doConvert(Object value, Class<T> target) {
return getConversionService().convert(value, target);
}
@@ -1160,8 +1159,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
* @param property the property.
* @return the return value, may be {@literal null}.
*/
@Nullable
private Object getReadValue(ConversionContext context, CassandraValueProvider valueProvider,
private @Nullable Object getReadValue(ConversionContext context, CassandraValueProvider valueProvider,
CassandraPersistentProperty property) {
if (property.isCompositePrimaryKey()) {
@@ -1183,8 +1181,12 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
Object value = valueProvider.getPropertyValue(property);
if (getCustomConversions().hasValueConverter(property)) {
return getCustomConversions().getPropertyValueConversions().getValueConverter(property).read(value,
new CassandraConversionContext(valueProvider, property, this, spELContext));
PropertyValueConverter<Object, Object, ValueConversionContext<CassandraPersistentProperty>> vc = getCustomConversions()
.getRequiredValueConverter(property);
CassandraConversionContext ccc = new CassandraConversionContext(valueProvider, property, this, spELContext);
return value != null ? vc.read(value, ccc) : vc.readNull(ccc);
}
return value == null ? null : context.convert(value, property.getTypeInformation());
@@ -1223,7 +1225,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
* @param targetType must not be {@literal null}.
* @return the converted {@link Collection} or array, will never be {@literal null}.
*/
protected Object readCollectionOrArray(ConversionContext context, Collection<?> source,
protected @Nullable Object readCollectionOrArray(ConversionContext context, Collection<?> source,
TypeInformation<?> targetType) {
Assert.notNull(targetType, "Target type must not be null");
@@ -1279,7 +1281,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
Class<?> rawKeyType = keyType != null ? keyType.getType() : null;
Map<Object, Object> map = CollectionFactory.createMap(resolveMapType(targetType), rawKeyType, source.size());
Map<Object, @Nullable Object> map = CollectionFactory.createMap(resolveMapType(targetType), rawKeyType,
source.size());
if (source.isEmpty()) {
return map;
@@ -1289,7 +1292,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
Object key = entry.getKey();
if (key != null && rawKeyType != null && !rawKeyType.isAssignableFrom(key.getClass())) {
if (key != null && keyType != null && rawKeyType != null && !rawKeyType.isAssignableFrom(key.getClass())) {
key = context.convert(key, keyType);
}
@@ -1317,9 +1320,10 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
INSTANCE;
@Override
public <T> T getParameterValue(Parameter<T, CassandraPersistentProperty> parameter) {
public <T> @Nullable T getParameterValue(Parameter<T, CassandraPersistentProperty> parameter) {
return null;
}
}
/**
@@ -1352,6 +1356,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
Parameter<T, CassandraPersistentProperty> parameter) {
return context.convert(object, parameter.getType());
}
}
/**
@@ -1497,9 +1502,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
this.parent = parent;
}
@Nullable
@SuppressWarnings("unchecked")
public <T> T getParameterValue(Parameter<T, CassandraPersistentProperty> parameter) {
public <T> @Nullable T getParameterValue(Parameter<T, CassandraPersistentProperty> parameter) {
InstanceCreatorMetadata<CassandraPersistentProperty> creatorMetadata = entity.getInstanceCreatorMetadata();
@@ -1540,7 +1544,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
}
@Override
public Object getProperty(PersistentProperty<?> property) {
public @Nullable Object getProperty(PersistentProperty<?> property) {
return delegate.getProperty(translate(property));
}
@@ -1569,9 +1573,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return delegate.hasProperty(translator.translate(property));
}
@Nullable
@Override
public <T> T getPropertyValue(CassandraPersistentProperty property) {
public <T> @Nullable T getPropertyValue(CassandraPersistentProperty property) {
return delegate.getPropertyValue(translator.translate(property));
}
@@ -1610,6 +1613,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return new ProjectingConversionContext(conversions, rowConverter, tupleConverter, udtConverter,
collectionConverter, mapConverter, elementConverter, property);
}
}
static class MapPersistentPropertyAccessor implements PersistentPropertyAccessor<Map<String, Object>> {
@@ -1622,7 +1626,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
}
@Override
public Object getProperty(PersistentProperty<?> persistentProperty) {
public @Nullable Object getProperty(PersistentProperty<?> persistentProperty) {
return map.get(persistentProperty.getName());
}
@@ -1630,6 +1634,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
public Map<String, Object> getBean() {
return map;
}
}
}

View File

@@ -23,6 +23,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.mapping.BasicCassandraPersistentEntity;
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
@@ -49,7 +50,6 @@ import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.mapping.PropertyReferenceException;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.PropertyValueProvider;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -145,8 +145,7 @@ public class QueryMapper {
return Filter.from(result);
}
@Nullable
private Object getMappedValue(Field field, CriteriaDefinition.Operator operator, Object value) {
private @Nullable Object getMappedValue(Field field, CriteriaDefinition.Operator operator, Object value) {
if (field.getProperty().isPresent()
&& field.getProperty().filter(it -> converter.getCustomConversions().hasValueConverter(it)).isPresent()) {
@@ -160,7 +159,7 @@ public class QueryMapper {
}, property, converter);
PropertyValueConverter<Object, Object, ValueConversionContext<CassandraPersistentProperty>> valueConverter = converter
.getCustomConversions().getPropertyValueConversions().getValueConverter(property);
.getCustomConversions().getRequiredValueConverter(property);
/* might be an $in clause with multiple entries */
if (!property.isCollectionLike() && value instanceof List<?> collection) {
@@ -233,18 +232,14 @@ public class QueryMapper {
private Selector getMappedSelector(Selector selector, CqlIdentifier cqlIdentifier, Field field) {
if (selector instanceof ColumnSelector) {
ColumnSelector columnSelector = (ColumnSelector) selector;
if (selector instanceof ColumnSelector columnSelector) {
ColumnSelector mappedColumnSelector = ColumnSelector.from(cqlIdentifier);
return columnSelector.getAlias().map(mappedColumnSelector::as).orElse(mappedColumnSelector);
}
if (selector instanceof FunctionCall) {
FunctionCall functionCall = (FunctionCall) selector;
if (selector instanceof FunctionCall functionCall) {
FunctionCall mappedFunctionCall = FunctionCall.from(functionCall.getExpression(),
functionCall.getParameters().stream().map(obj -> {
@@ -662,9 +657,10 @@ public class QueryMapper {
}
@Override
@SuppressWarnings("NullAway")
public ColumnName getMappedKey() {
if (!path.isPresent()) {
if (path.isEmpty()) {
return name;
}
@@ -691,4 +687,5 @@ public class QueryMapper {
return ColumnName.from(leafProperty.getColumnName());
}
}
}

View File

@@ -15,7 +15,7 @@
*/
package org.springframework.data.cassandra.core.convert;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -124,16 +124,14 @@ class RowReader {
*
* @throws ClassCastException if the value cannot be converted to the requested type.
*/
@Nullable
public <T> T get(int columnIndex, Class<T> requestedType) {
public <T> @Nullable T get(int columnIndex, Class<T> requestedType) {
Object value = get(columnIndex);
return requestedType.cast(value);
}
@Nullable
private Object getCollection(int index, DataType type) {
private @Nullable Object getCollection(int index, DataType type) {
if (type instanceof ListType) {
@@ -178,4 +176,5 @@ class RowReader {
public boolean contains(CqlIdentifier columnName) {
return row.getColumnDefinitions().contains(columnName);
}
}

View File

@@ -15,10 +15,10 @@
*/
package org.springframework.data.cassandra.core.convert;
import org.jspecify.annotations.Nullable;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
import org.springframework.lang.Nullable;
import com.datastax.oss.driver.api.core.cql.Row;
@@ -68,4 +68,5 @@ enum RowReaderPropertyAccessor implements PropertyAccessor {
public void write(EvaluationContext context, @Nullable Object target, String name, @Nullable Object newValue) {
throw new UnsupportedOperationException();
}
}

View File

@@ -15,9 +15,9 @@
*/
package org.springframework.data.cassandra.core.convert;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
import org.springframework.data.mapping.model.ValueExpressionEvaluator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.cql.Row;
@@ -51,10 +51,9 @@ public class RowValueProvider implements CassandraValueProvider {
this.evaluator = evaluator;
}
@Nullable
@Override
@SuppressWarnings("unchecked")
public <T> T getPropertyValue(CassandraPersistentProperty property) {
public <T> @Nullable T getPropertyValue(CassandraPersistentProperty property) {
String spelExpression = property.getSpelExpression();
@@ -74,4 +73,5 @@ public class RowValueProvider implements CassandraValueProvider {
public Object getSource() {
return this.reader.getRow();
}
}

View File

@@ -19,6 +19,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.cql.keyspace.CreateIndexSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.CreateTableSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.CreateUserTypeSpecification;
@@ -33,7 +34,6 @@ import org.springframework.data.domain.Vector;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
@@ -136,6 +136,7 @@ public class SchemaFactory {
* @return
* @since 2.2
*/
@SuppressWarnings("NullAway")
public CreateTableSpecification getCreateTableSpecificationFor(CassandraPersistentEntity<?> entity,
CqlIdentifier tableName) {
@@ -280,7 +281,7 @@ public class SchemaFactory {
if (property.isEmbedded()) {
if (property.isAnnotationPresent(Indexed.class)) {
Indexed indexed = property.findAnnotation(Indexed.class);
Indexed indexed = property.getRequiredAnnotation(Indexed.class);
for (CassandraPersistentProperty embeddedProperty : embeddedEntityOperations.getEntity(property)) {
indexes.add(IndexSpecificationFactory.createIndexSpecification(keyspace, indexed, embeddedProperty));
}
@@ -337,6 +338,7 @@ public class SchemaFactory {
}
enum ShallowUserTypeResolver implements UserTypeResolver {
INSTANCE;
@Override
@@ -367,9 +369,8 @@ public class SchemaFactory {
this.frozen = frozen;
}
@Nullable
@Override
public CqlIdentifier getKeyspace() {
public @Nullable CqlIdentifier getKeyspace() {
return keyspace;
}
@@ -461,4 +462,5 @@ public class SchemaFactory {
return "UDT(" + name.asCql(true) + ")";
}
}
}

View File

@@ -15,9 +15,9 @@
*/
package org.springframework.data.cassandra.core.convert;
import org.jspecify.annotations.Nullable;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
import org.springframework.data.mapping.model.ValueExpressionEvaluator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.data.TupleValue;
@@ -54,9 +54,8 @@ public class TupleValueProvider implements CassandraValueProvider {
this.evaluator = evaluator;
}
@Nullable
@Override
public <T> T getPropertyValue(CassandraPersistentProperty property) {
public <T> @Nullable T getPropertyValue(CassandraPersistentProperty property) {
String spelExpression = property.getSpelExpression();
@@ -79,4 +78,5 @@ public class TupleValueProvider implements CassandraValueProvider {
public Object getSource() {
return this.tupleValue;
}
}

Some files were not shown because too many files have changed in this diff Show More