Compare commits
No commits in common. "0f9b64be48b58e51795d02165460addba7140301" and "9379e6bb947909b2422898f65e13444ecd85c21b" have entirely different histories.
0f9b64be48
...
9379e6bb94
@ -1,37 +0,0 @@
|
|||||||
package dev.kske.eventbus.core;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps an event that was dispatched but for which no handler has been bound.
|
|
||||||
* <p>
|
|
||||||
* Handling dead events is useful as it can identify a poorly configured event distribution.
|
|
||||||
*
|
|
||||||
* @author Kai S. K. Engelbart
|
|
||||||
* @since 1.1.0
|
|
||||||
*/
|
|
||||||
public final class DeadEvent {
|
|
||||||
|
|
||||||
private final EventBus eventBus;
|
|
||||||
private final Object event;
|
|
||||||
|
|
||||||
DeadEvent(EventBus eventBus, Object event) {
|
|
||||||
this.eventBus = eventBus;
|
|
||||||
this.event = event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("DeadEvent[eventBus=%s, event=%s]", eventBus, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the event bus that dispatched this event
|
|
||||||
* @since 1.1.0
|
|
||||||
*/
|
|
||||||
public EventBus getEventBus() { return eventBus; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the event that could not be delivered
|
|
||||||
* @since 1.1.0
|
|
||||||
*/
|
|
||||||
public Object getEvent() { return event; }
|
|
||||||
}
|
|
@ -73,24 +73,13 @@ public final class EventBus {
|
|||||||
var state = dispatchState.get();
|
var state = dispatchState.get();
|
||||||
state.isDispatching = true;
|
state.isDispatching = true;
|
||||||
|
|
||||||
Iterator<EventHandler> handlers = getHandlersFor(event.getClass());
|
for (var handler : getHandlersFor(event.getClass()))
|
||||||
if (handlers.hasNext()) {
|
|
||||||
while (handlers.hasNext())
|
|
||||||
if (state.isCancelled) {
|
if (state.isCancelled) {
|
||||||
logger.log(Level.INFO, "Cancelled dispatching event {0}", event);
|
logger.log(Level.INFO, "Cancelled dispatching event {0}", event);
|
||||||
state.isCancelled = false;
|
state.isCancelled = false;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
handlers.next().execute(event);
|
handler.execute(event);
|
||||||
}
|
|
||||||
} else if (!(event instanceof DeadEvent)) {
|
|
||||||
|
|
||||||
// Dispatch dead event
|
|
||||||
dispatch(new DeadEvent(this, event));
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Warn about the dead event not being handled
|
|
||||||
logger.log(Level.WARNING, "{0} not handled", event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset dispatch state
|
// Reset dispatch state
|
||||||
@ -100,26 +89,25 @@ public final class EventBus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for the event handlers bound to an event class. This includes polymorphic handlers
|
* Searches for the event handlers bound to an event class.
|
||||||
* that are bound to a supertype of the event class.
|
|
||||||
*
|
*
|
||||||
* @param eventClass the event class to use for the search
|
* @param eventClass the event class to use for the search
|
||||||
* @return an iterator over the applicable handlers in descending order of priority
|
* @return all event handlers registered for the event class
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
private Iterator<EventHandler> getHandlersFor(Class<?> eventClass) {
|
private List<EventHandler> getHandlersFor(Class<?> eventClass) {
|
||||||
|
|
||||||
// Get handlers defined for the event class
|
// Get handlers defined for the event class
|
||||||
TreeSet<EventHandler> handlers = bindings.getOrDefault(eventClass, new TreeSet<>());
|
Set<EventHandler> handlers = bindings.getOrDefault(eventClass, new TreeSet<>());
|
||||||
|
|
||||||
// Get polymorphic handlers
|
// Get subtype handlers
|
||||||
for (var binding : bindings.entrySet())
|
for (var binding : bindings.entrySet())
|
||||||
if (binding.getKey().isAssignableFrom(eventClass))
|
if (binding.getKey().isAssignableFrom(eventClass))
|
||||||
for (var handler : binding.getValue())
|
for (var handler : binding.getValue())
|
||||||
if (handler.isPolymorphic())
|
if (handler.isPolymorphic())
|
||||||
handlers.add(handler);
|
handlers.add(handler);
|
||||||
|
|
||||||
return handlers.iterator();
|
return new ArrayList<>(handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,7 +68,7 @@ final class EventHandler implements Comparable<EventHandler> {
|
|||||||
* Compares this to another event handler based on priority. In case of equal priority a
|
* Compares this to another event handler based on priority. In case of equal priority a
|
||||||
* non-zero value based on hash codes is returned.
|
* non-zero value based on hash codes is returned.
|
||||||
* <p>
|
* <p>
|
||||||
* This is used to retrieve event handlers in descending order of priority from a tree set.
|
* This is used to retrieve event handlers in order of descending priority from a tree set.
|
||||||
*
|
*
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
package dev.kske.eventbus.core;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the dispatching of a dead event if an event could not be delivered.
|
|
||||||
*
|
|
||||||
* @author Kai S. K. Engelbart
|
|
||||||
* @since 1.1.0
|
|
||||||
*/
|
|
||||||
class DeadTest {
|
|
||||||
|
|
||||||
EventBus bus = new EventBus();
|
|
||||||
String event = "This event has no handler";
|
|
||||||
boolean deadEventHandled;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests dead event delivery.
|
|
||||||
*
|
|
||||||
* @since 1.1.0
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void testDeadEvent() {
|
|
||||||
bus.registerListener(this);
|
|
||||||
bus.dispatch(event);
|
|
||||||
assertTrue(deadEventHandled);
|
|
||||||
bus.removeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests how the event bus reacts to an unhandled dead event. This should not lead to an
|
|
||||||
* exception or endless recursion and instead be logged.
|
|
||||||
*
|
|
||||||
* @since 1.1.0
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void testUnhandledDeadEvent() {
|
|
||||||
bus.dispatch(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Event
|
|
||||||
void onDeadEvent(DeadEvent deadEvent) {
|
|
||||||
assertEquals(bus, deadEvent.getEventBus());
|
|
||||||
assertEquals(event, deadEvent.getEvent());
|
|
||||||
deadEventHandled = true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,8 +27,8 @@ class DispatchTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link EventBus#dispatch(Object)} with multiple handler priorities, a polymorphic
|
* Tests {@link EventBus#dispatch(Object)} with multiple handler priorities, a subtype handler
|
||||||
* handler and a static handler.
|
* and a static handler.
|
||||||
*
|
*
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user