CaffeineCacheMetrics nullability is incompatible with Caffeine 3.2.3 (original) (raw)

Describe the bug
CaffeineCacheMetrics is incompatible with newer versions of Caffeine due to differences in nullability markings.

The migration to JSpecify saw CaffeineCacheMetrics marked as @NullMarked. This works fine in the repository, because Caffeine 2.9 is in use, which doesn't have JSpecify annotations. However, version 3.2.3 of Caffeine also uses JSpecify annotations. CaffeineCacheMetrics and Caffeine's Cache classes mark their generics differently, resulting in an incompatibility.

public class CaffeineCacheMetrics<K, V, C extends Cache<K, V>> extends CacheMeterBinder {

public interface Cache<K, V extends @Nullable Object> {

Note that Caffeine's Cache explicitly marks V as being nullable.

The impact of this is that application code using both libraries may have a valid Cache, that cannot be passed to CaffeineCacheMetrics because the V type is out of bounds.

Other versions of Caffeine are likely impacted in the same way, but 3.2.3 happens to be the most recent release and what I was using.

Environment

To Reproduce
How to reproduce the bug:
A short excerpt from my code where the bug was witnessed:

interface ResultsIngester

val resultsIngestersByTaskInstanceSplitId = Caffeine .from(CaffeineSpec.parse("maximumSize=1000, expireAfterAccess=PT10M")) .recordStats() .build<Int, ResultsIngester?>() val metrics = CaffeineCacheMetrics( resultsIngestersByTaskInstanceSplitId, "results-ingesters-by-task-instance-split", emptyList(), )

I'll provide a PR with the fix. If additional reproduces are requested after that, let me know.

Expected behavior
The nullability behavior should match