Skip to content

Commit b6beffe

Browse files
committed
Merge pull request iluwatar#299 from genericmethod/master
iluwatar#113 Event-driven Architecture
2 parents 317a599 + 1987bdb commit b6beffe

17 files changed

Lines changed: 573 additions & 3 deletions

File tree

78.4 KB
Loading
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<class-diagram version="1.1.9" icons="true" automaticImage="PNG" always-add-relationships="true" generalizations="true"
3+
realizations="true" associations="true" dependencies="true" nesting-relationships="true" router="FAN">
4+
<class id="1" language="java" name="com.iluwatar.eda.model.User" project="event-driven-architecture"
5+
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/model/User.java" binary="false"
6+
corner="BOTTOM_RIGHT">
7+
<position height="-1" width="-1" x="937" y="618"/>
8+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
9+
sort-features="false" accessors="true" visibility="true">
10+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
11+
<operations public="true" package="true" protected="true" private="true" static="true"/>
12+
</display>
13+
</class>
14+
<class id="2" language="java" name="com.iluwatar.eda.handler.UserUpdatedEventHandler"
15+
project="event-driven-architecture"
16+
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java" binary="false"
17+
corner="BOTTOM_RIGHT">
18+
<position height="-1" width="-1" x="936" y="90"/>
19+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
20+
sort-features="false" accessors="true" visibility="true">
21+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
22+
<operations public="true" package="true" protected="true" private="true" static="true"/>
23+
</display>
24+
</class>
25+
<class id="3" language="java" name="com.iluwatar.eda.handler.UserCreatedEventHandler"
26+
project="event-driven-architecture"
27+
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java" binary="false"
28+
corner="BOTTOM_RIGHT">
29+
<position height="101" width="200" x="41" y="37"/>
30+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
31+
sort-features="false" accessors="true" visibility="true">
32+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
33+
<operations public="true" package="true" protected="true" private="true" static="true"/>
34+
</display>
35+
</class>
36+
<interface id="4" language="java" name="com.iluwatar.eda.framework.Message" project="event-driven-architecture"
37+
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Message.java" binary="false"
38+
corner="BOTTOM_RIGHT">
39+
<position height="-1" width="-1" x="298" y="189"/>
40+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
41+
sort-features="false" accessors="true" visibility="true">
42+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
43+
<operations public="true" package="true" protected="true" private="true" static="true"/>
44+
</display>
45+
</interface>
46+
<interface id="5" language="java" name="com.iluwatar.eda.framework.Handler" project="event-driven-architecture"
47+
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java" binary="false"
48+
corner="BOTTOM_RIGHT">
49+
<position height="-1" width="-1" x="532" y="89"/>
50+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
51+
sort-features="false" accessors="true" visibility="true">
52+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
53+
<operations public="true" package="true" protected="true" private="true" static="true"/>
54+
</display>
55+
</interface>
56+
<class id="6" language="java" name="com.iluwatar.eda.framework.EventDispatcher" project="event-driven-architecture"
57+
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java" binary="false"
58+
corner="BOTTOM_RIGHT">
59+
<position height="-1" width="-1" x="613" y="292"/>
60+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
61+
sort-features="false" accessors="true" visibility="true">
62+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
63+
<operations public="true" package="true" protected="true" private="true" static="true"/>
64+
</display>
65+
</class>
66+
<class id="7" language="java" name="com.iluwatar.eda.event.UserCreatedEvent" project="event-driven-architecture"
67+
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java" binary="false"
68+
corner="BOTTOM_RIGHT">
69+
<position height="-1" width="-1" x="145" y="618"/>
70+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
71+
sort-features="false" accessors="true" visibility="true">
72+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
73+
<operations public="true" package="true" protected="true" private="true" static="true"/>
74+
</display>
75+
</class>
76+
<class id="8" language="java" name="com.iluwatar.eda.event.UserUpdatedEvent" project="event-driven-architecture"
77+
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java" binary="false"
78+
corner="BOTTOM_RIGHT">
79+
<position height="-1" width="-1" x="769" y="455"/>
80+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
81+
sort-features="false" accessors="true" visibility="true">
82+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
83+
<operations public="true" package="true" protected="true" private="true" static="true"/>
84+
</display>
85+
</class>
86+
<class id="9" language="java" name="com.iluwatar.eda.event.Event" project="event-driven-architecture"
87+
file="/event-driven-architecture/src/main/java/com/iluwatar/eda/event/Event.java" binary="false"
88+
corner="BOTTOM_RIGHT">
89+
<position height="-1" width="-1" x="299" y="460"/>
90+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
91+
sort-features="false" accessors="true" visibility="true">
92+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
93+
<operations public="true" package="true" protected="true" private="true" static="true"/>
94+
</display>
95+
</class>
96+
<dependency id="10">
97+
<bendpoint x="869" y="253"/>
98+
<end type="SOURCE" refId="2"/>
99+
<end type="TARGET" refId="8"/>
100+
</dependency>
101+
<dependency id="11">
102+
<bendpoint x="140" y="196"/>
103+
<end type="SOURCE" refId="3"/>
104+
<end type="TARGET" refId="9"/>
105+
</dependency>
106+
<dependency id="12">
107+
<bendpoint x="17" y="90"/>
108+
<bendpoint x="17" y="708"/>
109+
<bendpoint x="939" y="703"/>
110+
<end type="SOURCE" refId="3"/>
111+
<end type="TARGET" refId="1"/>
112+
</dependency>
113+
<dependency id="13">
114+
<bendpoint x="935" y="318"/>
115+
<bendpoint x="936" y="417"/>
116+
<end type="SOURCE" refId="2"/>
117+
<end type="TARGET" refId="1"/>
118+
</dependency>
119+
<dependency id="14">
120+
<bendpoint x="757" y="378"/>
121+
<end type="SOURCE" refId="2"/>
122+
<end type="TARGET" refId="9"/>
123+
</dependency>
124+
<generalization id="15">
125+
<end type="SOURCE" refId="7"/>
126+
<end type="TARGET" refId="9"/>
127+
</generalization>
128+
<association id="16">
129+
<end type="SOURCE" refId="8" navigable="false">
130+
<attribute id="17" name="user"/>
131+
<multiplicity id="18" minimum="0" maximum="1"/>
132+
</end>
133+
<end type="TARGET" refId="1" navigable="true"/>
134+
<display labels="true" multiplicity="true"/>
135+
</association>
136+
<realization id="19">
137+
<end type="SOURCE" refId="2"/>
138+
<end type="TARGET" refId="5"/>
139+
</realization>
140+
<dependency id="20">
141+
<end type="SOURCE" refId="5"/>
142+
<end type="TARGET" refId="9"/>
143+
</dependency>
144+
<dependency id="21">
145+
<bendpoint x="301" y="114"/>
146+
<end type="SOURCE" refId="5"/>
147+
<end type="TARGET" refId="4"/>
148+
</dependency>
149+
<realization id="22">
150+
<end type="SOURCE" refId="9"/>
151+
<end type="TARGET" refId="4"/>
152+
</realization>
153+
<dependency id="23">
154+
<end type="SOURCE" refId="6"/>
155+
<end type="TARGET" refId="9"/>
156+
</dependency>
157+
<generalization id="24">
158+
<end type="SOURCE" refId="8"/>
159+
<end type="TARGET" refId="9"/>
160+
</generalization>
161+
<dependency id="25">
162+
<bendpoint x="141" y="250"/>
163+
<end type="SOURCE" refId="3"/>
164+
<end type="TARGET" refId="7"/>
165+
</dependency>
166+
<association id="26">
167+
<end type="SOURCE" refId="6" navigable="false">
168+
<attribute id="27" name="handlers">
169+
<position height="19" width="56" x="449" y="175"/>
170+
</attribute>
171+
<multiplicity id="28" minimum="0" maximum="2147483647">
172+
<position height="17" width="23" x="574" y="173"/>
173+
</multiplicity>
174+
</end>
175+
<end type="TARGET" refId="5" navigable="true"/>
176+
<display labels="true" multiplicity="true"/>
177+
</association>
178+
<association id="29">
179+
<end type="SOURCE" refId="7" navigable="false">
180+
<attribute id="30" name="user"/>
181+
<multiplicity id="31" minimum="0" maximum="1"/>
182+
</end>
183+
<end type="TARGET" refId="1" navigable="true"/>
184+
<display labels="true" multiplicity="true"/>
185+
</association>
186+
<realization id="32">
187+
<end type="SOURCE" refId="3"/>
188+
<end type="TARGET" refId="5"/>
189+
</realization>
190+
<classifier-display autosize="true" stereotype="true" package="true" initial-value="true" signature="true"
191+
sort-features="false" accessors="true" visibility="true">
192+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
193+
<operations public="true" package="true" protected="true" private="true" static="true"/>
194+
</classifier-display>
195+
<association-display labels="true" multiplicity="true"/>
196+
</class-diagram>

event-driven-architecture/index.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
layout: pattern
2+
title: Event Driven Architecture
3+
folder: event-driven-architecture
4+
permalink: /patterns/event-driven-architecture
5+
6+
7+
**Intent:** Send and notify state changes of your objects to other applications using an Event-driven Architecture.
8+
9+
![alt text](./etc/eda.png "Event Driven Architecture")
10+
11+
**Applicability:** Use an Event-driven architecture when
12+
13+
* you want to create a loosely coupled system
14+
* you want to build a more responsive system
15+
* you want a system that is easier to extend
16+
17+
**Real world examples:**
18+
19+
* SendGrid, an email API, sends events whenever an email is processed, delivered, opened etc... (https://sendgrid.com/docs/API_Reference/Webhooks/event.html)
20+
* Chargify, a billing API, exposes payment activity through various events (https://docs.chargify.com/api-events)
21+
* 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)
22+
* MySQL runs triggers based on events such as inserts and update events happening on database tables.
23+
24+
**Credits:**
25+
26+
* [Event-driven architecture - Wikipedia](http://www.computerweekly.com/feature/Write-through-write-around-write-back-Cache-explained)
27+
* [Fundamental Components of an Event-Driven Architecture](http://giocc.com/fundamental-components-of-an-event-driven-architecture.html)
28+
* [Real World Applications/Event Driven Applications](https://wiki.haskell.org/Real_World_Applications/Event_Driven_Applications)
29+
* [Event-driven architecture definition](http://searchsoa.techtarget.com/definition/event-driven-architecture)

event-driven-architecture/pom.xml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
6+
<modelVersion>4.0.0</modelVersion>
7+
<parent>
8+
<groupId>com.iluwatar</groupId>
9+
<artifactId>java-design-patterns</artifactId>
10+
<version>1.10.0-SNAPSHOT</version>
11+
</parent>
12+
13+
<artifactId>event-driven-architecture</artifactId>
14+
15+
<dependencies>
16+
<dependency>
17+
<groupId>junit</groupId>
18+
<artifactId>junit</artifactId>
19+
<scope>test</scope>
20+
</dependency>
21+
22+
<dependency>
23+
<groupId>org.mockito</groupId>
24+
<artifactId>mockito-core</artifactId>
25+
<scope>test</scope>
26+
</dependency>
27+
</dependencies>
28+
</project>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.iluwatar.eda;
2+
3+
import com.iluwatar.eda.event.Event;
4+
import com.iluwatar.eda.event.UserCreatedEvent;
5+
import com.iluwatar.eda.event.UserUpdatedEvent;
6+
import com.iluwatar.eda.framework.EventDispatcher;
7+
import com.iluwatar.eda.handler.UserCreatedEventHandler;
8+
import com.iluwatar.eda.handler.UserUpdatedEventHandler;
9+
import com.iluwatar.eda.model.User;
10+
11+
/**
12+
* An event-driven architecture (EDA) is a framework that orchestrates behavior around the
13+
* production, detection and consumption of events as well as the responses they evoke. An event is
14+
* any identifiable occurrence that has significance for system hardware or software. <p/> The
15+
* example below uses an {@link EventDispatcher} to link/register {@link Event} objects to their
16+
* respective handlers once an {@link Event} is dispatched, it's respective handler is invoked and
17+
* the {@link Event} is handled accordingly.
18+
*
19+
*/
20+
public class App {
21+
22+
/**
23+
* Once the {@link EventDispatcher} is initialised, handlers related to specific events have to be
24+
* made known to the dispatcher by registering them. In this case the {@link UserCreatedEvent} is
25+
* bound to the UserCreatedEventHandler, whilst the {@link UserUpdatedEvent} is bound to the
26+
* {@link UserUpdatedEventHandler}. The dispatcher can now be called to dispatch specific events.
27+
* When a user is saved, the {@link UserCreatedEvent} can be dispatched.
28+
* On the other hand, when a user is updated, {@link UserUpdatedEvent} can be dispatched.
29+
*
30+
*/
31+
public static void main(String[] args) {
32+
33+
EventDispatcher dispatcher = new EventDispatcher();
34+
dispatcher.registerChannel(UserCreatedEvent.class, new UserCreatedEventHandler());
35+
dispatcher.registerChannel(UserUpdatedEvent.class, new UserUpdatedEventHandler());
36+
37+
User user = new User("iluwatar");
38+
dispatcher.onEvent(new UserCreatedEvent(user));
39+
dispatcher.onEvent(new UserUpdatedEvent(user));
40+
}
41+
42+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.iluwatar.eda.event;
2+
3+
import com.iluwatar.eda.framework.EventDispatcher;
4+
import com.iluwatar.eda.framework.Message;
5+
6+
/**
7+
* The {@link Event} class serves as a base class for defining custom events happening with your
8+
* system. In this example we have two types of events defined.
9+
* <ul>
10+
* <li>{@link UserCreatedEvent} - used when a user is created</li>
11+
* <li>{@link UserUpdatedEvent} - used when a user is updated</li>
12+
* </ul>
13+
* Events can be distinguished using the {@link #getType() getType} method.
14+
*/
15+
public class Event implements Message {
16+
17+
/**
18+
* Returns the event type as a {@link Class} object
19+
* In this example, this method is used by the {@link EventDispatcher} to
20+
* dispatch events depending on their type.
21+
*
22+
* @return the Event type as a {@link Class}.
23+
*/
24+
public Class<? extends Message> getType() {
25+
return getClass();
26+
}
27+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.iluwatar.eda.event;
2+
3+
import com.iluwatar.eda.model.User;
4+
5+
/**
6+
* The {@link UserCreatedEvent} should should be dispatched whenever a user has been created.
7+
* This class can be extended to contain details about the user has been created. In this example,
8+
* the entire {@link User} object is passed on as data with the event.
9+
*/
10+
public class UserCreatedEvent extends Event {
11+
12+
private User user;
13+
14+
public UserCreatedEvent(User user) {
15+
this.user = user;
16+
}
17+
18+
public User getUser() {
19+
return user;
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.iluwatar.eda.event;
2+
3+
import com.iluwatar.eda.model.User;
4+
5+
/**
6+
* The {@link UserUpdatedEvent} should should be dispatched whenever a user has been updated.
7+
* This class can be extended to contain details about the user has been updated. In this example,
8+
* the entire {@link User} object is passed on as data with the event.
9+
*/
10+
public class UserUpdatedEvent extends Event {
11+
12+
private User user;
13+
14+
public UserUpdatedEvent(User user) {
15+
this.user = user;
16+
}
17+
18+
public User getUser() {
19+
return user;
20+
}
21+
}

0 commit comments

Comments
 (0)