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