From 321e9d4191cdb1a3592ce758fcc0238e31f3af19 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 23 Nov 2015 11:20:20 +0100 Subject: [PATCH] #113 Event Driven Architecture - added class diagram - added more comments --- .../etc/class_diagram.png | Bin 0 -> 38232 bytes event-driven-architecture/index.md | 6 ++- .../src/main/java/com/iluwatar/eda/App.java | 28 +++++++++++++ .../com/iluwatar/eda/EventDispatcher.java | 39 ++++++++++++++++++ .../java/com/iluwatar/eda/advanced/App.java | 18 -------- .../eda/advanced/EventDispatcher.java | 26 ------------ .../eda/advanced/events/UserCreatedEvent.java | 9 ---- .../eda/advanced/events/UserUpdatedEvent.java | 6 --- .../eda/advanced/framework/Channel.java | 8 ---- .../eda/advanced/framework/DynamicRouter.java | 6 --- .../eda/advanced/framework/Message.java | 6 --- .../eda/{advanced/events => event}/Event.java | 4 +- .../iluwatar/eda/event/UserCreatedEvent.java | 7 ++++ .../iluwatar/eda/event/UserUpdatedEvent.java | 4 ++ .../com/iluwatar/eda/framework/Channel.java | 9 ++++ .../iluwatar/eda/framework/DynamicRouter.java | 11 +++++ .../com/iluwatar/eda/framework/Message.java | 9 ++++ .../handler/UserCreatedEventHandler.java | 8 ++-- .../handler/UserUpdatedEventHandler.java | 9 ++-- .../java/com/iluwatar/eda/simple/App.java | 38 ----------------- .../java/com/iluwatar/eda/simple/Event.java | 15 ------- .../com/iluwatar/eda/simple/EventHandler.java | 15 ------- 22 files changed, 123 insertions(+), 158 deletions(-) create mode 100644 event-driven-architecture/etc/class_diagram.png create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/App.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/App.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/EventDispatcher.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserCreatedEvent.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserUpdatedEvent.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Channel.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/DynamicRouter.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Message.java rename event-driven-architecture/src/main/java/com/iluwatar/eda/{advanced/events => event}/Event.java (56%) create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Channel.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/framework/DynamicRouter.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Message.java rename event-driven-architecture/src/main/java/com/iluwatar/eda/{advanced => }/handler/UserCreatedEventHandler.java (52%) rename event-driven-architecture/src/main/java/com/iluwatar/eda/{advanced => }/handler/UserUpdatedEventHandler.java (50%) delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/simple/App.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/simple/Event.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/simple/EventHandler.java diff --git a/event-driven-architecture/etc/class_diagram.png b/event-driven-architecture/etc/class_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..69560e1f4b80d0d95dc5387189cc753e31d66f65 GIT binary patch literal 38232 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 + * The example below we uses an {@link EventDispatcher} to link/register {@link Event} objects to + * their respective handlers Once an {@link Event} is dispatched, + * it's respective handler is invoked and the {@link Event} is handled accordingly + */ +public class App { + + public static void main(String[] args) { + EventDispatcher dispatcher = new EventDispatcher(); + dispatcher.registerChannel(UserCreatedEvent.class, new UserCreatedEventHandler()); + dispatcher.registerChannel(UserUpdatedEvent.class, new UserUpdatedEventHandler()); + dispatcher.dispatch(new UserCreatedEvent()); + dispatcher.dispatch(new UserUpdatedEvent()); + } + +} 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 new file mode 100644 index 000000000..f947773d0 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java @@ -0,0 +1,39 @@ +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; + +/** + * The {@link Event Dispatcher} handles 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, Channel>(); + } + + /** + * 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); + } + + /** + * Dispathes 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); + } +} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/App.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/App.java deleted file mode 100644 index e7b8c01bc..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/App.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.iluwatar.eda.advanced; - -import com.iluwatar.eda.advanced.events.Event; -import com.iluwatar.eda.advanced.events.UserCreatedEvent; -import com.iluwatar.eda.advanced.events.UserUpdatedEvent; -import com.iluwatar.eda.advanced.handler.UserCreatedEventHandler; -import com.iluwatar.eda.advanced.handler.UserUpdatedEventHandler; - -public class App { - - public static void main(String[] args) { - EventDispatcher dispatcher = new EventDispatcher(); - dispatcher.registerChannel(UserCreatedEvent.class, new UserCreatedEventHandler()); - dispatcher.registerChannel(UserUpdatedEvent.class, new UserUpdatedEventHandler()); - dispatcher.dispatch(new UserCreatedEvent()); - dispatcher.dispatch(new UserUpdatedEvent()); - } -} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/EventDispatcher.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/EventDispatcher.java deleted file mode 100644 index 468160b45..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/EventDispatcher.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.iluwatar.eda.advanced; - -import com.iluwatar.eda.advanced.events.Event; -import com.iluwatar.eda.advanced.framework.Channel; -import com.iluwatar.eda.advanced.framework.DynamicRouter; - -import java.util.HashMap; -import java.util.Map; - -public class EventDispatcher implements DynamicRouter { - - private Map, Channel> handlers; - - public EventDispatcher() { - handlers = new HashMap, Channel>(); - } - - public void registerChannel(Class contentType, - Channel channel) { - handlers.put(contentType, channel); - } - - public void dispatch(Event content) { - handlers.get(content.getClass()).dispatch(content); - } -} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserCreatedEvent.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserCreatedEvent.java deleted file mode 100644 index 75dc776de..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserCreatedEvent.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.iluwatar.eda.advanced.events; - -import com.iluwatar.eda.advanced.events.Event; - -/** - * @author cfarrugia - */ -public class UserCreatedEvent extends Event { -} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserUpdatedEvent.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserUpdatedEvent.java deleted file mode 100644 index df1c0af43..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserUpdatedEvent.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.iluwatar.eda.advanced.events; - -import com.iluwatar.eda.advanced.events.Event; - -public class UserUpdatedEvent extends Event { -} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Channel.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Channel.java deleted file mode 100644 index 20a1cceaa..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Channel.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.iluwatar.eda.advanced.framework; - - -import com.iluwatar.eda.advanced.events.Event; - -public interface Channel { - void dispatch(E message); -} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/DynamicRouter.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/DynamicRouter.java deleted file mode 100644 index 2ae7291f9..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/DynamicRouter.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.iluwatar.eda.advanced.framework; - -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/advanced/framework/Message.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Message.java deleted file mode 100644 index 6243dda97..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Message.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.iluwatar.eda.advanced.framework; - - -public interface Message { - public Class getType(); -} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/Event.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/Event.java similarity index 56% rename from event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/Event.java rename to event-driven-architecture/src/main/java/com/iluwatar/eda/event/Event.java index 64b51ea84..5f3db28e8 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/Event.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/Event.java @@ -1,6 +1,6 @@ -package com.iluwatar.eda.advanced.events; +package com.iluwatar.eda.event; -import com.iluwatar.eda.advanced.framework.Message; +import com.iluwatar.eda.framework.Message; public class Event implements Message { public Class getType() { 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 new file mode 100644 index 000000000..14d83a783 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java @@ -0,0 +1,7 @@ +package com.iluwatar.eda.event; + +/** + * @author cfarrugia + */ +public class UserCreatedEvent extends 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 new file mode 100644 index 000000000..e0e3c3cd6 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java @@ -0,0 +1,4 @@ +package com.iluwatar.eda.event; + +public class UserUpdatedEvent extends 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 new file mode 100644 index 000000000..a8dd97044 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Channel.java @@ -0,0 +1,9 @@ +package com.iluwatar.eda.framework; + +/** + * Channels are delivery points for messages. + * Every {@link Channel} is responsible for a single type of message + */ +public interface Channel { + void dispatch(E 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 new file mode 100644 index 000000000..751318ada --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/DynamicRouter.java @@ -0,0 +1,11 @@ +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/Message.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Message.java new file mode 100644 index 000000000..61880e9cd --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Message.java @@ -0,0 +1,9 @@ +package com.iluwatar.eda.framework; + +/** + * A {@link Message} is an object with a specific type that is associated to a + * specific {@link Channel} + */ +public interface Message { + Class getType(); +} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/handler/UserCreatedEventHandler.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java similarity index 52% rename from event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/handler/UserCreatedEventHandler.java rename to event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java index f3f4535d1..b2e831bf8 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/handler/UserCreatedEventHandler.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java @@ -1,10 +1,10 @@ -package com.iluwatar.eda.advanced.handler; +package com.iluwatar.eda.handler; -import com.iluwatar.eda.advanced.events.UserCreatedEvent; -import com.iluwatar.eda.advanced.framework.Channel; +import com.iluwatar.eda.event.UserCreatedEvent; +import com.iluwatar.eda.framework.Channel; /** - * @author cfarrugia + * Handles the {@link UserCreatedEvent} message */ public class UserCreatedEventHandler implements Channel { diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/handler/UserUpdatedEventHandler.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java similarity index 50% rename from event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/handler/UserUpdatedEventHandler.java rename to event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java index 8ed5dcf51..c7762d247 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/handler/UserUpdatedEventHandler.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java @@ -1,8 +1,11 @@ -package com.iluwatar.eda.advanced.handler; +package com.iluwatar.eda.handler; -import com.iluwatar.eda.advanced.events.UserUpdatedEvent; -import com.iluwatar.eda.advanced.framework.Channel; +import com.iluwatar.eda.event.UserUpdatedEvent; +import com.iluwatar.eda.framework.Channel; +/** + * Handles the {@link UserUpdatedEvent} message + */ public class UserUpdatedEventHandler implements Channel { public void dispatch(UserUpdatedEvent message) { diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/App.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/App.java deleted file mode 100644 index 1399811bb..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/App.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.iluwatar.eda.simple; - -import java.util.LinkedList; -import java.util.Queue; - -/** - * Event-driven architecture (EDA) is a software architecture pattern promoting - * the production, detection, consumption of, and reaction to events. - *

- * This main class publishes events to queue. Each event on the queue is consumed - * and handled depending on the type defined in the {@link Event} - */ -public class App { - - public static void main(String args[]) { - - //create a list of events having different types - //add these events to a simple queue - Queue events = new LinkedList(); - events.add(new Event('A', "Hello")); - events.add(new Event('B', "event-driven")); - events.add(new Event('A', "world!")); - - Event e; - - //the event loop will go through the list of events - //and handle each one depending on it's type - while (!events.isEmpty()) { - e = events.remove(); - - //handle events depending on their type - if (e.type == 'A') - EventHandler.handleEventA(e); - if (e.type == 'B') - EventHandler.handleEventB(e); - } - } -} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/Event.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/Event.java deleted file mode 100644 index 1ba04c303..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/Event.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.iluwatar.eda.simple; - -/** - * The Event class defines the type of event and data related to the event. - */ -public class Event { - - public char type; - public String data; - - public Event(char type, String data){ - this.type = type; - this.data = data; - } -} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/EventHandler.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/EventHandler.java deleted file mode 100644 index d911c6c8e..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/EventHandler.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.iluwatar.eda.simple; - -/** - * The {@link EventHandler} class handles performs actions on {@link Event} objects - */ -public class EventHandler { - - public static void handleEventA(Event e){ - System.out.println(e.data); - } - - public static void handleEventB(Event e){ - System.out.println(e.data.toUpperCase()); - } -}