ClassNotFoundException while JedisClient initialization in Spring Boot 2.5.4 application
Asked Answered
G

4

13

I have a Spring Boot 2.5.4 application in which I would like to add Redis and access it via Spring Data Redis. My current configuration looks like this:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.4</version>
    <relativePath/>
  </parent>
  <groupId>com.application</groupId>
  <artifactId>ApiGateway</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>ApiGateway</name>
  <description>ApiGateway</description>
  <properties>
    <java.version>15</java.version>
    <spring-boot-starter-redis.version>2.5.0</spring-boot-starter-redis.version>
    <redis.version>3.1.0</redis.version>
  </properties>
  <dependencies>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
      <version>${spring-boot-starter-redis.version}</version>
    </dependency>

    <!-- OTHER DEPENDENCIES -->
    
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>${redis.version}</version>
      <type>jar</type>
    </dependency>

    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-java-sdk-cognitoidp</artifactId>
      <version>${aws.sdk.version}</version>
    </dependency>

    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-java-sdk</artifactId>
      <version>${aws.sdk.version}</version>
    </dependency>

    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-java-sdk-core</artifactId>
      <version>${aws.sdk.version}</version>
    </dependency>

    <!-- OTHER DEPENDENCIES -->

  </dependencies>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>${spring-cloud.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <excludes>
            <exclude>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
            </exclude>
          </excludes>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>

RedisConfiguration.java

@Configuration
@PropertySource("classpath:redis.properties")
public class RedisConfiguration {

  @Value("${redis.host}")
  private String host;

  @Value("${redis.port}")
  private int port;

  @Value("${redis.database}")
  private int database;

  @Value("${redis.password}")
  private String password;

  @Value("${redis.timeout}")
  private String timeout;

  @Bean
  public JedisConnectionFactory jedisConnectionFactory() {
    RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
    redisConfiguration.setHostName(host);
    redisConfiguration.setPort(port);
    redisConfiguration.setDatabase(database);
    redisConfiguration.setPassword(RedisPassword.of(password));

    JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder();
    jedisClientConfiguration.connectTimeout(Duration.ofMillis(Long.parseLong(timeout)));

    return new JedisConnectionFactory(redisConfiguration, jedisClientConfiguration.build());
  }

  @Bean
  public RedisTemplate<String, Object> redisTemplate() {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(jedisConnectionFactory());
    return template;
  }
}

for current configuration while application start I am receiving

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.core.RedisTemplate]: Factory method 'redisTemplate' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jedisConnectionFactory' defined in class path resource [com/application/apigateway/intrastructure/cache/RedisConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.jedis.JedisConnectionFactory]: Factory method 'jedisConnectionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: redis/clients/jedis/DefaultJedisClientConfig
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
    ... 33 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jedisConnectionFactory' defined in class path resource [com/application/apigateway/intrastructure/cache/RedisConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.jedis.JedisConnectionFactory]: Factory method 'jedisConnectionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: redis/clients/jedis/DefaultJedisClientConfig
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.resolveBeanReference(ConfigurationClassEnhancer.java:362)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:334)
    at com.application.apigateway.intrastructure.cache.RedisConfiguration$$EnhancerBySpringCGLIB$$63c8a244.jedisConnectionFactory(<generated>)
    at com.application.apigateway.intrastructure.cache.RedisConfiguration.redisTemplate(RedisConfiguration.java:51)
    at com.application.apigateway.intrastructure.cache.RedisConfiguration$$EnhancerBySpringCGLIB$$63c8a244.CGLIB$redisTemplate$0(<generated>)
    at com.application.apigateway.intrastructure.cache.RedisConfiguration$$EnhancerBySpringCGLIB$$63c8a244$$FastClassBySpringCGLIB$$c9ce6595.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
    at com.application.apigateway.intrastructure.cache.RedisConfiguration$$EnhancerBySpringCGLIB$$63c8a244.redisTemplate(<generated>)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 34 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.jedis.JedisConnectionFactory]: Factory method 'jedisConnectionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: redis/clients/jedis/DefaultJedisClientConfig
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
    ... 57 common frames omitted
Caused by: java.lang.NoClassDefFoundError: redis/clients/jedis/DefaultJedisClientConfig
    at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.<init>(JedisConnectionFactory.java:97)
    at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.<init>(JedisConnectionFactory.java:232)
    at com.application.apigateway.intrastructure.cache.RedisConfiguration.jedisConnectionFactory(RedisConfiguration.java:45)
    at com.application.apigateway.intrastructure.cache.RedisConfiguration$$EnhancerBySpringCGLIB$$63c8a244.CGLIB$jedisConnectionFactory$1(<generated>)
    at com.application.apigateway.intrastructure.cache.RedisConfiguration$$EnhancerBySpringCGLIB$$63c8a244$$FastClassBySpringCGLIB$$c9ce6595.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
    at com.application.apigateway.intrastructure.cache.RedisConfiguration$$EnhancerBySpringCGLIB$$63c8a244.jedisConnectionFactory(<generated>)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 58 common frames omitted
Caused by: java.lang.ClassNotFoundException: redis.clients.jedis.DefaultJedisClientConfig
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    ... 71 common frames omitted

So far I have tried manipulating the redis.clients and spring-boot-starter-data-redis versions by decreasing and increasing it but always problems with initialization occur. Every single tutorial which I found doesn't contain configuration for the new Spring Boot application version. I Will be grateful for suggestions on how to manipulate the pom.xml version of redis.clients and spring-boot-starter-data-redis to make the application starts again.

Gluey answered 8/9, 2021 at 20:9 Comment(0)
W
26

spring-boot-starter-data-redis already includes jedis as a dependency so you shouldn't add it to your pom.xml with a version that might not be compatible with your spring-boot-starter-data-redis.

In the case of spring-boot-starter-data-redis version 2.5.0, it includes jedis version 3.6.3 but you override this with version 3.1.0, which might not be compatible with spring-boot-starter-data-redis version 2.5.0.

Always check the dependencies already included in the Spring Boot Starters because incompatibilities are exactly what they try to avoid.

Having said all that, I am not completely sure that this will solve the issue, but it is a good place to start.


Update 26/01/2022

The spring-boot-starter-data-redis dependency pom.xml includes the following dependency:

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-redis</artifactId>
  <version>2.5.1</version>
  <scope>compile</scope>
</dependency>

This spring-data-redis dependency pom.xml already includes jedis version:

<properties>
  (...)
  <jedis>3.6.0</jedis>
  (...)
</properties>

And the dependency itself:

<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>${jedis}</version>
  <optional>true</optional>
</dependency>

This means that you should only add the dependency to your pom.xml but set no version so that the one set in spring-data-redis is used as follows:

<dependencies>
  (...)
  <!-- OTHER DEPENDENCIES -->
  
  <dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
  </dependency>
  
  (...)
  <!-- OTHER DEPENDENCIES -->
</dependencies>
Wreck answered 8/9, 2021 at 21:9 Comment(6)
Thanks @Joao Dias. redis.clients:jedis:3.6.3 is compatible with spring-boot-starter-data-redis:2.5.3Gremial
I can't find the jedis dependence under spring-boot-starter-data-redis, how did you find it ? the gradle command I use ./gradlew dependencies The dependence graph is [like this ](s3.bmp.ovh/imgs/2022/01/6e06a10ddae0f021.png)Gremial
Thank you. I found the source code of these version config. It's github.com/spring-projects/spring-boot/blob/v2.5.3/… in case someone want it.Gremial
Were you able to solve the issue?Dixiedixieland
Yes, it was solved, thank you Dias. I was trying to use jedis:4.0.1 with spring-boot-starter-data-redis:2.5.3, it failed.Gremial
Works for me without the <version> tag, thanks!Antalkali
C
4

Spent several hours, so posting for spring boot versions 2.7.3 to be helpful for others.

spring-boot-starter-data-redis uses lettuce by default instead of jedis client. You would have to exclude lettuce and include jedis instead.

implementation ('org.springframework.boot:spring-boot-starter-data-redis') {
        exclude group: 'io.lettuce.lettuce-core'
    }
    implementation 'com.github.houbb:redis-client-jedis:0.0.3'```
Chicoine answered 28/8, 2022 at 22:26 Comment(0)
T
1

For anyone facing the same issue in spring-boot 3.x+

The combination that worked for me is

// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis
    implementation 'org.springframework.boot:spring-boot-starter-data-redis:3.1.1'
    // https://mvnrepository.com/artifact/redis.clients/jedis
    implementation 'redis.clients:jedis:4.4.3'

Full build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.0'
    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-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    annotationProcessor 'org.projectlombok:lombok'
    // https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui
    implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
    // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis
    implementation 'org.springframework.boot:spring-boot-starter-data-redis:3.1.1'
    // https://mvnrepository.com/artifact/redis.clients/jedis
    implementation 'redis.clients:jedis:4.4.3'
}

tasks.named('test') {
    useJUnitPlatform()
}
Triclinic answered 4/7, 2023 at 5:45 Comment(0)
H
0

I had a similar issue(not exactly same) with spring boot 2.7.12
I dont't have enough time to elaborate the error perfectly. I got an error message
'java.lang.NoClassDefFoundError: redis/clients/jedis/JedisClientConfig'

Reason for this error "by default Redis is using lettuce". If we want to switch to jedis, we can do small trick explicitly add jedis dependency

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

By default i had spring-boot-starter-data-redis without version after adding above dependency my pom was

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
Heyde answered 15/6, 2023 at 7:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.