Skip to content

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

Closed
@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

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions