From cf6e82df9dc4458097c7fcf3137525e4bd2c5f21 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 14 Feb 2025 11:18:54 +0100 Subject: [PATCH] Migrate to JSpecify annotations for nullability constraints. Closes #618 Original pull request: #625 --- pom.xml | 1 - .../keyvalue/annotation/package-info.java | 3 +- .../keyvalue/aot/KeyValueRuntimeHints.java | 2 +- .../data/keyvalue/aot/package-info.java | 5 ++++ .../core/AbstractKeyValueAdapter.java | 8 ++---- .../data/keyvalue/core/CriteriaAccessor.java | 2 +- .../core/ForwardingCloseableIterator.java | 2 +- .../keyvalue/core/GeneratingIdAccessor.java | 3 +- .../data/keyvalue/core/KeyValueAdapter.java | 14 ++++------ .../data/keyvalue/core/KeyValueCallback.java | 2 +- .../keyvalue/core/KeyValueOperations.java | 12 ++++---- ...eyValuePersistenceExceptionTranslator.java | 6 ++-- .../data/keyvalue/core/KeyValueTemplate.java | 28 +++++++++++-------- .../data/keyvalue/core/PathSortAccessor.java | 5 ++-- .../keyvalue/core/PredicateQueryEngine.java | 10 +++---- .../keyvalue/core/PropertyPathComparator.java | 14 +++++----- .../data/keyvalue/core/QueryEngine.java | 5 ++-- .../core/SimplePropertyPathAccessor.java | 3 +- .../data/keyvalue/core/SortAccessor.java | 2 +- .../keyvalue/core/SpelCriteriaAccessor.java | 3 +- .../keyvalue/core/SpelPropertyComparator.java | 19 ++++++------- .../data/keyvalue/core/SpelQueryEngine.java | 3 +- .../data/keyvalue/core/SpelSortAccessor.java | 3 +- .../keyvalue/core/event/KeyValueEvent.java | 11 +++----- .../keyvalue/core/event/package-info.java | 3 +- .../AnnotationBasedKeySpaceResolver.java | 9 +++--- .../BasicKeyValuePersistentEntity.java | 8 +++--- .../core/mapping/KeySpaceResolver.java | 2 +- .../mapping/KeyValuePersistentEntity.java | 2 +- .../context/KeyValueMappingContext.java | 5 ++-- .../core/mapping/context/package-info.java | 3 +- .../keyvalue/core/mapping/package-info.java | 3 +- .../data/keyvalue/core/package-info.java | 3 +- .../keyvalue/core/query/KeyValueQuery.java | 5 ++-- .../keyvalue/core/query/package-info.java | 3 +- ...ValueRepositoryConfigurationExtension.java | 7 ++--- .../repository/config/package-info.java | 3 +- .../keyvalue/repository/package-info.java | 3 +- .../query/CachingKeyValuePartTreeQuery.java | 2 +- .../query/KeyValuePartTreeQuery.java | 8 +++--- .../query/PredicateQueryCreator.java | 2 +- .../repository/query/SpelQueryCreator.java | 3 +- .../repository/query/package-info.java | 3 +- .../support/KeyValueRepositoryFactory.java | 2 +- .../KeyValueRepositoryFactoryBean.java | 7 ++++- .../QuerydslKeyValuePredicateExecutor.java | 7 ++--- .../repository/support/package-info.java | 3 +- .../data/map/MapKeyValueAdapter.java | 11 ++++---- .../data/map/package-info.java | 3 +- .../MapRepositoryConfigurationExtension.java | 10 +++---- .../map/repository/config/package-info.java | 3 +- .../keyvalue/core/KeyValueTemplateTests.java | 2 +- .../core/KeyValueTemplateUnitTests.java | 4 +-- 53 files changed, 142 insertions(+), 153 deletions(-) create mode 100644 src/main/java/org/springframework/data/keyvalue/aot/package-info.java diff --git a/pom.xml b/pom.xml index 2f79fad..42d6570 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,6 @@ ${querydsl} true - diff --git a/src/main/java/org/springframework/data/keyvalue/annotation/package-info.java b/src/main/java/org/springframework/data/keyvalue/annotation/package-info.java index e4994ad..acad4dc 100644 --- a/src/main/java/org/springframework/data/keyvalue/annotation/package-info.java +++ b/src/main/java/org/springframework/data/keyvalue/annotation/package-info.java @@ -1,6 +1,5 @@ /** * Key-Value annotations for declarative keyspace configuration. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.keyvalue.annotation; diff --git a/src/main/java/org/springframework/data/keyvalue/aot/KeyValueRuntimeHints.java b/src/main/java/org/springframework/data/keyvalue/aot/KeyValueRuntimeHints.java index b4417b3..8959193 100644 --- a/src/main/java/org/springframework/data/keyvalue/aot/KeyValueRuntimeHints.java +++ b/src/main/java/org/springframework/data/keyvalue/aot/KeyValueRuntimeHints.java @@ -18,13 +18,13 @@ package org.springframework.data.keyvalue.aot; import java.util.Arrays; import java.util.List; +import org.jspecify.annotations.Nullable; import org.springframework.aot.hint.ExecutableMode; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.aot.hint.TypeReference; import org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery; -import org.springframework.lang.Nullable; /** * {@link RuntimeHintsRegistrar} for KeyValue. diff --git a/src/main/java/org/springframework/data/keyvalue/aot/package-info.java b/src/main/java/org/springframework/data/keyvalue/aot/package-info.java new file mode 100644 index 0000000..199fb4a --- /dev/null +++ b/src/main/java/org/springframework/data/keyvalue/aot/package-info.java @@ -0,0 +1,5 @@ +/** + * Support classes for key-value ahead of time computation + */ +@org.jspecify.annotations.NullMarked +package org.springframework.data.keyvalue.aot; diff --git a/src/main/java/org/springframework/data/keyvalue/core/AbstractKeyValueAdapter.java b/src/main/java/org/springframework/data/keyvalue/core/AbstractKeyValueAdapter.java index 80868a8..d64e226 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/AbstractKeyValueAdapter.java +++ b/src/main/java/org/springframework/data/keyvalue/core/AbstractKeyValueAdapter.java @@ -18,8 +18,8 @@ package org.springframework.data.keyvalue.core; import java.util.Collection; import java.util.Comparator; +import org.jspecify.annotations.Nullable; import org.springframework.data.keyvalue.core.query.KeyValueQuery; -import org.springframework.lang.Nullable; /** * Base implementation of {@link KeyValueAdapter} holds {@link QueryEngine} to delegate {@literal find} and @@ -69,15 +69,13 @@ public abstract class AbstractKeyValueAdapter implements KeyValueAdapter { return engine; } - @Nullable @Override - public T get(Object id, String keyspace, Class type) { + public @Nullable T get(Object id, String keyspace, Class type) { return type.cast(get(id, keyspace)); } - @Nullable @Override - public T delete(Object id, String keyspace, Class type) { + public @Nullable T delete(Object id, String keyspace, Class type) { return type.cast(delete(id, keyspace)); } diff --git a/src/main/java/org/springframework/data/keyvalue/core/CriteriaAccessor.java b/src/main/java/org/springframework/data/keyvalue/core/CriteriaAccessor.java index d50c626..2e226de 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/CriteriaAccessor.java +++ b/src/main/java/org/springframework/data/keyvalue/core/CriteriaAccessor.java @@ -15,8 +15,8 @@ */ package org.springframework.data.keyvalue.core; +import org.jspecify.annotations.Nullable; import org.springframework.data.keyvalue.core.query.KeyValueQuery; -import org.springframework.lang.Nullable; /** * Resolves the criteria object from given {@link KeyValueQuery}. diff --git a/src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java b/src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java index 3867d74..4a3a89f 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java +++ b/src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java @@ -17,8 +17,8 @@ package org.springframework.data.keyvalue.core; import java.util.Iterator; +import org.jspecify.annotations.Nullable; import org.springframework.data.util.CloseableIterator; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** diff --git a/src/main/java/org/springframework/data/keyvalue/core/GeneratingIdAccessor.java b/src/main/java/org/springframework/data/keyvalue/core/GeneratingIdAccessor.java index 46a07ac..d4ccc68 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/GeneratingIdAccessor.java +++ b/src/main/java/org/springframework/data/keyvalue/core/GeneratingIdAccessor.java @@ -15,6 +15,7 @@ */ package org.springframework.data.keyvalue.core; +import org.jspecify.annotations.Nullable; import org.springframework.data.mapping.IdentifierAccessor; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentPropertyAccessor; @@ -55,7 +56,7 @@ class GeneratingIdAccessor implements IdentifierAccessor { } @Override - public Object getIdentifier() { + public @Nullable Object getIdentifier() { return accessor.getProperty(identifierProperty); } diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java b/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java index f3eaf1d..e484830 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java +++ b/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java @@ -18,10 +18,10 @@ package org.springframework.data.keyvalue.core; import java.util.Collection; import java.util.Map; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.DisposableBean; import org.springframework.data.keyvalue.core.query.KeyValueQuery; import org.springframework.data.util.CloseableIterator; -import org.springframework.lang.Nullable; /** * {@link KeyValueAdapter} unifies access and shields the underlying key/value specific implementation. @@ -39,7 +39,7 @@ public interface KeyValueAdapter extends DisposableBean { * @param keyspace must not be {@literal null}. * @return the item previously associated with the id. */ - Object put(Object id, Object item, String keyspace); + @Nullable Object put(Object id, Object item, String keyspace); /** * Check if a object with given id exists in keyspace. @@ -69,8 +69,7 @@ public interface KeyValueAdapter extends DisposableBean { * @return {@literal null} in case no matching item exists. * @since 1.1 */ - @Nullable - T get(Object id, String keyspace, Class type); + @Nullable T get(Object id, String keyspace, Class type); /** * Delete and return the object with given type and id. @@ -91,8 +90,7 @@ public interface KeyValueAdapter extends DisposableBean { * @return {@literal null} if object could not be found * @since 1.1 */ - @Nullable - T delete(Object id, String keyspace, Class type); + @Nullable T delete(Object id, String keyspace, Class type); /** * Get all elements for given keyspace. @@ -100,7 +98,7 @@ public interface KeyValueAdapter extends DisposableBean { * @param keyspace must not be {@literal null}. * @return empty {@link Collection} if nothing found. */ - Iterable getAllOf(String keyspace); + Iterable getAllOf(String keyspace); /** * Get all elements for given keyspace. @@ -132,7 +130,7 @@ public interface KeyValueAdapter extends DisposableBean { * @since 2.5 */ @SuppressWarnings("unchecked") - default CloseableIterator> entries(String keyspace, Class type) { + default CloseableIterator> entries(String keyspace, Class type) { return (CloseableIterator) entries(keyspace); } diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeyValueCallback.java b/src/main/java/org/springframework/data/keyvalue/core/KeyValueCallback.java index 9732849..0014206 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/KeyValueCallback.java +++ b/src/main/java/org/springframework/data/keyvalue/core/KeyValueCallback.java @@ -15,7 +15,7 @@ */ package org.springframework.data.keyvalue.core; -import org.springframework.lang.Nullable; +import org.jspecify.annotations.Nullable; /** * Generic callback interface for code that operates on a {@link KeyValueAdapter}. This is particularly useful for diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeyValueOperations.java b/src/main/java/org/springframework/data/keyvalue/core/KeyValueOperations.java index 4caa2a0..e8f426f 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/KeyValueOperations.java +++ b/src/main/java/org/springframework/data/keyvalue/core/KeyValueOperations.java @@ -17,12 +17,12 @@ package org.springframework.data.keyvalue.core; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.DisposableBean; import org.springframework.data.domain.Sort; import org.springframework.data.keyvalue.annotation.KeySpace; import org.springframework.data.keyvalue.core.query.KeyValueQuery; import org.springframework.data.mapping.context.MappingContext; -import org.springframework.lang.Nullable; /** * Interface that specifies a basic set of key/value operations. Implemented by {@link KeyValueTemplate}. @@ -84,8 +84,8 @@ public interface KeyValueOperations extends DisposableBean { * @param action must not be {@literal null}. * @return */ - @Nullable - T execute(KeyValueCallback action); + + @Nullable T execute(KeyValueCallback action); /** * Get all elements matching the given query.
@@ -145,8 +145,7 @@ public interface KeyValueOperations extends DisposableBean { * @param objectToDelete must not be {@literal null}. * @return */ - @Nullable - T delete(T objectToDelete); + @Nullable T delete(T objectToDelete); /** * Delete item of type with given id. @@ -155,8 +154,7 @@ public interface KeyValueOperations extends DisposableBean { * @param type must not be {@literal null}. * @return the deleted item or {@literal null} if no match found. */ - @Nullable - T delete(Object id, Class type); + @Nullable T delete(Object id, Class type); /** * Total number of elements with given type available. Respects {@link KeySpace} if present and therefore counts all diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeyValuePersistenceExceptionTranslator.java b/src/main/java/org/springframework/data/keyvalue/core/KeyValuePersistenceExceptionTranslator.java index 3543c91..7a4f9ff 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/KeyValuePersistenceExceptionTranslator.java +++ b/src/main/java/org/springframework/data/keyvalue/core/KeyValuePersistenceExceptionTranslator.java @@ -17,10 +17,10 @@ package org.springframework.data.keyvalue.core; import java.util.NoSuchElementException; +import org.jspecify.annotations.Nullable; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.dao.support.PersistenceExceptionTranslator; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -32,9 +32,9 @@ import org.springframework.util.Assert; */ public class KeyValuePersistenceExceptionTranslator implements PersistenceExceptionTranslator { - @Nullable @Override - public DataAccessException translateExceptionIfPossible(RuntimeException exception) { + @SuppressWarnings("NullAway") + public @Nullable DataAccessException translateExceptionIfPossible(RuntimeException exception) { Assert.notNull(exception, "Exception must not be null"); diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java b/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java index f1cd793..3b33b82 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java +++ b/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import org.jspecify.annotations.Nullable; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.dao.DataAccessException; @@ -34,7 +35,6 @@ import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext; import org.springframework.data.keyvalue.core.query.KeyValueQuery; import org.springframework.data.mapping.context.MappingContext; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; @@ -143,7 +143,7 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationEventPub KeyValuePersistentEntity entity = getKeyValuePersistentEntity(objectToInsert); GeneratingIdAccessor generatingIdAccessor = new GeneratingIdAccessor(entity.getPropertyAccessor(objectToInsert), - entity.getIdProperty(), identifierGenerator); + entity.getRequiredIdProperty(), identifierGenerator); Object id = generatingIdAccessor.getOrGenerateIdentifier(); return insert(id, objectToInsert); @@ -213,7 +213,8 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationEventPub return executeRequired(adapter -> { - Iterable values = adapter.getAllOf(resolveKeySpace(type), type); + String keyspace = resolveKeySpace(type); + Iterable values = adapter.getAllOf(keyspace, type); ArrayList filtered = new ArrayList<>(); for (Object candidate : values) { @@ -258,7 +259,6 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationEventPub Assert.notNull(type, "Type to delete must not be null"); String keyspace = resolveKeySpace(type); - potentiallyPublishEvent(KeyValueEvent.beforeDropKeySpace(keyspace, type)); execute((KeyValueCallback) adapter -> { @@ -272,16 +272,16 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationEventPub @SuppressWarnings("unchecked") @Override - public T delete(T objectToDelete) { + public @Nullable T delete(T objectToDelete) { Class type = (Class) ClassUtils.getUserClass(objectToDelete); KeyValuePersistentEntity entity = getKeyValuePersistentEntity(objectToDelete); - return delete(entity.getIdentifierAccessor(objectToDelete).getIdentifier(), type); + return delete(entity.getIdentifierAccessor(objectToDelete).getRequiredIdentifier(), type); } @Override - public T delete(Object id, Class type) { + public @Nullable T delete(Object id, Class type) { Assert.notNull(id, "Id for object to be deleted must not be null"); Assert.notNull(type, "Type to delete must not be null"); @@ -301,12 +301,12 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationEventPub public long count(Class type) { Assert.notNull(type, "Type for count must not be null"); - return adapter.count(resolveKeySpace(type)); + String keyspace = resolveKeySpace(type); + return adapter.count(keyspace); } - @Nullable @Override - public T execute(KeyValueCallback action) { + public @Nullable T execute(KeyValueCallback action) { Assert.notNull(action, "KeyValueCallback must not be null"); @@ -401,8 +401,12 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationEventPub return this.mappingContext.getRequiredPersistentEntity(ClassUtils.getUserClass(objectToInsert)); } - private String resolveKeySpace(Class type) { - return this.mappingContext.getRequiredPersistentEntity(type).getKeySpace(); + + private String resolveKeySpace(Class type) { + + String keyspace = this.mappingContext.getRequiredPersistentEntity(type).getKeySpace(); + Assert.notNull(keyspace, "Keyspace must not be null"); + return keyspace; } private RuntimeException resolveExceptionIfPossible(RuntimeException e) { diff --git a/src/main/java/org/springframework/data/keyvalue/core/PathSortAccessor.java b/src/main/java/org/springframework/data/keyvalue/core/PathSortAccessor.java index 5e6bcab..3441f0d 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/PathSortAccessor.java +++ b/src/main/java/org/springframework/data/keyvalue/core/PathSortAccessor.java @@ -18,11 +18,11 @@ package org.springframework.data.keyvalue.core; import java.util.Comparator; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.NullHandling; import org.springframework.data.domain.Sort.Order; import org.springframework.data.keyvalue.core.query.KeyValueQuery; -import org.springframework.lang.Nullable; /** * @author Christoph Strobl @@ -30,9 +30,8 @@ import org.springframework.lang.Nullable; */ public class PathSortAccessor implements SortAccessor> { - @Nullable @Override - public Comparator resolve(KeyValueQuery query) { + public @Nullable Comparator resolve(KeyValueQuery query) { if (query.getSort().isUnsorted()) { return null; diff --git a/src/main/java/org/springframework/data/keyvalue/core/PredicateQueryEngine.java b/src/main/java/org/springframework/data/keyvalue/core/PredicateQueryEngine.java index 8c51fe6..b8bb755 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/PredicateQueryEngine.java +++ b/src/main/java/org/springframework/data/keyvalue/core/PredicateQueryEngine.java @@ -22,8 +22,8 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.springframework.data.keyvalue.core.query.KeyValueQuery; -import org.springframework.lang.Nullable; /** * {@link QueryEngine} implementation specific for executing {@link Predicate} based {@link KeyValueQuery} against @@ -46,9 +46,9 @@ public class PredicateQueryEngine extends QueryEngine> sortAccessor) { super(new CriteriaAccessor<>() { - @Nullable + @Override - public Predicate resolve(KeyValueQuery query) { + public @Nullable Predicate resolve(KeyValueQuery query) { return (Predicate) query.getCriteria(); } }, sortAccessor); @@ -78,12 +78,12 @@ public class PredicateQueryEngine extends QueryEngine List filterMatchingRange(List source, @Nullable Predicate criteria, long offset, int rows) { + private static List filterMatchingRange(List source, @Nullable Predicate criteria, long offset, int rows) { Stream stream = source.stream(); if (criteria != null) { - stream = stream.filter(criteria); + stream = stream.filter((Predicate) criteria); } if (offset > 0) { stream = stream.skip(offset); diff --git a/src/main/java/org/springframework/data/keyvalue/core/PropertyPathComparator.java b/src/main/java/org/springframework/data/keyvalue/core/PropertyPathComparator.java index c6392aa..ff28cb3 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/PropertyPathComparator.java +++ b/src/main/java/org/springframework/data/keyvalue/core/PropertyPathComparator.java @@ -19,8 +19,8 @@ import java.util.Comparator; import java.util.HashMap; import java.util.Map; +import org.jspecify.annotations.Nullable; import org.springframework.data.mapping.PropertyPath; -import org.springframework.lang.Nullable; /** * {@link Comparator} implementation to compare objects based on a {@link PropertyPath}. This comparator obtains the @@ -67,12 +67,12 @@ public class PropertyPathComparator implements Comparator { return getComparator().compare(value1, value2) * (asc ? 1 : -1); } - protected Object getCompareValue(T object, PropertyPath propertyPath) { + protected @Nullable Object getCompareValue(S object, PropertyPath propertyPath) { return new SimplePropertyPathAccessor<>(object).getValue(propertyPath); } @SuppressWarnings("unchecked") - private Comparator getComparator() { + private Comparator<@Nullable Object> getComparator() { return (Comparator) (nullsFirst ? NULLS_FIRST : NULLS_LAST); } @@ -81,7 +81,7 @@ public class PropertyPathComparator implements Comparator { * * @return */ - public PropertyPathComparator asc() { + public PropertyPathComparator<@Nullable T> asc() { this.asc = true; return this; } @@ -91,7 +91,7 @@ public class PropertyPathComparator implements Comparator { * * @return */ - public PropertyPathComparator desc() { + public PropertyPathComparator<@Nullable T> desc() { this.asc = false; return this; } @@ -101,7 +101,7 @@ public class PropertyPathComparator implements Comparator { * * @return */ - public PropertyPathComparator nullsFirst() { + public PropertyPathComparator<@Nullable T> nullsFirst() { this.nullsFirst = true; return this; } @@ -111,7 +111,7 @@ public class PropertyPathComparator implements Comparator { * * @return */ - public PropertyPathComparator nullsLast() { + public PropertyPathComparator<@Nullable T> nullsLast() { this.nullsFirst = false; return this; } diff --git a/src/main/java/org/springframework/data/keyvalue/core/QueryEngine.java b/src/main/java/org/springframework/data/keyvalue/core/QueryEngine.java index 33b581c..9b9969f 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/QueryEngine.java +++ b/src/main/java/org/springframework/data/keyvalue/core/QueryEngine.java @@ -18,8 +18,8 @@ package org.springframework.data.keyvalue.core; import java.util.Collection; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.springframework.data.keyvalue.core.query.KeyValueQuery; -import org.springframework.lang.Nullable; /** * Base implementation for accessing and executing {@link KeyValueQuery} against a {@link KeyValueAdapter}. @@ -125,8 +125,7 @@ public abstract class QueryEngine { this.root = source; } - public Object getValue(PropertyPath path) { + public @Nullable Object getValue(PropertyPath path) { Object currentValue = root; for (PropertyPath current : path) { diff --git a/src/main/java/org/springframework/data/keyvalue/core/SortAccessor.java b/src/main/java/org/springframework/data/keyvalue/core/SortAccessor.java index e7c4390..9ef228f 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/SortAccessor.java +++ b/src/main/java/org/springframework/data/keyvalue/core/SortAccessor.java @@ -15,9 +15,9 @@ */ package org.springframework.data.keyvalue.core; +import org.jspecify.annotations.Nullable; import org.springframework.data.domain.Sort; import org.springframework.data.keyvalue.core.query.KeyValueQuery; -import org.springframework.lang.Nullable; /** * Resolves the {@link Sort} object from given {@link KeyValueQuery} and potentially converts it into a store specific diff --git a/src/main/java/org/springframework/data/keyvalue/core/SpelCriteriaAccessor.java b/src/main/java/org/springframework/data/keyvalue/core/SpelCriteriaAccessor.java index 4f91aa5..74c419b 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/SpelCriteriaAccessor.java +++ b/src/main/java/org/springframework/data/keyvalue/core/SpelCriteriaAccessor.java @@ -15,6 +15,7 @@ */ package org.springframework.data.keyvalue.core; +import org.jspecify.annotations.Nullable; import org.springframework.data.keyvalue.core.query.KeyValueQuery; import org.springframework.expression.spel.standard.SpelExpression; import org.springframework.expression.spel.standard.SpelExpressionParser; @@ -43,7 +44,7 @@ class SpelCriteriaAccessor implements CriteriaAccessor { } @Override - public SpelCriteria resolve(KeyValueQuery query) { + public @Nullable SpelCriteria resolve(KeyValueQuery query) { if (query.getCriteria() == null) { return null; diff --git a/src/main/java/org/springframework/data/keyvalue/core/SpelPropertyComparator.java b/src/main/java/org/springframework/data/keyvalue/core/SpelPropertyComparator.java index b464c1a..3aafcf0 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/SpelPropertyComparator.java +++ b/src/main/java/org/springframework/data/keyvalue/core/SpelPropertyComparator.java @@ -17,10 +17,10 @@ package org.springframework.data.keyvalue.core; import java.util.Comparator; +import org.jspecify.annotations.Nullable; import org.springframework.expression.spel.standard.SpelExpression; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.SimpleEvaluationContext; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -63,7 +63,7 @@ public class SpelPropertyComparator implements Comparator { * * @return */ - public SpelPropertyComparator asc() { + public SpelPropertyComparator<@Nullable T> asc() { this.asc = true; return this; } @@ -73,7 +73,7 @@ public class SpelPropertyComparator implements Comparator { * * @return */ - public SpelPropertyComparator desc() { + public SpelPropertyComparator<@Nullable T> desc() { this.asc = false; return this; } @@ -83,7 +83,7 @@ public class SpelPropertyComparator implements Comparator { * * @return */ - public SpelPropertyComparator nullsFirst() { + public SpelPropertyComparator<@Nullable T> nullsFirst() { this.nullsFirst = true; return this; } @@ -93,7 +93,7 @@ public class SpelPropertyComparator implements Comparator { * * @return */ - public SpelPropertyComparator nullsLast() { + public SpelPropertyComparator<@Nullable T> nullsLast() { this.nullsFirst = false; return this; } @@ -119,14 +119,12 @@ public class SpelPropertyComparator implements Comparator { */ protected String buildExpressionForPath() { - String rawExpression = String.format("#comparator.compare(#arg1?.%s,#arg2?.%s)", path.replace(".", "?."), + return String.format("#comparator.compare(#arg1?.%s,#arg2?.%s)", path.replace(".", "?."), path.replace(".", "?.")); - - return rawExpression; } @Override - public int compare(T arg1, T arg2) { + public int compare(@Nullable T arg1, @Nullable T arg2) { SpelExpression expressionToUse = getExpression(); @@ -137,7 +135,8 @@ public class SpelPropertyComparator implements Comparator { expressionToUse.setEvaluationContext(ctx); - return expressionToUse.getValue(Integer.class) * (asc ? 1 : -1); + Integer value = expressionToUse.getValue(Integer.class); + return (value != null ? value : 0) * (asc ? 1 : -1); } /** diff --git a/src/main/java/org/springframework/data/keyvalue/core/SpelQueryEngine.java b/src/main/java/org/springframework/data/keyvalue/core/SpelQueryEngine.java index cd8c27f..4ce81fb 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/SpelQueryEngine.java +++ b/src/main/java/org/springframework/data/keyvalue/core/SpelQueryEngine.java @@ -21,11 +21,11 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.springframework.data.keyvalue.core.query.KeyValueQuery; import org.springframework.expression.spel.SpelEvaluationException; import org.springframework.expression.spel.standard.SpelExpression; import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.lang.Nullable; /** * {@link QueryEngine} implementation specific for executing {@link SpelExpression} based {@link KeyValueQuery} against @@ -97,6 +97,7 @@ public class SpelQueryEngine extends QueryEngine> { } @Override - public Comparator resolve(KeyValueQuery query) { + public @Nullable Comparator resolve(KeyValueQuery query) { if (query.getSort().isUnsorted()) { return null; diff --git a/src/main/java/org/springframework/data/keyvalue/core/event/KeyValueEvent.java b/src/main/java/org/springframework/data/keyvalue/core/event/KeyValueEvent.java index bae7114..0daca13 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/event/KeyValueEvent.java +++ b/src/main/java/org/springframework/data/keyvalue/core/event/KeyValueEvent.java @@ -15,8 +15,8 @@ */ package org.springframework.data.keyvalue.core.event; +import org.jspecify.annotations.Nullable; import org.springframework.context.ApplicationEvent; -import org.springframework.lang.Nullable; /** * {@link KeyValueEvent} gets published for operations executed by eg. @@ -235,8 +235,7 @@ public class KeyValueEvent extends ApplicationEvent { * * @return */ - @Nullable - public T getPayload() { + public @Nullable T getPayload() { return payload; } } @@ -336,8 +335,7 @@ public class KeyValueEvent extends ApplicationEvent { * * @return */ - @Nullable - public Object before() { + public @Nullable Object before() { return existing; } @@ -346,8 +344,7 @@ public class KeyValueEvent extends ApplicationEvent { * * @return can be {@literal null}. */ - @Nullable - public T after() { + public @Nullable T after() { return getPayload(); } } diff --git a/src/main/java/org/springframework/data/keyvalue/core/event/package-info.java b/src/main/java/org/springframework/data/keyvalue/core/event/package-info.java index 7ec69d8..c33d24c 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/event/package-info.java +++ b/src/main/java/org/springframework/data/keyvalue/core/event/package-info.java @@ -1,6 +1,5 @@ /** * Support classes for key-value events, like standard persistence lifecycle events. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.keyvalue.core.event; diff --git a/src/main/java/org/springframework/data/keyvalue/core/mapping/AnnotationBasedKeySpaceResolver.java b/src/main/java/org/springframework/data/keyvalue/core/mapping/AnnotationBasedKeySpaceResolver.java index 004a77a..cbd3362 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/mapping/AnnotationBasedKeySpaceResolver.java +++ b/src/main/java/org/springframework/data/keyvalue/core/mapping/AnnotationBasedKeySpaceResolver.java @@ -15,11 +15,11 @@ */ package org.springframework.data.keyvalue.core.mapping; +import org.jspecify.annotations.Nullable; import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; import org.springframework.data.annotation.Persistent; import org.springframework.data.keyvalue.annotation.KeySpace; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -36,8 +36,7 @@ public enum AnnotationBasedKeySpaceResolver implements KeySpaceResolver { INSTANCE; @Override - @Nullable - public String resolveKeySpace(Class type) { + public @Nullable String resolveKeySpace(Class type) { Assert.notNull(type, "Type for keyspace for null"); @@ -47,8 +46,8 @@ public enum AnnotationBasedKeySpaceResolver implements KeySpaceResolver { return keySpace != null ? keySpace.toString() : null; } - @Nullable - private static Object getKeySpace(Class type) { + + private static @Nullable Object getKeySpace(Class type) { MergedAnnotation annotation = MergedAnnotations .from(type, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY).get(KeySpace.class); diff --git a/src/main/java/org/springframework/data/keyvalue/core/mapping/BasicKeyValuePersistentEntity.java b/src/main/java/org/springframework/data/keyvalue/core/mapping/BasicKeyValuePersistentEntity.java index d1b4ade..379b8e5 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/mapping/BasicKeyValuePersistentEntity.java +++ b/src/main/java/org/springframework/data/keyvalue/core/mapping/BasicKeyValuePersistentEntity.java @@ -15,6 +15,7 @@ */ package org.springframework.data.keyvalue.core.mapping; +import org.jspecify.annotations.Nullable; import org.springframework.data.expression.ValueExpression; import org.springframework.data.expression.ValueExpressionParser; import org.springframework.data.mapping.model.BasicPersistentEntity; @@ -22,7 +23,6 @@ import org.springframework.data.util.TypeInformation; import org.springframework.expression.Expression; import org.springframework.expression.common.LiteralExpression; import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -40,7 +40,7 @@ public class BasicKeyValuePersistentEntity, P * @return the current {@link KeySpaceResolver}. Can be {@literal null}. * @since 3.1 */ - @Nullable - public KeySpaceResolver getKeySpaceResolver() { + public @Nullable KeySpaceResolver getKeySpaceResolver() { return keySpaceResolver; } diff --git a/src/main/java/org/springframework/data/keyvalue/core/mapping/context/package-info.java b/src/main/java/org/springframework/data/keyvalue/core/mapping/context/package-info.java index fa07bdc..345ca1c 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/mapping/context/package-info.java +++ b/src/main/java/org/springframework/data/keyvalue/core/mapping/context/package-info.java @@ -1,6 +1,5 @@ /** * Infrastructure for the Key-Value mapping context. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.keyvalue.core.mapping.context; diff --git a/src/main/java/org/springframework/data/keyvalue/core/mapping/package-info.java b/src/main/java/org/springframework/data/keyvalue/core/mapping/package-info.java index aa504fc..a411590 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/mapping/package-info.java +++ b/src/main/java/org/springframework/data/keyvalue/core/mapping/package-info.java @@ -1,6 +1,5 @@ /** * Infrastructure for the Key-Value mapping subsystem and keyspace resolution. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.keyvalue.core.mapping; diff --git a/src/main/java/org/springframework/data/keyvalue/core/package-info.java b/src/main/java/org/springframework/data/keyvalue/core/package-info.java index e246194..03eb9ea 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/package-info.java +++ b/src/main/java/org/springframework/data/keyvalue/core/package-info.java @@ -1,6 +1,5 @@ /** * Core key/value implementation. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.keyvalue.core; diff --git a/src/main/java/org/springframework/data/keyvalue/core/query/KeyValueQuery.java b/src/main/java/org/springframework/data/keyvalue/core/query/KeyValueQuery.java index d1dd1bc..0cf1a3f 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/query/KeyValueQuery.java +++ b/src/main/java/org/springframework/data/keyvalue/core/query/KeyValueQuery.java @@ -15,8 +15,8 @@ */ package org.springframework.data.keyvalue.core.query; +import org.jspecify.annotations.Nullable; import org.springframework.data.domain.Sort; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -76,8 +76,7 @@ public class KeyValueQuery { * @return * @since 2.0 */ - @Nullable - public T getCriteria() { + public @Nullable T getCriteria() { return criteria; } diff --git a/src/main/java/org/springframework/data/keyvalue/core/query/package-info.java b/src/main/java/org/springframework/data/keyvalue/core/query/package-info.java index b47343b..b876430 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/query/package-info.java +++ b/src/main/java/org/springframework/data/keyvalue/core/query/package-info.java @@ -1,6 +1,5 @@ /** * Key/value specific query and abstractions. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.keyvalue.core.query; diff --git a/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java b/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java index 9a99d09..f276451 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.Map; import java.util.Optional; +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; @@ -36,7 +37,6 @@ import org.springframework.data.repository.config.AnnotationRepositoryConfigurat import org.springframework.data.repository.config.RepositoryConfigurationExtension; import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport; import org.springframework.data.repository.config.RepositoryConfigurationSource; -import org.springframework.lang.Nullable; /** * {@link RepositoryConfigurationExtension} for {@link KeyValueRepository}. @@ -145,7 +145,7 @@ public abstract class KeyValueRepositoryConfigurationExtension extends Repositor AbstractBeanDefinition beanDefinition = getDefaultKeyValueTemplateBeanDefinition(configurationSource); - if (beanDefinition != null) { + if (beanDefinition != null && configurationSource.getSource() != null) { registerIfNotAlreadyRegistered(() -> beanDefinition, registry, keyValueTemplateName.get(), configurationSource.getSource()); } @@ -158,8 +158,7 @@ public abstract class KeyValueRepositoryConfigurationExtension extends Repositor * @return {@literal null} to explicitly not register a template. * @see #getDefaultKeyValueTemplateRef() */ - @Nullable - protected AbstractBeanDefinition getDefaultKeyValueTemplateBeanDefinition( + protected @Nullable AbstractBeanDefinition getDefaultKeyValueTemplateBeanDefinition( RepositoryConfigurationSource configurationSource) { return null; } diff --git a/src/main/java/org/springframework/data/keyvalue/repository/config/package-info.java b/src/main/java/org/springframework/data/keyvalue/repository/config/package-info.java index 8257cd5..87e9dcf 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/config/package-info.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/config/package-info.java @@ -1,6 +1,5 @@ /** * Support infrastructure for the configuration of key/value specific repositories. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.keyvalue.repository.config; diff --git a/src/main/java/org/springframework/data/keyvalue/repository/package-info.java b/src/main/java/org/springframework/data/keyvalue/repository/package-info.java index 8212e37..cd152cc 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/package-info.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/package-info.java @@ -1,6 +1,5 @@ /** * Key/value specific repository implementation. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.keyvalue.repository; diff --git a/src/main/java/org/springframework/data/keyvalue/repository/query/CachingKeyValuePartTreeQuery.java b/src/main/java/org/springframework/data/keyvalue/repository/query/CachingKeyValuePartTreeQuery.java index cbb2311..e11b6db 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/query/CachingKeyValuePartTreeQuery.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/query/CachingKeyValuePartTreeQuery.java @@ -15,13 +15,13 @@ */ package org.springframework.data.keyvalue.repository.query; +import org.jspecify.annotations.Nullable; import org.springframework.data.keyvalue.core.KeyValueOperations; import org.springframework.data.keyvalue.core.query.KeyValueQuery; import org.springframework.data.repository.query.QueryMethod; import org.springframework.data.repository.query.ValueExpressionDelegate; import org.springframework.data.repository.query.parser.AbstractQueryCreator; import org.springframework.data.repository.query.parser.PartTree; -import org.springframework.lang.Nullable; /** * {@link KeyValuePartTreeQuery} implementation deriving queries from {@link PartTree} using a predefined diff --git a/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java b/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java index 18a8db4..7632579 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java @@ -17,6 +17,7 @@ package org.springframework.data.keyvalue.repository.query; import java.lang.reflect.Constructor; +import org.jspecify.annotations.Nullable; import org.springframework.beans.BeanUtils; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -38,7 +39,6 @@ import org.springframework.data.repository.query.parser.PartTree; import org.springframework.data.spel.EvaluationContextProvider; import org.springframework.data.util.Lazy; import org.springframework.expression.spel.standard.SpelExpression; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -105,7 +105,7 @@ public class KeyValuePartTreeQuery implements RepositoryQuery { } @Override - public Object execute(Object[] parameters) { + public @Nullable Object execute(Object[] parameters) { ParameterAccessor accessor = new ParametersParameterAccessor(getQueryMethod().getParameters(), parameters); KeyValueQuery query = prepareQuery(parameters); @@ -118,9 +118,8 @@ public class KeyValuePartTreeQuery implements RepositoryQuery { * @param parameters * @param query */ - @Nullable @SuppressWarnings({ "unchecked", "rawtypes" }) - protected Object doExecute(Object[] parameters, KeyValueQuery query) { + protected @Nullable Object doExecute(Object[] parameters, KeyValueQuery query) { if (queryMethod.isPageQuery() || queryMethod.isSliceQuery()) { @@ -203,6 +202,7 @@ public class KeyValuePartTreeQuery implements RepositoryQuery { * @param accessor must not be {@literal null}. * @return the {@link KeyValueQuery}. */ + @SuppressWarnings("NullAway") public KeyValueQuery createQuery(ParameterAccessor accessor) { PartTree tree = this.partTree.get(); diff --git a/src/main/java/org/springframework/data/keyvalue/repository/query/PredicateQueryCreator.java b/src/main/java/org/springframework/data/keyvalue/repository/query/PredicateQueryCreator.java index 12a2472..a1b6361 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/query/PredicateQueryCreator.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/query/PredicateQueryCreator.java @@ -24,6 +24,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Pattern; +import org.jspecify.annotations.Nullable; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.domain.Sort; import org.springframework.data.keyvalue.core.SimplePropertyPathAccessor; @@ -34,7 +35,6 @@ import org.springframework.data.repository.query.parser.AbstractQueryCreator; import org.springframework.data.repository.query.parser.Part; import org.springframework.data.repository.query.parser.Part.IgnoreCaseType; import org.springframework.data.repository.query.parser.PartTree; -import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; /** diff --git a/src/main/java/org/springframework/data/keyvalue/repository/query/SpelQueryCreator.java b/src/main/java/org/springframework/data/keyvalue/repository/query/SpelQueryCreator.java index 8660c3b..25da442 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/query/SpelQueryCreator.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/query/SpelQueryCreator.java @@ -17,6 +17,7 @@ package org.springframework.data.keyvalue.repository.query; import java.util.Iterator; +import org.jspecify.annotations.Nullable; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.domain.Sort; import org.springframework.data.keyvalue.core.query.KeyValueQuery; @@ -74,7 +75,7 @@ public class SpelQueryCreator extends AbstractQueryCreator complete(String criteria, Sort sort) { + protected KeyValueQuery complete(@Nullable String criteria, Sort sort) { KeyValueQuery query = new KeyValueQuery<>(this.expression); diff --git a/src/main/java/org/springframework/data/keyvalue/repository/query/package-info.java b/src/main/java/org/springframework/data/keyvalue/repository/query/package-info.java index 64ad179..11a2946 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/query/package-info.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/query/package-info.java @@ -1,6 +1,5 @@ /** * Query derivation mechanism for key/value specific repositories providing a generic SpEL based implementation. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.keyvalue.repository.query; diff --git a/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactory.java b/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactory.java index 76b6db3..1b7d245 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactory.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactory.java @@ -22,6 +22,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.springframework.beans.BeanUtils; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.keyvalue.core.KeyValueOperations; @@ -44,7 +45,6 @@ import org.springframework.data.repository.query.QueryMethod; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.ValueExpressionDelegate; import org.springframework.data.repository.query.parser.AbstractQueryCreator; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; diff --git a/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBean.java b/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBean.java index 04942d8..7a47fbf 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBean.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBean.java @@ -15,6 +15,7 @@ */ package org.springframework.data.keyvalue.repository.support; +import org.jspecify.annotations.Nullable; import org.springframework.data.keyvalue.core.KeyValueOperations; import org.springframework.data.keyvalue.repository.KeyValueRepository; import org.springframework.data.keyvalue.repository.config.QueryCreatorType; @@ -24,7 +25,6 @@ import org.springframework.data.repository.core.support.RepositoryFactoryBeanSup import org.springframework.data.repository.core.support.RepositoryFactorySupport; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.parser.AbstractQueryCreator; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -95,6 +95,11 @@ public class KeyValueRepositoryFactoryBean, S, ID> @Override protected final RepositoryFactorySupport createRepositoryFactory() { + + Assert.notNull(operations, "Operations must not be null"); + Assert.notNull(queryCreator, "QueryCreator must not be null"); + Assert.notNull(repositoryQueryType, "QueryType must not be null"); + return createRepositoryFactory(operations, queryCreator, repositoryQueryType); } diff --git a/src/main/java/org/springframework/data/keyvalue/repository/support/QuerydslKeyValuePredicateExecutor.java b/src/main/java/org/springframework/data/keyvalue/repository/support/QuerydslKeyValuePredicateExecutor.java index 46f60de..9c5d504 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/support/QuerydslKeyValuePredicateExecutor.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/support/QuerydslKeyValuePredicateExecutor.java @@ -25,7 +25,7 @@ import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; - +import org.jspecify.annotations.Nullable; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.data.convert.DtoInstantiatingConverter; import org.springframework.data.domain.Page; @@ -46,7 +46,6 @@ import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.data.querydsl.SimpleEntityPathResolver; import org.springframework.data.repository.core.EntityInformation; import org.springframework.data.repository.query.FluentQuery; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; import com.querydsl.collections.AbstractCollQuery; @@ -281,7 +280,7 @@ public class QuerydslKeyValuePredicateExecutor implements ListQuerydslPredica } @Override - public R oneValue() { + public @Nullable R oneValue() { List results = createQuery().limit(2).fetch(); @@ -299,7 +298,7 @@ public class QuerydslKeyValuePredicateExecutor implements ListQuerydslPredica } @Override - public R firstValue() { + public @Nullable R firstValue() { List results = createQuery().limit(1).fetch(); diff --git a/src/main/java/org/springframework/data/keyvalue/repository/support/package-info.java b/src/main/java/org/springframework/data/keyvalue/repository/support/package-info.java index fd58c5a..0f67f8e 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/support/package-info.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/support/package-info.java @@ -1,6 +1,5 @@ /** * Support infrastructure for query derivation of key/value specific repositories. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.keyvalue.repository.support; diff --git a/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java b/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java index ebe39ef..3018c10 100644 --- a/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java +++ b/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java @@ -21,6 +21,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; +import org.jspecify.annotations.Nullable; import org.springframework.core.CollectionFactory; import org.springframework.data.keyvalue.core.AbstractKeyValueAdapter; import org.springframework.data.keyvalue.core.ForwardingCloseableIterator; @@ -131,7 +132,7 @@ public class MapKeyValueAdapter extends AbstractKeyValueAdapter { * @param engine the query engine. */ @SuppressWarnings("rawtypes") - private MapKeyValueAdapter(Map> store, Class keySpaceMapType, QueryEngine engine) { + private MapKeyValueAdapter(Map> store, Class keySpaceMapType, @Nullable QueryEngine engine) { super(engine); @@ -143,7 +144,7 @@ public class MapKeyValueAdapter extends AbstractKeyValueAdapter { } @Override - public Object put(Object id, Object item, String keyspace) { + public @Nullable Object put(Object id, Object item, String keyspace) { Assert.notNull(id, "Cannot add item with null id"); Assert.notNull(keyspace, "Cannot add item for null collection"); @@ -162,21 +163,21 @@ public class MapKeyValueAdapter extends AbstractKeyValueAdapter { } @Override - public Object get(Object id, String keyspace) { + public @Nullable Object get(Object id, String keyspace) { Assert.notNull(id, "Cannot get item with null id"); return getKeySpaceMap(keyspace).get(id); } @Override - public Object delete(Object id, String keyspace) { + public @Nullable Object delete(Object id, String keyspace) { Assert.notNull(id, "Cannot delete item with null id"); return getKeySpaceMap(keyspace).remove(id); } @Override - public Collection getAllOf(String keyspace) { + public Collection getAllOf(String keyspace) { return getKeySpaceMap(keyspace).values(); } diff --git a/src/main/java/org/springframework/data/map/package-info.java b/src/main/java/org/springframework/data/map/package-info.java index d184db6..09ccd20 100644 --- a/src/main/java/org/springframework/data/map/package-info.java +++ b/src/main/java/org/springframework/data/map/package-info.java @@ -1,6 +1,5 @@ /** * Repository implementation backed by generic {@link java.util.Map} instances. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.map; diff --git a/src/main/java/org/springframework/data/map/repository/config/MapRepositoryConfigurationExtension.java b/src/main/java/org/springframework/data/map/repository/config/MapRepositoryConfigurationExtension.java index e0632a4..411f22e 100644 --- a/src/main/java/org/springframework/data/map/repository/config/MapRepositoryConfigurationExtension.java +++ b/src/main/java/org/springframework/data/map/repository/config/MapRepositoryConfigurationExtension.java @@ -18,6 +18,7 @@ package org.springframework.data.map.repository.config; import java.lang.reflect.Constructor; import java.util.Map; +import org.jspecify.annotations.Nullable; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; @@ -32,7 +33,6 @@ import org.springframework.data.keyvalue.repository.config.KeyValueRepositoryCon import org.springframework.data.map.MapKeyValueAdapter; import org.springframework.data.repository.config.RepositoryConfigurationExtension; import org.springframework.data.repository.config.RepositoryConfigurationSource; -import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; /** @@ -83,14 +83,13 @@ public class MapRepositoryConfigurationExtension extends KeyValueRepositoryConfi return ParsingUtils.getSourceBeanDefinition(builder, configurationSource.getSource()); } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({ "unchecked", "rawtypes", "NullAway" }) private static Class getMapTypeToUse(RepositoryConfigurationSource source) { return (Class) getAnnotationAttributes(source).get("mapType"); } - @Nullable - private static SortAccessor getSortAccessor(RepositoryConfigurationSource source) { + private static @Nullable SortAccessor getSortAccessor(RepositoryConfigurationSource source) { Class> sortAccessorType = (Class>) getAnnotationAttributes( source).get("sortAccessor"); @@ -102,8 +101,7 @@ public class MapRepositoryConfigurationExtension extends KeyValueRepositoryConfi return null; } - @Nullable - private static QueryEngine getQueryEngine(@Nullable SortAccessor sortAccessor, + private static @Nullable QueryEngine getQueryEngine(@Nullable SortAccessor sortAccessor, RepositoryConfigurationSource source) { Class queryEngineFactoryType = (Class) getAnnotationAttributes( diff --git a/src/main/java/org/springframework/data/map/repository/config/package-info.java b/src/main/java/org/springframework/data/map/repository/config/package-info.java index 346ace9..6b7b28e 100644 --- a/src/main/java/org/springframework/data/map/repository/config/package-info.java +++ b/src/main/java/org/springframework/data/map/repository/config/package-info.java @@ -1,6 +1,5 @@ /** * Support infrastructure for the configuration of {@link java.util.Map} repositories. */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields +@org.jspecify.annotations.NullMarked package org.springframework.data.map.repository.config; diff --git a/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateTests.java b/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateTests.java index 4967357..b794840 100644 --- a/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateTests.java +++ b/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateTests.java @@ -197,7 +197,7 @@ class KeyValueTemplateTests { @Test // DATACMNS-525 void deleteThrowsExceptionWhenIdCannotBeExctracted() { - assertThatIllegalArgumentException().isThrownBy(() -> operations.delete(FOO_ONE)); + assertThatIllegalStateException().isThrownBy(() -> operations.delete(FOO_ONE)); } @Test // DATACMNS-525 diff --git a/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java b/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java index 6953e95..22774b0 100644 --- a/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java +++ b/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java @@ -140,7 +140,7 @@ class KeyValueTemplateUnitTests { @Test // DATACMNS-525 void insertShouldThrowErrorWhenIdCannotBeResolved() { - assertThatIllegalArgumentException().isThrownBy(() -> template.insert(FOO_ONE)); + assertThatIllegalStateException().isThrownBy(() -> template.insert(FOO_ONE)); } @Test // DATACMNS-525 @@ -281,7 +281,7 @@ class KeyValueTemplateUnitTests { @Test // DATACMNS-525 void deleteThrowsExceptionWhenIdCannotBeExctracted() { - assertThatIllegalArgumentException().isThrownBy(() -> template.delete(FOO_ONE)); + assertThatIllegalStateException().isThrownBy(() -> template.delete(FOO_ONE)); } @Test // DATACMNS-525