Skip to content
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

Proxy created with IntroductionInterceptor but without target always throws an exception #33985

Closed
martokarski opened this issue Nov 28, 2024 · 0 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression
Milestone

Comments

@martokarski
Copy link

Hi, I'm from Atlassian DC team. Our products are using Gemini Blueprint that integrates Spring into OSGi framework. I'm working on adding support for Spring 6.2 and I detected regression caused by #31304

Gemini defines proxies without target, instead it adds several mix-ins by adding custom advices implementing DelegatingIntroductionInterceptor. That interceptor registers all interfaces defined by the implementing subclass. Those interfaces are later registered in ProxyFactory. New code validates registered interfaces in ProxyFactory with interfaces from all registered IntroductionAdvisor with use of a method org.springframework.aop.framework.AdvisedSupport#hasUserSuppliedInterfaces. Effectively that method returns true only if ProxyFactory defines at least one interface that isn't defined by one of the registered IntroductionAdvisor.

In some cases the requested interfaces may be the same as defined in registered IntroductionAdvisor. Method hasUserSuppliedInterfaces will return false and ProxyFactory will follow with default pattern, resulting in an exception:

org.springframework.aop.framework.AopConfigException: TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.

The update linked above effectively changed the definition of an "user interface". It used to be any interface that is not SpringProxy. Right now it is an interface that isn't SpringProxy and isn't one of the interfaces defined by IntroductionAdvisor. It caused a regression in Gemini use case. It looks like if there is no target but there are any interfaces, ProxyFactory should still try to use JdkDynamicAopProxy. That change would maintain behvaviour existing for many years before the recent update.

Example Code:

public static void main(String[] args) {
        final ProxyFactory factory = new ProxyFactory();

        // register `IntroductionAdvisor` that delegates calls to `ImportedOsgiServiceProxy`
        factory.addAdvice(new DelegatingInterceptor());
        // request proxy to implement `ImportedOsgiServiceProxy`
        factory.addInterface(ImportedOsgiServiceProxy.class);

        // should return proxy
        // instead throws exception suggesting that either an interface or a target is required
        Object proxy = factory.getProxy();
    }

    private static class DelegatingInterceptor extends DelegatingIntroductionInterceptor implements ImportedOsgiServiceProxy {
        @Override
        public ServiceReferenceProxy getServiceReference() {
            // implementation detail
            return null;
        }
    }
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Nov 28, 2024
@jhoeller jhoeller added type: regression A bug that is also a regression in: core Issues in core modules (aop, beans, core, context, expression) and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Nov 28, 2024
@jhoeller jhoeller self-assigned this Nov 28, 2024
@jhoeller jhoeller added this to the 6.2.1 milestone Nov 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

3 participants