Skip to content

Commit 27e2d9b

Browse files
christophstroblmp911de
authored andcommitted
Migrate to JSpecify annotations for nullability constraints.
Closes #618 Original pull request: #625
1 parent 1f07322 commit 27e2d9b

File tree

53 files changed

+142
-153
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+142
-153
lines changed

pom.xml

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
<version>${querydsl}</version>
4646
<optional>true</optional>
4747
</dependency>
48-
4948
</dependencies>
5049

5150
<build>
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/**
22
* Key-Value annotations for declarative keyspace configuration.
33
*/
4-
@org.springframework.lang.NonNullApi
5-
@org.springframework.lang.NonNullFields
4+
@org.jspecify.annotations.NullMarked
65
package org.springframework.data.keyvalue.annotation;

src/main/java/org/springframework/data/keyvalue/aot/KeyValueRuntimeHints.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818
import java.util.Arrays;
1919
import java.util.List;
2020

21+
import org.jspecify.annotations.Nullable;
2122
import org.springframework.aot.hint.ExecutableMode;
2223
import org.springframework.aot.hint.MemberCategory;
2324
import org.springframework.aot.hint.RuntimeHints;
2425
import org.springframework.aot.hint.RuntimeHintsRegistrar;
2526
import org.springframework.aot.hint.TypeReference;
2627
import org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery;
27-
import org.springframework.lang.Nullable;
2828

2929
/**
3030
* {@link RuntimeHintsRegistrar} for KeyValue.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/**
2+
* Support classes for key-value ahead of time computation
3+
*/
4+
@org.jspecify.annotations.NullMarked
5+
package org.springframework.data.keyvalue.aot;

src/main/java/org/springframework/data/keyvalue/core/AbstractKeyValueAdapter.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
import java.util.Collection;
1919
import java.util.Comparator;
2020

21+
import org.jspecify.annotations.Nullable;
2122
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
22-
import org.springframework.lang.Nullable;
2323

2424
/**
2525
* Base implementation of {@link KeyValueAdapter} holds {@link QueryEngine} to delegate {@literal find} and
@@ -69,15 +69,13 @@ protected AbstractKeyValueAdapter(@Nullable QueryEngine<? extends KeyValueAdapte
6969
return engine;
7070
}
7171

72-
@Nullable
7372
@Override
74-
public <T> T get(Object id, String keyspace, Class<T> type) {
73+
public <T> @Nullable T get(Object id, String keyspace, Class<T> type) {
7574
return type.cast(get(id, keyspace));
7675
}
7776

78-
@Nullable
7977
@Override
80-
public <T> T delete(Object id, String keyspace, Class<T> type) {
78+
public <T> @Nullable T delete(Object id, String keyspace, Class<T> type) {
8179
return type.cast(delete(id, keyspace));
8280
}
8381

src/main/java/org/springframework/data/keyvalue/core/CriteriaAccessor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
*/
1616
package org.springframework.data.keyvalue.core;
1717

18+
import org.jspecify.annotations.Nullable;
1819
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
19-
import org.springframework.lang.Nullable;
2020

2121
/**
2222
* Resolves the criteria object from given {@link KeyValueQuery}.

src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717

1818
import java.util.Iterator;
1919

20+
import org.jspecify.annotations.Nullable;
2021
import org.springframework.data.util.CloseableIterator;
21-
import org.springframework.lang.Nullable;
2222
import org.springframework.util.Assert;
2323

2424
/**

src/main/java/org/springframework/data/keyvalue/core/GeneratingIdAccessor.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.keyvalue.core;
1717

18+
import org.jspecify.annotations.Nullable;
1819
import org.springframework.data.mapping.IdentifierAccessor;
1920
import org.springframework.data.mapping.PersistentProperty;
2021
import org.springframework.data.mapping.PersistentPropertyAccessor;
@@ -55,7 +56,7 @@ class GeneratingIdAccessor implements IdentifierAccessor {
5556
}
5657

5758
@Override
58-
public Object getIdentifier() {
59+
public @Nullable Object getIdentifier() {
5960
return accessor.getProperty(identifierProperty);
6061
}
6162

src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java

+6-8
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
import java.util.Collection;
1919
import java.util.Map;
2020

21+
import org.jspecify.annotations.Nullable;
2122
import org.springframework.beans.factory.DisposableBean;
2223
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
2324
import org.springframework.data.util.CloseableIterator;
24-
import org.springframework.lang.Nullable;
2525

2626
/**
2727
* {@link KeyValueAdapter} unifies access and shields the underlying key/value specific implementation.
@@ -39,7 +39,7 @@ public interface KeyValueAdapter extends DisposableBean {
3939
* @param keyspace must not be {@literal null}.
4040
* @return the item previously associated with the id.
4141
*/
42-
Object put(Object id, Object item, String keyspace);
42+
@Nullable Object put(Object id, Object item, String keyspace);
4343

4444
/**
4545
* Check if a object with given id exists in keyspace.
@@ -69,8 +69,7 @@ public interface KeyValueAdapter extends DisposableBean {
6969
* @return {@literal null} in case no matching item exists.
7070
* @since 1.1
7171
*/
72-
@Nullable
73-
<T> T get(Object id, String keyspace, Class<T> type);
72+
<T> @Nullable T get(Object id, String keyspace, Class<T> type);
7473

7574
/**
7675
* Delete and return the object with given type and id.
@@ -91,16 +90,15 @@ public interface KeyValueAdapter extends DisposableBean {
9190
* @return {@literal null} if object could not be found
9291
* @since 1.1
9392
*/
94-
@Nullable
95-
<T> T delete(Object id, String keyspace, Class<T> type);
93+
<T> @Nullable T delete(Object id, String keyspace, Class<T> type);
9694

9795
/**
9896
* Get all elements for given keyspace.
9997
*
10098
* @param keyspace must not be {@literal null}.
10199
* @return empty {@link Collection} if nothing found.
102100
*/
103-
Iterable<?> getAllOf(String keyspace);
101+
Iterable<Object> getAllOf(String keyspace);
104102

105103
/**
106104
* Get all elements for given keyspace.
@@ -132,7 +130,7 @@ default <T> Iterable<T> getAllOf(String keyspace, Class<T> type) {
132130
* @since 2.5
133131
*/
134132
@SuppressWarnings("unchecked")
135-
default <T> CloseableIterator<Map.Entry<Object, T>> entries(String keyspace, Class<T> type) {
133+
default <T> CloseableIterator<Map.Entry<Object,T>> entries(String keyspace, Class<T> type) {
136134
return (CloseableIterator) entries(keyspace);
137135
}
138136

src/main/java/org/springframework/data/keyvalue/core/KeyValueCallback.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package org.springframework.data.keyvalue.core;
1717

18-
import org.springframework.lang.Nullable;
18+
import org.jspecify.annotations.Nullable;
1919

2020
/**
2121
* Generic callback interface for code that operates on a {@link KeyValueAdapter}. This is particularly useful for

src/main/java/org/springframework/data/keyvalue/core/KeyValueOperations.java

+5-7
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717

1818
import java.util.Optional;
1919

20+
import org.jspecify.annotations.Nullable;
2021
import org.springframework.beans.factory.DisposableBean;
2122
import org.springframework.data.domain.Sort;
2223
import org.springframework.data.keyvalue.annotation.KeySpace;
2324
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
2425
import org.springframework.data.mapping.context.MappingContext;
25-
import org.springframework.lang.Nullable;
2626

2727
/**
2828
* Interface that specifies a basic set of key/value operations. Implemented by {@link KeyValueTemplate}.
@@ -84,8 +84,8 @@ public interface KeyValueOperations extends DisposableBean {
8484
* @param action must not be {@literal null}.
8585
* @return
8686
*/
87-
@Nullable
88-
<T> T execute(KeyValueCallback<T> action);
87+
88+
<T> @Nullable T execute(KeyValueCallback<T> action);
8989

9090
/**
9191
* Get all elements matching the given query. <br />
@@ -145,8 +145,7 @@ public interface KeyValueOperations extends DisposableBean {
145145
* @param objectToDelete must not be {@literal null}.
146146
* @return
147147
*/
148-
@Nullable
149-
<T> T delete(T objectToDelete);
148+
<T> @Nullable T delete(T objectToDelete);
150149

151150
/**
152151
* Delete item of type with given id.
@@ -155,8 +154,7 @@ public interface KeyValueOperations extends DisposableBean {
155154
* @param type must not be {@literal null}.
156155
* @return the deleted item or {@literal null} if no match found.
157156
*/
158-
@Nullable
159-
<T> T delete(Object id, Class<T> type);
157+
<T> @Nullable T delete(Object id, Class<T> type);
160158

161159
/**
162160
* Total number of elements with given type available. Respects {@link KeySpace} if present and therefore counts all

src/main/java/org/springframework/data/keyvalue/core/KeyValuePersistenceExceptionTranslator.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717

1818
import java.util.NoSuchElementException;
1919

20+
import org.jspecify.annotations.Nullable;
2021
import org.springframework.dao.DataAccessException;
2122
import org.springframework.dao.DataRetrievalFailureException;
2223
import org.springframework.dao.support.PersistenceExceptionTranslator;
23-
import org.springframework.lang.Nullable;
2424
import org.springframework.util.Assert;
2525

2626
/**
@@ -32,9 +32,9 @@
3232
*/
3333
public class KeyValuePersistenceExceptionTranslator implements PersistenceExceptionTranslator {
3434

35-
@Nullable
3635
@Override
37-
public DataAccessException translateExceptionIfPossible(RuntimeException exception) {
36+
@SuppressWarnings("NullAway")
37+
public @Nullable DataAccessException translateExceptionIfPossible(RuntimeException exception) {
3838

3939
Assert.notNull(exception, "Exception must not be null");
4040

src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java

+16-12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Optional;
2222
import java.util.Set;
2323

24+
import org.jspecify.annotations.Nullable;
2425
import org.springframework.context.ApplicationEventPublisher;
2526
import org.springframework.context.ApplicationEventPublisherAware;
2627
import org.springframework.dao.DataAccessException;
@@ -34,7 +35,6 @@
3435
import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext;
3536
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
3637
import org.springframework.data.mapping.context.MappingContext;
37-
import org.springframework.lang.Nullable;
3838
import org.springframework.util.Assert;
3939
import org.springframework.util.ClassUtils;
4040
import org.springframework.util.CollectionUtils;
@@ -143,7 +143,7 @@ public <T> T insert(T objectToInsert) {
143143
KeyValuePersistentEntity<?, ?> entity = getKeyValuePersistentEntity(objectToInsert);
144144

145145
GeneratingIdAccessor generatingIdAccessor = new GeneratingIdAccessor(entity.getPropertyAccessor(objectToInsert),
146-
entity.getIdProperty(), identifierGenerator);
146+
entity.getRequiredIdProperty(), identifierGenerator);
147147
Object id = generatingIdAccessor.getOrGenerateIdentifier();
148148

149149
return insert(id, objectToInsert);
@@ -213,7 +213,8 @@ public <T> Iterable<T> findAll(Class<T> type) {
213213

214214
return executeRequired(adapter -> {
215215

216-
Iterable<?> values = adapter.getAllOf(resolveKeySpace(type), type);
216+
String keyspace = resolveKeySpace(type);
217+
Iterable<?> values = adapter.getAllOf(keyspace, type);
217218

218219
ArrayList<T> filtered = new ArrayList<>();
219220
for (Object candidate : values) {
@@ -258,7 +259,6 @@ public void delete(Class<?> type) {
258259
Assert.notNull(type, "Type to delete must not be null");
259260

260261
String keyspace = resolveKeySpace(type);
261-
262262
potentiallyPublishEvent(KeyValueEvent.beforeDropKeySpace(keyspace, type));
263263

264264
execute((KeyValueCallback<Void>) adapter -> {
@@ -272,16 +272,16 @@ public void delete(Class<?> type) {
272272

273273
@SuppressWarnings("unchecked")
274274
@Override
275-
public <T> T delete(T objectToDelete) {
275+
public <T> @Nullable T delete(T objectToDelete) {
276276

277277
Class<T> type = (Class<T>) ClassUtils.getUserClass(objectToDelete);
278278
KeyValuePersistentEntity<?, ?> entity = getKeyValuePersistentEntity(objectToDelete);
279279

280-
return delete(entity.getIdentifierAccessor(objectToDelete).getIdentifier(), type);
280+
return delete(entity.getIdentifierAccessor(objectToDelete).getRequiredIdentifier(), type);
281281
}
282282

283283
@Override
284-
public <T> T delete(Object id, Class<T> type) {
284+
public <T> @Nullable T delete(Object id, Class<T> type) {
285285

286286
Assert.notNull(id, "Id for object to be deleted must not be null");
287287
Assert.notNull(type, "Type to delete must not be null");
@@ -301,12 +301,12 @@ public <T> T delete(Object id, Class<T> type) {
301301
public long count(Class<?> type) {
302302

303303
Assert.notNull(type, "Type for count must not be null");
304-
return adapter.count(resolveKeySpace(type));
304+
String keyspace = resolveKeySpace(type);
305+
return adapter.count(keyspace);
305306
}
306307

307-
@Nullable
308308
@Override
309-
public <T> T execute(KeyValueCallback<T> action) {
309+
public <T> @Nullable T execute(KeyValueCallback<T> action) {
310310

311311
Assert.notNull(action, "KeyValueCallback must not be null");
312312

@@ -401,8 +401,12 @@ public void destroy() throws Exception {
401401
return this.mappingContext.getRequiredPersistentEntity(ClassUtils.getUserClass(objectToInsert));
402402
}
403403

404-
private String resolveKeySpace(Class<?> type) {
405-
return this.mappingContext.getRequiredPersistentEntity(type).getKeySpace();
404+
405+
private String resolveKeySpace(Class<?> type) {
406+
407+
String keyspace = this.mappingContext.getRequiredPersistentEntity(type).getKeySpace();
408+
Assert.notNull(keyspace, "Keyspace must not be null");
409+
return keyspace;
406410
}
407411

408412
private RuntimeException resolveExceptionIfPossible(RuntimeException e) {

src/main/java/org/springframework/data/keyvalue/core/PathSortAccessor.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,20 @@
1818
import java.util.Comparator;
1919
import java.util.Optional;
2020

21+
import org.jspecify.annotations.Nullable;
2122
import org.springframework.data.domain.Sort.Direction;
2223
import org.springframework.data.domain.Sort.NullHandling;
2324
import org.springframework.data.domain.Sort.Order;
2425
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
25-
import org.springframework.lang.Nullable;
2626

2727
/**
2828
* @author Christoph Strobl
2929
* @since 3.1.10
3030
*/
3131
public class PathSortAccessor implements SortAccessor<Comparator<?>> {
3232

33-
@Nullable
3433
@Override
35-
public Comparator<?> resolve(KeyValueQuery<?> query) {
34+
public @Nullable Comparator<?> resolve(KeyValueQuery<?> query) {
3635

3736
if (query.getSort().isUnsorted()) {
3837
return null;

src/main/java/org/springframework/data/keyvalue/core/PredicateQueryEngine.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
import java.util.stream.Collectors;
2323
import java.util.stream.Stream;
2424

25+
import org.jspecify.annotations.Nullable;
2526
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
26-
import org.springframework.lang.Nullable;
2727

2828
/**
2929
* {@link QueryEngine} implementation specific for executing {@link Predicate} based {@link KeyValueQuery} against
@@ -46,9 +46,9 @@ public PredicateQueryEngine() {
4646
*/
4747
public PredicateQueryEngine(SortAccessor<Comparator<?>> sortAccessor) {
4848
super(new CriteriaAccessor<>() {
49-
@Nullable
49+
5050
@Override
51-
public Predicate<?> resolve(KeyValueQuery<?> query) {
51+
public @Nullable Predicate<?> resolve(KeyValueQuery<?> query) {
5252
return (Predicate<?>) query.getCriteria();
5353
}
5454
}, sortAccessor);
@@ -78,12 +78,12 @@ private List<?> sortAndFilterMatchingRange(Iterable<?> source, @Nullable Predica
7878
return filterMatchingRange(tmp, criteria, offset, rows);
7979
}
8080

81-
private static <S> List<S> filterMatchingRange(List<S> source, @Nullable Predicate criteria, long offset, int rows) {
81+
private static <S> List<S> filterMatchingRange(List<S> source, @Nullable Predicate<?> criteria, long offset, int rows) {
8282

8383
Stream<S> stream = source.stream();
8484

8585
if (criteria != null) {
86-
stream = stream.filter(criteria);
86+
stream = stream.filter((Predicate<? super S>) criteria);
8787
}
8888
if (offset > 0) {
8989
stream = stream.skip(offset);

0 commit comments

Comments
 (0)