Skip to content

Connection proxy creation fails when using package-protected RedisConnectionProxy interface  #2016

Closed
@streuspeicher

Description

@streuspeicher

Tested with Spring Boot 2.4.4:

When accessing REDIS through an transactional RedisTemplate from within a REST Controller, the call fails with the following exception:

java.lang.IllegalArgumentException: non-public interface is not defined by the given loader
	at java.base/java.lang.reflect.Proxy$ProxyBuilder.mapToModule(Proxy.java:798)
	at java.base/java.lang.reflect.Proxy$ProxyBuilder.<init>(Proxy.java:630)
	at java.base/java.lang.reflect.Proxy.lambda$getProxyConstructor$1(Proxy.java:426)
	at java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:329)
	at java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:205)
	at java.base/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:424)
	at java.base/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1006)
	at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:126)
	at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:118)
	at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:97)
	at org.springframework.data.redis.core.RedisConnectionUtils.createConnectionSplittingProxy(RedisConnectionUtils.java:230)
	at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:151)
	at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:105)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:209)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:189)
	at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96)
	at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:236)
	at com.example.redisissuedemo.DemoController.root(DemoController.kt:21)
	at com.example.redisissuedemo.DemoController$$FastClassBySpringCGLIB$$47e9043b.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
	at com.example.redisissuedemo.DemoController$$EnhancerBySpringCGLIB$$9e9e515d.root(<generated>)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
....

Controller:

@RestController
class DemoController(
    private val redisTemplate: RedisTemplate<String, String>
) {

    @GetMapping("/")
    @Transactional
    fun root(): String {
        val value = Instant.now().toString()
        redisTemplate.opsForValue().set("Value", value)
        return value
    }
}

Configuration:

@SpringBootApplication
class RedisIssueDemoApplication {

    @Bean
    fun redisConnectionFactory() = LettuceConnectionFactory()

    @Bean
    fun redisTemplate(redisConnectionFactory: RedisConnectionFactory) = RedisTemplate<String, String>().apply {
		setConnectionFactory(redisConnectionFactory)
		setEnableTransactionSupport(true)
                afterPropertiesSet()
    }
}

When using Spring Boot 2.4.4 and accessing http://127.0.0.1:8080, the exception above is thrown.
Running the same controller with Spring Boot 2.4.0 works without issues

An example project is available here: https://github.com/streuspeicher/redis-issue-demo

A related SO question is waiting for an answer: https://stackoverflow.com/questions/65551277/redistemplate-convertandsend-causes-illegalargumentexception-non-public-interf

Metadata

Metadata

Assignees

Labels

type: regressionA regression from a previous release

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions