Skip to content

Use to JSpecify for nullness checks #3159

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 9 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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion 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-redis</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-GH-3290-SNAPSHOT</version>

<name>Spring Data Redis</name>
<description>Spring Data module for Redis</description>
Expand All @@ -28,6 +28,7 @@
<multithreadedtc>1.01</multithreadedtc>
<netty>4.1.121.Final</netty>
<java-module-name>spring.data.redis</java-module-name>
<junit5>5.12.2</junit5>
</properties>

<scm>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.io.Serial;

import org.jspecify.annotations.Nullable;
import org.springframework.dao.DataRetrievalFailureException;

/**
Expand All @@ -29,8 +30,7 @@
*/
public class ClusterRedirectException extends DataRetrievalFailureException {

@Serial
private static final long serialVersionUID = -857075813794333965L;
private static final @Serial long serialVersionUID = -857075813794333965L;

private final int slot;
private final String host;
Expand All @@ -44,7 +44,7 @@ public class ClusterRedirectException extends DataRetrievalFailureException {
* @param targetPort the port on the host.
* @param e the root cause from the data access API in use.
*/
public ClusterRedirectException(int slot, String targetHost, int targetPort, Throwable e) {
public ClusterRedirectException(int slot, String targetHost, int targetPort, @Nullable Throwable e) {

super("Redirect: slot %s to %s:%s.".formatted(slot, targetHost, targetPort), e);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.io.Serial;

import org.jspecify.annotations.Nullable;
import org.springframework.dao.DataAccessResourceFailureException;

/**
Expand All @@ -30,15 +31,14 @@
*/
public class ClusterStateFailureException extends DataAccessResourceFailureException {

@Serial
private static final long serialVersionUID = 333399051713240852L;
private static final @Serial long serialVersionUID = 333399051713240852L;

/**
* Creates new {@link ClusterStateFailureException}.
*
* @param msg the detail message.
*/
public ClusterStateFailureException(String msg) {
public ClusterStateFailureException(@Nullable String msg) {
super(msg);
}

Expand All @@ -48,7 +48,7 @@ public ClusterStateFailureException(String msg) {
* @param msg the detail message.
* @param cause the nested exception.
*/
public ClusterStateFailureException(String msg, Throwable cause) {
public ClusterStateFailureException(@Nullable String msg, @Nullable Throwable cause) {
super(msg, cause);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
*/
package org.springframework.data.redis;

import org.jspecify.annotations.Nullable;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;

/**
* Potentially translates an {@link Exception} into appropriate {@link DataAccessException}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
*/
package org.springframework.data.redis;

import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.converter.Converter;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;

/**
* {@link PassThroughExceptionTranslationStrategy} returns {@literal null} for unknown {@link Exception}s.
Expand All @@ -34,9 +34,8 @@ public PassThroughExceptionTranslationStrategy(Converter<Exception, DataAccessEx
this.converter = converter;
}

@Nullable
@Override
public DataAccessException translate(Exception e) {
public @Nullable DataAccessException translate(Exception e) {
return this.converter.convert(e);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.springframework.data.redis;

import org.jspecify.annotations.Nullable;
import org.springframework.dao.DataAccessResourceFailureException;

/**
Expand All @@ -27,15 +28,15 @@ public class RedisConnectionFailureException extends DataAccessResourceFailureEx
/**
* @param msg the detail message.
*/
public RedisConnectionFailureException(String msg) {
public RedisConnectionFailureException(@Nullable String msg) {
super(msg);
}

/**
* @param msg the detail message.
* @param cause the nested exception.
*/
public RedisConnectionFailureException(String msg, Throwable cause) {
public RedisConnectionFailureException(@Nullable String msg, @Nullable Throwable cause) {
super(msg, cause);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
*/
package org.springframework.data.redis;

import org.jspecify.annotations.Nullable;
import org.springframework.dao.UncategorizedDataAccessException;
import org.springframework.lang.Nullable;

/**
* Exception thrown when we can't classify a Redis exception into one of Spring generic data access exceptions.
Expand All @@ -29,7 +29,7 @@ public class RedisSystemException extends UncategorizedDataAccessException {
* @param msg the detail message.
* @param cause the root cause from the data access API in use.
*/
public RedisSystemException(String msg, @Nullable Throwable cause) {
public RedisSystemException(@Nullable String msg, @Nullable Throwable cause) {
super(msg, cause);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.io.Serial;

import org.jspecify.annotations.Nullable;
import org.springframework.dao.DataRetrievalFailureException;

/**
Expand All @@ -27,15 +28,14 @@
*/
public class TooManyClusterRedirectionsException extends DataRetrievalFailureException {

@Serial
private static final long serialVersionUID = -2818933672669154328L;
private static final @Serial long serialVersionUID = -2818933672669154328L;

/**
* Creates new {@link TooManyClusterRedirectionsException}.
*
* @param msg the detail message.
*/
public TooManyClusterRedirectionsException(String msg) {
public TooManyClusterRedirectionsException(@Nullable String msg) {
super(msg);
}

Expand All @@ -45,7 +45,7 @@ public TooManyClusterRedirectionsException(String msg) {
* @param msg the detail message.
* @param cause the root cause from the data access API in use.
*/
public TooManyClusterRedirectionsException(String msg, Throwable cause) {
public TooManyClusterRedirectionsException(@Nullable String msg, @Nullable Throwable cause) {
super(msg, cause);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.Arrays;
import java.util.function.Consumer;

import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
Expand Down Expand Up @@ -50,7 +51,6 @@
import org.springframework.data.redis.repository.query.RedisPartTreeQuery;
import org.springframework.data.redis.repository.query.RedisQueryCreator;
import org.springframework.data.redis.repository.support.RedisRepositoryFactoryBean;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;

/**
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/org/springframework/data/redis/aot/package-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* AOT Runtime hints.
*/
@org.jspecify.annotations.NullMarked
package org.springframework.data.redis.aot;
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Optional;

import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisKeyCommands;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -79,11 +80,13 @@ static class Keys implements BatchStrategy {
@Override
public long cleanCache(RedisConnection connection, String name, byte[] pattern) {

byte[][] keys = Optional.ofNullable(connection.keys(pattern)).orElse(Collections.emptySet())
RedisKeyCommands commands = connection.keyCommands();

byte[][] keys = Optional.ofNullable(commands.keys(pattern)).orElse(Collections.emptySet())
.toArray(new byte[0][]);

if (keys.length > 0) {
connection.del(keys);
commands.del(keys);
}

return keys.length;
Expand All @@ -104,7 +107,9 @@ static class Scan implements BatchStrategy {
@Override
public long cleanCache(RedisConnection connection, String name, byte[] pattern) {

Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().count(batchSize).match(pattern).build());
RedisKeyCommands commands = connection.keyCommands();

Cursor<byte[]> cursor = commands.scan(ScanOptions.scanOptions().count(batchSize).match(pattern).build());

long count = 0;

Expand All @@ -116,8 +121,8 @@ public long cleanCache(RedisConnection connection, String name, byte[] pattern)

count += keys.size();

if (keys.size() > 0) {
connection.del(keys.toArray(new byte[0][]));
if (!keys.isEmpty()) {
commands.del(keys.toArray(new byte[0][]));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.function.Function;
import java.util.function.Supplier;

import org.jspecify.annotations.Nullable;
import org.springframework.dao.PessimisticLockingFailureException;
import org.springframework.data.redis.connection.ReactiveRedisConnection;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
Expand All @@ -38,7 +39,6 @@
import org.springframework.data.redis.connection.RedisStringCommands.SetOption;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.data.redis.util.ByteUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
Expand Down Expand Up @@ -129,24 +129,24 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
}

@Override
public byte[] get(String name, byte[] key) {
public byte @Nullable [] get(String name, byte[] key) {
return get(name, key, null);
}

@Override
public byte[] get(String name, byte[] key, @Nullable Duration ttl) {
public byte @Nullable [] get(String name, byte[] key, @Nullable Duration ttl) {

Assert.notNull(name, "Name must not be null");
Assert.notNull(key, "Key must not be null");

return execute(name, connection -> doGet(connection, name, key, ttl));
}

@Nullable
private byte[] doGet(RedisConnection connection, String name, byte[] key, @Nullable Duration ttl) {
@SuppressWarnings("NullAway")
private byte @Nullable[] doGet(RedisConnection connection, String name, byte[] key, @Nullable Duration ttl) {

byte[] result = shouldExpireWithin(ttl) ? connection.stringCommands().getEx(key, Expiration.from(ttl))
: connection.stringCommands().get(key);
RedisStringCommands commands = connection.stringCommands();
byte[] result = shouldExpireWithin(ttl) ? commands.getEx(key, Expiration.from(ttl)) : commands.get(key);

statistics.incGets(name);

Expand Down Expand Up @@ -241,6 +241,7 @@ public void put(String name, byte[] key, byte[] value, @Nullable Duration ttl) {

}

@SuppressWarnings("NullAway")
private void doPut(RedisConnection connection, String name, byte[] key, byte[] value, @Nullable Duration ttl) {

if (shouldExpireWithin(ttl)) {
Expand All @@ -265,6 +266,7 @@ public CompletableFuture<Void> store(String name, byte[] key, byte[] value, @Nul
}

@Override
@SuppressWarnings("NullAway")
public byte[] putIfAbsent(String name, byte[] key, byte[] value, @Nullable Duration ttl) {

Assert.notNull(name, "Name must not be null");
Expand Down Expand Up @@ -538,6 +540,7 @@ public boolean isSupported() {
}

@Override
@SuppressWarnings("NullAway")
public CompletableFuture<byte[]> retrieve(String name, byte[] key, @Nullable Duration ttl) {

return doWithConnection(connection -> {
Expand Down Expand Up @@ -572,6 +575,7 @@ private Mono<Boolean> doStoreWithLocking(String name, byte[] key, byte[] value,
unused -> doUnlock(name, connection));
}

@SuppressWarnings("NullAway")
private Mono<Boolean> doStore(byte[] cacheKey, byte[] value, @Nullable Duration ttl,
ReactiveRedisConnection connection) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

import java.time.Duration;

import org.jspecify.annotations.Nullable;
import org.springframework.data.redis.cache.RedisCacheWriter.TtlFunction;
import org.springframework.lang.Nullable;

/**
* {@link TtlFunction} implementation returning the given, predetermined {@link Duration} used for per cache entry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import java.time.Instant;
import java.util.concurrent.TimeUnit;

import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ObjectUtils;

/**
Expand Down
Loading