Resolves checkstyle errors for event-* (#1070)
* Reduces checkstyle errors in event-aggregator * Reduces checkstyle errors in event-asynchronous * Reduces checkstyle errors in event-driven-architecture * Reduces checkstyle errors in event-queue * Reduces checkstyle errors in event-sourcing
This commit is contained in:
parent
7c888e8886
commit
5ae2ce6e2e
@ -27,24 +27,22 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* A system with lots of objects can lead to complexities when a client wants to subscribe to
|
* A system with lots of objects can lead to complexities when a client wants to subscribe to
|
||||||
* events. The client has to find and register for each object individually, if each object has
|
* events. The client has to find and register for each object individually, if each object has
|
||||||
* multiple events then each event requires a separate subscription.
|
* multiple events then each event requires a separate subscription.
|
||||||
* <p>
|
|
||||||
* An Event Aggregator acts as a single source of events for many objects. It registers for all the
|
|
||||||
* events of the many objects allowing clients to register with just the aggregator.
|
|
||||||
* <p>
|
|
||||||
* In the example {@link LordBaelish}, {@link LordVarys} and {@link Scout} deliver events to
|
|
||||||
* {@link KingsHand}. {@link KingsHand}, the event aggregator, then delivers the events to
|
|
||||||
* {@link KingJoffrey}.
|
|
||||||
*
|
*
|
||||||
|
* <p>An Event Aggregator acts as a single source of events for many objects. It registers for all
|
||||||
|
* the events of the many objects allowing clients to register with just the aggregator.
|
||||||
|
*
|
||||||
|
* <p>In the example {@link LordBaelish}, {@link LordVarys} and {@link Scout} deliver events to
|
||||||
|
* {@link KingsHand}. {@link KingsHand}, the event aggregator, then delivers the events to {@link
|
||||||
|
* KingJoffrey}.
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Program entry point
|
* Program entry point.
|
||||||
*
|
*
|
||||||
* @param args command line args
|
* @param args command line args
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.event.aggregator;
|
package com.iluwatar.event.aggregator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Event enumeration.
|
* Event enumeration.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public enum Event {
|
public enum Event {
|
||||||
|
|
||||||
|
@ -27,9 +27,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* EventEmitter is the base class for event producers that can be observed.
|
* EventEmitter is the base class for event producers that can be observed.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public abstract class EventEmitter {
|
public abstract class EventEmitter {
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.event.aggregator;
|
package com.iluwatar.event.aggregator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Observers of events implement this interface.
|
* Observers of events implement this interface.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface EventObserver {
|
public interface EventObserver {
|
||||||
|
|
||||||
|
@ -27,9 +27,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* KingJoffrey observes events from {@link KingsHand}.
|
* KingJoffrey observes events from {@link KingsHand}.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class KingJoffrey implements EventObserver {
|
public class KingJoffrey implements EventObserver {
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.event.aggregator;
|
package com.iluwatar.event.aggregator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* KingsHand observes events from multiple sources and delivers them to listeners.
|
* KingsHand observes events from multiple sources and delivers them to listeners.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class KingsHand extends EventEmitter implements EventObserver {
|
public class KingsHand extends EventEmitter implements EventObserver {
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.event.aggregator;
|
package com.iluwatar.event.aggregator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* LordBaelish produces events.
|
* LordBaelish produces events.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class LordBaelish extends EventEmitter {
|
public class LordBaelish extends EventEmitter {
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.event.aggregator;
|
package com.iluwatar.event.aggregator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* LordVarys produces events.
|
* LordVarys produces events.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class LordVarys extends EventEmitter {
|
public class LordVarys extends EventEmitter {
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.event.aggregator;
|
package com.iluwatar.event.aggregator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Scout produces events.
|
* Scout produces events.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class Scout extends EventEmitter {
|
public class Scout extends EventEmitter {
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
package com.iluwatar.event.aggregator;
|
package com.iluwatar.event.aggregator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Weekday enumeration.
|
||||||
* Weekday enumeration
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public enum Weekday {
|
public enum Weekday {
|
||||||
|
|
||||||
|
@ -23,38 +23,38 @@
|
|||||||
|
|
||||||
package com.iluwatar.event.asynchronous;
|
package com.iluwatar.event.asynchronous;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This application demonstrates the <b>Event-based Asynchronous</b> pattern. Essentially, users (of
|
||||||
|
* the pattern) may choose to run events in an Asynchronous or Synchronous mode. There can be
|
||||||
|
* multiple Asynchronous events running at once but only one Synchronous event can run at a time.
|
||||||
|
* Asynchronous events are synonymous to multi-threads. The key point here is that the threads run
|
||||||
|
* in the background and the user is free to carry on with other processes. Once an event is
|
||||||
|
* complete, the appropriate listener/callback method will be called. The listener then proceeds to
|
||||||
|
* carry out further processing depending on the needs of the user.
|
||||||
*
|
*
|
||||||
* This application demonstrates the <b>Event-based Asynchronous</b> pattern. Essentially, users (of the pattern) may
|
* <p>The {@link EventManager} manages the events/threads that the user creates. Currently, the
|
||||||
* choose to run events in an Asynchronous or Synchronous mode. There can be multiple Asynchronous events running at
|
* supported event operations are: <code>start</code>, <code>stop</code>, <code>getStatus</code>.
|
||||||
* once but only one Synchronous event can run at a time. Asynchronous events are synonymous to multi-threads. The key
|
* For Synchronous events, the user is unable to start another (Synchronous) event if one is already
|
||||||
* point here is that the threads run in the background and the user is free to carry on with other processes. Once an
|
* running at the time. The running event would have to either be stopped or completed before a new
|
||||||
* event is complete, the appropriate listener/callback method will be called. The listener then proceeds to carry out
|
* event can be started.
|
||||||
* further processing depending on the needs of the user.
|
|
||||||
*
|
*
|
||||||
* The {@link EventManager} manages the events/threads that the user creates. Currently, the supported event operations
|
* <p>The Event-based Asynchronous Pattern makes available the advantages of multithreaded
|
||||||
* are: <code>start</code>, <code>stop</code>, <code>getStatus</code>. For Synchronous events, the user is unable to
|
* applications while hiding many of the complex issues inherent in multithreaded design. Using a
|
||||||
* start another (Synchronous) event if one is already running at the time. The running event would have to either be
|
* class that supports this pattern can allow you to:- (1) Perform time-consuming tasks, such as
|
||||||
* stopped or completed before a new event can be started.
|
* downloads and database operations, "in the background," without interrupting your application.
|
||||||
*
|
* (2) Execute multiple operations simultaneously, receiving notifications when each completes. (3)
|
||||||
* The Event-based Asynchronous Pattern makes available the advantages of multithreaded applications while hiding many
|
* Wait for resources to become available without stopping ("hanging") your application. (4)
|
||||||
* of the complex issues inherent in multithreaded design. Using a class that supports this pattern can allow you to:-
|
* Communicate with pending asynchronous operations using the familiar events-and-delegates model.
|
||||||
* (1) Perform time-consuming tasks, such as downloads and database operations, "in the background," without
|
|
||||||
* interrupting your application. (2) Execute multiple operations simultaneously, receiving notifications when each
|
|
||||||
* completes. (3) Wait for resources to become available without stopping ("hanging") your application. (4) Communicate
|
|
||||||
* with pending asynchronous operations using the familiar events-and-delegates model.
|
|
||||||
*
|
*
|
||||||
* @see EventManager
|
* @see EventManager
|
||||||
* @see Event
|
* @see Event
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
@ -67,8 +67,7 @@ public class App {
|
|||||||
/**
|
/**
|
||||||
* Program entry point.
|
* Program entry point.
|
||||||
*
|
*
|
||||||
* @param args
|
* @param args command line args
|
||||||
* command line args
|
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
App app = new App();
|
App app = new App();
|
||||||
@ -78,8 +77,9 @@ public class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App can run in interactive mode or not. Interactive mode == Allow user interaction with command line.
|
* App can run in interactive mode or not. Interactive mode == Allow user interaction with command
|
||||||
* Non-interactive is a quick sequential run through the available {@link EventManager} operations.
|
* line. Non-interactive is a quick sequential run through the available {@link EventManager}
|
||||||
|
* operations.
|
||||||
*/
|
*/
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
Properties prop = new Properties();
|
Properties prop = new Properties();
|
||||||
@ -118,24 +118,24 @@ public class App {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Create an Asynchronous event.
|
// Create an Asynchronous event.
|
||||||
int aEventId = eventManager.createAsync(60);
|
int asyncEventId = eventManager.createAsync(60);
|
||||||
LOGGER.info("Async Event [{}] has been created.", aEventId);
|
LOGGER.info("Async Event [{}] has been created.", asyncEventId);
|
||||||
eventManager.start(aEventId);
|
eventManager.start(asyncEventId);
|
||||||
LOGGER.info("Async Event [{}] has been started.", aEventId);
|
LOGGER.info("Async Event [{}] has been started.", asyncEventId);
|
||||||
|
|
||||||
// Create a Synchronous event.
|
// Create a Synchronous event.
|
||||||
int sEventId = eventManager.create(60);
|
int syncEventId = eventManager.create(60);
|
||||||
LOGGER.info("Sync Event [{}] has been created.", sEventId);
|
LOGGER.info("Sync Event [{}] has been created.", syncEventId);
|
||||||
eventManager.start(sEventId);
|
eventManager.start(syncEventId);
|
||||||
LOGGER.info("Sync Event [{}] has been started.", sEventId);
|
LOGGER.info("Sync Event [{}] has been started.", syncEventId);
|
||||||
|
|
||||||
eventManager.status(aEventId);
|
eventManager.status(asyncEventId);
|
||||||
eventManager.status(sEventId);
|
eventManager.status(syncEventId);
|
||||||
|
|
||||||
eventManager.cancel(aEventId);
|
eventManager.cancel(asyncEventId);
|
||||||
LOGGER.info("Async Event [{}] has been stopped.", aEventId);
|
LOGGER.info("Async Event [{}] has been stopped.", asyncEventId);
|
||||||
eventManager.cancel(sEventId);
|
eventManager.cancel(syncEventId);
|
||||||
LOGGER.info("Sync Event [{}] has been stopped.", sEventId);
|
LOGGER.info("Sync Event [{}] has been stopped.", syncEventId);
|
||||||
|
|
||||||
} catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException
|
} catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException
|
||||||
| InvalidOperationException e) {
|
| InvalidOperationException e) {
|
||||||
@ -211,7 +211,8 @@ public class App {
|
|||||||
int eventId = eventManager.createAsync(eventTime);
|
int eventId = eventManager.createAsync(eventTime);
|
||||||
eventManager.start(eventId);
|
eventManager.start(eventId);
|
||||||
LOGGER.info("Egg [{}] is being boiled.", eventId);
|
LOGGER.info("Egg [{}] is being boiled.", eventId);
|
||||||
} catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) {
|
} catch (MaxNumOfEventsAllowedException | LongRunningEventException
|
||||||
|
| EventDoesNotExistException e) {
|
||||||
LOGGER.error(e.getMessage());
|
LOGGER.error(e.getMessage());
|
||||||
}
|
}
|
||||||
} else if (eventType.equalsIgnoreCase("S")) {
|
} else if (eventType.equalsIgnoreCase("S")) {
|
||||||
@ -219,8 +220,8 @@ public class App {
|
|||||||
int eventId = eventManager.create(eventTime);
|
int eventId = eventManager.create(eventTime);
|
||||||
eventManager.start(eventId);
|
eventManager.start(eventId);
|
||||||
LOGGER.info("Egg [{}] is being boiled.", eventId);
|
LOGGER.info("Egg [{}] is being boiled.", eventId);
|
||||||
} catch (MaxNumOfEventsAllowedException | InvalidOperationException | LongRunningEventException
|
} catch (MaxNumOfEventsAllowedException | InvalidOperationException
|
||||||
| EventDoesNotExistException e) {
|
| LongRunningEventException | EventDoesNotExistException e) {
|
||||||
LOGGER.error(e.getMessage());
|
LOGGER.error(e.getMessage());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -27,9 +27,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Each Event runs as a separate/individual thread.
|
* Each Event runs as a separate/individual thread.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class Event implements IEvent, Runnable {
|
public class Event implements IEvent, Runnable {
|
||||||
|
|
||||||
@ -43,9 +41,10 @@ public class Event implements IEvent, Runnable {
|
|||||||
private ThreadCompleteListener eventListener;
|
private ThreadCompleteListener eventListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param eventId event ID
|
* @param eventId event ID
|
||||||
* @param eventTime event time
|
* @param eventTime event time
|
||||||
* @param isSynchronous is of synchronous type
|
* @param isSynchronous is of synchronous type
|
||||||
*/
|
*/
|
||||||
public Event(final int eventId, final int eventTime, final boolean isSynchronous) {
|
public Event(final int eventId, final int eventTime, final boolean isSynchronous) {
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
package com.iluwatar.event.asynchronous;
|
package com.iluwatar.event.asynchronous;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom Exception Class for Non Existent Event
|
* Custom Exception Class for Non Existent Event.
|
||||||
*/
|
*/
|
||||||
public class EventDoesNotExistException extends Exception {
|
public class EventDoesNotExistException extends Exception {
|
||||||
|
|
||||||
|
@ -29,29 +29,28 @@ import java.util.Random;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* EventManager handles and maintains a pool of event threads. {@link Event} threads are created
|
||||||
* EventManager handles and maintains a pool of event threads. {@link Event} threads are created upon user request. Thre
|
* upon user request. Thre are two types of events; Asynchronous and Synchronous. There can be
|
||||||
* are two types of events; Asynchronous and Synchronous. There can be multiple Asynchronous events running at once but
|
* multiple Asynchronous events running at once but only one Synchronous event running at a time.
|
||||||
* only one Synchronous event running at a time. Currently supported event operations are: start, stop, and getStatus.
|
* Currently supported event operations are: start, stop, and getStatus. Once an event is complete,
|
||||||
* Once an event is complete, it then notifies EventManager through a listener. The EventManager then takes the event
|
* it then notifies EventManager through a listener. The EventManager then takes the event out of
|
||||||
* out of the pool.
|
* the pool.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class EventManager implements ThreadCompleteListener {
|
public class EventManager implements ThreadCompleteListener {
|
||||||
|
|
||||||
public static final int MAX_RUNNING_EVENTS = 1000; // Just don't wanna have too many running events. :)
|
public static final int MAX_RUNNING_EVENTS = 1000;
|
||||||
|
// Just don't wanna have too many running events. :)
|
||||||
public static final int MIN_ID = 1;
|
public static final int MIN_ID = 1;
|
||||||
public static final int MAX_ID = MAX_RUNNING_EVENTS;
|
public static final int MAX_ID = MAX_RUNNING_EVENTS;
|
||||||
public static final int MAX_EVENT_TIME = 1800; // in seconds / 30 minutes.
|
public static final int MAX_EVENT_TIME = 1800; // in seconds / 30 minutes.
|
||||||
private int currentlyRunningSyncEvent = -1;
|
private int currentlyRunningSyncEvent = -1;
|
||||||
private Random rand;
|
private Random rand;
|
||||||
private Map<Integer, Event> eventPool;
|
private Map<Integer, Event> eventPool;
|
||||||
|
|
||||||
private static final String DOES_NOT_EXIST = " does not exist.";
|
private static final String DOES_NOT_EXIST = " does not exist.";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EventManager constructor.
|
* EventManager constructor.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public EventManager() {
|
public EventManager() {
|
||||||
rand = new Random(1);
|
rand = new Random(1);
|
||||||
@ -65,14 +64,15 @@ public class EventManager implements ThreadCompleteListener {
|
|||||||
* @param eventTime Time an event should run for.
|
* @param eventTime Time an event should run for.
|
||||||
* @return eventId
|
* @return eventId
|
||||||
* @throws MaxNumOfEventsAllowedException When too many events are running at a time.
|
* @throws MaxNumOfEventsAllowedException When too many events are running at a time.
|
||||||
* @throws InvalidOperationException No new synchronous events can be created when one is already running.
|
* @throws InvalidOperationException No new synchronous events can be created when one is
|
||||||
* @throws LongRunningEventException Long running events are not allowed in the app.
|
* already running.
|
||||||
|
* @throws LongRunningEventException Long running events are not allowed in the app.
|
||||||
*/
|
*/
|
||||||
public int create(int eventTime)
|
public int create(int eventTime)
|
||||||
throws MaxNumOfEventsAllowedException, InvalidOperationException, LongRunningEventException {
|
throws MaxNumOfEventsAllowedException, InvalidOperationException, LongRunningEventException {
|
||||||
if (currentlyRunningSyncEvent != -1) {
|
if (currentlyRunningSyncEvent != -1) {
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException("Event [" + currentlyRunningSyncEvent + "] is still"
|
||||||
"Event [" + currentlyRunningSyncEvent + "] is still running. Please wait until it finishes and try again.");
|
+ " running. Please wait until it finishes and try again.");
|
||||||
}
|
}
|
||||||
|
|
||||||
int eventId = createEvent(eventTime, true);
|
int eventId = createEvent(eventTime, true);
|
||||||
@ -87,16 +87,18 @@ public class EventManager implements ThreadCompleteListener {
|
|||||||
* @param eventTime Time an event should run for.
|
* @param eventTime Time an event should run for.
|
||||||
* @return eventId
|
* @return eventId
|
||||||
* @throws MaxNumOfEventsAllowedException When too many events are running at a time.
|
* @throws MaxNumOfEventsAllowedException When too many events are running at a time.
|
||||||
* @throws LongRunningEventException Long running events are not allowed in the app.
|
* @throws LongRunningEventException Long running events are not allowed in the app.
|
||||||
*/
|
*/
|
||||||
public int createAsync(int eventTime) throws MaxNumOfEventsAllowedException, LongRunningEventException {
|
public int createAsync(int eventTime) throws MaxNumOfEventsAllowedException,
|
||||||
|
LongRunningEventException {
|
||||||
return createEvent(eventTime, false);
|
return createEvent(eventTime, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int createEvent(int eventTime, boolean isSynchronous)
|
private int createEvent(int eventTime, boolean isSynchronous)
|
||||||
throws MaxNumOfEventsAllowedException, LongRunningEventException {
|
throws MaxNumOfEventsAllowedException, LongRunningEventException {
|
||||||
if (eventPool.size() == MAX_RUNNING_EVENTS) {
|
if (eventPool.size() == MAX_RUNNING_EVENTS) {
|
||||||
throw new MaxNumOfEventsAllowedException("Too many events are running at the moment. Please try again later.");
|
throw new MaxNumOfEventsAllowedException("Too many events are running at the moment."
|
||||||
|
+ " Please try again later.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventTime >= MAX_EVENT_TIME) {
|
if (eventTime >= MAX_EVENT_TIME) {
|
||||||
@ -185,7 +187,8 @@ public class EventManager implements ThreadCompleteListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a pseudo-random number between min and max, inclusive. The difference between min and max can be at most
|
* Returns a pseudo-random number between min and max, inclusive. The difference between min and
|
||||||
|
* max can be at most
|
||||||
* <code>Integer.MAX_VALUE - 1</code>.
|
* <code>Integer.MAX_VALUE - 1</code>.
|
||||||
*/
|
*/
|
||||||
private int generateId() {
|
private int generateId() {
|
||||||
|
@ -24,8 +24,7 @@
|
|||||||
package com.iluwatar.event.asynchronous;
|
package com.iluwatar.event.asynchronous;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Events that fulfill the start stop and list out current status behaviour
|
* Events that fulfill the start stop and list out current status behaviour follow this interface.
|
||||||
* follow this interface
|
|
||||||
*/
|
*/
|
||||||
public interface IEvent {
|
public interface IEvent {
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
package com.iluwatar.event.asynchronous;
|
package com.iluwatar.event.asynchronous;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type of Exception raised when the Operation being invoked is Invalid
|
* Type of Exception raised when the Operation being invoked is Invalid.
|
||||||
*/
|
*/
|
||||||
public class InvalidOperationException extends Exception {
|
public class InvalidOperationException extends Exception {
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
package com.iluwatar.event.asynchronous;
|
package com.iluwatar.event.asynchronous;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type of Exception raised when the Operation being invoked is Long Running
|
* Type of Exception raised when the Operation being invoked is Long Running.
|
||||||
*/
|
*/
|
||||||
public class LongRunningEventException extends Exception {
|
public class LongRunningEventException extends Exception {
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
package com.iluwatar.event.asynchronous;
|
package com.iluwatar.event.asynchronous;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type of Exception raised when the max number of allowed events is exceeded
|
* Type of Exception raised when the max number of allowed events is exceeded.
|
||||||
*/
|
*/
|
||||||
public class MaxNumOfEventsAllowedException extends Exception {
|
public class MaxNumOfEventsAllowedException extends Exception {
|
||||||
|
|
||||||
|
@ -34,11 +34,11 @@ import com.iluwatar.eda.model.User;
|
|||||||
/**
|
/**
|
||||||
* An event-driven architecture (EDA) is a framework that orchestrates behavior around the
|
* 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
|
* 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. <p> The
|
* any identifiable occurrence that has significance for system hardware or software.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
|
* <p>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 {
|
public class App {
|
||||||
|
|
||||||
@ -47,9 +47,8 @@ public class App {
|
|||||||
* made known to the dispatcher by registering them. In this case the {@link UserCreatedEvent} is
|
* 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
|
* bound to the UserCreatedEventHandler, whilst the {@link UserUpdatedEvent} is bound to the
|
||||||
* {@link UserUpdatedEventHandler}. The dispatcher can now be called to dispatch specific events.
|
* {@link UserUpdatedEventHandler}. The dispatcher can now be called to dispatch specific events.
|
||||||
* When a user is saved, the {@link UserCreatedEvent} can be dispatched.
|
* When a user is saved, the {@link UserCreatedEvent} can be dispatched. On the other hand, when a
|
||||||
* On the other hand, when a user is updated, {@link UserUpdatedEvent} can be dispatched.
|
* user is updated, {@link UserUpdatedEvent} can be dispatched.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
@ -23,12 +23,12 @@
|
|||||||
|
|
||||||
package com.iluwatar.eda.event;
|
package com.iluwatar.eda.event;
|
||||||
|
|
||||||
import com.iluwatar.eda.framework.EventDispatcher;
|
|
||||||
import com.iluwatar.eda.framework.Event;
|
import com.iluwatar.eda.framework.Event;
|
||||||
|
import com.iluwatar.eda.framework.EventDispatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link AbstractEvent} class serves as a base class for defining custom events happening with your
|
* The {@link AbstractEvent} class serves as a base class for defining custom events happening with
|
||||||
* system. In this example we have two types of events defined.
|
* your system. In this example we have two types of events defined.
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link UserCreatedEvent} - used when a user is created</li>
|
* <li>{@link UserCreatedEvent} - used when a user is created</li>
|
||||||
* <li>{@link UserUpdatedEvent} - used when a user is updated</li>
|
* <li>{@link UserUpdatedEvent} - used when a user is updated</li>
|
||||||
@ -38,9 +38,8 @@ import com.iluwatar.eda.framework.Event;
|
|||||||
public abstract class AbstractEvent implements Event {
|
public abstract class AbstractEvent implements Event {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the event type as a {@link Class} object
|
* Returns the event type as a {@link Class} object In this example, this method is used by the
|
||||||
* In this example, this method is used by the {@link EventDispatcher} to
|
* {@link EventDispatcher} to dispatch events depending on their type.
|
||||||
* dispatch events depending on their type.
|
|
||||||
*
|
*
|
||||||
* @return the AbstractEvent type as a {@link Class}.
|
* @return the AbstractEvent type as a {@link Class}.
|
||||||
*/
|
*/
|
||||||
|
@ -26,9 +26,9 @@ package com.iluwatar.eda.event;
|
|||||||
import com.iluwatar.eda.model.User;
|
import com.iluwatar.eda.model.User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link UserCreatedEvent} should should be dispatched whenever a user has been created.
|
* The {@link UserCreatedEvent} should should be dispatched whenever a user has been created. This
|
||||||
* This class can be extended to contain details about the user has been created. In this example,
|
* class can be extended to contain details about the user has been created. In this example, the
|
||||||
* the entire {@link User} object is passed on as data with the event.
|
* entire {@link User} object is passed on as data with the event.
|
||||||
*/
|
*/
|
||||||
public class UserCreatedEvent extends AbstractEvent {
|
public class UserCreatedEvent extends AbstractEvent {
|
||||||
|
|
||||||
|
@ -26,9 +26,9 @@ package com.iluwatar.eda.event;
|
|||||||
import com.iluwatar.eda.model.User;
|
import com.iluwatar.eda.model.User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link UserUpdatedEvent} should should be dispatched whenever a user has been updated.
|
* The {@link UserUpdatedEvent} should should be dispatched whenever a user has been updated. This
|
||||||
* This class can be extended to contain details about the user has been updated. In this example,
|
* class can be extended to contain details about the user has been updated. In this example, the
|
||||||
* the entire {@link User} object is passed on as data with the event.
|
* entire {@link User} object is passed on as data with the event.
|
||||||
*/
|
*/
|
||||||
public class UserUpdatedEvent extends AbstractEvent {
|
public class UserUpdatedEvent extends AbstractEvent {
|
||||||
|
|
||||||
|
@ -24,14 +24,15 @@
|
|||||||
package com.iluwatar.eda.framework;
|
package com.iluwatar.eda.framework;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link Event} is an object with a specific type that is associated
|
* A {@link Event} is an object with a specific type that is associated to a specific {@link
|
||||||
* to a specific {@link Handler}.
|
* Handler}.
|
||||||
*/
|
*/
|
||||||
public interface Event {
|
public interface Event {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the message type as a {@link Class} object. In this example the message type is
|
* Returns the message type as a {@link Class} object. In this example the message type is used to
|
||||||
* used to handle events by their type.
|
* handle events by their type.
|
||||||
|
*
|
||||||
* @return the message type as a {@link Class}.
|
* @return the message type as a {@link Class}.
|
||||||
*/
|
*/
|
||||||
Class<? extends Event> getType();
|
Class<? extends Event> getType();
|
||||||
|
@ -27,8 +27,8 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the routing of {@link Event} messages to associated handlers.
|
* Handles the routing of {@link Event} messages to associated handlers. A {@link HashMap} is used
|
||||||
* A {@link HashMap} is used to store the association between events and their respective handlers.
|
* to store the association between events and their respective handlers.
|
||||||
*/
|
*/
|
||||||
public class EventDispatcher {
|
public class EventDispatcher {
|
||||||
|
|
||||||
|
@ -24,16 +24,18 @@
|
|||||||
package com.iluwatar.eda.framework;
|
package com.iluwatar.eda.framework;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface can be implemented to handle different types of messages.
|
* This interface can be implemented to handle different types of messages. Every handler is
|
||||||
* Every handler is responsible for a single of type message
|
* responsible for a single of type message
|
||||||
|
*
|
||||||
* @param <E> Handler can handle events of type E
|
* @param <E> Handler can handle events of type E
|
||||||
*/
|
*/
|
||||||
public interface Handler<E extends Event> {
|
public interface Handler<E extends Event> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The onEvent method should implement and handle behavior related to the event.
|
* The onEvent method should implement and handle behavior related to the event. This can be as
|
||||||
* This can be as simple as calling another service to handle the event on publishing the event on
|
* simple as calling another service to handle the event on publishing the event on a queue to be
|
||||||
* a queue to be consumed by other sub systems.
|
* consumed by other sub systems.
|
||||||
|
*
|
||||||
* @param event the {@link Event} object to be handled.
|
* @param event the {@link Event} object to be handled.
|
||||||
*/
|
*/
|
||||||
void onEvent(E event);
|
void onEvent(E event);
|
||||||
|
@ -27,8 +27,8 @@ import com.iluwatar.eda.event.UserCreatedEvent;
|
|||||||
import com.iluwatar.eda.event.UserUpdatedEvent;
|
import com.iluwatar.eda.event.UserUpdatedEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This {@link User} class is a basic pojo used to demonstrate user data sent along with
|
* This {@link User} class is a basic pojo used to demonstrate user data sent along with the {@link
|
||||||
* the {@link UserCreatedEvent} and {@link UserUpdatedEvent} events.
|
* UserCreatedEvent} and {@link UserUpdatedEvent} events.
|
||||||
*/
|
*/
|
||||||
public class User {
|
public class User {
|
||||||
|
|
||||||
|
@ -23,40 +23,40 @@
|
|||||||
|
|
||||||
package com.iluwatar.event.queue;
|
package com.iluwatar.event.queue;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event or message queues provide an asynchronous communications protocol, meaning that the sender
|
* Event or message queues provide an asynchronous communications protocol, meaning that the sender
|
||||||
* and receiver of the message do not need to interact with the message queue at the same time.
|
* and receiver of the message do not need to interact with the message queue at the same time.
|
||||||
* Events or messages placed onto the queue are stored until the recipient retrieves them. Event
|
* Events or messages placed onto the queue are stored until the recipient retrieves them. Event or
|
||||||
* or message queues have implicit or explicit limits on the size of data that may be transmitted
|
* message queues have implicit or explicit limits on the size of data that may be transmitted in a
|
||||||
* in a single message and the number of messages that may remain outstanding on the queue.
|
* single message and the number of messages that may remain outstanding on the queue. A queue
|
||||||
* A queue stores a series of notifications or requests in first-in, first-out order.
|
* stores a series of notifications or requests in first-in, first-out order. Sending a notification
|
||||||
* Sending a notification enqueues the request and returns. The request processor then processes
|
* enqueues the request and returns. The request processor then processes items from the queue at a
|
||||||
* items from the queue at a later time.
|
* later time.
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Program entry point.
|
* Program entry point.
|
||||||
*
|
*
|
||||||
* @param args command line args
|
* @param args command line args
|
||||||
* @throws IOException when there is a problem with the audio file loading
|
* @throws IOException when there is a problem with the audio file loading
|
||||||
* @throws UnsupportedAudioFileException when the loaded audio file is unsupported
|
* @throws UnsupportedAudioFileException when the loaded audio file is unsupported
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) throws UnsupportedAudioFileException, IOException, InterruptedException {
|
public static void main(String[] args) throws UnsupportedAudioFileException, IOException,
|
||||||
|
InterruptedException {
|
||||||
Audio audio = Audio.getInstance();
|
Audio audio = Audio.getInstance();
|
||||||
audio.playSound(audio.getAudioStream("./etc/Bass-Drum-1.wav"), -10.0f);
|
audio.playSound(audio.getAudioStream("./etc/Bass-Drum-1.wav"), -10.0f);
|
||||||
audio.playSound(audio.getAudioStream("./etc/Closed-Hi-Hat-1.wav"), -8.0f);
|
audio.playSound(audio.getAudioStream("./etc/Closed-Hi-Hat-1.wav"), -8.0f);
|
||||||
|
|
||||||
LOGGER.info("Press Enter key to stop the program...");
|
LOGGER.info("Press Enter key to stop the program...");
|
||||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
|
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
|
||||||
br.read();
|
br.read();
|
||||||
|
@ -23,22 +23,20 @@
|
|||||||
|
|
||||||
package com.iluwatar.event.queue;
|
package com.iluwatar.event.queue;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.sound.sampled.AudioInputStream;
|
import javax.sound.sampled.AudioInputStream;
|
||||||
import javax.sound.sampled.AudioSystem;
|
import javax.sound.sampled.AudioSystem;
|
||||||
import javax.sound.sampled.Clip;
|
import javax.sound.sampled.Clip;
|
||||||
import javax.sound.sampled.LineUnavailableException;
|
import javax.sound.sampled.LineUnavailableException;
|
||||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements the Event Queue pattern.
|
* This class implements the Event Queue pattern.
|
||||||
* @author mkuprivecz
|
|
||||||
*
|
*
|
||||||
|
* @author mkuprivecz
|
||||||
*/
|
*/
|
||||||
public class Audio {
|
public class Audio {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(Audio.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(Audio.class);
|
||||||
@ -73,9 +71,10 @@ public class Audio {
|
|||||||
updateThread.join();
|
updateThread.join();
|
||||||
updateThread = null;
|
updateThread = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method check the Update Method's thread is started.
|
* This method check the Update Method's thread is started.
|
||||||
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public synchronized boolean isServiceRunning() {
|
public synchronized boolean isServiceRunning() {
|
||||||
@ -83,8 +82,8 @@ public class Audio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the thread for the Update Method pattern if it was not started previously.
|
* Starts the thread for the Update Method pattern if it was not started previously. Also when the
|
||||||
* Also when the thread is is ready initializes the indexes of the queue
|
* thread is is ready initializes the indexes of the queue
|
||||||
*/
|
*/
|
||||||
public void init() {
|
public void init() {
|
||||||
if (updateThread == null) {
|
if (updateThread == null) {
|
||||||
@ -96,9 +95,9 @@ public class Audio {
|
|||||||
}
|
}
|
||||||
startThread();
|
startThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a synchronized thread starter
|
* This is a synchronized thread starter.
|
||||||
*/
|
*/
|
||||||
private synchronized void startThread() {
|
private synchronized void startThread() {
|
||||||
if (!updateThread.isAlive()) {
|
if (!updateThread.isAlive()) {
|
||||||
@ -110,8 +109,9 @@ public class Audio {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method adds a new audio into the queue.
|
* This method adds a new audio into the queue.
|
||||||
|
*
|
||||||
* @param stream is the AudioInputStream for the method
|
* @param stream is the AudioInputStream for the method
|
||||||
* @param volume is the level of the audio's volume
|
* @param volume is the level of the audio's volume
|
||||||
*/
|
*/
|
||||||
public void playSound(AudioInputStream stream, float volume) {
|
public void playSound(AudioInputStream stream, float volume) {
|
||||||
init();
|
init();
|
||||||
@ -128,10 +128,9 @@ public class Audio {
|
|||||||
getPendingAudio()[tailIndex] = new PlayMessage(stream, volume);
|
getPendingAudio()[tailIndex] = new PlayMessage(stream, volume);
|
||||||
tailIndex = (tailIndex + 1) % MAX_PENDING;
|
tailIndex = (tailIndex + 1) % MAX_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method uses the Update Method pattern.
|
* This method uses the Update Method pattern. It takes the audio from the queue and plays it
|
||||||
* It takes the audio from the queue and plays it
|
|
||||||
*/
|
*/
|
||||||
private void update() {
|
private void update() {
|
||||||
// If there are no pending requests, do nothing.
|
// If there are no pending requests, do nothing.
|
||||||
@ -155,11 +154,12 @@ public class Audio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the AudioInputStream of a file
|
* Returns the AudioInputStream of a file.
|
||||||
|
*
|
||||||
* @param filePath is the path of the audio file
|
* @param filePath is the path of the audio file
|
||||||
* @return AudioInputStream
|
* @return AudioInputStream
|
||||||
* @throws UnsupportedAudioFileException when the audio file is not supported
|
* @throws UnsupportedAudioFileException when the audio file is not supported
|
||||||
* @throws IOException when the file is not readable
|
* @throws IOException when the file is not readable
|
||||||
*/
|
*/
|
||||||
public AudioInputStream getAudioStream(String filePath)
|
public AudioInputStream getAudioStream(String filePath)
|
||||||
throws UnsupportedAudioFileException, IOException {
|
throws UnsupportedAudioFileException, IOException {
|
||||||
@ -167,7 +167,8 @@ public class Audio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns with the message array of the queue
|
* Returns with the message array of the queue.
|
||||||
|
*
|
||||||
* @return PlayMessage[]
|
* @return PlayMessage[]
|
||||||
*/
|
*/
|
||||||
public PlayMessage[] getPendingAudio() {
|
public PlayMessage[] getPendingAudio() {
|
||||||
|
@ -27,15 +27,15 @@ import javax.sound.sampled.AudioInputStream;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The Event Queue's queue will store the instances of this class.
|
* The Event Queue's queue will store the instances of this class.
|
||||||
* @author mkuprivecz
|
|
||||||
*
|
*
|
||||||
|
* @author mkuprivecz
|
||||||
*/
|
*/
|
||||||
public class PlayMessage {
|
public class PlayMessage {
|
||||||
|
|
||||||
private AudioInputStream stream;
|
private AudioInputStream stream;
|
||||||
|
|
||||||
private float volume;
|
private float volume;
|
||||||
|
|
||||||
public PlayMessage(AudioInputStream stream, float volume) {
|
public PlayMessage(AudioInputStream stream, float volume) {
|
||||||
setStream(stream);
|
setStream(stream);
|
||||||
setVolume(volume);
|
setVolume(volume);
|
||||||
|
@ -42,13 +42,13 @@ import org.slf4j.LoggerFactory;
|
|||||||
* transactional data, and maintain full audit trails and history that can enable compensating
|
* transactional data, and maintain full audit trails and history that can enable compensating
|
||||||
* actions.
|
* actions.
|
||||||
*
|
*
|
||||||
* This App class is an example usage of Event Sourcing pattern. As an example, two bank account is
|
* <p>This App class is an example usage of Event Sourcing pattern. As an example, two bank account
|
||||||
* created, then some money deposit and transfer actions are taken so a new state of accounts is
|
* is created, then some money deposit and transfer actions are taken so a new state of accounts is
|
||||||
* created. At that point, state is cleared in order to represent a system shot down. After the shot
|
* created. At that point, state is cleared in order to represent a system shot down. After the shot
|
||||||
* down, system state is recovered by re-creating the past events from event journal. Then state is
|
* down, system state is recovered by re-creating the past events from event journal. Then state is
|
||||||
* printed so a user can view the last state is same with the state before system shot down.
|
* printed so a user can view the last state is same with the state before system shot down.
|
||||||
*
|
*
|
||||||
* Created by Serdar Hamzaogullari on 06.08.2017.
|
* <p>Created by Serdar Hamzaogullari on 06.08.2017.
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
@ -86,10 +86,10 @@ public class App {
|
|||||||
LOGGER.info("Do some money operations............");
|
LOGGER.info("Do some money operations............");
|
||||||
|
|
||||||
eventProcessor.process(new MoneyDepositEvent(
|
eventProcessor.process(new MoneyDepositEvent(
|
||||||
2, new Date().getTime(), ACCOUNT_OF_DAENERYS, new BigDecimal("100000")));
|
2, new Date().getTime(), ACCOUNT_OF_DAENERYS, new BigDecimal("100000")));
|
||||||
|
|
||||||
eventProcessor.process(new MoneyDepositEvent(
|
eventProcessor.process(new MoneyDepositEvent(
|
||||||
3, new Date().getTime(), ACCOUNT_OF_JON, new BigDecimal("100")));
|
3, new Date().getTime(), ACCOUNT_OF_JON, new BigDecimal("100")));
|
||||||
|
|
||||||
eventProcessor.process(new MoneyTransferEvent(
|
eventProcessor.process(new MoneyTransferEvent(
|
||||||
4, new Date().getTime(), new BigDecimal("10000"), ACCOUNT_OF_DAENERYS,
|
4, new Date().getTime(), new BigDecimal("10000"), ACCOUNT_OF_DAENERYS,
|
||||||
|
@ -32,11 +32,11 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the Account class that holds the account info, the account number,
|
* This is the Account class that holds the account info, the account number, account owner name and
|
||||||
* account owner name and money of the account. Account class also have the business logic of events
|
* money of the account. Account class also have the business logic of events that effects this
|
||||||
* that effects this account.
|
* account.
|
||||||
*
|
*
|
||||||
* Created by Serdar Hamzaogullari on 06.08.2017.
|
* <p>Created by Serdar Hamzaogullari on 06.08.2017.
|
||||||
*/
|
*/
|
||||||
public class Account {
|
public class Account {
|
||||||
|
|
||||||
@ -45,14 +45,15 @@ public class Account {
|
|||||||
private final int accountNo;
|
private final int accountNo;
|
||||||
private final String owner;
|
private final String owner;
|
||||||
private BigDecimal money;
|
private BigDecimal money;
|
||||||
|
|
||||||
private static final String MSG = "Some external api for only realtime execution could be called here.";
|
private static final String MSG =
|
||||||
|
"Some external api for only realtime execution could be called here.";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new Account.
|
* Instantiates a new Account.
|
||||||
*
|
*
|
||||||
* @param accountNo the account no
|
* @param accountNo the account no
|
||||||
* @param owner the owner
|
* @param owner the owner
|
||||||
*/
|
*/
|
||||||
public Account(int accountNo, String owner) {
|
public Account(int accountNo, String owner) {
|
||||||
this.accountNo = accountNo;
|
this.accountNo = accountNo;
|
||||||
|
@ -27,12 +27,11 @@ import com.iluwatar.event.sourcing.domain.Account;
|
|||||||
import com.iluwatar.event.sourcing.state.AccountAggregate;
|
import com.iluwatar.event.sourcing.state.AccountAggregate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the class that implements account create event.
|
* This is the class that implements account create event. Holds the necessary info for an account
|
||||||
* Holds the necessary info for an account create event.
|
* create event. Implements the process function that finds the event related domain objects and
|
||||||
* Implements the process function that finds the event related
|
* calls the related domain object's handle event functions
|
||||||
* domain objects and calls the related domain object's handle event functions
|
|
||||||
*
|
*
|
||||||
* Created by Serdar Hamzaogullari on 06.08.2017.
|
* <p>Created by Serdar Hamzaogullari on 06.08.2017.
|
||||||
*/
|
*/
|
||||||
public class AccountCreateEvent extends DomainEvent {
|
public class AccountCreateEvent extends DomainEvent {
|
||||||
|
|
||||||
@ -42,10 +41,10 @@ public class AccountCreateEvent extends DomainEvent {
|
|||||||
/**
|
/**
|
||||||
* Instantiates a new Account create event.
|
* Instantiates a new Account create event.
|
||||||
*
|
*
|
||||||
* @param sequenceId the sequence id
|
* @param sequenceId the sequence id
|
||||||
* @param createdTime the created time
|
* @param createdTime the created time
|
||||||
* @param accountNo the account no
|
* @param accountNo the account no
|
||||||
* @param owner the owner
|
* @param owner the owner
|
||||||
*/
|
*/
|
||||||
public AccountCreateEvent(long sequenceId, long createdTime, int accountNo, String owner) {
|
public AccountCreateEvent(long sequenceId, long createdTime, int accountNo, String owner) {
|
||||||
super(sequenceId, createdTime, "AccountCreateEvent");
|
super(sequenceId, createdTime, "AccountCreateEvent");
|
||||||
|
@ -28,7 +28,7 @@ import java.io.Serializable;
|
|||||||
/**
|
/**
|
||||||
* This is the base class for domain events. All events must extend this class.
|
* This is the base class for domain events. All events must extend this class.
|
||||||
*
|
*
|
||||||
* Created by Serdar Hamzaogullari on 06.08.2017.
|
* <p>Created by Serdar Hamzaogullari on 06.08.2017.
|
||||||
*/
|
*/
|
||||||
public abstract class DomainEvent implements Serializable {
|
public abstract class DomainEvent implements Serializable {
|
||||||
|
|
||||||
@ -40,8 +40,8 @@ public abstract class DomainEvent implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* Instantiates a new Domain event.
|
* Instantiates a new Domain event.
|
||||||
*
|
*
|
||||||
* @param sequenceId the sequence id
|
* @param sequenceId the sequence id
|
||||||
* @param createdTime the created time
|
* @param createdTime the created time
|
||||||
* @param eventClassName the event class name
|
* @param eventClassName the event class name
|
||||||
*/
|
*/
|
||||||
public DomainEvent(long sequenceId, long createdTime, String eventClassName) {
|
public DomainEvent(long sequenceId, long createdTime, String eventClassName) {
|
||||||
|
@ -28,12 +28,11 @@ import com.iluwatar.event.sourcing.state.AccountAggregate;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the class that implements money deposit event.
|
* This is the class that implements money deposit event. Holds the necessary info for a money
|
||||||
* Holds the necessary info for a money deposit event.
|
* deposit event. Implements the process function that finds the event related domain objects and
|
||||||
* Implements the process function that finds the event related
|
* calls the related domain object's handle event functions
|
||||||
* domain objects and calls the related domain object's handle event functions
|
|
||||||
*
|
*
|
||||||
* Created by Serdar Hamzaogullari on 06.08.2017.
|
* <p>Created by Serdar Hamzaogullari on 06.08.2017.
|
||||||
*/
|
*/
|
||||||
public class MoneyDepositEvent extends DomainEvent {
|
public class MoneyDepositEvent extends DomainEvent {
|
||||||
|
|
||||||
@ -43,10 +42,10 @@ public class MoneyDepositEvent extends DomainEvent {
|
|||||||
/**
|
/**
|
||||||
* Instantiates a new Money deposit event.
|
* Instantiates a new Money deposit event.
|
||||||
*
|
*
|
||||||
* @param sequenceId the sequence id
|
* @param sequenceId the sequence id
|
||||||
* @param createdTime the created time
|
* @param createdTime the created time
|
||||||
* @param accountNo the account no
|
* @param accountNo the account no
|
||||||
* @param money the money
|
* @param money the money
|
||||||
*/
|
*/
|
||||||
public MoneyDepositEvent(long sequenceId, long createdTime, int accountNo, BigDecimal money) {
|
public MoneyDepositEvent(long sequenceId, long createdTime, int accountNo, BigDecimal money) {
|
||||||
super(sequenceId, createdTime, "MoneyDepositEvent");
|
super(sequenceId, createdTime, "MoneyDepositEvent");
|
||||||
|
@ -28,12 +28,11 @@ import com.iluwatar.event.sourcing.state.AccountAggregate;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the class that implements money transfer event.
|
* This is the class that implements money transfer event. Holds the necessary info for a money
|
||||||
* Holds the necessary info for a money transfer event.
|
* transfer event. Implements the process function that finds the event related domain objects and
|
||||||
* Implements the process function that finds the event related
|
* calls the related domain object's handle event functions
|
||||||
* domain objects and calls the related domain object's handle event functions
|
|
||||||
*
|
*
|
||||||
* Created by Serdar Hamzaogullari on 06.08.2017.
|
* <p>Created by Serdar Hamzaogullari on 06.08.2017.
|
||||||
*/
|
*/
|
||||||
public class MoneyTransferEvent extends DomainEvent {
|
public class MoneyTransferEvent extends DomainEvent {
|
||||||
|
|
||||||
@ -44,14 +43,14 @@ public class MoneyTransferEvent extends DomainEvent {
|
|||||||
/**
|
/**
|
||||||
* Instantiates a new Money transfer event.
|
* Instantiates a new Money transfer event.
|
||||||
*
|
*
|
||||||
* @param sequenceId the sequence id
|
* @param sequenceId the sequence id
|
||||||
* @param createdTime the created time
|
* @param createdTime the created time
|
||||||
* @param money the money
|
* @param money the money
|
||||||
* @param accountNoFrom the account no from
|
* @param accountNoFrom the account no from
|
||||||
* @param accountNoTo the account no to
|
* @param accountNoTo the account no to
|
||||||
*/
|
*/
|
||||||
public MoneyTransferEvent(long sequenceId, long createdTime, BigDecimal money, int accountNoFrom,
|
public MoneyTransferEvent(long sequenceId, long createdTime, BigDecimal money, int accountNoFrom,
|
||||||
int accountNoTo) {
|
int accountNoTo) {
|
||||||
super(sequenceId, createdTime, "MoneyTransferEvent");
|
super(sequenceId, createdTime, "MoneyTransferEvent");
|
||||||
this.money = money;
|
this.money = money;
|
||||||
this.accountNoFrom = accountNoFrom;
|
this.accountNoFrom = accountNoFrom;
|
||||||
|
@ -26,11 +26,10 @@ package com.iluwatar.event.sourcing.processor;
|
|||||||
import com.iluwatar.event.sourcing.event.DomainEvent;
|
import com.iluwatar.event.sourcing.event.DomainEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the implementation of event processor.
|
* This is the implementation of event processor. All events are processed by this class. This
|
||||||
* All events are processed by this class.
|
* processor uses processorJournal to persist and recover events.
|
||||||
* This processor uses processorJournal to persist and recover events.
|
|
||||||
*
|
*
|
||||||
* Created by Serdar Hamzaogullari on 06.08.2017.
|
* <p>Created by Serdar Hamzaogullari on 06.08.2017.
|
||||||
*/
|
*/
|
||||||
public class DomainEventProcessor {
|
public class DomainEventProcessor {
|
||||||
|
|
||||||
|
@ -43,15 +43,14 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the implementation of event journal.
|
* This is the implementation of event journal. This implementation serialize/deserialize the events
|
||||||
* This implementation serialize/deserialize the events with JSON
|
* with JSON and writes/reads them on a Journal.json file at the working directory.
|
||||||
* and writes/reads them on a Journal.json file at the working directory.
|
|
||||||
*
|
*
|
||||||
* Created by Serdar Hamzaogullari on 06.08.2017.
|
* <p>Created by Serdar Hamzaogullari on 06.08.2017.
|
||||||
*/
|
*/
|
||||||
public class JsonFileJournal {
|
public class JsonFileJournal {
|
||||||
|
|
||||||
private final File aFile;
|
private final File file;
|
||||||
private final List<String> events = new ArrayList<>();
|
private final List<String> events = new ArrayList<>();
|
||||||
private int index = 0;
|
private int index = 0;
|
||||||
|
|
||||||
@ -59,10 +58,10 @@ public class JsonFileJournal {
|
|||||||
* Instantiates a new Json file journal.
|
* Instantiates a new Json file journal.
|
||||||
*/
|
*/
|
||||||
public JsonFileJournal() {
|
public JsonFileJournal() {
|
||||||
aFile = new File("Journal.json");
|
file = new File("Journal.json");
|
||||||
if (aFile.exists()) {
|
if (file.exists()) {
|
||||||
try (BufferedReader input = new BufferedReader(
|
try (BufferedReader input = new BufferedReader(
|
||||||
new InputStreamReader(new FileInputStream(aFile), "UTF-8"))) {
|
new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
|
||||||
String line;
|
String line;
|
||||||
while ((line = input.readLine()) != null) {
|
while ((line = input.readLine()) != null) {
|
||||||
events.add(line);
|
events.add(line);
|
||||||
@ -88,14 +87,14 @@ public class JsonFileJournal {
|
|||||||
jsonElement = gson.toJsonTree(domainEvent, AccountCreateEvent.class);
|
jsonElement = gson.toJsonTree(domainEvent, AccountCreateEvent.class);
|
||||||
} else if (domainEvent instanceof MoneyDepositEvent) {
|
} else if (domainEvent instanceof MoneyDepositEvent) {
|
||||||
jsonElement = gson.toJsonTree(domainEvent, MoneyDepositEvent.class);
|
jsonElement = gson.toJsonTree(domainEvent, MoneyDepositEvent.class);
|
||||||
} else if (domainEvent instanceof MoneyTransferEvent) {
|
} else if (domainEvent instanceof MoneyTransferEvent) {
|
||||||
jsonElement = gson.toJsonTree(domainEvent, MoneyTransferEvent.class);
|
jsonElement = gson.toJsonTree(domainEvent, MoneyTransferEvent.class);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Journal Event not recegnized");
|
throw new RuntimeException("Journal Event not recegnized");
|
||||||
}
|
}
|
||||||
|
|
||||||
try (Writer output = new BufferedWriter(
|
try (Writer output = new BufferedWriter(
|
||||||
new OutputStreamWriter(new FileOutputStream(aFile, true), "UTF-8"))) {
|
new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8"))) {
|
||||||
String eventString = jsonElement.toString();
|
String eventString = jsonElement.toString();
|
||||||
output.write(eventString + "\r\n");
|
output.write(eventString + "\r\n");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -108,7 +107,7 @@ public class JsonFileJournal {
|
|||||||
* Reset.
|
* Reset.
|
||||||
*/
|
*/
|
||||||
public void reset() {
|
public void reset() {
|
||||||
aFile.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -135,7 +134,7 @@ public class JsonFileJournal {
|
|||||||
domainEvent = gson.fromJson(jsonElement, MoneyDepositEvent.class);
|
domainEvent = gson.fromJson(jsonElement, MoneyDepositEvent.class);
|
||||||
} else if (eventClassName.equals("MoneyTransferEvent")) {
|
} else if (eventClassName.equals("MoneyTransferEvent")) {
|
||||||
domainEvent = gson.fromJson(jsonElement, MoneyTransferEvent.class);
|
domainEvent = gson.fromJson(jsonElement, MoneyTransferEvent.class);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Journal Event not recegnized");
|
throw new RuntimeException("Journal Event not recegnized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,10 +28,9 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the static accounts map holder class.
|
* This is the static accounts map holder class. This class holds the state of the accounts.
|
||||||
* This class holds the state of the accounts.
|
|
||||||
*
|
*
|
||||||
* Created by Serdar Hamzaogullari on 06.08.2017.
|
* <p>Created by Serdar Hamzaogullari on 06.08.2017.
|
||||||
*/
|
*/
|
||||||
public class AccountAggregate {
|
public class AccountAggregate {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user