Mehrdad Yami
Mehrdad Yami

Reputation: 1681

Nested Proxy using cglib in spring

Preface: I want to create a proxy of an existed proxy (Using cglib package in spring) , like when I call the original method class both methods of both proxies called first. Does it make any sense at all? or is it possible?

Problem: When I'm creating the second enhancer, i get the java.lang.ClassFormatError-->Duplicate method name "newInstance" with signature " exception.


Sample code is as follows

Original Class

public class OriginalClass {

    public void print(){
        System.out.println("MAIN METHOD");
    }

}

Create Two Proxies

public class Main {

    public static void main(String[] args) {

        //Create First Proxy
        Enhancer firstEnhancer= new Enhancer();
        firstEnhancer.setSuperclass(OriginalClass.class);
        firstEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
            System.out.println("METHOD INTERCEPTOR AT FIRST PROXY");
            return methodProxy.invokeSuper(o, objects);
        });
        OriginalClass firstProxy = (OriginalClass) firstEnhancer.create();

        //Create Second Proxy
        Enhancer secondEnhancer= new Enhancer();
        secondEnhancer.setSuperclass(firstProxy.getClass());
        secondEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
            System.out.println("METHOD INTERCEPTOR AT SECOND PROXY");
            return methodProxy.invokeSuper(o, objects);
        });

        //Getting Exception on this line
        OriginalClass secondProxy = (OriginalClass) secondEnhancer.create();

        //Call 
        secondProxy.print();
    }
}

The expected result is as follows (Print)

METHOD INTERCEPTOR AT SECOND PROXY
METHOD INTERCEPTOR AT FIRST PROXY
MAIN METHOD

But I get the below Exception (when creating the second proxy)

Caused by: java.lang.ClassFormatError: Duplicate method name "newInstance" with signature "([Lorg.springframework.cglib.proxy.Callback;)Ljava.lang.Object;" in class file com/test/OriginalClass$$EnhancerByCGLIB$$37b306ed$$EnhancerByCGLIB$$15133919

Real World Scenario

I want to wrap a proxy on all beans that have been proxied by spring, using BeanPostProcessors and cglib. For example, I want to wrap a proxy on all @transactional methods (log before and after the transactions).

Update: I prefer to create proxies, not AOPs.(AOP is itself a proxy)

Upvotes: 0

Views: 1273

Answers (1)

Krzysztof Cichocki
Krzysztof Cichocki

Reputation: 6412

I've found working soultion, it works when used methodProxy.invoke() instead of methodProxy.invokeSuper() in the second enhancer, also the firstProxy need to be passed to the invocation instead of the o object and the superClass is set to the original one, that doesn't have the newInstance method:

public class Test {
     public static void main(String[] args) {

            //Create First Proxy
            Enhancer firstEnhancer= new Enhancer();
            firstEnhancer.setSuperclass(OriginalClass.class);
            firstEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
                System.out.println("METHOD INTERCEPTOR AT FIRST PROXY");
                return methodProxy.invokeSuper(o, objects);
            });
            OriginalClass firstProxy = (OriginalClass) firstEnhancer.create();

            //Create Second Proxy
            Enhancer secondEnhancer= new Enhancer();
            secondEnhancer.setSuperclass(firstProxy.getClass().getSuperclass());
            // secondEnhancer.setSuperclass(OriginalClass.class);
            secondEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
                System.out.println("METHOD INTERCEPTOR AT SECOND PROXY");
                return methodProxy.invoke(firstProxy, objects);
            });

            //Getting Exception on this line
            OriginalClass secondProxy = (OriginalClass) secondEnhancer.create();

            //Call 
            secondProxy.print();
        }
}

result:

METHOD INTERCEPTOR AT SECOND PROXY
METHOD INTERCEPTOR AT FIRST PROXY
MAIN METHOD

Upvotes: 3

Related Questions