0
votes

Ok, so I am basically trying to create my own events/listener system for a project I'm working on. I'm trying to have a system where I create an event with an abstract class and I can then create a listener that every time that event is called, the code within the listener is also called. Here's what I've got so far:

Event.java (Abstract class where I will be able to create new events)

private String name;
private boolean cancelled;

public String getEventName() {
    if (this.name == null) {
        this.name = this.getClass().getSimpleName();
    }
    return this.name;
}

public void setName(String name) {
    this.name = name;
}

public boolean isCancelled() {
    return cancelled;
}

public void setCancelled(boolean cancelled) {
    this.cancelled = cancelled;
}

EventHandler.java (Interface for being able to recognise when a method is a listener)

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventHandler {}

Listener.java (Interface for being able to recognise when a class contains a listener)

public interface Listener {}

EventExecutor.java (A class that will execute the listener code, I've started but this is where I need help to call the method to execute the code)

public void execute(Class clazz){
    if(!clazz.isAssignableFrom(Listener.class)) return;
    for(Method method : clazz.getMethods()){
        if(!method.isAnnotationPresent(EventHandler.class)) continue;
    }
}

So what I am asking is how (in EventExecutor) could I call (invoke) the method when the annotation is present. The method for example could be public void onUpdate(ProgramUpdateEvent event) or be onClose(ProgramCloseEvent event). Thanks any help is appreciated.

1
Are you asking how you can invoke the method you've found? Like, method.invoke(...)? - lexicore
No, I'm trying to call a method that I will define but can contain different args. Like the example above: public void onUpdate(ProgramUpdateEvent event) or be onClose(ProgramCloseEvent event). However both these classes will implement the Listener interface. - user8469677
I'm trying to understand what you want. In your execute method you check if class implements Listener and search for methods marked with @EventHandler. You have the method right there, in the cycle. Do you want to invoke it or not? On which instance? With which event? - lexicore
That's what I'm confused about, I've never worked with something like this. Do I need to invoke it? If so how? My current method checks if it is a listener class and if a method has the EventHandler annotation. Next I want to (invoke?) call the that method just like I would call it for example runCode(); - user8469677
I still have no idea what you actually want to do. Normally you have listeners which subscribe to events and get called when event is published. But I'm not sure what do you want to do with annotation and Listener interface. Why execute(Class) and if you want to publish events then where do you get these events? And how are listeners registered? - lexicore

1 Answers

0
votes

You need to actually have an instance of the listener. Your execute method should look like this:

public void execute(Listener listener) {

To invoke, just put

method.invoke(listener, event);

The first argument is the object to actually invoke the method on, and the second one is the parameter for the method. Because the methods aren't static, you need a reference to the object. (if you make them static, just put null instead of the listener)