Skip to content

Migrate to JSpecify annotations for nullability constraints. #625

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .mvn/jvm.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
3 changes: 1 addition & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-keyvalue</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.x-GH-618-SNAPSHOT</version>

<name>Spring Data KeyValue</name>

Expand Down Expand Up @@ -45,7 +45,6 @@
<version>${querydsl}</version>
<optional>true</optional>
</dependency>

</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
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.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* Support classes for key-value ahead of time computation
*/
@org.jspecify.annotations.NullMarked
package org.springframework.data.keyvalue.aot;
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
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
Expand Down Expand Up @@ -69,15 +69,13 @@ protected AbstractKeyValueAdapter(@Nullable QueryEngine<? extends KeyValueAdapte
return engine;
}

@Nullable
@Override
public <T> T get(Object id, String keyspace, Class<T> type) {
public <T> @Nullable T get(Object id, String keyspace, Class<T> type) {
return type.cast(get(id, keyspace));
}

@Nullable
@Override
public <T> T delete(Object id, String keyspace, Class<T> type) {
public <T> @Nullable T delete(Object id, String keyspace, Class<T> type) {
return type.cast(delete(id, keyspace));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

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;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -55,7 +56,7 @@ class GeneratingIdAccessor implements IdentifierAccessor {
}

@Override
public Object getIdentifier() {
public @Nullable Object getIdentifier() {
return accessor.getProperty(identifierProperty);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import java.util.Collections;
import java.util.List;

import org.jspecify.annotations.Nullable;
import org.springframework.lang.Contract;

/**
* Converter capable of transforming a given {@link Iterable} into a collection type.
*
Expand All @@ -36,7 +39,12 @@ private IterableConverter() {}
* @param source
* @return {@link Collections#emptyList()} when source is {@literal null}.
*/
public static <T> List<T> toList(Iterable<T> source) {
@Contract("_ -> !null")
public static <T> List<T> toList(@Nullable Iterable<T> source) {

if(source == null) {
return Collections.emptyList();
}

if (source instanceof List) {
return (List<T>) source;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
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.
Expand All @@ -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.
Expand Down Expand Up @@ -69,8 +69,7 @@ public interface KeyValueAdapter extends DisposableBean {
* @return {@literal null} in case no matching item exists.
* @since 1.1
*/
@Nullable
<T> T get(Object id, String keyspace, Class<T> type);
<T> @Nullable T get(Object id, String keyspace, Class<T> type);

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

/**
* Get all elements for given keyspace.
*
* @param keyspace must not be {@literal null}.
* @return empty {@link Collection} if nothing found.
*/
Iterable<?> getAllOf(String keyspace);
Iterable<Object> getAllOf(String keyspace);

/**
* Get all elements for given keyspace.
Expand Down Expand Up @@ -132,7 +130,7 @@ default <T> Iterable<T> getAllOf(String keyspace, Class<T> type) {
* @since 2.5
*/
@SuppressWarnings("unchecked")
default <T> CloseableIterator<Map.Entry<Object, T>> entries(String keyspace, Class<T> type) {
default <T> CloseableIterator<Map.Entry<Object,T>> entries(String keyspace, Class<T> type) {
return (CloseableIterator) entries(keyspace);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@

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}.
Expand Down Expand Up @@ -84,8 +84,8 @@ public interface KeyValueOperations extends DisposableBean {
* @param action must not be {@literal null}.
* @return
*/
@Nullable
<T> T execute(KeyValueCallback<T> action);

<T> @Nullable T execute(KeyValueCallback<T> action);

/**
* Get all elements matching the given query. <br />
Expand Down Expand Up @@ -145,8 +145,7 @@ public interface KeyValueOperations extends DisposableBean {
* @param objectToDelete must not be {@literal null}.
* @return
*/
@Nullable
<T> T delete(T objectToDelete);
<T> @Nullable T delete(T objectToDelete);

/**
* Delete item of type with given id.
Expand All @@ -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> T delete(Object id, Class<T> type);
<T> @Nullable T delete(Object id, Class<T> type);

/**
* Total number of elements with given type available. Respects {@link KeySpace} if present and therefore counts all
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

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;

/**
Expand All @@ -32,9 +32,9 @@
*/
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");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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;
Expand All @@ -34,7 +35,6 @@
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;
Expand Down Expand Up @@ -143,7 +143,7 @@ public <T> T insert(T objectToInsert) {
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);
Expand Down Expand Up @@ -213,7 +213,8 @@ public <T> Iterable<T> findAll(Class<T> type) {

return executeRequired(adapter -> {

Iterable<?> values = adapter.getAllOf(resolveKeySpace(type), type);
String keyspace = resolveKeySpace(type);
Iterable<?> values = adapter.getAllOf(keyspace, type);

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

String keyspace = resolveKeySpace(type);

potentiallyPublishEvent(KeyValueEvent.beforeDropKeySpace(keyspace, type));

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

@SuppressWarnings("unchecked")
@Override
public <T> T delete(T objectToDelete) {
public <T> @Nullable T delete(T objectToDelete) {

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

return delete(entity.getIdentifierAccessor(objectToDelete).getIdentifier(), type);
return delete(entity.getIdentifierAccessor(objectToDelete).getRequiredIdentifier(), type);
}

@Override
public <T> T delete(Object id, Class<T> type) {
public <T> @Nullable T delete(Object id, Class<T> type) {

Assert.notNull(id, "Id for object to be deleted must not be null");
Assert.notNull(type, "Type to delete must not be null");
Expand All @@ -301,12 +301,12 @@ public <T> T delete(Object id, Class<T> type) {
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> T execute(KeyValueCallback<T> action) {
public <T> @Nullable T execute(KeyValueCallback<T> action) {

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

Expand Down Expand Up @@ -401,8 +401,12 @@ public void destroy() throws Exception {
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) {
Expand Down
Loading