0

Is there a way to create a proxy for a class with no empty constructor using ByteBuddy?

The idea is to create a proxy for a given concrete type and then redirect all the methods to a handler.

This test showcases the scenario of creation of a proxy for a clas with no empty constructor and it throws a java.lang.NoSuchMethodException

@Test
public void testProxyCreation_NoDefaultConstructor() throws InstantiationException, IllegalAccessException {

    // setup

    // exercise
    Class<?> dynamicType = new ByteBuddy() //
            .subclass(FooEntity.class) //
            .method(ElementMatchers.named("toString")) //
            .intercept(FixedValue.value("Hello World!")) //
            .make().load(getClass().getClassLoader()).getLoaded();

    // verify
    FooEntity newInstance = (FooEntity) dynamicType.newInstance();
    Assert.assertThat(newInstance.toString(), Matchers.is("Hello World!"));
}

The entity:

public class FooEntity {

    private String value;

    public FooEntity(String value) {
        this.value = value;
    }

    public String getValue() {
        return this.value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}
diegomtassis
  • 3,557
  • 2
  • 19
  • 29

1 Answers1

1

You call to subclass(FooEntity.class) implies that Byte Buddy implicitly mimics all constructors defined by the super class. You can add a custom ConstructorStrategy as a second argument to change this behavior.

However, the JVM requires that any constructor invokes a super constructor eventually where your proxied class only offers one with a single constructor. Given your code, you can create the proxy by simply providing a default argument:

FooEntity newInstance = (FooEntity) dynamicType
      .getConstuctor(String.class)
      .newInstance(null);

The field is then set to null. Alternatively, you can instantiate classes with a library like Objenesis that uses JVM internals to create instances without any constructor calls.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • The code here is only sample. In the real product the proxy creation is done inside a factory where the class of the proxied object is not known at compilation. I was expecting something like what objenesis does, actually I don't want the super constructors to be invoked. – diegomtassis Jan 26 '18 at 09:09
  • Oh, I did not get that Objenesis could be used together with ByteBuddy. Thanks, problem solved. – diegomtassis Jan 26 '18 at 09:31
  • 1
    For the next version, I do actually add a constructor strategy that solves this problem as long as a constructor is side-effect free. – Rafael Winterhalter Jan 26 '18 at 15:57