Skip to content

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

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
streuspeicher opened this issue Mar 23, 2021 · 4 comments
Assignees
Labels
type: regression A regression from a previous release

Comments

@streuspeicher
Copy link

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

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Mar 23, 2021
@mp911de mp911de self-assigned this Mar 24, 2021
@mp911de mp911de added type: regression A regression from a previous release and removed status: waiting-for-triage An issue we've not yet triaged labels Mar 24, 2021
@mp911de mp911de added this to the 2.4.7 (2020.0.7) milestone Mar 24, 2021
mp911de added a commit that referenced this issue Mar 24, 2021
RedisConnectionProxy is now public so it can be used properly for Java proxy creation across different class loaders. Previously, creating a Java proxy from a different class loader failed because of visibility/access restrictions.

Closes #2016
@mp911de mp911de changed the title Transactional call fails with IllegalArgumentException when executed from within REST Controller Connection proxy creation fails when using package-protected RedisConnectionProxy interface Mar 24, 2021
@mp911de
Copy link
Member

mp911de commented Mar 24, 2021

Thanks for report and apologies for inconvenience. That's fixed now.

@linyongfu2013

This comment has been minimized.

@mp911de

This comment has been minimized.

@ThiruvenkatamRengarajan
Copy link

ThiruvenkatamRengarajan commented Sep 7, 2022

I am still facing this issue. I am using version 2.4.7 @mp911de

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

5 participants