Reputation: 16248
I am attempting to implement this:
@Override // java.util.Function
public Object apply(final ThingWithParameters thing) {
return bozo(thing.getParameters());
}
private Object bozo(final Object[] parameters) {
// Use magic ByteBuddy stuff to "spread" the parameters out
return this.object.baz(parameter0, parameter1); // ...where these are the first two parameters in the array
}
I've tried:
builder = builder
.defineMethod("bozo" ...)
.implement(MethodCall.invoke(bazDescription)
.onField(thisObjectFieldDescription)
.withArgumentArrayElements(0, 2))
.implement(parameterizedTypeFunctionThingWithParametersObject) // Function<ThingWithParameters, Object>
.intercept(MethodCall.invoke(bozoDescription) // implement apply(ThingWithParameters thing): call bozo()...
.withMethodCall(MethodCall.invoke(getParametersMethodDescription) // ...with the result of invoking getParameters()...
.onArgument(0))); // ...on thing (except see below)
…but this does not work. The error message is deeply weird and leads me to believe that argument 0
is not referring to thing
, but to something else entirely (maybe the receiver type somehow?). Here is a snippet from the stack:
java.lang.IllegalStateException: Cannot invoke public java.lang.Object[] com.foo.ThingWithParameters.getParameters() on java.util.function.Function<? super V, ? extends com.foo.ThingWithParameters>
at net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodParameter$Resolved.toStackManipulation(MethodCall.java:2530)
at net.bytebuddy.implementation.MethodCall$Appender.toStackManipulation(MethodCall.java:3548)
at net.bytebuddy.implementation.MethodCall$ArgumentLoader$ForMethodCall.toStackManipulation(MethodCall.java:1687)
at net.bytebuddy.implementation.MethodCall$Appender.toStackManipulation(MethodCall.java:3545)
at net.bytebuddy.implementation.MethodCall$Appender.apply(MethodCall.java:3509)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:708)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:693)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:600)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:5660)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:2166)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:232)
Note that while my proxy class does in fact implement Function
, it actually implements Function<ThingWithParameters, Object>
. And, I never define V
. I'm assuming ByteBuddy does this internally somewhere.
What is the recipe I should be using?
Upvotes: 2
Views: 251
Reputation: 44077
The Function
class defines multiple methods, some of them as default methods. Byte Buddy will attempt to implement all those methods by your Implementation
where it works for the apply
method but fails for others. Therefore, rather define an explicit matcher to indicate the method you'd like to implement.
Upvotes: 1