mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-19 09:26:25 +00:00
deps: Refactor dependencies (#3224)
* remove spring dep move junit, logging, mockito under dep mgmt * upgrade anti-corruption-layer deps * async method invocation * balking, bloc * bridge to bytecode * caching * callback - cqrs * component - health check * hexagonal - metadata mapping * rest of the patterns * remove checkstyle, take spotless into use
This commit is contained in:
@@ -97,9 +97,7 @@ public class App {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run program in either interactive mode or not.
|
||||
*/
|
||||
/** Run program in either interactive mode or not. */
|
||||
public void run() {
|
||||
if (interactiveMode) {
|
||||
runInteractiveMode();
|
||||
@@ -108,9 +106,7 @@ public class App {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run program in non-interactive mode.
|
||||
*/
|
||||
/** Run program in non-interactive mode. */
|
||||
public void quickRun() {
|
||||
var eventManager = new EventManager();
|
||||
|
||||
@@ -135,15 +131,15 @@ public class App {
|
||||
eventManager.cancel(syncEventId);
|
||||
LOGGER.info("Sync Event [{}] has been stopped.", syncEventId);
|
||||
|
||||
} catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException
|
||||
} catch (MaxNumOfEventsAllowedException
|
||||
| LongRunningEventException
|
||||
| EventDoesNotExistException
|
||||
| InvalidOperationException e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run program in interactive mode.
|
||||
*/
|
||||
/** Run program in interactive mode. */
|
||||
public void runInteractiveMode() {
|
||||
var eventManager = new EventManager();
|
||||
|
||||
@@ -151,7 +147,8 @@ public class App {
|
||||
var option = -1;
|
||||
while (option != 4) {
|
||||
LOGGER.info("Hello. Would you like to boil some eggs?");
|
||||
LOGGER.info("""
|
||||
LOGGER.info(
|
||||
"""
|
||||
(1) BOIL AN EGG
|
||||
(2) STOP BOILING THIS EGG
|
||||
(3) HOW ARE MY EGGS?
|
||||
@@ -214,7 +211,8 @@ public class App {
|
||||
var eventId = eventManager.createAsync(eventTime);
|
||||
eventManager.start(eventId);
|
||||
LOGGER.info("Egg [{}] is being boiled.", eventId);
|
||||
} catch (MaxNumOfEventsAllowedException | LongRunningEventException
|
||||
} catch (MaxNumOfEventsAllowedException
|
||||
| LongRunningEventException
|
||||
| EventDoesNotExistException e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
}
|
||||
@@ -223,13 +221,14 @@ public class App {
|
||||
var eventId = eventManager.create(eventTime);
|
||||
eventManager.start(eventId);
|
||||
LOGGER.info("Egg [{}] is being boiled.", eventId);
|
||||
} catch (MaxNumOfEventsAllowedException | InvalidOperationException
|
||||
| LongRunningEventException | EventDoesNotExistException e) {
|
||||
} catch (MaxNumOfEventsAllowedException
|
||||
| InvalidOperationException
|
||||
| LongRunningEventException
|
||||
| EventDoesNotExistException e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
LOGGER.info("Unknown event type.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+3
-6
@@ -32,17 +32,14 @@ import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Each Event runs as a separate/individual thread.
|
||||
*/
|
||||
/** Each Event runs as a separate/individual thread. */
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class AsyncEvent implements Event, Runnable {
|
||||
|
||||
private final int eventId;
|
||||
private final Duration eventTime;
|
||||
@Getter
|
||||
private final boolean synchronous;
|
||||
@Getter private final boolean synchronous;
|
||||
private Thread thread;
|
||||
private final AtomicBoolean isComplete = new AtomicBoolean(false);
|
||||
private ThreadCompleteListener eventListener;
|
||||
@@ -97,4 +94,4 @@ public class AsyncEvent implements Event, Runnable {
|
||||
eventListener.completedEventHandler(eventId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,5 +34,4 @@ public interface Event {
|
||||
void stop();
|
||||
|
||||
void status();
|
||||
|
||||
}
|
||||
|
||||
+2
-5
@@ -26,13 +26,10 @@ package com.iluwatar.event.asynchronous;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* Custom Exception Class for Non-Existent Event.
|
||||
*/
|
||||
/** Custom Exception Class for Non-Existent Event. */
|
||||
public class EventDoesNotExistException extends Exception {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -3398463738273811509L;
|
||||
@Serial private static final long serialVersionUID = -3398463738273811509L;
|
||||
|
||||
public EventDoesNotExistException(String message) {
|
||||
super(message);
|
||||
|
||||
+25
-32
@@ -31,9 +31,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* EventManager handles and maintains a pool of event threads. {@link AsyncEvent} threads are created
|
||||
* upon user request. Thre are two types of events; Asynchronous and Synchronous. There can be
|
||||
* multiple Asynchronous events running at once but only one Synchronous event running at a time.
|
||||
* EventManager handles and maintains a pool of event threads. {@link AsyncEvent} threads are
|
||||
* created upon user request. Thre are two types of events; Asynchronous and Synchronous. There can
|
||||
* be multiple Asynchronous events running at once but only one Synchronous event running at a time.
|
||||
* Currently supported event operations are: start, stop, and getStatus. Once an event is complete,
|
||||
* it then notifies EventManager through a listener. The EventManager then takes the event out of
|
||||
* the pool.
|
||||
@@ -48,18 +48,14 @@ public class EventManager implements ThreadCompleteListener {
|
||||
private int currentlyRunningSyncEvent = -1;
|
||||
private final SecureRandom rand;
|
||||
|
||||
@Getter
|
||||
private final Map<Integer, AsyncEvent> eventPool;
|
||||
@Getter private final Map<Integer, AsyncEvent> eventPool;
|
||||
|
||||
private static final String DOES_NOT_EXIST = " does not exist.";
|
||||
|
||||
/**
|
||||
* EventManager constructor.
|
||||
*/
|
||||
/** EventManager constructor. */
|
||||
public EventManager() {
|
||||
rand = new SecureRandom();
|
||||
eventPool = new ConcurrentHashMap<>(MAX_RUNNING_EVENTS);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,15 +64,18 @@ public class EventManager implements ThreadCompleteListener {
|
||||
* @param eventTime Time an event should run for.
|
||||
* @return eventId
|
||||
* @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 LongRunningEventException Long-running events are not allowed in the app.
|
||||
* @throws InvalidOperationException No new synchronous events can be created when one is already
|
||||
* running.
|
||||
* @throws LongRunningEventException Long-running events are not allowed in the app.
|
||||
*/
|
||||
public int create(Duration eventTime)
|
||||
throws MaxNumOfEventsAllowedException, InvalidOperationException, LongRunningEventException {
|
||||
if (currentlyRunningSyncEvent != -1) {
|
||||
throw new InvalidOperationException("Event [" + currentlyRunningSyncEvent + "] is still"
|
||||
+ " running. Please wait until it finishes and try again.");
|
||||
throw new InvalidOperationException(
|
||||
"Event ["
|
||||
+ currentlyRunningSyncEvent
|
||||
+ "] is still"
|
||||
+ " running. Please wait until it finishes and try again.");
|
||||
}
|
||||
|
||||
var eventId = createEvent(eventTime, true);
|
||||
@@ -91,10 +90,10 @@ public class EventManager implements ThreadCompleteListener {
|
||||
* @param eventTime Time an event should run for.
|
||||
* @return eventId
|
||||
* @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(Duration eventTime) throws MaxNumOfEventsAllowedException,
|
||||
LongRunningEventException {
|
||||
public int createAsync(Duration eventTime)
|
||||
throws MaxNumOfEventsAllowedException, LongRunningEventException {
|
||||
return createEvent(eventTime, false);
|
||||
}
|
||||
|
||||
@@ -105,8 +104,8 @@ public class EventManager implements ThreadCompleteListener {
|
||||
}
|
||||
|
||||
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.getSeconds() > MAX_EVENT_TIME.getSeconds()) {
|
||||
@@ -170,17 +169,13 @@ public class EventManager implements ThreadCompleteListener {
|
||||
eventPool.get(eventId).status();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets status of all running events.
|
||||
*/
|
||||
/** Gets status of all running events. */
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void statusOfAllEvents() {
|
||||
eventPool.entrySet().forEach(entry -> ((AsyncEvent) ((Map.Entry) entry).getValue()).status());
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop all running events.
|
||||
*/
|
||||
/** Stop all running events. */
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void shutdown() {
|
||||
eventPool.entrySet().forEach(entry -> ((AsyncEvent) ((Map.Entry) entry).getValue()).stop());
|
||||
@@ -188,8 +183,7 @@ 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
|
||||
* <code>Integer.MAX_VALUE - 1</code>.
|
||||
* max can be at most <code>Integer.MAX_VALUE - 1</code>.
|
||||
*/
|
||||
private int generateId() {
|
||||
// nextInt is normally exclusive of the top value,
|
||||
@@ -203,7 +197,8 @@ public class EventManager implements ThreadCompleteListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback from an {@link AsyncEvent} (once it is complete). The Event is then removed from the pool.
|
||||
* Callback from an {@link AsyncEvent} (once it is complete). The Event is then removed from the
|
||||
* pool.
|
||||
*/
|
||||
@Override
|
||||
public void completedEventHandler(int eventId) {
|
||||
@@ -214,10 +209,8 @@ public class EventManager implements ThreadCompleteListener {
|
||||
eventPool.remove(eventId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of currently running Synchronous events.
|
||||
*/
|
||||
/** Get number of currently running Synchronous events. */
|
||||
public int numOfCurrentlyRunningSyncEvent() {
|
||||
return currentlyRunningSyncEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-6
@@ -26,16 +26,12 @@ package com.iluwatar.event.asynchronous;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -6191545255213410803L;
|
||||
@Serial private static final long serialVersionUID = -6191545255213410803L;
|
||||
|
||||
public InvalidOperationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-5
@@ -26,13 +26,10 @@ package com.iluwatar.event.asynchronous;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -483423544320148809L;
|
||||
@Serial private static final long serialVersionUID = -483423544320148809L;
|
||||
|
||||
public LongRunningEventException(String message) {
|
||||
super(message);
|
||||
|
||||
+2
-5
@@ -26,13 +26,10 @@ package com.iluwatar.event.asynchronous;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -8430876973516292695L;
|
||||
@Serial private static final long serialVersionUID = -8430876973516292695L;
|
||||
|
||||
public MaxNumOfEventsAllowedException(String message) {
|
||||
super(message);
|
||||
|
||||
+1
-3
@@ -24,9 +24,7 @@
|
||||
*/
|
||||
package com.iluwatar.event.asynchronous;
|
||||
|
||||
/**
|
||||
* Interface with listener behaviour related to Thread Completion.
|
||||
*/
|
||||
/** Interface with listener behaviour related to Thread Completion. */
|
||||
public interface ThreadCompleteListener {
|
||||
void completedEventHandler(final int eventId);
|
||||
}
|
||||
|
||||
+6
-10
@@ -24,23 +24,19 @@
|
||||
*/
|
||||
package com.iluwatar.event.asynchronous;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
/**
|
||||
* Tests that EventAsynchronous example runs without errors.
|
||||
*/
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Tests that EventAsynchronous example runs without errors. */
|
||||
class AppTest {
|
||||
|
||||
/**
|
||||
* Issue: Add at least one assertion to this test case.
|
||||
* Solution: Inserted assertion to check whether the execution of the main method in {@link App#main(String[])}
|
||||
* throws an exception.
|
||||
* Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check
|
||||
* whether the execution of the main method in {@link App#main(String[])} throws an exception.
|
||||
*/
|
||||
|
||||
@Test
|
||||
void shouldExecuteApplicationWithoutException() {
|
||||
assertDoesNotThrow(() -> App.main(new String[]{}));
|
||||
assertDoesNotThrow(() -> App.main(new String[] {}));
|
||||
}
|
||||
}
|
||||
|
||||
+29
-34
@@ -31,13 +31,11 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.time.Duration;
|
||||
import lombok.SneakyThrows;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* Application test
|
||||
*/
|
||||
/** Application test */
|
||||
class EventAsynchronousTest {
|
||||
|
||||
@Test
|
||||
@@ -46,7 +44,7 @@ class EventAsynchronousTest {
|
||||
var eventManager = new EventManager();
|
||||
var aEventId = eventManager.createAsync(Duration.ofSeconds(60));
|
||||
|
||||
assertDoesNotThrow(() ->eventManager.start(aEventId));
|
||||
assertDoesNotThrow(() -> eventManager.start(aEventId));
|
||||
|
||||
assertEquals(1, eventManager.getEventPool().size());
|
||||
assertTrue(eventManager.getEventPool().size() < EventManager.MAX_RUNNING_EVENTS);
|
||||
@@ -54,7 +52,6 @@ class EventAsynchronousTest {
|
||||
|
||||
assertDoesNotThrow(() -> eventManager.cancel(aEventId));
|
||||
assertTrue(eventManager.getEventPool().isEmpty());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -70,7 +67,6 @@ class EventAsynchronousTest {
|
||||
|
||||
assertDoesNotThrow(() -> eventManager.cancel(sEventId));
|
||||
assertTrue(eventManager.getEventPool().isEmpty());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -86,21 +82,21 @@ class EventAsynchronousTest {
|
||||
eventManager.start(sEventId);
|
||||
|
||||
await().until(() -> eventManager.getEventPool().isEmpty());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void testUnsuccessfulSynchronousEvent() {
|
||||
assertThrows(InvalidOperationException.class, () -> {
|
||||
var eventManager = new EventManager();
|
||||
assertThrows(
|
||||
InvalidOperationException.class,
|
||||
() -> {
|
||||
var eventManager = new EventManager();
|
||||
|
||||
var sEventId = assertDoesNotThrow(() -> eventManager.create(Duration.ofSeconds(60)));
|
||||
eventManager.start(sEventId);
|
||||
sEventId = eventManager.create(Duration.ofSeconds(60));
|
||||
eventManager.start(sEventId);
|
||||
|
||||
});
|
||||
var sEventId = assertDoesNotThrow(() -> eventManager.create(Duration.ofSeconds(60)));
|
||||
eventManager.start(sEventId);
|
||||
sEventId = eventManager.create(Duration.ofSeconds(60));
|
||||
eventManager.start(sEventId);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -119,28 +115,27 @@ class EventAsynchronousTest {
|
||||
eventManager.start(aEventId3);
|
||||
|
||||
await().until(() -> eventManager.getEventPool().isEmpty());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLongRunningEventException(){
|
||||
assertThrows(LongRunningEventException.class, () -> {
|
||||
var eventManager = new EventManager();
|
||||
eventManager.createAsync(Duration.ofMinutes(31));
|
||||
});
|
||||
void testLongRunningEventException() {
|
||||
assertThrows(
|
||||
LongRunningEventException.class,
|
||||
() -> {
|
||||
var eventManager = new EventManager();
|
||||
eventManager.createAsync(Duration.ofMinutes(31));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testMaxNumOfEventsAllowedException(){
|
||||
assertThrows(MaxNumOfEventsAllowedException.class, () -> {
|
||||
final var eventManager = new EventManager();
|
||||
for(int i=0;i<1100;i++){
|
||||
eventManager.createAsync(Duration.ofSeconds(i));
|
||||
}
|
||||
});
|
||||
void testMaxNumOfEventsAllowedException() {
|
||||
assertThrows(
|
||||
MaxNumOfEventsAllowedException.class,
|
||||
() -> {
|
||||
final var eventManager = new EventManager();
|
||||
for (int i = 0; i < 1100; i++) {
|
||||
eventManager.createAsync(Duration.ofSeconds(i));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user