-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
I’m sorry if this comes across as offensive, but I’m somewhat skeptical whether the official Spring Data Redis development team has ever actually used their own library in real-world projects.
If you had, you would have easily noticed that the usage of @Nullable
annotations across many Spring Data Redis APIs is deeply problematic.
Take, for example, the API org.springframework.data.redis.core.ValueOperations#increment(K)
. Its return value is annotated with @Nullable
.
However, in reality, this Redis command never returns null.
I understand that the official team might argue: “In Redis pipelining or transactions, this command returns null.”
But please think carefully:
First, any Redis command is used in one of two scenarios:
- Direct usage in Java code:
// code snippet 1
Long value = redisTemplate().opsForValue().increment("redisKey");
// value must be NOT null
- Usage within Redis pipelining or transactions:
// code snippet 2
redisTemplate.executePipelined(new SessionCallback<>() {
@Override
public List<Object> execute(RedisOperations operations) throws DataAccessException {
Long value = operations.opsForValue().increment("redisKey");
// value is always null
return null;
}
});
In 2nd scenario, every Redis command returns null.
So, who in the real world would actually capture the return value inside a pipeline or transaction and write code like this?
// code snippet 3
redisTemplate.executePipelined(new SessionCallback<>() {
@Override
public List<Object> execute(RedisOperations operations) throws DataAccessException {
Long value = operations.opsForValue().increment("redisKey"); // value always null
if (value == null) {
// do something when value is null
} else if (value > 100) {
// do something when value > 100
} else {
// do something when value <= 100
}
return null;
}
});
Since value
is always null
, the if-else
logic code above is meaningless in practice.
In real-world applications, no one captures and uses Redis command return values inside pipelines or transactions.
This is simply not a realistic business scenario.
In the real world, the vast majority of Redis commands are executed in first scenario.
Yet, because of the poorly applied @Nullable
annotations, every usage of Redis commands now forces developers to suppress or handle IDE null
warnings — adding unnecessary overhead — even though null
will never be returned.
It’s highly questionable to annotate all non-null APIs with @Nullable
just to accommodate an unrealistic edge case that shouldn’t exist in production.
Secondly, the official team might argue that adding @Nullable
helps remind developers to use Redis command return values correctly within pipelines or transactions.
Let’s analyze both possibilities:
- If a developer understands pipelining/transactions correctly, they won’t capture the return value at all — so whether
@Nullable
is present or not makes no difference. - If a developer is a beginner unfamiliar with pipelining/transactions, and mistakenly captures the return value inside a pipeline,
seeing the IDE null warning might lead them to instinctively write code like code snippet 3 — addingif (value == null) else ...
branches to silence the warning.
While this avoids runtime errors, it introduces serious logical bugs, because theelse if/else
branches will never execute.
In this case, If the API is not annotated with@Nullable
, developers won’t add null-checking code, and any incorrect usage will trigger anNullPointerException
directly at runtime — which, ironically, is the most effective way to expose the issue sooner.
Moreover, even according to your own reasoning — ValueOperations#increment(K)
requires the @Nullable
annotation, because it may return null
in pipelines or transaction, then why does NOT HashOperations#increment(H, HK, long)
receive the same annotation? Shouldn’t nearly all Redis commands be consistently annotated with @Nullable
?
Your usage of the @Nullable
annotation is confusing, logically inconsistent, and lacks rigor and scientific grounding — it fails to meet the objective demands of real-world scenarios.
To cope with this poor design, we developers are forced to pay an unnecessary additional cost.
Genuine suggestion: Please do not add @Nullable
annotations solely based on extreme edge cases — such as capturing return values inside pipelines or transactions — which hold no practical meaning in the real world.
If an API does not return null under normal (non-pipeline, non-transaction) usage, it should not be annotated with @Nullable
.