From eb396217d0018f5aaa0545d0f1c5a31fb8eab423 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 22 Nov 2015 19:40:07 +0100 Subject: [PATCH 01/16] #113 Event Driven Architecture - initial commit includes a simple and advanced example of Event-driven architecture --- event-driven-architecture/index.md | 31 +++++++++++++++ event-driven-architecture/pom.xml | 22 +++++++++++ .../java/com/iluwatar/eda/advanced/App.java | 10 +++++ .../com/iluwatar/eda/advanced/Channel.java | 6 +++ .../iluwatar/eda/advanced/DynamicRouter.java | 6 +++ .../java/com/iluwatar/eda/advanced/Event.java | 7 ++++ .../eda/advanced/EventDispatcher.java | 21 ++++++++++ .../com/iluwatar/eda/advanced/Handler.java | 7 ++++ .../com/iluwatar/eda/advanced/Message.java | 6 +++ .../java/com/iluwatar/eda/simple/App.java | 38 +++++++++++++++++++ .../java/com/iluwatar/eda/simple/Event.java | 15 ++++++++ .../com/iluwatar/eda/simple/EventHandler.java | 15 ++++++++ 12 files changed, 184 insertions(+) create mode 100644 event-driven-architecture/index.md create mode 100644 event-driven-architecture/pom.xml create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/App.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Channel.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/DynamicRouter.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Event.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/EventDispatcher.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Handler.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Message.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/simple/App.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/simple/Event.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/simple/EventHandler.java diff --git a/event-driven-architecture/index.md b/event-driven-architecture/index.md new file mode 100644 index 000000000..d5b501c3a --- /dev/null +++ b/event-driven-architecture/index.md @@ -0,0 +1,31 @@ +layout: pattern +title: Event Driven Architecture +folder: event-driven-architecture +permalink: /patterns/event-driven-architecture + + +**Intent:** Send and notify state changes of your objects to other applications using an Event-driven Architecture. + +![alt text](./etc/class_diagram.png "Event Driven Architecture") + +**Applicability:** Use an Event-driven architecture when + +* you want to create a loosely coupled system +* you want to build a more responsive system +* you want a system that is easier to extend + +**Real world examples:** + +* A Loan Application has been accepted/rejected (commercial business). +* A new Rostering Schedule is ready for distribution to all crew (Airline Management System). +* An Illegal Trade Pattern has been detected (Trading Fraud Detection System). +* A simulated car has hits another simulated car (Commercial Racing Game). +* A robot has reached its destination (Real Time Warehouse Management System). +* A HTML message has been received (Web Server). +* A key has been pressed (Text Editor). + +**Credits:** + +* [Event-driven architecture - Wikipedia](http://www.computerweekly.com/feature/Write-through-write-around-write-back-Cache-explained) +* [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) \ No newline at end of file diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml new file mode 100644 index 000000000..fdea3855f --- /dev/null +++ b/event-driven-architecture/pom.xml @@ -0,0 +1,22 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.8.0-SNAPSHOT + + + event-driven-architecture + + + + junit + junit + test + + + \ 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 new file mode 100644 index 000000000..bcd2120d8 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/App.java @@ -0,0 +1,10 @@ +package com.iluwatar.eda.advanced; + +public class App { + + public static void main(String[] args) { + EventDispatcher dispatcher = new EventDispatcher(); + dispatcher.registerChannel(Event.class, new Handler()); + dispatcher.dispatch(new Event()); + } +} diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Channel.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Channel.java new file mode 100644 index 000000000..a977010c6 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Channel.java @@ -0,0 +1,6 @@ +package com.iluwatar.eda.advanced; + + +public interface Channel { + public void dispatch(E message); +} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/DynamicRouter.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/DynamicRouter.java new file mode 100644 index 000000000..f72b79150 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/DynamicRouter.java @@ -0,0 +1,6 @@ +package com.iluwatar.eda.advanced; + +public interface DynamicRouter { + public void registerChannel(Class contentType, Channel channel); + public void dispatch(E content); +} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Event.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Event.java new file mode 100644 index 000000000..8ad48c704 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Event.java @@ -0,0 +1,7 @@ +package com.iluwatar.eda.advanced; + +public class Event implements Message { + public Class getType() { + return getClass(); + } +} \ No newline at end of file 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 new file mode 100644 index 000000000..def8920c1 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/EventDispatcher.java @@ -0,0 +1,21 @@ +package com.iluwatar.eda.advanced; + +import java.util.HashMap; +import java.util.Map; + +public class EventDispatcher implements DynamicRouter { + private Map, Handler> handlers; + + public EventDispatcher() { + handlers = new HashMap, Handler>(); + } + + public void registerChannel(Class contentType, + Channel channel) { + handlers.put(contentType, (Handler)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/Handler.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Handler.java new file mode 100644 index 000000000..68631b207 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Handler.java @@ -0,0 +1,7 @@ +package com.iluwatar.eda.advanced; + +public class Handler implements Channel { + public void dispatch(Event message) { + System.out.println(message.getClass()); + } +} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Message.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Message.java new file mode 100644 index 000000000..00d335191 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Message.java @@ -0,0 +1,6 @@ +package com.iluwatar.eda.advanced; + + +public interface Message { + public Class getType(); +} 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 new file mode 100644 index 000000000..1399811bb --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/App.java @@ -0,0 +1,38 @@ +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 new file mode 100644 index 000000000..1ba04c303 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/Event.java @@ -0,0 +1,15 @@ +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 new file mode 100644 index 000000000..d911c6c8e --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/simple/EventHandler.java @@ -0,0 +1,15 @@ +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()); + } +} From 3ef0921f203fbc022c8081fe717ec0af5587ce77 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 23 Nov 2015 00:02:58 +0100 Subject: [PATCH 02/16] #113 Event Driven Architecture - refactored and moved around some classes --- .../main/java/com/iluwatar/eda/advanced/App.java | 12 ++++++++++-- .../java/com/iluwatar/eda/advanced/Channel.java | 6 ------ .../com/iluwatar/eda/advanced/DynamicRouter.java | 6 ------ .../iluwatar/eda/advanced/EventDispatcher.java | 13 +++++++++---- .../java/com/iluwatar/eda/advanced/Handler.java | 7 ------- .../iluwatar/eda/advanced/{ => events}/Event.java | 4 +++- .../eda/advanced/events/UserCreatedEvent.java | 9 +++++++++ .../eda/advanced/events/UserUpdatedEvent.java | 6 ++++++ .../iluwatar/eda/advanced/framework/Channel.java | 8 ++++++++ .../eda/advanced/framework/DynamicRouter.java | 6 ++++++ .../eda/advanced/{ => framework}/Message.java | 2 +- .../advanced/handler/UserCreatedEventHandler.java | 15 +++++++++++++++ .../advanced/handler/UserUpdatedEventHandler.java | 12 ++++++++++++ 13 files changed, 79 insertions(+), 27 deletions(-) delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Channel.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/DynamicRouter.java delete mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Handler.java rename event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/{ => events}/Event.java (56%) create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserCreatedEvent.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserUpdatedEvent.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Channel.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/DynamicRouter.java rename event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/{ => framework}/Message.java (63%) create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/handler/UserCreatedEventHandler.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/handler/UserUpdatedEventHandler.java 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 index bcd2120d8..e7b8c01bc 100644 --- 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 @@ -1,10 +1,18 @@ 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(Event.class, new Handler()); - dispatcher.dispatch(new Event()); + 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/Channel.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Channel.java deleted file mode 100644 index a977010c6..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Channel.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.iluwatar.eda.advanced; - - -public interface Channel { - public void dispatch(E message); -} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/DynamicRouter.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/DynamicRouter.java deleted file mode 100644 index f72b79150..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/DynamicRouter.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.iluwatar.eda.advanced; - -public interface DynamicRouter { - public void registerChannel(Class contentType, Channel channel); - public void dispatch(E content); -} \ No newline at end of file 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 index def8920c1..468160b45 100644 --- 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 @@ -1,18 +1,23 @@ 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, Handler> handlers; + + private Map, Channel> handlers; public EventDispatcher() { - handlers = new HashMap, Handler>(); + handlers = new HashMap, Channel>(); } public void registerChannel(Class contentType, - Channel channel) { - handlers.put(contentType, (Handler)channel); + Channel channel) { + handlers.put(contentType, channel); } public void dispatch(Event content) { diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Handler.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Handler.java deleted file mode 100644 index 68631b207..000000000 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Handler.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.iluwatar.eda.advanced; - -public class Handler implements Channel { - public void dispatch(Event message) { - System.out.println(message.getClass()); - } -} \ No newline at end of file diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Event.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/Event.java similarity index 56% rename from event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Event.java rename to event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/Event.java index 8ad48c704..64b51ea84 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Event.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/Event.java @@ -1,4 +1,6 @@ -package com.iluwatar.eda.advanced; +package com.iluwatar.eda.advanced.events; + +import com.iluwatar.eda.advanced.framework.Message; public class Event implements Message { public Class getType() { 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 new file mode 100644 index 000000000..75dc776de --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserCreatedEvent.java @@ -0,0 +1,9 @@ +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 new file mode 100644 index 000000000..df1c0af43 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/events/UserUpdatedEvent.java @@ -0,0 +1,6 @@ +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 new file mode 100644 index 000000000..20a1cceaa --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Channel.java @@ -0,0 +1,8 @@ +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 new file mode 100644 index 000000000..2ae7291f9 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/DynamicRouter.java @@ -0,0 +1,6 @@ +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/Message.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Message.java similarity index 63% rename from event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Message.java rename to event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Message.java index 00d335191..6243dda97 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/Message.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/framework/Message.java @@ -1,4 +1,4 @@ -package com.iluwatar.eda.advanced; +package com.iluwatar.eda.advanced.framework; public interface Message { 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/advanced/handler/UserCreatedEventHandler.java new file mode 100644 index 000000000..caacd5583 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/handler/UserCreatedEventHandler.java @@ -0,0 +1,15 @@ +package com.iluwatar.eda.advanced.handler; + +import com.iluwatar.eda.advanced.events.Event; +import com.iluwatar.eda.advanced.events.UserCreatedEvent; +import com.iluwatar.eda.advanced.framework.Channel; + +/** + * @author cfarrugia + */ +public class UserCreatedEventHandler implements Channel { + + public void dispatch(UserCreatedEvent message) { + System.out.println("User Created!"); + } +} 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/advanced/handler/UserUpdatedEventHandler.java new file mode 100644 index 000000000..dada6fafc --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/advanced/handler/UserUpdatedEventHandler.java @@ -0,0 +1,12 @@ +package com.iluwatar.eda.advanced.handler; + +import com.iluwatar.eda.advanced.events.Event; +import com.iluwatar.eda.advanced.events.UserUpdatedEvent; +import com.iluwatar.eda.advanced.framework.Channel; + +public class UserUpdatedEventHandler implements Channel { + + public void dispatch(UserUpdatedEvent message) { + System.out.println("User Updated!"); + } +} From b4aeca3aa0117e899c87e4b648fc7acc3601aa1f Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 23 Nov 2015 00:04:44 +0100 Subject: [PATCH 03/16] #113 Event Driven Architecture - removed unused imports --- .../iluwatar/eda/advanced/handler/UserCreatedEventHandler.java | 1 - .../iluwatar/eda/advanced/handler/UserUpdatedEventHandler.java | 1 - 2 files changed, 2 deletions(-) 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/advanced/handler/UserCreatedEventHandler.java index caacd5583..f3f4535d1 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/advanced/handler/UserCreatedEventHandler.java @@ -1,6 +1,5 @@ package com.iluwatar.eda.advanced.handler; -import com.iluwatar.eda.advanced.events.Event; import com.iluwatar.eda.advanced.events.UserCreatedEvent; import com.iluwatar.eda.advanced.framework.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/advanced/handler/UserUpdatedEventHandler.java index dada6fafc..8ed5dcf51 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/advanced/handler/UserUpdatedEventHandler.java @@ -1,6 +1,5 @@ package com.iluwatar.eda.advanced.handler; -import com.iluwatar.eda.advanced.events.Event; import com.iluwatar.eda.advanced.events.UserUpdatedEvent; import com.iluwatar.eda.advanced.framework.Channel; From 321e9d4191cdb1a3592ce758fcc0238e31f3af19 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 23 Nov 2015 11:20:20 +0100 Subject: [PATCH 04/16] #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()); - } -} From fc70a706c680ff1e58cf930846dbe2f3d15b8240 Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Sat, 28 Nov 2015 10:57:00 +0100 Subject: [PATCH 05/16] #113 Event Driven Architecture Adds module to the root pom.xml Fixes indentation --- pom.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index bcdf9affe..e0e6a0cc6 100644 --- a/pom.xml +++ b/pom.xml @@ -76,16 +76,17 @@ front-controller repository async-method-invocation - monostate + monostate step-builder - business-delegate - half-sync-half-async + business-delegate + half-sync-half-async layers message-channel fluentinterface reactor caching publish-subscribe + event-driven-architecture From b8b94b697aef8601f4d2564b8be7ee2a443f7688 Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Sat, 28 Nov 2015 13:12:16 +0100 Subject: [PATCH 06/16] #113 Event Driven Architecture Adds more Javadoc --- event-driven-architecture/pom.xml | 24 ++++++++++ .../src/main/java/com/iluwatar/eda/App.java | 27 ++++++----- .../com/iluwatar/eda/EventDispatcher.java | 46 ++++++++++--------- .../java/com/iluwatar/eda/event/Event.java | 23 ++++++++-- .../iluwatar/eda/event/UserCreatedEvent.java | 3 +- .../iluwatar/eda/event/UserUpdatedEvent.java | 4 ++ .../com/iluwatar/eda/framework/Channel.java | 8 ++-- .../iluwatar/eda/framework/DynamicRouter.java | 10 ++-- .../com/iluwatar/eda/framework/Message.java | 6 +-- .../eda/handler/UserCreatedEventHandler.java | 9 ++-- .../eda/handler/UserUpdatedEventHandler.java | 9 ++-- pom.xml | 4 +- 12 files changed, 112 insertions(+), 61 deletions(-) diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml index fdea3855f..0c72f2157 100644 --- a/event-driven-architecture/pom.xml +++ b/event-driven-architecture/pom.xml @@ -19,4 +19,28 @@ test + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.15 + + + validate + + check + + validate + + checkstyle.xml + UTF-8 + true + true + + + + + + \ 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 e8b8d2d09..ab4b2e489 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 @@ -7,22 +7,21 @@ import com.iluwatar.eda.handler.UserCreatedEventHandler; import com.iluwatar.eda.handler.UserUpdatedEventHandler; /** - * An event-driven architecture (EDA) is a framework that orchestrates behavior around the production, - * detection and consumption of events as well as the responses they evoke. - * An event is any identifiable occurrence that has significance for system hardware or software. - *

- * 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 + * An event-driven architecture (EDA) is a framework that orchestrates behavior around the + * production, detection and consumption of events as well as the responses they evoke. An event is + * any identifiable occurrence that has significance for system hardware or software.

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()); - } + 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 index f947773d0..3b44a414a 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java @@ -8,32 +8,36 @@ import java.util.HashMap; import java.util.Map; /** - * The {@link Event Dispatcher} handles routing of {@link Event} messages to associated channels. + * 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; + private Map, Channel> handlers; - public EventDispatcher() { - handlers = new HashMap, Channel>(); - } + 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); - } + /** + * 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); - } + /** + * 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); + } } \ 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 5f3db28e8..9a2518ebf 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 @@ -2,8 +2,25 @@ package com.iluwatar.eda.event; import com.iluwatar.eda.framework.Message; +/** + * The {@link Event} class serves as a base class for defining custom events happening with your + * system. In this example we have two types of events defined. + *

    + *
  • {@link UserCreatedEvent} - used when a user is created
  • + *
  • {@link UserUpdatedEvent} - used when a user is updated
  • + *
+ * Events can be distinguished using the {@link #getType() getType} method. + */ public class Event implements Message { - public Class getType() { - return getClass(); - } + + /** + * 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. + * + * @return the Event type as a {@link Class}. + */ + public Class getType() { + return getClass(); + } } \ No newline at end of file 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 14d83a783..1a61dfa59 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 @@ -1,7 +1,8 @@ package com.iluwatar.eda.event; /** - * @author cfarrugia + * The {@link UserCreatedEvent} class should should be dispatched whenever a user has been created. + * This class can be extended to contain details about the user has been created. */ 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 index e0e3c3cd6..3b401ecd1 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 @@ -1,4 +1,8 @@ package com.iluwatar.eda.event; +/** + * The {@link UserUpdatedEvent} class should should be dispatched whenever a user has been updated. + * This class can be extended to contain details about the user has been updated. + */ 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 index a8dd97044..32eca09d4 100644 --- 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 @@ -1,9 +1,11 @@ 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 + * Channels are delivery points for messages. Every {@link Channel} is responsible for a single type + * of message */ public interface Channel { - void dispatch(E message); + 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 index 751318ada..23fd6044f 100644 --- 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 @@ -2,10 +2,12 @@ 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. + * 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); + + 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 index 61880e9cd..2f8acb343 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 @@ -1,9 +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} + * A {@link Message} is an object with a specific type that is associated + * to a specific {@link Channel}. */ public interface Message { - Class getType(); + 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 b2e831bf8..e406f7c51 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 @@ -4,11 +4,10 @@ import com.iluwatar.eda.event.UserCreatedEvent; import com.iluwatar.eda.framework.Channel; /** - * Handles the {@link UserCreatedEvent} message + * Handles the {@link UserCreatedEvent} message. */ public class UserCreatedEventHandler implements Channel { - - public void dispatch(UserCreatedEvent message) { - System.out.println("User Created!"); - } + public void dispatch(UserCreatedEvent message) { + System.out.println("User Created!"); + } } 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 c7762d247..d59954806 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 @@ -4,11 +4,10 @@ import com.iluwatar.eda.event.UserUpdatedEvent; import com.iluwatar.eda.framework.Channel; /** - * Handles the {@link UserUpdatedEvent} message + * Handles the {@link UserUpdatedEvent} message. */ public class UserUpdatedEventHandler implements Channel { - - public void dispatch(UserUpdatedEvent message) { - System.out.println("User Updated!"); - } + public void dispatch(UserUpdatedEvent message) { + System.out.println("User Updated!"); + } } diff --git a/pom.xml b/pom.xml index e0e6a0cc6..9e4c39bf9 100644 --- a/pom.xml +++ b/pom.xml @@ -244,8 +244,8 @@ checkstyle.xml UTF-8 - false - false + true + true From e1c0731f7e2c58fba76c3c6ec393890b578e4370 Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Sat, 28 Nov 2015 15:03:22 +0100 Subject: [PATCH 07/16] #113 Event Driven Architecture Adds more Javadoc and fixes checkstyle issues. --- event-driven-architecture/pom.xml | 25 +------------------ .../src/main/java/com/iluwatar/eda/App.java | 24 ++++++++++++++---- .../com/iluwatar/eda/EventDispatcher.java | 7 +++--- .../iluwatar/eda/event/UserCreatedEvent.java | 16 +++++++++++- .../iluwatar/eda/event/UserUpdatedEvent.java | 15 ++++++++++- .../com/iluwatar/eda/framework/Channel.java | 2 +- .../eda/handler/UserCreatedEventHandler.java | 10 ++++++-- .../eda/handler/UserUpdatedEventHandler.java | 10 ++++++-- .../java/com/iluwatar/eda/model/User.java | 21 ++++++++++++++++ 9 files changed, 90 insertions(+), 40 deletions(-) create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/model/User.java diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml index 0c72f2157..2c011759b 100644 --- a/event-driven-architecture/pom.xml +++ b/event-driven-architecture/pom.xml @@ -19,28 +19,5 @@ test - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 2.15 - - - validate - - check - - validate - - checkstyle.xml - UTF-8 - true - true - - - - - - + \ 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 ab4b2e489..5ef58d20b 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 @@ -5,23 +5,37 @@ 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; /** * An event-driven architecture (EDA) is a framework that orchestrates behavior around the * production, detection and consumption of events as well as the responses they evoke. An event is * any identifiable occurrence that has significance for system hardware or software.

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 + * example below 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 { + /** + * Once the {@link EventDispatcher} is initialised, channels 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. + * When a user is saved, the {@link UserCreatedEvent} can be dispatched. + * On the other hand, when a user is updated, {@link UserUpdatedEvent} can be dispatched. + * + */ 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()); + + User user = new User("iluwatar"); + dispatcher.dispatch(new UserCreatedEvent(user)); + dispatcher.dispatch(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 index 3b44a414a..e52f9db46 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java @@ -8,21 +8,20 @@ import java.util.HashMap; import java.util.Map; /** - * The {@link Event Dispatcher} handles routing of {@link Event} messages - * to associated channels. + * 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; + private Map, Channel> handlers; public EventDispatcher() { handlers = new HashMap<>(); } /** - * Links an {@link Event} to a specific {@link 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} 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 1a61dfa59..3d6187b7e 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 @@ -1,8 +1,22 @@ 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. - * This class can be extended to contain details about the 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. */ public class UserCreatedEvent extends Event { + + private User user; + + public UserCreatedEvent(User user) { + this.user = user; + } + + + public User getUser() { + return user; + } } 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 3b401ecd1..f3bce8124 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 @@ -1,8 +1,21 @@ 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. - * This class can be extended to contain details about the 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. */ public class UserUpdatedEvent extends Event { + + private User user; + + public UserUpdatedEvent(User user) { + this.user = user; + } + + public User getUser() { + return user; + } } 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 index 32eca09d4..1684a9641 100644 --- 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 @@ -7,5 +7,5 @@ import com.iluwatar.eda.event.Event; * of message */ public interface Channel { - void dispatch(E message); + void dispatch(Event message); } \ No newline at end of file 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 e406f7c51..49d209eb0 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 @@ -1,13 +1,19 @@ 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; /** * Handles the {@link UserCreatedEvent} message. */ public class UserCreatedEventHandler implements Channel { - public void dispatch(UserCreatedEvent message) { - System.out.println("User Created!"); + + @Override + public void dispatch(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 d59954806..fd3a6d3ba 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,5 +1,7 @@ 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; @@ -7,7 +9,11 @@ import com.iluwatar.eda.framework.Channel; * Handles the {@link UserUpdatedEvent} message. */ public class UserUpdatedEventHandler implements Channel { - public void dispatch(UserUpdatedEvent message) { - System.out.println("User Updated!"); + + @Override + public void dispatch(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/main/java/com/iluwatar/eda/model/User.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/model/User.java new file mode 100644 index 000000000..02a7a4641 --- /dev/null +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/model/User.java @@ -0,0 +1,21 @@ +package com.iluwatar.eda.model; + +import com.iluwatar.eda.event.UserCreatedEvent; +import com.iluwatar.eda.event.UserUpdatedEvent; + +/** + * This {@link User} class is a basic pojo used to demonstrate user data sent along with + * the {@link UserCreatedEvent} and {@link UserUpdatedEvent} events. + */ +public class User { + + private String username; + + public User(String username) { + this.username = username; + } + + public String getUsername() { + return username; + } +} From 3ad36020aac253a0b1cbf857db7825cd729ee108 Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Sat, 28 Nov 2015 17:25:15 +0100 Subject: [PATCH 08/16] #113 Event Driven Architecture Adds unit test to assert and verify pattern behaviour --- event-driven-architecture/pom.xml | 7 ++- .../com/iluwatar/eda/EventDispatcher.java | 8 ++++ .../iluwatar/eda/event/UserCreatedEvent.java | 1 - .../src/test/java/EventDrivenTest.java | 47 +++++++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 event-driven-architecture/src/test/java/EventDrivenTest.java diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml index 2c011759b..77504657f 100644 --- a/event-driven-architecture/pom.xml +++ b/event-driven-architecture/pom.xml @@ -18,6 +18,11 @@ junit test - + + org.mockito + mockito-core + test + + \ No newline at end of file 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 index e52f9db46..89f8de71b 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java @@ -39,4 +39,12 @@ public class EventDispatcher implements DynamicRouter { public void dispatch(Event content) { handlers.get(content.getClass()).dispatch(content); } + + /** + * Returns a map of registered event handlers. + * @return {@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/UserCreatedEvent.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java index 3d6187b7e..da2e31c8a 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 @@ -15,7 +15,6 @@ public class UserCreatedEvent extends Event { this.user = user; } - public User getUser() { return user; } diff --git a/event-driven-architecture/src/test/java/EventDrivenTest.java b/event-driven-architecture/src/test/java/EventDrivenTest.java new file mode 100644 index 000000000..70579d557 --- /dev/null +++ b/event-driven-architecture/src/test/java/EventDrivenTest.java @@ -0,0 +1,47 @@ +import com.iluwatar.eda.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; + +import static org.junit.Assert.assertEquals; + +public class EventDrivenTest { + + @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); + + } +} From d9a1d1cef9184bda742e1164d7c1887735b47e82 Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Sat, 28 Nov 2015 17:58:32 +0100 Subject: [PATCH 09/16] #113 Event Driven Architecture Adds unit test to assert and verify pattern event get type behaviour. Also added unit test comments. --- .../src/test/java/EventDrivenTest.java | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/event-driven-architecture/src/test/java/EventDrivenTest.java b/event-driven-architecture/src/test/java/EventDrivenTest.java index 70579d557..addc5fafa 100644 --- a/event-driven-architecture/src/test/java/EventDrivenTest.java +++ b/event-driven-architecture/src/test/java/EventDrivenTest.java @@ -1,4 +1,5 @@ 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; @@ -6,20 +7,25 @@ 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(){ + public void testEventDriverPattern() { EventDispatcher dispatcher = spy(new EventDispatcher()); - UserCreatedEventHandler userCreatedEventHandler = new UserCreatedEventHandler(); + UserCreatedEventHandler userCreatedEventHandler = new UserCreatedEventHandler(); UserUpdatedEventHandler userUpdatedEventHandler = new UserUpdatedEventHandler(); dispatcher.registerChannel(UserCreatedEvent.class, userCreatedEventHandler); dispatcher.registerChannel(UserUpdatedEvent.class, userUpdatedEventHandler); @@ -27,10 +33,10 @@ public class EventDrivenTest { assertEquals("Two handlers must be registered", 2, dispatcher.getHandlers().size()); assertEquals("UserCreatedEvent must return the UserCreatedEventHandler", userCreatedEventHandler, - (UserCreatedEventHandler)dispatcher.getHandlers().get(UserCreatedEvent.class)); + (UserCreatedEventHandler) dispatcher.getHandlers().get(UserCreatedEvent.class)); assertEquals("UserUpdatedEvent must be registered to the UserUpdatedEventHandler", userUpdatedEventHandler, - (UserUpdatedEventHandler)dispatcher.getHandlers().get(UserUpdatedEvent.class)); + (UserUpdatedEventHandler) dispatcher.getHandlers().get(UserUpdatedEvent.class)); User user = new User("iluwatar"); @@ -42,6 +48,16 @@ public class EventDrivenTest { //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()); } } From 9e857d7dd6e6f0653953c4da787a72c2cfd0c0be Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Sat, 28 Nov 2015 19:05:23 +0100 Subject: [PATCH 10/16] #113 Event Driven Architecture Fixed javadoc --- .../src/main/java/com/iluwatar/eda/EventDispatcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 89f8de71b..f68fdb71b 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/EventDispatcher.java @@ -42,7 +42,7 @@ public class EventDispatcher implements DynamicRouter { /** * Returns a map of registered event handlers. - * @return {@Map} of registered event handlers. + * @return {@link Map} of registered event handlers. */ public Map, Channel> getHandlers() { return handlers; From cfb0fafc7d5f98ec94cd41ffaaf28af80489dc6c Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Tue, 1 Dec 2015 23:30:01 +0100 Subject: [PATCH 11/16] #113 Event Driven Architecture Adds various changes including : - Fixes to Javadoc - Test refactoring and improvements - Refactored EventDispatcher to be immutable - Removed DynamicRouter interface since it not needed - Renamed Channel to a more appropriate name - Handler --- event-driven-architecture/index.md | 1 - .../src/main/java/com/iluwatar/eda/App.java | 7 ++- .../com/iluwatar/eda/EventDispatcher.java | 50 --------------- .../java/com/iluwatar/eda/event/Event.java | 5 +- .../iluwatar/eda/event/UserCreatedEvent.java | 2 +- .../iluwatar/eda/event/UserUpdatedEvent.java | 2 +- .../com/iluwatar/eda/framework/Channel.java | 11 ---- .../iluwatar/eda/framework/DynamicRouter.java | 13 ---- .../eda/framework/EventDispatcher.java | 42 +++++++++++++ .../com/iluwatar/eda/framework/Handler.java | 18 ++++++ .../com/iluwatar/eda/framework/Message.java | 8 ++- .../eda/handler/UserCreatedEventHandler.java | 7 +-- .../eda/handler/UserUpdatedEventHandler.java | 7 +-- .../src/test/java/EventDrivenTest.java | 63 ------------------- .../eda/event/UserCreatedEventTest.java | 24 +++++++ .../eda/framework/EventDispatcherTest.java | 50 +++++++++++++++ 16 files changed, 156 insertions(+), 154 deletions(-) delete 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/framework/Channel.java delete 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/EventDispatcher.java create mode 100644 event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java delete mode 100644 event-driven-architecture/src/test/java/EventDrivenTest.java create mode 100644 event-driven-architecture/src/test/java/com/iluwatar/eda/event/UserCreatedEventTest.java create mode 100644 event-driven-architecture/src/test/java/com/iluwatar/eda/framework/EventDispatcherTest.java 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); + } + + +} From 2aa20b7445c27caf540af62ca1be60dcb2ddf631 Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Tue, 1 Dec 2015 23:33:26 +0100 Subject: [PATCH 12/16] #113 Event Driven Architecture Adds various changes including : - Fixes to Javadoc --- .../src/main/java/com/iluwatar/eda/event/Event.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9ef3dd7db..bcf78f275 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 @@ -17,7 +17,7 @@ public class Event implements Message { /** * Returns the event type as a {@link Class} object * In this example, this method is used by the {@link EventDispatcher} to - * onEvent events depending on their type. + * dispatch events depending on their type. * * @return the Event type as a {@link Class}. */ From 0b46a9985df028bb0445bd52df0708d6bc2dea98 Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Wed, 2 Dec 2015 01:39:20 +0100 Subject: [PATCH 13/16] #113 Event Driven Architecture Updated index.md with eda uses --- event-driven-architecture/index.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/event-driven-architecture/index.md b/event-driven-architecture/index.md index 0a4be0bb6..f7b586c88 100644 --- a/event-driven-architecture/index.md +++ b/event-driven-architecture/index.md @@ -16,13 +16,10 @@ permalink: /patterns/event-driven-architecture **Real world examples:** -* A Loan Application has been accepted/rejected (Commercial Business). -* A new Rostering Schedule is ready for distribution to all crew (Airline Management System). -* An Illegal Trade Pattern has been detected (Trading Fraud Detection System). -* A simulated car has hits another simulated car (Commercial Racing Game). -* A robot has reached its destination (Real Time Warehouse Management System). -* A HTML message has been received (Web Server). -* A key has been pressed (Text Editor). +* SendGrid, an email API, sends events whenever an email is processed, delivered, opened etc... (https://sendgrid.com/docs/API_Reference/Webhooks/event.html) +* Chargify, a billing API, exposes payment activity through various events (https://docs.chargify.com/api-events) +* Amazon's AWS Lambda, lets you execute code in response to such as changes to Amazon S3 buckets, updates to an Amazon DynamoDB table, or custom events generated by your applications or devices. (https://aws.amazon.com/lambda) +* MySQL runs triggers based on events such as inserts and update events happening on database tables. **Credits:** From 898f3a428c508418e1fc2ca27c793bd395e7a7e0 Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Wed, 2 Dec 2015 01:43:34 +0100 Subject: [PATCH 14/16] #113 Event Driven Architecture Fixed a typo in index.md --- event-driven-architecture/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/event-driven-architecture/index.md b/event-driven-architecture/index.md index f7b586c88..40d84004d 100644 --- a/event-driven-architecture/index.md +++ b/event-driven-architecture/index.md @@ -18,7 +18,7 @@ permalink: /patterns/event-driven-architecture * SendGrid, an email API, sends events whenever an email is processed, delivered, opened etc... (https://sendgrid.com/docs/API_Reference/Webhooks/event.html) * Chargify, a billing API, exposes payment activity through various events (https://docs.chargify.com/api-events) -* Amazon's AWS Lambda, lets you execute code in response to such as changes to Amazon S3 buckets, updates to an Amazon DynamoDB table, or custom events generated by your applications or devices. (https://aws.amazon.com/lambda) +* Amazon's AWS Lambda, lets you execute code in response to events such as changes to Amazon S3 buckets, updates to an Amazon DynamoDB table, or custom events generated by your applications or devices. (https://aws.amazon.com/lambda) * MySQL runs triggers based on events such as inserts and update events happening on database tables. **Credits:** From 2ea9bfef19f6683ad493b1aee448c347c2adc6fc Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Sat, 2 Jan 2016 14:04:07 +0100 Subject: [PATCH 15/16] #113 Event Driven Architecture Fixed PMD errors --- .../main/java/com/iluwatar/eda/framework/EventDispatcher.java | 1 - 1 file changed, 1 deletion(-) 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 index fef303937..d5436acbf 100644 --- 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 @@ -1,7 +1,6 @@ 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; From 7176b861461a850ba226857cae9d203d4d1e9c04 Mon Sep 17 00:00:00 2001 From: cfarrugia Date: Sat, 2 Jan 2016 14:05:36 +0100 Subject: [PATCH 16/16] #113 Event Driven Architecture bumped up version to 1.10 --- event-driven-architecture/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml index 77504657f..32b0bfb3e 100644 --- a/event-driven-architecture/pom.xml +++ b/event-driven-architecture/pom.xml @@ -7,7 +7,7 @@ com.iluwatar java-design-patterns - 1.8.0-SNAPSHOT + 1.10.0-SNAPSHOT event-driven-architecture