Skip to content

Eager initialization of LettuceConnectionFactory configured for Redis Cluster causes ClassCastException #2186

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sangeethaPrem opened this issue Oct 27, 2021 · 6 comments
Assignees
Labels
type: bug A general bug

Comments

@sangeethaPrem
Copy link

Hi,

 

When I try to call the initConnection() on my clustered redis, i get the error java.lang.ClassCastException: io.lettuce.core.cluster.StatefulRedisClusterConnectionImpl cannot be cast to io.lettuce.core.api.StatefulRedisConnection

                at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:975)

 

looking at the code it seems like the class cast is only for the StatefulRedisConnection, where as the validateConnection() supports both StatefulRedisConnection and StatefulRedisClusterConnection.

 

any one faced this before? on how to achieve this?
We are doing lazy initialisation to the redis cluster.
Please help.
 

Thanks.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 27, 2021
@mp911de
Copy link
Member

mp911de commented Nov 8, 2021

If you would like us to spend some time helping you to diagnose the problem, please spend some time describing it and, ideally, providing a minimal sample that reproduces the problem.

@mp911de mp911de added the status: waiting-for-feedback We need additional information before we can continue label Nov 8, 2021
@aronica
Copy link

aronica commented Nov 11, 2021

@mp911de
I encounter this issue here, you only need to enable eagerInitialization while configure Bean LettuceConnectionFactory with Redis cluster mode,
I made a sample project here. https://github.com/aronica/demo.
The stacktrace of my application is like below,

        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.12.jar!/:5.3.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.12.jar!/:5.3.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.12.jar!/:5.3.12]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.12.jar!/:5.3.12]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.12.jar!/:5.3.12]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.12.jar!/:5.3.12]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.12.jar!/:5.3.12]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.12.jar!/:5.3.12]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.12.jar!/:5.3.12]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.12.jar!/:5.3.12]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.6.jar!/:2.5.6]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) [spring-boot-2.5.6.jar!/:2.5.6]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) [spring-boot-2.5.6.jar!/:2.5.6]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) [spring-boot-2.5.6.jar!/:2.5.6]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) [spring-boot-2.5.6.jar!/:2.5.6]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) [spring-boot-2.5.6.jar!/:2.5.6]
        at com.example.demo.DemoApplication.main(DemoApplication.java:10) [classes!/:0.0.1-SNAPSHOT]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_292]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_292]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_292]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_292]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) [demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) [demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) [demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88) [demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: java.lang.ClassCastException: io.lettuce.core.cluster.StatefulRedisClusterConnectionImpl cannot be cast to io.lettuce.core.api.StatefulRedisConnection
        at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:1089) ~[spring-data-redis-2.5.6.jar!/:2.5.6]
        at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.initConnection(LettuceConnectionFactory.java:543) ~[spring-data-redis-2.5.6.jar!/:2.5.6]
        at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.afterPropertiesSet(LettuceConnectionFactory.java:355) ~[spring-data-redis-2.5.6.jar!/:2.5.6]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.12.jar!/:5.3.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.12.jar!/:5.3.12]
        ... 24 common frames omitted

The line throws exception is as below:

         @Nullable
	protected StatefulRedisConnection<byte[], byte[]> getSharedConnection() {
		return shareNativeConnection ? (StatefulRedisConnection) getOrCreateSharedConnection().getConnection() : null;
	}

when we are in cluster mode, getOrCreateSharedConnection().getConnection() will return io.lettuce.core.cluster.StatefulRedisClusterConnectionImpl instead of instance of io.lettuce.core.api.StatefulRedisConnection

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 11, 2021
@mp911de
Copy link
Member

mp911de commented Nov 11, 2021

That is expected. When configuring to run with Redis Cluster, you will receive a StatefulRedisClusterConnection object (instead of StatefulRedisConnection) because Redis Cluster works differently from standalone Redis.

@mp911de mp911de closed this as completed Nov 11, 2021
@mp911de mp911de added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels Nov 11, 2021
@aronica
Copy link

aronica commented Nov 11, 2021

That is expected. When configuring to run with Redis Cluster, you will receive a StatefulRedisClusterConnection object (instead of StatefulRedisConnection) because Redis Cluster works differently from standalone Redis.

So we could not use eagerInitialization with redis cluster mode? but we don't have a cluster mode LettuceConnectionFactory

@aronica
Copy link

aronica commented Nov 12, 2021

That is expected. When configuring to run with Redis Cluster, you will receive a StatefulRedisClusterConnection object (instead of StatefulRedisConnection) because Redis Cluster works differently from standalone Redis.

@mp911de please take a review again, I do not quite understand the reason on it, the workflow is when I enabled eagerInitialization in LettuceConnectionFactory, the call stack is (all code is in LettuceConnectionFactory.java)

afterPropertiesSet()->initConnection()->getSharedConnection()->getOrCreateSharedConnection().getConnection() 

as you said, getSharedConnection() always tried to cast StatefulRedisClusterConnection to StatefulRedisConnection when we are in redis cluster mode, if you think that's expected, then we should clarify it that eagerInitialization only works with none redis cluster mode in javadoc.

@mp911de mp911de removed the status: invalid An issue that we don't feel is valid label Nov 12, 2021
@mp911de
Copy link
Member

mp911de commented Nov 12, 2021

Thanks for elaborating more. Initially, the ticket description was confusing so the fact that Spring Data Redis has a bug went unnoticed. I can confirm that there's a bug and we need to fix it.

@mp911de mp911de reopened this Nov 12, 2021
@mp911de mp911de self-assigned this Nov 12, 2021
@mp911de mp911de added the type: bug A general bug label Nov 12, 2021
@mp911de mp911de added this to the 2.4.15 (2020.0.15) milestone Nov 12, 2021
@mp911de mp911de changed the title java.lang.ClassCastException: io.lettuce.core.cluster.StatefulRedisClusterConnectionImpl cannot be cast to io.lettuce.core.api.StatefulRedisConnection Eager initialization of LettuceConnectionFactory configured for Redis Cluster causes ClassCastException Nov 12, 2021
mp911de added a commit that referenced this issue Nov 12, 2021
…tory initialization.

We now no longer try to cast the Lettuce connection to StatefulRedisConnection when eagerly initializing the shared connection. Instead, we now introduced another method to obtain the cluster connection.

Closes #2186
mp911de added a commit that referenced this issue Nov 12, 2021
…tory initialization.

We now no longer try to cast the Lettuce connection to StatefulRedisConnection when eagerly initializing the shared connection. Instead, we now introduced another method to obtain the cluster connection.

Closes #2186
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

4 participants