Skip to content

Binary-incompatible removal of SetParams.ex(long) override in Jedis 6.x causes NoSuchMethodError #3144

@maarten-blokker

Description

@maarten-blokker

After upgrading to Jedis 6.0.0 while using Spring Data Redis 3.4.5, any call to StringRedisTemplate.opsForValue().set(...) (or equivalent) fails with:

java.lang.NoSuchMethodError: 'redis.clients.jedis.params.SetParams redis.clients.jedis.params.SetParams.ex(long)'
  at org.springframework.data.redis.connection.jedis.JedisConverters.toSetCommandExPxArgument(JedisConverters.java:382)
  at org.springframework.data.redis.connection.jedis.JedisStringCommands.set(JedisStringCommands.java:112)
  at org.springframework.data.redis.connection.DefaultedRedisConnection.set(DefaultedRedisConnection.java:326)
  at org.springframework.data.redis.core.DefaultValueOperations.lambda$set$15(DefaultValueOperations.java:208)
  at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:411)
  at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:378)
  at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:117)
  at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:208)
  at org.springframework.data.redis.core.ValueOperations.set(ValueOperations.java:75)

Spring Data Redis was compiled against a version of Jedis where SetParams declared its own public SetParams.ex(long) override. In Jedis PR #4095, that override was removed (inheriting the method from a now-package-private superclass), breaking binary compatibility.

Reproducability

Use spring-data-redis 3.4.5 in combination with Jedis 6.0.0

// build.gradle
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.2'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'
    implementation 'org.springframework.data:spring-data-redis:3.4.5'
    implementation 'redis.clients:jedis:6.0.0'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
//src/test/java/com/example/RedisReproducerTest.java
package com.example;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.time.Duration;

@SpringBootTest
class RedisReproducerTest {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Test
    void testSetWithExpiry() {
        // This triggers the NoSuchMethodError at runtime
        redisTemplate.opsForValue().set("test:key", "value", Duration.ofSeconds(10));
    }
}

Expected behaviour

JedisConverters.toSetCommandExPxArgument should be able to call SetParams.ex(long).

Either:

  • Jedis 6.x re-introduces the public override SetParams.ex(long) in SetParams (i can create an issue there as well)
  • Spring-data-redis updates its converter to call the inherited method reflectively or adapt to the new class hierarchy. (unlikely a good idea)
  • Documentation is updated to note that Jedis 6.x is currently not binary-compatible and pinning to 5.x is required until spring-data-redis is compiled against the new Jedis version. (most pragmatic solution)

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions