diff --git a/event-driven-architecture/index.md b/event-driven-architecture/index.md index fb438c3e9..0a4be0bb6 100644 --- a/event-driven-architecture/index.md +++ b/event-driven-architecture/index.md @@ -30,4 +30,3 @@ permalink: /patterns/event-driven-architecture * [Fundamental Components of an Event-Driven Architecture](http://giocc.com/fundamental-components-of-an-event-driven-architecture.html) * [Real World Applications/Event Driven Applications](https://wiki.haskell.org/Real_World_Applications/Event_Driven_Applications) * [Event-driven architecture definition](http://searchsoa.techtarget.com/definition/event-driven-architecture) -* \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java index 5ef58d20b..a1e4c6652 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java @@ -3,6 +3,7 @@ package com.iluwatar.eda; import com.iluwatar.eda.event.Event; import com.iluwatar.eda.event.UserCreatedEvent; import com.iluwatar.eda.event.UserUpdatedEvent; +import com.iluwatar.eda.framework.EventDispatcher; import com.iluwatar.eda.handler.UserCreatedEventHandler; import com.iluwatar.eda.handler.UserUpdatedEventHandler; import com.iluwatar.eda.model.User; @@ -19,7 +20,7 @@ import com.iluwatar.eda.model.User; public class App { /** - * Once the {@link EventDispatcher} is initialised, channels related to specific events have to be + * Once the {@link EventDispatcher} is initialised, handlers related to specific events have to be * made known to the dispatcher by registering them. In this case the {@link UserCreatedEvent} is * bound to the UserCreatedEventHandler, whilst the {@link UserUpdatedEvent} is bound to the * {@link UserUpdatedEventHandler}. The dispatcher can now be called to dispatch specific events. @@ -34,8 +35,8 @@ public class App { dispatcher.registerChannel(UserUpdatedEvent.class, new UserUpdatedEventHandler()); User user = new User("iluwatar"); - dispatcher.dispatch(new UserCreatedEvent(user)); - dispatcher.dispatch(new UserUpdatedEvent(user)); + dispatcher.onEvent(new UserCreatedEvent(user)); + dispatcher.onEvent(new UserUpdatedEvent(user)); } } diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java deleted file mode 100644 index f68fdb71b..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.iluwatar.eda; - -import com.iluwatar.eda.event.Event; -import com.iluwatar.eda.framework.Channel; -import com.iluwatar.eda.framework.DynamicRouter; - -import java.util.HashMap; -import java.util.Map; - -/** - * Handles the routing of {@link Event} messages to associated channels. - * A {@link HashMap} is used to store the association between events and their respective handlers. - * - */ -public class EventDispatcher implements DynamicRouter { - - private Map, Channel> handlers; - - public EventDispatcher() { - handlers = new HashMap<>(); - } - - /** - * Links an {@link Event} to a specific {@link Channel}. - * - * @param contentType The {@link Event} to be registered - * @param channel The {@link Channel} that will be handling the {@link Event} - */ - public void registerChannel(Class contentType, - Channel channel) { - handlers.put(contentType, channel); - } - - /** - * Dispatches an {@link Event} depending on it's type. - * - * @param content The {@link Event} to be dispatched - */ - public void dispatch(Event content) { - handlers.get(content.getClass()).dispatch(content); - } - - /** - * Returns a map of registered event handlers. - * @return {@link Map} of registered event handlers. - */ - public Map, Channel> getHandlers() { - return handlers; - } -} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/Event.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/Event.java index 9a2518ebf..9ef3dd7db 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/Event.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/Event.java @@ -1,5 +1,6 @@ package com.iluwatar.eda.event; +import com.iluwatar.eda.framework.EventDispatcher; import com.iluwatar.eda.framework.Message; /** @@ -15,8 +16,8 @@ public class Event implements Message { /** * Returns the event type as a {@link Class} object - * In this example, this method is used by the {@link com.iluwatar.eda.EventDispatcher} to - * dispatch events depending on their type. + * In this example, this method is used by the {@link EventDispatcher} to + * onEvent events depending on their type. * * @return the Event type as a {@link Class}. */ diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java index da2e31c8a..f7beaf82c 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java @@ -3,7 +3,7 @@ package com.iluwatar.eda.event; import com.iluwatar.eda.model.User; /** - * The {@link UserCreatedEvent} class should should be dispatched whenever a user has been created. + * The {@link UserCreatedEvent} should should be dispatched whenever a user has been created. * This class can be extended to contain details about the user has been created. In this example, * the entire {@link User} object is passed on as data with the event. */ diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java index f3bce8124..c07e83e7c 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java @@ -3,7 +3,7 @@ package com.iluwatar.eda.event; import com.iluwatar.eda.model.User; /** - * The {@link UserUpdatedEvent} class should should be dispatched whenever a user has been updated. + * The {@link UserUpdatedEvent} should should be dispatched whenever a user has been updated. * This class can be extended to contain details about the user has been updated. In this example, * the entire {@link User} object is passed on as data with the event. */ diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Channel.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Channel.java deleted file mode 100644 index 1684a9641..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Channel.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.iluwatar.eda.framework; - -import com.iluwatar.eda.event.Event; - -/** - * Channels are delivery points for messages. Every {@link Channel} is responsible for a single type - * of message - */ -public interface Channel { - void dispatch(Event message); -} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/DynamicRouter.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/DynamicRouter.java deleted file mode 100644 index 23fd6044f..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/DynamicRouter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.iluwatar.eda.framework; - -/** - * A {@link DynamicRouter} is responsible for selecting the proper path of a {@link Message} - * Messages can be associated to Channels through the registerChannel method and dispatched by - * calling the dispatch method. - */ -public interface DynamicRouter { - - void registerChannel(Class contentType, Channel channel); - - void dispatch(E content); -} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java new file mode 100644 index 000000000..fef303937 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java @@ -0,0 +1,42 @@ +package com.iluwatar.eda.framework; + +import com.iluwatar.eda.event.Event; +import com.iluwatar.eda.framework.Handler; + +import java.util.HashMap; +import java.util.Map; + +/** + * Handles the routing of {@link Event} messages to associated handlers. + * A {@link HashMap} is used to store the association between events and their respective handlers. + * + */ +public class EventDispatcher { + + private Map, Handler> handlers; + + public EventDispatcher() { + handlers = new HashMap<>(); + } + + /** + * Links an {@link Event} to a specific {@link Handler}. + * + * @param eventType The {@link Event} to be registered + * @param handler The {@link Handler} that will be handling the {@link Event} + */ + public void registerChannel(Class eventType, + Handler handler) { + handlers.put(eventType, handler); + } + + /** + * Dispatches an {@link Event} depending on it's type. + * + * @param event The {@link Event} to be dispatched + */ + public void onEvent(Event event) { + handlers.get(event.getClass()).onEvent(event); + } + +} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java new file mode 100644 index 000000000..cba2f08b2 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java @@ -0,0 +1,18 @@ +package com.iluwatar.eda.framework; + +import com.iluwatar.eda.event.Event; + +/** + * This interface can be implemented to handle different types of messages. + * Every handler is responsible for a single of type message + */ +public interface Handler { + + /** + * The onEvent method should implement and handle behavior related to the event. + * This can be as simple as calling another service to handle the event on publishing the event on + * a queue to be consumed by other sub systems. + * @param event the {@link Event} object to be handled. + */ + void onEvent(Event event); +} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Message.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Message.java index 2f8acb343..f8f8c7dfc 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Message.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Message.java @@ -2,8 +2,14 @@ package com.iluwatar.eda.framework; /** * A {@link Message} is an object with a specific type that is associated - * to a specific {@link Channel}. + * to a specific {@link Handler}. */ public interface Message { + + /** + * Returns the message type as a {@link Class} object. In this example the message type is + * used to handle events by their type. + * @return the message type as a {@link Class}. + */ Class getType(); } diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java index 49d209eb0..7db4a2d81 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java @@ -2,16 +2,15 @@ package com.iluwatar.eda.handler; import com.iluwatar.eda.event.Event; import com.iluwatar.eda.event.UserCreatedEvent; -import com.iluwatar.eda.framework.Channel; -import com.iluwatar.eda.model.User; +import com.iluwatar.eda.framework.Handler; /** * Handles the {@link UserCreatedEvent} message. */ -public class UserCreatedEventHandler implements Channel { +public class UserCreatedEventHandler implements Handler { @Override - public void dispatch(Event message) { + public void onEvent(Event message) { UserCreatedEvent userCreatedEvent = (UserCreatedEvent) message; System.out.printf("User with %s has been Created!", userCreatedEvent.getUser().getUsername()); diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java index fd3a6d3ba..754a75c45 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java @@ -1,17 +1,16 @@ package com.iluwatar.eda.handler; import com.iluwatar.eda.event.Event; -import com.iluwatar.eda.event.UserCreatedEvent; import com.iluwatar.eda.event.UserUpdatedEvent; -import com.iluwatar.eda.framework.Channel; +import com.iluwatar.eda.framework.Handler; /** * Handles the {@link UserUpdatedEvent} message. */ -public class UserUpdatedEventHandler implements Channel { +public class UserUpdatedEventHandler implements Handler { @Override - public void dispatch(Event message) { + public void onEvent(Event message) { UserUpdatedEvent userUpdatedEvent = (UserUpdatedEvent) message; System.out.printf("User with %s has been Updated!", userUpdatedEvent.getUser().getUsername()); diff --git a/event-driven-architecture/src/test/java/EventDrivenTest.java b/event-driven-architecture/src/test/java/EventDrivenTest.java deleted file mode 100644 index addc5fafa..000000000 --- a/event-driven-architecture/src/test/java/EventDrivenTest.java +++ /dev/null @@ -1,63 +0,0 @@ -import com.iluwatar.eda.EventDispatcher; -import com.iluwatar.eda.event.Event; -import com.iluwatar.eda.event.UserCreatedEvent; -import com.iluwatar.eda.event.UserUpdatedEvent; -import com.iluwatar.eda.handler.UserCreatedEventHandler; -import com.iluwatar.eda.handler.UserUpdatedEventHandler; -import com.iluwatar.eda.model.User; - -import org.junit.Test; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.junit.Assert.assertEquals; - - -/** - * Event Driven Pattern unit tests to assert and verify correct pattern behaviour - */ -public class EventDrivenTest { - - /** - * This unit test should register events and event handlers correctly with the event dispatcher - * and events should be dispatched accordingly. - */ - @Test - public void testEventDriverPattern() { - - EventDispatcher dispatcher = spy(new EventDispatcher()); - UserCreatedEventHandler userCreatedEventHandler = new UserCreatedEventHandler(); - UserUpdatedEventHandler userUpdatedEventHandler = new UserUpdatedEventHandler(); - dispatcher.registerChannel(UserCreatedEvent.class, userCreatedEventHandler); - dispatcher.registerChannel(UserUpdatedEvent.class, userUpdatedEventHandler); - - assertEquals("Two handlers must be registered", 2, dispatcher.getHandlers().size()); - assertEquals("UserCreatedEvent must return the UserCreatedEventHandler", - userCreatedEventHandler, - (UserCreatedEventHandler) dispatcher.getHandlers().get(UserCreatedEvent.class)); - assertEquals("UserUpdatedEvent must be registered to the UserUpdatedEventHandler", - userUpdatedEventHandler, - (UserUpdatedEventHandler) dispatcher.getHandlers().get(UserUpdatedEvent.class)); - - User user = new User("iluwatar"); - - UserCreatedEvent userCreatedEvent = new UserCreatedEvent(user); - UserUpdatedEvent userUpdatedEvent = new UserUpdatedEvent(user); - dispatcher.dispatch(userCreatedEvent); - dispatcher.dispatch(userUpdatedEvent); - - //verify that the events have been dispatched - verify(dispatcher).dispatch(userCreatedEvent); - verify(dispatcher).dispatch(userUpdatedEvent); - } - - /** - * This unit test should correctly return the {@link Event} class type when calling the - * {@link Event#getType() getType} method. - */ - @Test - public void testGetEventType() { - User user = new User("iluwatar"); - UserCreatedEvent userCreatedEvent = new UserCreatedEvent(user); - assertEquals(UserCreatedEvent.class, userCreatedEvent.getType()); - } -} diff --git a/event-driven-architecture/src/test/java/com/iluwatar/eda/event/UserCreatedEventTest.java b/event-driven-architecture/src/test/java/com/iluwatar/eda/event/UserCreatedEventTest.java new file mode 100644 index 000000000..108280bf1 --- /dev/null +++ b/event-driven-architecture/src/test/java/com/iluwatar/eda/event/UserCreatedEventTest.java @@ -0,0 +1,24 @@ +package com.iluwatar.eda.event; + +import com.iluwatar.eda.model.User; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * {@link UserCreatedEventTest} tests and verifies {@link Event} behaviour. + */ +public class UserCreatedEventTest { + + /** + * This unit test should correctly return the {@link Event} class type when calling the + * {@link Event#getType() getType} method. + */ + @Test + public void testGetEventType() { + User user = new User("iluwatar"); + UserCreatedEvent userCreatedEvent = new UserCreatedEvent(user); + assertEquals(UserCreatedEvent.class, userCreatedEvent.getType()); + } +} diff --git a/event-driven-architecture/src/test/java/com/iluwatar/eda/framework/EventDispatcherTest.java b/event-driven-architecture/src/test/java/com/iluwatar/eda/framework/EventDispatcherTest.java new file mode 100644 index 000000000..163ffed6e --- /dev/null +++ b/event-driven-architecture/src/test/java/com/iluwatar/eda/framework/EventDispatcherTest.java @@ -0,0 +1,50 @@ +package com.iluwatar.eda.framework; + +import com.iluwatar.eda.framework.EventDispatcher; +import com.iluwatar.eda.event.UserCreatedEvent; +import com.iluwatar.eda.event.UserUpdatedEvent; +import com.iluwatar.eda.handler.UserCreatedEventHandler; +import com.iluwatar.eda.handler.UserUpdatedEventHandler; +import com.iluwatar.eda.model.User; + +import org.junit.Test; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +/** + * Event Dispatcher unit tests to assert and verify correct event dispatcher behaviour + */ +public class EventDispatcherTest { + + /** + * This unit test should register events and event handlers correctly with the event dispatcher + * and events should be dispatched accordingly. + */ + @Test + public void testEventDriverPattern() { + + EventDispatcher dispatcher = spy(new EventDispatcher()); + UserCreatedEventHandler userCreatedEventHandler = spy(new UserCreatedEventHandler()); + UserUpdatedEventHandler userUpdatedEventHandler = spy(new UserUpdatedEventHandler()); + dispatcher.registerChannel(UserCreatedEvent.class, userCreatedEventHandler); + dispatcher.registerChannel(UserUpdatedEvent.class, userUpdatedEventHandler); + + User user = new User("iluwatar"); + + UserCreatedEvent userCreatedEvent = new UserCreatedEvent(user); + UserUpdatedEvent userUpdatedEvent = new UserUpdatedEvent(user); + + //fire a userCreatedEvent and verify that userCreatedEventHandler has been invoked. + dispatcher.onEvent(userCreatedEvent); + verify(userCreatedEventHandler).onEvent(userCreatedEvent); + verify(dispatcher).onEvent(userCreatedEvent); + + //fire a userCreatedEvent and verify that userUpdatedEventHandler has been invoked. + dispatcher.onEvent(userUpdatedEvent); + verify(userUpdatedEventHandler).onEvent(userUpdatedEvent); + verify(dispatcher).onEvent(userUpdatedEvent); + } + + +}