I created an EventEmitter that passes the events to the listeners in a new thread:
public class EventEmitter{
private Map<String,List<EventListener>> listeners = new HashMap<String,List<EventListener>>();
private Executor executor = Executors.newCachedThreadPool();
protected EventEmitter(Executor executor){
this.executor = executor;
}
public void publish(Event e) {
listeners.get(e.getClass().toString()).stream().forEach(listener->{
executor.execute(()->{listener.beNotifiedOfEvent(e);});
});
}
public void subscribe(EventListener listener,Class<?> eventClass) {
assert Arrays.asList(eventClass.getInterfaces()).contains(Event.class);
List<EventListener> listenersThatListenToIt = listeners.get(eventClass.toString());
if(listenersThatListenToIt!=null){
listenersThatListenToIt.add(listener);
} else {
listenersThatListenToIt = new ArrayList<EventListener>();
listenersThatListenToIt.add(listener);
listeners.put(eventClass.toString(),listenersThatListenToIt);
}
}
}
I also print a message in the listener after two seconds when an event is received:
@Component
public class StudentRegisteredEventListener implements EventListener {
@Override
public void beNotifiedOfEvent(Event e) {
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
StudentRegisteredEvent studentRegisteredEvent = (StudentRegisteredEvent) e;
System.out.println("Received student registered event! Student's name is: "+studentRegisteredEvent.getRegisteredStudent());
}
}
I have the following JUnit test:
@Test
public void test_emitter_notifies_listener() {
//given
EventEmitter emitter = new CachedThreadPoolEventEmitter();
//StudentRegisteredEvent event = new StudentRegisteredEvent();
EventListener listener = Mockito.mock(StudentRegisteredEventListener.class);
Student registeredStudent = new Student();
registeredStudent.setName("studentName");
//when
emitter.subscribe(listener,StudentRegisteredEvent.class);
emitter.publish(new StudentRegisteredEvent(registeredStudent));
//then
System.out.println("end of test");
}
My problem is that when the parent thread ends before the end of the "beNotifiedOfEvent" call, the line from the listener method is not printed, so I only see "end of test" on the console.
What I'm interested in is: what is the reason for this behaviour, and whether or not this will work outside of the context of a test. I plan to publish the event from a Spring MVC controller. Is this guaranteed to complete after the the parent thread is done with the execution?