Peter Jurkovic
Peter Jurkovic

Reputation: 2896

How to subclass an abstract class with 1+ args constructor using ByteBuddy

I would like to proxy java.net.HttpURLConnection which has one constructor: HttpURLConnection(URL u). How can I subclass such a class with ByteBuddy without creating custom "Empty" class with the non-arg constructor?

 new ByteBuddy().subclass(HttpURLConnection.class)
                .method(ElementMatchers.any())
                .intercept(InvocationHandlerAdapter.of(proxyHandler))
                .make()
                .load(HttpURLConnection.class.getClassLoader())
                .getLoaded()
                .newInstance();

Currently, it fails due to

Caused by: java.lang.NoSuchMethodException: net.bytebuddy.renamed.java.net.HttpURLConnection$ByteBuddy$Mr8B9wE2.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082)

I would like to delegate a custom URL to that super constructor it is possible.

But if I create a custom class

public class ProxiedHttpURLConnection extends HttpURLConnection{

    protected ProxiedHttpURLConnection() {
        super(null); // <---
    }

}

and use that one in new ByteBuddy().subclass(ProxiedHttpURLConnection.class) it works fine. There is simple issue with a contractor, not quite sure how to do it.

Upvotes: 0

Views: 291

Answers (1)

Rafael Winterhalter
Rafael Winterhalter

Reputation: 44032

You can define a custom constructor and invoke a specific super constructor using the MethodCall instrumentation, e.g.

builder = builder.defineConstructor(Visibility.PUBLIC)
  .intercept(MethodCall.invoke(HttpURLConnection.class.getDeclaredConstructor(URL.class))
                 .with((Object) null))

By default, Byte Buddy immitates the super class constructors, you can therefore lookup a declared constructor that takes a URL and provide the null argument manually.

You can avoid this creation by defining a ConstructorStrategy as a second argument to subclass.

Upvotes: 2

Related Questions