Skip to content

Instantly share code, notes, and snippets.

@veganaize
Created June 22, 2024 02:32
Show Gist options
  • Save veganaize/0a1b23297d0fbe5fcea3f4bd7d02cccd to your computer and use it in GitHub Desktop.
Save veganaize/0a1b23297d0fbe5fcea3f4bd7d02cccd to your computer and use it in GitHub Desktop.
Example of event sourcing in java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Main entry point
*/
class EventSource {
public static void
main(String args[]) {
Service.startRepeatingEvent();
EventStore eventStore = new EventStore();
Client clientA = new Client(eventStore);
System.out.println("\nAccumlating events...");
try { Thread.sleep(3000L); } catch (Exception e) { }
System.out.println("\nFinal state: "+ clientA.state);
System.out.println("\nEvent store contents...");
for (Object event : eventStore.events) {
System.out.println((Map) event);
}
EventStore newStore = new EventStore();
Client clientB = new Client(newStore);
System.out.println("\nReplaying events on new instance...");
eventStore.replay(clientA, clientB);
System.out.println("\nFinal state: "+ clientB.state);
}
}
/**
* Handles events
*/
interface EventHandler {
void handle(Object event, Object data);
}
/**
* Can be subscribed to
*/
interface Subscribable {
void subscribe(EventHandler subscriber, Object publisher, Object event);
}
/**
* Example of a client object
*/
class Client implements EventHandler {
EventStore eventStore;
String state = "";
Client(EventStore es) {
eventStore = es;
eventStore.subscribe(this, new Service(), Service.Event.TIMER);
}
@Override public void
handle(Object event, Object data) {
state = event +": "+ data;
System.out.println(state);
}
}
/**
* All (state changing) events routed through an event store instance
*/
class EventStore implements EventHandler, Subscribable {
List events = new ArrayList();
Map subscriptions = new HashMap();
void
addSubscriber(EventHandler subscriber, Object event) {
Set subscribers = (Set) subscriptions.getOrDefault(event, new HashSet());
subscribers.add(subscriber);
subscriptions.put(event, subscribers);
}
@Override public void
subscribe(EventHandler subscriber,
Object publisher,
Object event)
{
addSubscriber(subscriber, event);
((Subscribable) publisher).subscribe(this, publisher, event);
System.out.println("\nSubscribe to class: "+ publisher);
}
@Override public void
handle(Object event, Object data) {
/* Save event */
Map map = new HashMap();
map.put("event", event);
map.put("data", data);
events.add(map);
/* Notify subscribers */
Set subscribers = (Set) subscriptions.getOrDefault(event, new HashSet());
for (Object subscriber : subscribers) {
((EventHandler) subscriber).handle(event, data);
}
}
void
replay(EventHandler oldClient, EventHandler newClient) {
Set emptySet = new HashSet();
for (Object event : events) {
Set subscribers = (Set) subscriptions.getOrDefault(
((Map) event).get("event"), emptySet);
if (subscribers.contains(oldClient)) {
newClient.handle(
((Map) event).get("event"), ((Map) event).get("data"));
}
}
}
}
/**
* An example of a service
*/
class Service extends java.util.TimerTask implements Subscribable {
static enum Event { TIMER }
static Set subscribers = new HashSet();
static void
startRepeatingEvent() {
new java.util.Timer(true).scheduleAtFixedRate(new Service(), 0L, 1000L);
}
/* Publish repeating event */
@Override public void
run() {
for (Object subscriber : subscribers) {
((EventHandler) subscriber).handle(
Event.TIMER, java.time.LocalDateTime.now());
}
}
@Override public void
subscribe(EventHandler subscriber,
Object publisher,
Object event)
{
subscribers.add(subscriber);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment