diff --git a/event-driven-architecture/etc/class_diagram.png b/event-driven-architecture/etc/class_diagram.png
new file mode 100644
index 000000000000..69560e1f4b80
Binary files /dev/null and b/event-driven-architecture/etc/class_diagram.png differ
diff --git a/event-driven-architecture/index.md b/event-driven-architecture/index.md
new file mode 100644
index 000000000000..40d84004d4d0
--- /dev/null
+++ b/event-driven-architecture/index.md
@@ -0,0 +1,29 @@
+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:**
+
+* 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 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:**
+
+* [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)
+* [Event-driven architecture definition](http://searchsoa.techtarget.com/definition/event-driven-architecture)
diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml
new file mode 100644
index 000000000000..32b0bfb3e93d
--- /dev/null
+++ b/event-driven-architecture/pom.xml
@@ -0,0 +1,28 @@
+
+
+
+ 4.0.0
+
+ com.iluwatar
+ java-design-patterns
+ 1.10.0-SNAPSHOT
+
+
+ event-driven-architecture
+
+
+
+ junit
+ 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/App.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java
new file mode 100644
index 000000000000..a1e4c6652191
--- /dev/null
+++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java
@@ -0,0 +1,42 @@
+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;
+
+/**
+ * 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 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, 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.
+ * 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());
+
+ User user = new User("iluwatar");
+ dispatcher.onEvent(new UserCreatedEvent(user));
+ dispatcher.onEvent(new UserUpdatedEvent(user));
+ }
+
+}
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
new file mode 100644
index 000000000000..bcf78f275554
--- /dev/null
+++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/Event.java
@@ -0,0 +1,27 @@
+package com.iluwatar.eda.event;
+
+import com.iluwatar.eda.framework.EventDispatcher;
+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 {
+
+ /**
+ * Returns the event type as a {@link Class} object
+ * In this example, this method is used by the {@link EventDispatcher} to
+ * dispatch events depending on their type.
+ *
+ * @return the Event type as a {@link Class}.
+ */
+ public Class extends Message> 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
new file mode 100644
index 000000000000..f7beaf82c233
--- /dev/null
+++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java
@@ -0,0 +1,21 @@
+package com.iluwatar.eda.event;
+
+import com.iluwatar.eda.model.User;
+
+/**
+ * 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.
+ */
+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
new file mode 100644
index 000000000000..c07e83e7c1c8
--- /dev/null
+++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java
@@ -0,0 +1,21 @@
+package com.iluwatar.eda.event;
+
+import com.iluwatar.eda.model.User;
+
+/**
+ * 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.
+ */
+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/EventDispatcher.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java
new file mode 100644
index 000000000000..d5436acbf045
--- /dev/null
+++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java
@@ -0,0 +1,41 @@
+package com.iluwatar.eda.framework;
+
+import com.iluwatar.eda.event.Event;
+
+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 extends Event> 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 000000000000..cba2f08b2088
--- /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
new file mode 100644
index 000000000000..f8f8c7dfca3f
--- /dev/null
+++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Message.java
@@ -0,0 +1,15 @@
+package com.iluwatar.eda.framework;
+
+/**
+ * A {@link Message} is an object with a specific type that is associated
+ * 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 extends Message> 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
new file mode 100644
index 000000000000..7db4a2d81c48
--- /dev/null
+++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java
@@ -0,0 +1,18 @@
+package com.iluwatar.eda.handler;
+
+import com.iluwatar.eda.event.Event;
+import com.iluwatar.eda.event.UserCreatedEvent;
+import com.iluwatar.eda.framework.Handler;
+
+/**
+ * Handles the {@link UserCreatedEvent} message.
+ */
+public class UserCreatedEventHandler implements Handler {
+
+ @Override
+ 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
new file mode 100644
index 000000000000..754a75c45a73
--- /dev/null
+++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java
@@ -0,0 +1,18 @@
+package com.iluwatar.eda.handler;
+
+import com.iluwatar.eda.event.Event;
+import com.iluwatar.eda.event.UserUpdatedEvent;
+import com.iluwatar.eda.framework.Handler;
+
+/**
+ * Handles the {@link UserUpdatedEvent} message.
+ */
+public class UserUpdatedEventHandler implements Handler {
+
+ @Override
+ 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/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 000000000000..02a7a464177a
--- /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;
+ }
+}
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 000000000000..108280bf122a
--- /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 000000000000..163ffed6e4d8
--- /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);
+ }
+
+
+}
diff --git a/pom.xml b/pom.xml
index 027ba824bdb3..c929f2945f8e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -79,10 +79,10 @@
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
@@ -90,6 +90,7 @@
caching
publish-subscribe
delegation
+ event-driven-architecture