Description
Problem Description
Hello Spring Data Redis team,
I am using Spring Data Redis in a Kotlin 1.9-based project and have run into an issue when overriding the delete()
method from RedisKeyValueAdapter
. While the abstract class that RedisKeyValueAdapter
implements (or extends) includes a @Nullable
annotation on this method, it appears that the actual implementation in RedisKeyValueAdapter
does not. As a result, Kotlin 1.9 does not recognize that the method can return null
, which leads to a compile-time error when trying to override it with a nullable return type.
Background
In the following excerpt from RedisKeyValueAdapter
, the delete()
method may return null, as shown in the example logic. However, there is no
@Nullable
annotation to indicate this possibility:
Because there is no @Nullable
annotation here, Kotlin sees T as non-null. However, the method may actually return null. When we attempt to override it in Kotlin, such as:
override fun <T> delete(id: Any, keyspace: String, type: Class<T>): T? {
// ...
}
Kotlin 1.9 raises an error along the lines of:
Return type of 'delete' is not a subtype of the return type
of the overridden member 'public open fun <T> delete(...) : T'
This stricter nullability check is documented in KT-36770, kotlin docs,where Kotlin 1.9 enforces a stronger rule about Java methods that appear to return non-null. Older Kotlin versions often allowed a nullable return type with just a warning, but 1.9 treats it as a compilation error.
Why @Nullable
?
- The code clearly can return null, so adding
@Nullable
directly on thedelete()
method in RedisKeyValueAdapter
would help Kotlin accurately recognize this possibility. - If
@Nullable
were present, Kotlin would interpret the method as returningT?
, preventing the error when overriding. - This aligns with the nullability information already present in the abstract class, which currently is not being picked up due to the missing annotation in the concrete implementation.
Example Change
If the delete() method were annotated like this:
@Override
@Nullable
public <T> T delete(Object id, String keyspace, Class<T> type) {
T value = get(id, keyspace, type);
// ...
return value;
}
Then Kotlin code such as:
override fun <T> delete(id: Any, keyspace: String, type: Class<T>): T? {
// ...
}
I understand there might be other recommended workarounds or best practices, so please feel free to correct me if I am misunderstanding anything. Any advice on handling this situation would be greatly appreciated. My goal is simply to ensure that Spring Data Redis integrates smoothly with Kotlin 1.9 and higher.
Thank you very much for taking the time to review this issue, and for all your hard work on the Spring Data projects.