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:
Ilkka Seppälä
2025-03-29 19:34:27 +02:00
committed by GitHub
parent 371439aeaa
commit 0ca162a55c
1863 changed files with 14408 additions and 17637 deletions
@@ -27,39 +27,40 @@ package com.iluwatar.singleton;
import lombok.extern.slf4j.Slf4j;
/**
* <p>Singleton pattern ensures that the class can have only one existing instance per Java
* classloader instance and provides global access to it.</p>
* Singleton pattern ensures that the class can have only one existing instance per Java classloader
* instance and provides global access to it.
*
* <p>One of the risks of this pattern is that bugs resulting from setting a singleton up in a
* distributed environment can be tricky to debug since it will work fine if you debug with a
* single classloader. Additionally, these problems can crop up a while after the implementation of
* a singleton, since they may start synchronous and only become async with time, so it may
* not be clear why you are seeing certain changes in behavior.</p>
* distributed environment can be tricky to debug since it will work fine if you debug with a single
* classloader. Additionally, these problems can crop up a while after the implementation of a
* singleton, since they may start synchronous and only become async with time, so it may not be
* clear why you are seeing certain changes in behavior.
*
* <p>There are many ways to implement the Singleton. The first one is the eagerly initialized
* instance in {@link IvoryTower}. Eager initialization implies that the implementation is thread
* safe. If you can afford to give up control of the instantiation moment, then this implementation
* will suit you fine.</p>
* will suit you fine.
*
* <p>The other option to implement eagerly initialized Singleton is enum-based Singleton. The
* example is found in {@link EnumIvoryTower}. At first glance, the code looks short and simple.
* However, you should be aware of the downsides including committing to implementation strategy,
* extending the enum class, serializability, and restrictions to coding. These are extensively
* discussed in Stack Overflow: http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing
* -a-singleton-with-javas-enum</p>
* discussed in Stack Overflow:
* http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing
* -a-singleton-with-javas-enum
*
* <p>{@link ThreadSafeLazyLoadedIvoryTower} is a Singleton implementation that is initialized on
* demand. The downside is that it is very slow to access since the whole access method is
* synchronized.</p>
* synchronized.
*
* <p>Another Singleton implementation that is initialized on demand is found in
* {@link ThreadSafeDoubleCheckLocking}. It is somewhat faster than {@link
* ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method but only the
* method internals on specific conditions.</p>
* <p>Another Singleton implementation that is initialized on demand is found in {@link
* ThreadSafeDoubleCheckLocking}. It is somewhat faster than {@link ThreadSafeLazyLoadedIvoryTower}
* since it doesn't synchronize the whole access method but only the method internals on specific
* conditions.
*
* <p>Yet another way to implement thread-safe lazily initialized Singleton can be found in
* {@link InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8
* API level to work.</p>
* <p>Yet another way to implement thread-safe lazily initialized Singleton can be found in {@link
* InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8 API level
* to work.
*/
@Slf4j
public class App {
@@ -25,20 +25,16 @@
package com.iluwatar.singleton;
/**
* <p>Bill Pugh Singleton Implementation.</p>
*
* <p>This implementation of the singleton design pattern takes advantage of the
* Java memory model's guarantees about class initialization. Each class is
* initialized only once, when it is first used. If the class hasn't been used
* yet, it won't be loaded into memory, and no memory will be allocated for
* a static instance. This makes the singleton instance lazy-loaded and thread-safe.</p>
* Bill Pugh Singleton Implementation.
*
* <p>This implementation of the singleton design pattern takes advantage of the Java memory model's
* guarantees about class initialization. Each class is initialized only once, when it is first
* used. If the class hasn't been used yet, it won't be loaded into memory, and no memory will be
* allocated for a static instance. This makes the singleton instance lazy-loaded and thread-safe.
*/
public final class BillPughImplementation {
/**
* Private constructor to prevent instantiation from outside the class.
*/
/** Private constructor to prevent instantiation from outside the class. */
private BillPughImplementation() {
// to prevent instantiating by Reflection call
if (InstanceHolder.instance != null) {
@@ -47,24 +43,19 @@ public final class BillPughImplementation {
}
/**
* The InstanceHolder is a static inner class, and it holds the Singleton instance.
* It is not loaded into memory until the getInstance() method is called.
* The InstanceHolder is a static inner class, and it holds the Singleton instance. It is not
* loaded into memory until the getInstance() method is called.
*/
private static class InstanceHolder {
/**
* Singleton instance of the class.
*/
/** Singleton instance of the class. */
private static BillPughImplementation instance = new BillPughImplementation();
}
/**
* Public accessor for the singleton instance.
*
* <p>
* When this method is called, the InstanceHolder is loaded into memory
* and creates the Singleton instance. This method provides a global access point
* for the singleton instance.
* </p>
* <p>When this method is called, the InstanceHolder is loaded into memory and creates the
* Singleton instance. This method provides a global access point for the singleton instance.
*
* @return an instance of the class.
*/
@@ -25,16 +25,14 @@
package com.iluwatar.singleton;
/**
* <p>Enum based singleton implementation. Effective Java 2nd Edition (Joshua Bloch) p. 18</p>
* Enum based singleton implementation. Effective Java 2nd Edition (Joshua Bloch) p. 18
*
* <p>This implementation is thread safe, however adding any other method and its thread safety
* is developers responsibility.</p>
* <p>This implementation is thread safe, however adding any other method and its thread safety is
* developers responsibility.
*/
public enum EnumIvoryTower {
/**
* The singleton instance of the class, created by the Java enum singleton pattern.
*/
/** The singleton instance of the class, created by the Java enum singleton pattern. */
INSTANCE;
@Override
@@ -25,23 +25,20 @@
package com.iluwatar.singleton;
/**
* <p>The Initialize-on-demand-holder idiom is a secure way of creating a lazy initialized singleton
* object in Java.</p>
* The Initialize-on-demand-holder idiom is a secure way of creating a lazy initialized singleton
* object in Java.
*
* <p>The technique is as lazy as possible and works in all known versions of Java. It takes
* advantage of language guarantees about class initialization, and will therefore work correctly
* in all Java-compliant compilers and virtual machines.</p>
* advantage of language guarantees about class initialization, and will therefore work correctly in
* all Java-compliant compilers and virtual machines.
*
* <p>The inner class is referenced no earlier (and therefore loaded no earlier by the class loader)
* than the moment that getInstance() is called. Thus, this solution is thread-safe without
* requiring special language constructs (i.e. volatile or synchronized).</p>
*
* requiring special language constructs (i.e. volatile or synchronized).
*/
public final class InitializingOnDemandHolderIdiom {
/**
* Private constructor.
*/
/** Private constructor. */
private InitializingOnDemandHolderIdiom() {
// to prevent instantiating by Reflection call
if (HelperHolder.INSTANCE != null) {
@@ -58,14 +55,10 @@ public final class InitializingOnDemandHolderIdiom {
return HelperHolder.INSTANCE;
}
/**
* Provides the lazy-loaded Singleton instance.
*/
/** Provides the lazy-loaded Singleton instance. */
private static class HelperHolder {
/**
* Singleton instance of the class.
*/
/** Singleton instance of the class. */
private static final InitializingOnDemandHolderIdiom INSTANCE =
new InitializingOnDemandHolderIdiom();
}
@@ -1,55 +1,49 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.singleton;
/**
* Singleton class. Eagerly initialized static instance guarantees thread safety.
*/
public final class IvoryTower {
/**
* Private constructor so nobody can instantiate the class.
*/
private IvoryTower() {
// to prevent instantiating by Reflection call
if (INSTANCE != null) {
throw new IllegalStateException("Already initialized.");
}
}
/**
* Static to class instance of the class.
*/
private static final IvoryTower INSTANCE = new IvoryTower();
/**
* To be called by user to obtain instance of the class.
*
* @return instance of the singleton.
*/
public static IvoryTower getInstance() {
return INSTANCE;
}
}
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.singleton;
/** Singleton class. Eagerly initialized static instance guarantees thread safety. */
public final class IvoryTower {
/** Private constructor so nobody can instantiate the class. */
private IvoryTower() {
// to prevent instantiating by Reflection call
if (INSTANCE != null) {
throw new IllegalStateException("Already initialized.");
}
}
/** Static to class instance of the class. */
private static final IvoryTower INSTANCE = new IvoryTower();
/**
* To be called by user to obtain instance of the class.
*
* @return instance of the singleton.
*/
public static IvoryTower getInstance() {
return INSTANCE;
}
}
@@ -25,22 +25,20 @@
package com.iluwatar.singleton;
/**
* <p>Double check locking.</p>
* Double check locking.
*
* <p>http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html</p>
*
* <p>Broken under Java 1.4.</p>
* <p>http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
*
* <p>Broken under Java 1.4.
*/
public final class ThreadSafeDoubleCheckLocking {
/**
* Singleton instance of the class, declared as volatile to ensure atomic access by multiple threads.
* Singleton instance of the class, declared as volatile to ensure atomic access by multiple
* threads.
*/
private static volatile ThreadSafeDoubleCheckLocking instance;
/**
* private constructor to prevent client from instantiating.
*/
/** private constructor to prevent client from instantiating. */
private ThreadSafeDoubleCheckLocking() {
// to prevent instantiating by Reflection call
if (instance != null) {
@@ -25,20 +25,18 @@
package com.iluwatar.singleton;
/**
* <p>Thread-safe Singleton class. The instance is lazily initialized and thus needs synchronization
* mechanism.</p>
*
* Thread-safe Singleton class. The instance is lazily initialized and thus needs synchronization
* mechanism.
*/
public final class ThreadSafeLazyLoadedIvoryTower {
/**
* Singleton instance of the class, declared as volatile to ensure atomic access by multiple threads.
* Singleton instance of the class, declared as volatile to ensure atomic access by multiple
* threads.
*/
private static volatile ThreadSafeLazyLoadedIvoryTower instance;
/**
* Private constructor to prevent instantiation from outside the class.
*/
/** Private constructor to prevent instantiation from outside the class. */
private ThreadSafeLazyLoadedIvoryTower() {
// Protect against instantiation via reflection
if (instance != null) {
@@ -24,17 +24,15 @@
*/
package com.iluwatar.singleton;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
/**
* Application test.
*/
import org.junit.jupiter.api.Test;
/** Application test. */
class AppTest {
@Test
void shouldExecuteWithoutException() {
assertDoesNotThrow(() -> App.main(new String[]{}));
assertDoesNotThrow(() -> App.main(new String[] {}));
}
}
@@ -24,16 +24,10 @@
*/
package com.iluwatar.singleton;
/**
* BillPughImplementationTest
*
*/
public class BillPughImplementationTest
extends SingletonTest<BillPughImplementation>{
/**
* Create a new singleton test instance using the given 'getInstance' method.
*/
public BillPughImplementationTest() {
super(BillPughImplementation::getInstance);
}
/** BillPughImplementationTest */
public class BillPughImplementationTest extends SingletonTest<BillPughImplementation> {
/** Create a new singleton test instance using the given 'getInstance' method. */
public BillPughImplementationTest() {
super(BillPughImplementation::getInstance);
}
}
@@ -24,31 +24,24 @@
*/
package com.iluwatar.singleton;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* EnumIvoryTowerTest
*
*/
import org.junit.jupiter.api.Test;
/** EnumIvoryTowerTest */
class EnumIvoryTowerTest extends SingletonTest<EnumIvoryTower> {
/**
* Create a new singleton test instance using the given 'getInstance' method.
*/
/** Create a new singleton test instance using the given 'getInstance' method. */
public EnumIvoryTowerTest() {
super(() -> EnumIvoryTower.INSTANCE);
}
/**
* Test creating new instance by reflection.
*/
/** Test creating new instance by reflection. */
@Override
@Test
void testCreatingNewInstanceByReflection() throws Exception {
// Java does not allow Enum instantiation http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9
// Java does not allow Enum instantiation
// http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9
assertThrows(ReflectiveOperationException.class, EnumIvoryTower.class::getDeclaredConstructor);
}
}
@@ -24,18 +24,11 @@
*/
package com.iluwatar.singleton;
/**
* InitializingOnDemandHolderIdiomTest
*
*/
class InitializingOnDemandHolderIdiomTest
extends SingletonTest<InitializingOnDemandHolderIdiom> {
/** InitializingOnDemandHolderIdiomTest */
class InitializingOnDemandHolderIdiomTest extends SingletonTest<InitializingOnDemandHolderIdiom> {
/**
* Create a new singleton test instance using the given 'getInstance' method.
*/
/** Create a new singleton test instance using the given 'getInstance' method. */
public InitializingOnDemandHolderIdiomTest() {
super(InitializingOnDemandHolderIdiom::getInstance);
}
}
}
@@ -24,17 +24,11 @@
*/
package com.iluwatar.singleton;
/**
* IvoryTowerTest
*
*/
/** IvoryTowerTest */
class IvoryTowerTest extends SingletonTest<IvoryTower> {
/**
* Create a new singleton test instance using the given 'getInstance' method.
*/
/** Create a new singleton test instance using the given 'getInstance' method. */
public IvoryTowerTest() {
super(IvoryTower::getInstance);
}
}
}
@@ -40,19 +40,17 @@ import java.util.stream.IntStream;
import org.junit.jupiter.api.Test;
/**
* <p>This class provides several test case that test singleton construction.</p>
* This class provides several test case that test singleton construction.
*
* <p>The first proves that multiple calls to the singleton getInstance object are the same when
* called in the SAME thread. The second proves that multiple calls to the singleton getInstance
* object are the same when called in the DIFFERENT thread.</p>
* object are the same when called in the DIFFERENT thread.
*
* @param <S> Supplier method generating singletons
*/
abstract class SingletonTest<S> {
/**
* The singleton's getInstance method.
*/
/** The singleton's getInstance method. */
private final Supplier<S> singletonInstanceMethod;
/**
@@ -64,9 +62,7 @@ abstract class SingletonTest<S> {
this.singletonInstanceMethod = singletonInstanceMethod;
}
/**
* Test the singleton in a non-concurrent setting.
*/
/** Test the singleton in a non-concurrent setting. */
@Test
void testMultipleCallsReturnTheSameObjectInSameThread() {
// Create several instances in the same calling thread
@@ -79,38 +75,36 @@ abstract class SingletonTest<S> {
assertSame(instance2, instance3);
}
/**
* Test singleton instance in a concurrent setting.
*/
/** Test singleton instance in a concurrent setting. */
@Test
void testMultipleCallsReturnTheSameObjectInDifferentThreads() {
assertTimeout(ofMillis(10000), () -> {
// Create 10000 tasks and inside each callable instantiate the singleton class
final var tasks = IntStream.range(0, 10000)
.<Callable<S>>mapToObj(i -> this.singletonInstanceMethod::get)
.collect(Collectors.toCollection(ArrayList::new));
assertTimeout(
ofMillis(10000),
() -> {
// Create 10000 tasks and inside each callable instantiate the singleton class
final var tasks =
IntStream.range(0, 10000)
.<Callable<S>>mapToObj(i -> this.singletonInstanceMethod::get)
.collect(Collectors.toCollection(ArrayList::new));
// Use up to 8 concurrent threads to handle the tasks
final var executorService = Executors.newFixedThreadPool(8);
final var results = executorService.invokeAll(tasks);
// Use up to 8 concurrent threads to handle the tasks
final var executorService = Executors.newFixedThreadPool(8);
final var results = executorService.invokeAll(tasks);
// wait for all the threads to complete
final var expectedInstance = this.singletonInstanceMethod.get();
for (var res : results) {
final var instance = res.get();
assertNotNull(instance);
assertSame(expectedInstance, instance);
}
// tidy up the executor
executorService.shutdown();
});
// wait for all the threads to complete
final var expectedInstance = this.singletonInstanceMethod.get();
for (var res : results) {
final var instance = res.get();
assertNotNull(instance);
assertSame(expectedInstance, instance);
}
// tidy up the executor
executorService.shutdown();
});
}
/**
* Test creating new instance by reflection.
*/
/** Test creating new instance by reflection. */
@Test
void testCreatingNewInstanceByReflection() throws Exception {
var firstTimeInstantiated = this.singletonInstanceMethod.get();
@@ -24,17 +24,11 @@
*/
package com.iluwatar.singleton;
/**
* ThreadSafeDoubleCheckLockingTest
*
*/
/** ThreadSafeDoubleCheckLockingTest */
class ThreadSafeDoubleCheckLockingTest extends SingletonTest<ThreadSafeDoubleCheckLocking> {
/**
* Create a new singleton test instance using the given 'getInstance' method.
*/
/** Create a new singleton test instance using the given 'getInstance' method. */
public ThreadSafeDoubleCheckLockingTest() {
super(ThreadSafeDoubleCheckLocking::getInstance);
}
}
@@ -24,18 +24,11 @@
*/
package com.iluwatar.singleton;
/**
* ThreadSafeLazyLoadedIvoryTowerTest
*
*/
class ThreadSafeLazyLoadedIvoryTowerTest
extends SingletonTest<ThreadSafeLazyLoadedIvoryTower> {
/** ThreadSafeLazyLoadedIvoryTowerTest */
class ThreadSafeLazyLoadedIvoryTowerTest extends SingletonTest<ThreadSafeLazyLoadedIvoryTower> {
/**
* Create a new singleton test instance using the given 'getInstance' method.
*/
/** Create a new singleton test instance using the given 'getInstance' method. */
public ThreadSafeLazyLoadedIvoryTowerTest() {
super(ThreadSafeLazyLoadedIvoryTower::getInstance);
}
}