Despite the fact that I have read all the documentation that I know about, I cannot solve the problem of using lambdas to execute the method. To give a little background, my use case is a plugin system. I use annotation (@EventHandle) which can be assigned to any method. I use reflection and repeat each method in the class and check if it has an annotation if it is added to the handler object (which is added to the list to process each “checkmark”). Here is my handler class:
package me.b3nw.dev.Events; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import java.lang.invoke.*; import java.lang.reflect.Method; import java.lang.reflect.Type; @Slf4j public class Handler { @Getter private final Method method; @Getter private final EventHandle handle; private final MethodHandles.Lookup lookup; private final MethodHandle methodHandle; private final EventHandler invoker; public Handler(Method method, EventHandle handle) throws Throwable { this.method = method; log.info(method.getGenericReturnType() + ""); for(Type type : method.getParameterTypes()) { log.info(type.getTypeName()); } this.handle = handle; this.lookup = MethodHandles.lookup(); this.methodHandle = lookup.unreflect(method); log.info("" + methodHandle.type().toMethodDescriptorString()); this.invoker = (EventHandler) LambdaMetafactory.metafactory(lookup, "handle", MethodType.methodType(EventHandler.class), methodHandle.type(), methodHandle, methodHandle.type()).getTarget().invokeExact(); } public void invoke(GameEvent evt) throws Throwable { invoker.handle(evt); } }
In the current iteration of this class, I throw directly into the EventHandler functional interface, source:
package me.b3nw.dev.Events; @FunctionalInterface public interface EventHandler { boolean handle(GameEvent evt); }
I am currently getting the following error:
ERROR mbdHGamemodeHandler - java.lang.AbstractMethodError: me.b3nw.dev.Events.Handler$$Lambda$3/1704984363.handle(Lme/b3nw/dev/Events/GameEvent;)Z at me.b3nw.dev.Events.Handler.invoke(Handler.java:40) ~[classes/:na] at me.b3nw.dev.Handlers.GamemodeHandler.userEventTriggered(GamemodeHandler.java:34) ~[classes/:na]
GamemodeHandler simply calls the invoke method in the Handler class.
Thus, it throws AbstractMethodError when I just pass the EventHandler event and execute when I don't use it, I get another error that:
java.lang.invoke.WrongMethodTypeException: expected ()EventHandler but found ()void at java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:294) ~[na:1.8.0_45] at java.lang.invoke.Invokers.checkExactType(Invokers.java:305) ~[na:1.8.0_45] at me.b3nw.dev.Events.Handler.invoke(Handler.java:40) ~[classes/:na] at me.b3nw.dev.Handlers.GamemodeHandler.userEventTriggered(GamemodeHandler.java:34) ~[classes/:na]
Modified Handler to reflect changes:
package me.b3nw.dev.Events; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import java.lang.invoke.*; import java.lang.reflect.Method; import java.lang.reflect.Type; @Slf4j public class Handler { @Getter private final Method method; @Getter private final EventHandle handle; private final MethodHandles.Lookup lookup; private final MethodHandle methodHandle; private final MethodHandle invoker; public Handler(Method method, EventHandle handle) throws Throwable { this.method = method; log.info(method.getGenericReturnType() + ""); for(Type type : method.getParameterTypes()) { log.info(type.getTypeName()); } this.handle = handle; this.lookup = MethodHandles.lookup(); this.methodHandle = lookup.unreflect(method); log.info("" + methodHandle.type().toMethodDescriptorString()); this.invoker = LambdaMetafactory.metafactory(lookup, "handle", MethodType.methodType(EventHandler.class), methodHandle.type(), methodHandle, methodHandle.type()).getTarget(); } public void invoke(GameEvent evt) throws Throwable { invoker.invokeExact(); } }
This class has a method that is annotated and should implement the signature of the functional interface, but .. obviously not :( Here is the class:
package me.b3nw.dev.Gamemode; import lombok.extern.slf4j.Slf4j; import me.b3nw.dev.Events.EventHandle; import me.b3nw.dev.Events.GameEvent; @Slf4j public class Vanilla extends Gamemode { public void testMethod() { } @EventHandle(type = EventHandle.Type.NICKANNOUNCE) public boolean testMethod2(GameEvent evt) { log.info("Fuck yeah!"); return true; } }
How can I fix this, I'm using lambdas completely wrong here?
Thanks.