0

I have class 'A' that implements interface 'I'. I have two classes 'B' and 'C', each extends A and adds a new method. C and B do not override any method in A. The new method in Class 'B' has a signature different from that of 'C' and the new method is the only difference between C and B. I need to create a Proxy (sort of composite of objects of 'B' and 'C') that should have all the methods of A and the new methods in 'B' and 'C'.

I tried to use Mixin$Generator in CGLIB to create a composite proxy but I get Error "java.lang.ClassFormatError: Duplicate interface name in class file".

Has anyone encountered a similar situation? Any suggestions for solving this issue?

Thanks for your time.

Here is the code updated with the interface and all the classes.

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Mixin;
import net.sf.cglib.proxy.Mixin.Generator;

interface I {
    public boolean testSomething();
}

class A implements I {

    @Override
    public boolean testSomething() {
        boolean isRoot = true;
        System.out.println("Returning '" + isRoot + "' from '" + this + "' ...");
        return isRoot;
    }
}

class B extends A {
    public boolean isB() {
        boolean isRoot1 = true;
        System.out.println("Returning " + isRoot1 + " from : " + this);
        return isRoot1;
    }
}

class C extends A {
    public int getInt() {
        int someInt = 2;
        System.out.println("Returning " + someInt + " from : " + this);
        return someInt;
    }
}
    public class TestMixin {

        public static Object invokeMethod(Object target, String methodName)
                throws Exception {
            Method method = target.getClass().getMethod(methodName);
            return method.invoke(target);
        }

        public static Mixin newInstance(Object[] delegates) {
            return newInstance(null, delegates);
        }

        public static Mixin newInstance(Class[] interfaces, Object[] delegates) {
            Generator gen = new Generator();
            gen.setStyle(Mixin.STYLE_EVERYTHING);
            if(interfaces != null) {
                gen.setClasses(interfaces);
            }
            gen.setDelegates(delegates);
            return gen.create();
        }

        public static void main(String[] args) throws Exception {
           // B and C extend Class 'A' which implements 'I' interface
            B root1 = new B();
            C root2 = new C();
            A[] roots = { root1, root2 };
            Class<?>[] interfaces = new Class[] { B.class, C.class };
            // newInstance causes java.lang.ClassFormatError: Duplicate interface
            // name in class file com/mycom/cglib/B$$MixinByCGLIB$$831a43ec
            Mixin mixin = TestMixin.newInstance(interfaces, roots);
            System.out.println("Mixin Object: " + mixin);
            System.out.println(invokeMethod(mixin, "testSomething"));
            System.out.println(invokeMethod(mixin, "isB"));
            System.out.println(invokeMethod(mixin, "getInt"));
        }
    }
5
  • Post the code you are using to generate the proxy. Commented Jan 29, 2014 at 16:56
  • This has been answered before. stackoverflow.com/q/5003285/3224483 stackoverflow.com/q/3556652/3224483 Commented Jan 29, 2014 at 17:10
  • @John That post does not answer my question. The post discusses how to implement/simulate multiple inheritance using interfaces. My question is how to create dynamically a proxy class that can inherit methods from two different subclasses of the same parent class. I do not want to write any code to accomplish that using composition. Commented Jan 29, 2014 at 18:31
  • What are root1 and root2? Your above code does not compile. Commented Jan 30, 2014 at 7:55
  • I have updated the code with root1 and root2. Commented Jan 30, 2014 at 17:07

1 Answer 1

1

I guess you are aware of the fact that cglib cannot make multiple inheritence happen in Java. All that cglib does is creating a proxy class which implements all the methods and all the interfaces found on any (super)class that is added to the Mixin generator. Note that the super class of the proxy will still Object.

Since you are adding two classes C and B which both inherit from class A which implements interface I, this interface will be added twice to the implementing proxy. However, this is not allowed in Java and the verifier will complain about it when the class is loaded. The idea of cglib is: I create a new class implementing n interfaces and you provide me n feedback classes with methods of the same signature to which these calls will be mapped. You defined a mapping equivalent to:

  1. I to B
  2. I to C

But how could cglib solve this problem? It could implement interface I only once. However, since the Mixin works by delegating any interface method calls to its registered feedback objects, thiis would not help much. Should this feedback object be the instance of B or of C that you provided? Cglib cannot decide this for you, even though it should of course give you a better error message over this ambiguity instead of plainly following the protocol.

By the way, you are using the internal cglib Mixin.Generator for your purposes. You are officially supposed to use the public Mixin#create(Class<?>[], Object[]) method. I wrote a little bit on how to use cglib, if you are interested. Also, the official API allows you to decide which interface is mapped to which feedback object. Furthermore, it allows you to add additional, unmapped interfaces to implement such that your proxy can be casted to this type.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the comments. I was not aware that cglib cannot make multiple inheritance happen in Java though I guessed it after I got the error. Now I get that cglib cannot do what I am trying to do.
I will try to solve this by writing a class that implements MethodInterceptor of cglib. In the intercept method, I will try to delegate to the appropriate object (B or C) by looking at the name of the method and finding which object has the method. If the method is available in B and C, I will delegate the call to B or C. In my case it does not matter since both B and C extend A.
As in your other thread on this topic: Why do you need cglib for that? Just implement a delegator that inherits from A. If your answer is solved, consider marking my answer as accepted. Thanks!
Thanks for your time. You are right. I can just implement a delegator that inherits from A but in my case, other subclasses of A (D or E) may be added in future. So I want the delegator to be dynamic. I think a MethodInterceptor implementation can look at the method being invoked at runtime and figure out which subclass object of A (B or C or D) has the method and delegate to it. Hope I have made it clear.
Be aware that this implies a performance penalty due to the reflective method invocation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.