Resolves checkstyle errors for ambassador, async-method-invocation, balking, bridge, builder (#1058)

* Decreases checkstyle errors for ambassador pattern

* Reduces checkstyle errors in async-method-invocation

* Reduces checkstyle errors in balking

* Reduces checkstyle errors in bridge

* Reduces checkstyle errors in builder
This commit is contained in:
Anurag Agarwal 2019-11-10 00:33:22 +05:30 committed by Ilkka Seppälä
parent 1fa8a604eb
commit 6d1c0b1563
29 changed files with 179 additions and 225 deletions

View File

@ -24,27 +24,26 @@
package com.iluwatar.ambassador; package com.iluwatar.ambassador;
/** /**
*
* The ambassador pattern creates a helper service that sends network requests on behalf of a * The ambassador pattern creates a helper service that sends network requests on behalf of a
* client. It is often used in cloud-based applications to offload features of a remote service. * client. It is often used in cloud-based applications to offload features of a remote service.
* *
* An ambassador service can be thought of as an out-of-process proxy that is co-located with * <p>An ambassador service can be thought of as an out-of-process proxy that is co-located with
* the client. Similar to the proxy design pattern, the ambassador service provides an interface * the client. Similar to the proxy design pattern, the ambassador service provides an interface for
* for another remote service. In addition to the interface, the ambassador provides extra * another remote service. In addition to the interface, the ambassador provides extra functionality
* functionality and features, specifically offloaded common connectivity tasks. This usually * and features, specifically offloaded common connectivity tasks. This usually consists of
* consists of monitoring, logging, routing, security etc. This is extremely useful in * monitoring, logging, routing, security etc. This is extremely useful in legacy applications where
* legacy applications where the codebase is difficult to modify and allows for improvements * the codebase is difficult to modify and allows for improvements in the application's networking
* in the application's networking capabilities. * capabilities.
* *
* In this example, we will the ({@link ServiceAmbassador}) class represents the ambassador while the * <p>In this example, we will the ({@link ServiceAmbassador}) class represents the ambassador while
* the
* ({@link RemoteService}) class represents a remote application. * ({@link RemoteService}) class represents a remote application.
*
*/ */
public class App { public class App {
/** /**
* Entry point * Entry point.
*/ */
public static void main(String[] args) { public static void main(String[] args) {
Client host1 = new Client(); Client host1 = new Client();
Client host2 = new Client(); Client host2 = new Client();

View File

@ -23,12 +23,11 @@
package com.iluwatar.ambassador; package com.iluwatar.ambassador;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
/** /**
* A simple Client * A simple Client.
*/ */
public class Client { public class Client {

View File

@ -23,12 +23,12 @@
package com.iluwatar.ambassador; package com.iluwatar.ambassador;
import static java.lang.Thread.sleep;
import com.iluwatar.ambassador.util.RandomProvider; import com.iluwatar.ambassador.util.RandomProvider;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static java.lang.Thread.sleep;
/** /**
* A remote legacy application represented by a Singleton implementation. * A remote legacy application represented by a Singleton implementation.
*/ */
@ -55,9 +55,11 @@ public class RemoteService implements RemoteServiceInterface {
RemoteService(RandomProvider randomProvider) { RemoteService(RandomProvider randomProvider) {
this.randomProvider = randomProvider; this.randomProvider = randomProvider;
} }
/** /**
* Remote function takes a value and multiplies it by 10 taking a random amount of time. * Remote function takes a value and multiplies it by 10 taking a random amount of time. Will
* Will sometimes return -1. This imitates connectivity issues a client might have to account for. * sometimes return -1. This imitates connectivity issues a client might have to account for.
*
* @param value integer value to be multiplied. * @param value integer value to be multiplied.
* @return if waitTime is less than {@link RemoteService#THRESHOLD}, it returns value * 10, * @return if waitTime is less than {@link RemoteService#THRESHOLD}, it returns value * 10,
* otherwise {@link RemoteServiceInterface#FAILURE}. * otherwise {@link RemoteServiceInterface#FAILURE}.

View File

@ -23,17 +23,15 @@
package com.iluwatar.ambassador; package com.iluwatar.ambassador;
import static java.lang.Thread.sleep;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static java.lang.Thread.sleep;
/** /**
*
* ServiceAmbassador provides an interface for a ({@link Client}) to access ({@link RemoteService}). * ServiceAmbassador provides an interface for a ({@link Client}) to access ({@link RemoteService}).
* The interface adds logging, latency testing and usage of the service in a safe way that will not * The interface adds logging, latency testing and usage of the service in a safe way that will not
* add stress to the remote service when connectivity issues occur. * add stress to the remote service when connectivity issues occur.
*
*/ */
public class ServiceAmbassador implements RemoteServiceInterface { public class ServiceAmbassador implements RemoteServiceInterface {
@ -41,7 +39,8 @@ public class ServiceAmbassador implements RemoteServiceInterface {
private static final int RETRIES = 3; private static final int RETRIES = 3;
private static final int DELAY_MS = 3000; private static final int DELAY_MS = 3000;
ServiceAmbassador() {} ServiceAmbassador() {
}
@Override @Override
public long doRemoteFunction(int value) { public long doRemoteFunction(int value) {

View File

@ -23,35 +23,34 @@
package com.iluwatar.async.method.invocation; package com.iluwatar.async.method.invocation;
import java.util.concurrent.Callable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.concurrent.Callable;
/** /**
* This application demonstrates the async method invocation pattern. Key parts of the pattern are * This application demonstrates the async method invocation pattern. Key parts of the pattern are
* <code>AsyncResult</code> which is an intermediate container for an asynchronously evaluated value, * <code>AsyncResult</code> which is an intermediate container for an asynchronously evaluated
* <code>AsyncCallback</code> which can be provided to be executed on task completion and <code>AsyncExecutor</code> * value, <code>AsyncCallback</code> which can be provided to be executed on task completion and
* that manages the execution of the async tasks. * <code>AsyncExecutor</code> that manages the execution of the async tasks.
* <p> *
* The main method shows example flow of async invocations. The main thread starts multiple tasks with variable * <p>The main method shows example flow of async invocations. The main thread starts multiple
* durations and then continues its own work. When the main thread has done it's job it collects the results of the * tasks with variable durations and then continues its own work. When the main thread has done it's
* async tasks. Two of the tasks are handled with callbacks, meaning the callbacks are executed immediately when the * job it collects the results of the async tasks. Two of the tasks are handled with callbacks,
* tasks complete. * meaning the callbacks are executed immediately when the tasks complete.
* <p> *
* Noteworthy difference of thread usage between the async results and callbacks is that the async results are collected * <p>Noteworthy difference of thread usage between the async results and callbacks is that the
* in the main thread but the callbacks are executed within the worker threads. This should be noted when working with * async results are collected in the main thread but the callbacks are executed within the worker
* thread pools. * threads. This should be noted when working with thread pools.
* <p> *
* Java provides its own implementations of async method invocation pattern. FutureTask, CompletableFuture and * <p>Java provides its own implementations of async method invocation pattern. FutureTask,
* ExecutorService are the real world implementations of this pattern. But due to the nature of parallel programming, * CompletableFuture and ExecutorService are the real world implementations of this pattern. But due
* the implementations are not trivial. This example does not take all possible scenarios into account but rather * to the nature of parallel programming, the implementations are not trivial. This example does not
* provides a simple version that helps to understand the pattern. * take all possible scenarios into account but rather provides a simple version that helps to
* understand the pattern.
* *
* @see AsyncResult * @see AsyncResult
* @see AsyncCallback * @see AsyncCallback
* @see AsyncExecutor * @see AsyncExecutor
*
* @see java.util.concurrent.FutureTask * @see java.util.concurrent.FutureTask
* @see java.util.concurrent.CompletableFuture * @see java.util.concurrent.CompletableFuture
* @see java.util.concurrent.ExecutorService * @see java.util.concurrent.ExecutorService
@ -61,27 +60,29 @@ 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.
*/ */
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// construct a new executor that will run async tasks // construct a new executor that will run async tasks
AsyncExecutor executor = new ThreadAsyncExecutor(); AsyncExecutor executor = new ThreadAsyncExecutor();
// start few async tasks with varying processing times, two last with callback handlers // start few async tasks with varying processing times, two last with callback handlers
AsyncResult<Integer> asyncResult1 = executor.startProcess(lazyval(10, 500)); final AsyncResult<Integer> asyncResult1 = executor.startProcess(lazyval(10, 500));
AsyncResult<String> asyncResult2 = executor.startProcess(lazyval("test", 300)); final AsyncResult<String> asyncResult2 = executor.startProcess(lazyval("test", 300));
AsyncResult<Long> asyncResult3 = executor.startProcess(lazyval(50L, 700)); final AsyncResult<Long> asyncResult3 = executor.startProcess(lazyval(50L, 700));
AsyncResult<Integer> asyncResult4 = executor.startProcess(lazyval(20, 400), callback("Callback result 4")); final AsyncResult<Integer> asyncResult4 =
AsyncResult<String> asyncResult5 = executor.startProcess(lazyval("callback", 600), callback("Callback result 5")); executor.startProcess(lazyval(20, 400), callback("Callback result 4"));
final AsyncResult<String> asyncResult5 =
executor.startProcess(lazyval("callback", 600), callback("Callback result 5"));
// emulate processing in the current thread while async tasks are running in their own threads // emulate processing in the current thread while async tasks are running in their own threads
Thread.sleep(350); // Oh boy I'm working hard here Thread.sleep(350); // Oh boy I'm working hard here
log("Some hard work done"); log("Some hard work done");
// wait for completion of the tasks // wait for completion of the tasks
Integer result1 = executor.endProcess(asyncResult1); final Integer result1 = executor.endProcess(asyncResult1);
String result2 = executor.endProcess(asyncResult2); final String result2 = executor.endProcess(asyncResult2);
Long result3 = executor.endProcess(asyncResult3); final Long result3 = executor.endProcess(asyncResult3);
asyncResult4.await(); asyncResult4.await();
asyncResult5.await(); asyncResult5.await();
@ -94,10 +95,8 @@ public class App {
/** /**
* Creates a callable that lazily evaluates to given value with artificial delay. * Creates a callable that lazily evaluates to given value with artificial delay.
* *
* @param value * @param value value to evaluate
* value to evaluate * @param delayMillis artificial delay in milliseconds
* @param delayMillis
* artificial delay in milliseconds
* @return new callable for lazy evaluation * @return new callable for lazy evaluation
*/ */
private static <T> Callable<T> lazyval(T value, long delayMillis) { private static <T> Callable<T> lazyval(T value, long delayMillis) {
@ -111,8 +110,7 @@ public class App {
/** /**
* Creates a simple callback that logs the complete status of the async result. * Creates a simple callback that logs the complete status of the async result.
* *
* @param name * @param name callback name
* callback name
* @return new async callback * @return new async callback
*/ */
private static <T> AsyncCallback<T> callback(String name) { private static <T> AsyncCallback<T> callback(String name) {

View File

@ -26,11 +26,9 @@ package com.iluwatar.async.method.invocation;
import java.util.Optional; import java.util.Optional;
/** /**
* * AsyncCallback interface.
* AsyncCallback interface
* *
* @param <T> * @param <T> Type of Result
*
*/ */
public interface AsyncCallback<T> { public interface AsyncCallback<T> {
@ -38,7 +36,7 @@ public interface AsyncCallback<T> {
* Complete handler which is executed when async task is completed or fails execution. * Complete handler which is executed when async task is completed or fails execution.
* *
* @param value the evaluated value from async task, undefined when execution fails * @param value the evaluated value from async task, undefined when execution fails
* @param ex empty value if execution succeeds, some exception if executions fails * @param ex empty value if execution succeeds, some exception if executions fails
*/ */
void onComplete(T value, Optional<Exception> ex); void onComplete(T value, Optional<Exception> ex);
} }

View File

@ -27,9 +27,7 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
/** /**
* * AsyncExecutor interface.
* AsyncExecutor interface
*
*/ */
public interface AsyncExecutor { public interface AsyncExecutor {
@ -45,7 +43,7 @@ public interface AsyncExecutor {
* Starts processing of an async task. Returns immediately with async result. Executes callback * Starts processing of an async task. Returns immediately with async result. Executes callback
* when the task is completed. * when the task is completed.
* *
* @param task task to be executed asynchronously * @param task task to be executed asynchronously
* @param callback callback to be executed on task completion * @param callback callback to be executed on task completion
* @return async result for the task * @return async result for the task
*/ */
@ -57,7 +55,7 @@ public interface AsyncExecutor {
* *
* @param asyncResult async result of a task * @param asyncResult async result of a task
* @return evaluated value of the completed task * @return evaluated value of the completed task
* @throws ExecutionException if execution has failed, containing the root cause * @throws ExecutionException if execution has failed, containing the root cause
* @throws InterruptedException if the execution is interrupted * @throws InterruptedException if the execution is interrupted
*/ */
<T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException; <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException;

View File

@ -26,7 +26,8 @@ package com.iluwatar.async.method.invocation;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
/** /**
* AsyncResult interface * AsyncResult interface.
*
* @param <T> parameter returned when getValue is invoked * @param <T> parameter returned when getValue is invoked
*/ */
public interface AsyncResult<T> { public interface AsyncResult<T> {
@ -42,7 +43,7 @@ public interface AsyncResult<T> {
* Gets the value of completed async task. * Gets the value of completed async task.
* *
* @return evaluated value or throws ExecutionException if execution has failed * @return evaluated value or throws ExecutionException if execution has failed
* @throws ExecutionException if execution has failed, containing the root cause * @throws ExecutionException if execution has failed, containing the root cause
* @throws IllegalStateException if execution is not completed * @throws IllegalStateException if execution is not completed
*/ */
T getValue() throws ExecutionException; T getValue() throws ExecutionException;

View File

@ -29,13 +29,13 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
/** /**
*
* Implementation of async executor that creates a new thread for every task. * Implementation of async executor that creates a new thread for every task.
*
*/ */
public class ThreadAsyncExecutor implements AsyncExecutor { public class ThreadAsyncExecutor implements AsyncExecutor {
/** Index for thread naming */ /**
* Index for thread naming.
*/
private final AtomicInteger idx = new AtomicInteger(0); private final AtomicInteger idx = new AtomicInteger(0);
@Override @Override
@ -52,12 +52,13 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
} catch (Exception ex) { } catch (Exception ex) {
result.setException(ex); result.setException(ex);
} }
} , "executor-" + idx.incrementAndGet()).start(); }, "executor-" + idx.incrementAndGet()).start();
return result; return result;
} }
@Override @Override
public <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException { public <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException,
InterruptedException {
if (!asyncResult.isCompleted()) { if (!asyncResult.isCompleted()) {
asyncResult.await(); asyncResult.await();
} }
@ -65,8 +66,9 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
} }
/** /**
* Simple implementation of async result that allows completing it successfully with a value or exceptionally with an * Simple implementation of async result that allows completing it successfully with a value or
* exception. A really simplified version from its real life cousins FutureTask and CompletableFuture. * exceptionally with an exception. A really simplified version from its real life cousins
* FutureTask and CompletableFuture.
* *
* @see java.util.concurrent.FutureTask * @see java.util.concurrent.FutureTask
* @see java.util.concurrent.CompletableFuture * @see java.util.concurrent.CompletableFuture
@ -90,11 +92,10 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
} }
/** /**
* Sets the value from successful execution and executes callback if available. Notifies any thread waiting for * Sets the value from successful execution and executes callback if available. Notifies any
* completion. * thread waiting for completion.
* *
* @param value * @param value value of the evaluated task
* value of the evaluated task
*/ */
void setValue(T value) { void setValue(T value) {
this.value = value; this.value = value;
@ -106,11 +107,10 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
} }
/** /**
* Sets the exception from failed execution and executes callback if available. Notifies any thread waiting for * Sets the exception from failed execution and executes callback if available. Notifies any
* completion. * thread waiting for completion.
* *
* @param exception * @param exception exception of the failed task
* exception of the failed task
*/ */
void setException(Exception exception) { void setException(Exception exception) {
this.exception = exception; this.exception = exception;

View File

@ -26,9 +26,7 @@ package com.iluwatar.async.method.invocation;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
*
* Application test * Application test
*
*/ */
public class AppTest { public class AppTest {

View File

@ -23,30 +23,18 @@
package com.iluwatar.async.method.invocation; package com.iluwatar.async.method.invocation;
import org.junit.jupiter.api.Test; import static java.time.Duration.ofMillis;
import org.mockito.ArgumentCaptor; import static org.junit.jupiter.api.Assertions.*;
import org.mockito.Matchers; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
import static org.mockito.internal.verification.VerificationModeFactory.times;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.Test;
import static java.time.Duration.ofMillis; import org.mockito.ArgumentCaptor;
import static org.junit.jupiter.api.Assertions.assertEquals; import org.mockito.Matchers;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTimeout;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.internal.verification.VerificationModeFactory.times;
/** /**
* Date: 12/6/15 - 10:49 AM * Date: 12/6/15 - 10:49 AM
@ -82,7 +70,8 @@ public class ThreadAsyncExecutorTest {
} }
/** /**
* Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable,
* AsyncCallback)}
*/ */
@Test @Test
public void testSuccessfulTaskWithCallback() throws Exception { public void testSuccessfulTaskWithCallback() throws Exception {
@ -104,7 +93,8 @@ public class ThreadAsyncExecutorTest {
verify(task, times(1)).call(); verify(task, times(1)).call();
// ... same for the callback, we expect our object // ... same for the callback, we expect our object
final ArgumentCaptor<Optional<Exception>> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); final ArgumentCaptor<Optional<Exception>> optionalCaptor =
ArgumentCaptor.forClass((Class) Optional.class);
verify(callback, times(1)).onComplete(eq(result), optionalCaptor.capture()); verify(callback, times(1)).onComplete(eq(result), optionalCaptor.capture());
final Optional<Exception> optionalException = optionalCaptor.getValue(); final Optional<Exception> optionalException = optionalCaptor.getValue();
@ -117,8 +107,8 @@ public class ThreadAsyncExecutorTest {
} }
/** /**
* Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a task takes a while * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a
* to execute * task takes a while to execute
*/ */
@Test @Test
public void testLongRunningTaskWithoutCallback() throws Exception { public void testLongRunningTaskWithoutCallback() throws Exception {
@ -158,8 +148,8 @@ public class ThreadAsyncExecutorTest {
} }
/** /**
* Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when a task * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable,
* takes a while to execute * AsyncCallback)} when a task takes a while to execute
*/ */
@Test @Test
public void testLongRunningTaskWithCallback() throws Exception { public void testLongRunningTaskWithCallback() throws Exception {
@ -191,7 +181,8 @@ public class ThreadAsyncExecutorTest {
// Our task should only execute once, but it can take a while ... // Our task should only execute once, but it can take a while ...
verify(task, timeout(3000).times(1)).call(); verify(task, timeout(3000).times(1)).call();
final ArgumentCaptor<Optional<Exception>> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); final ArgumentCaptor<Optional<Exception>> optionalCaptor =
ArgumentCaptor.forClass((Class) Optional.class);
verify(callback, timeout(3000).times(1)).onComplete(eq(result), optionalCaptor.capture()); verify(callback, timeout(3000).times(1)).onComplete(eq(result), optionalCaptor.capture());
final Optional<Exception> optionalException = optionalCaptor.getValue(); final Optional<Exception> optionalException = optionalCaptor.getValue();
@ -209,8 +200,9 @@ public class ThreadAsyncExecutorTest {
} }
/** /**
* Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a task takes a while * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a
* to execute, while waiting on the result using {@link ThreadAsyncExecutor#endProcess(AsyncResult)} * task takes a while to execute, while waiting on the result using {@link
* ThreadAsyncExecutor#endProcess(AsyncResult)}
*/ */
@Test @Test
public void testEndProcess() throws Exception { public void testEndProcess() throws Exception {
@ -247,7 +239,8 @@ public class ThreadAsyncExecutorTest {
} }
/** /**
* Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable)} when the callable is 'null' * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable)} when
* the callable is 'null'
*/ */
@Test @Test
public void testNullTask() throws Exception { public void testNullTask() throws Exception {
@ -273,8 +266,8 @@ public class ThreadAsyncExecutorTest {
} }
/** /**
* Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when the * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable,
* callable is 'null', but the asynchronous callback is provided * AsyncCallback)} when the callable is 'null', but the asynchronous callback is provided
*/ */
@Test @Test
public void testNullTaskWithCallback() throws Exception { public void testNullTaskWithCallback() throws Exception {
@ -288,7 +281,8 @@ public class ThreadAsyncExecutorTest {
asyncResult.await(); // Prevent timing issues, and wait until the result is available asyncResult.await(); // Prevent timing issues, and wait until the result is available
assertTrue(asyncResult.isCompleted()); assertTrue(asyncResult.isCompleted());
final ArgumentCaptor<Optional<Exception>> optionalCaptor = ArgumentCaptor.forClass((Class) Optional.class); final ArgumentCaptor<Optional<Exception>> optionalCaptor =
ArgumentCaptor.forClass((Class) Optional.class);
verify(callback, times(1)).onComplete(Matchers.isNull(), optionalCaptor.capture()); verify(callback, times(1)).onComplete(Matchers.isNull(), optionalCaptor.capture());
final Optional<Exception> optionalException = optionalCaptor.getValue(); final Optional<Exception> optionalException = optionalCaptor.getValue();
@ -312,8 +306,8 @@ public class ThreadAsyncExecutorTest {
} }
/** /**
* Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable, AsyncCallback)} when both * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable,
* the callable and the asynchronous callback are 'null' * AsyncCallback)} when both the callable and the asynchronous callback are 'null'
*/ */
@Test @Test
public void testNullTaskWithNullCallback() throws Exception { public void testNullTaskWithNullCallback() throws Exception {

View File

@ -23,23 +23,22 @@
package com.iluwatar.balking; package com.iluwatar.balking;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* In Balking Design Pattern if an objects method is invoked when it is in an inappropriate state, * In Balking Design Pattern if an objects method is invoked when it is in an inappropriate state,
* then the method will return without doing anything. Objects that use this pattern are generally only in a * then the method will return without doing anything. Objects that use this pattern are generally
* state that is prone to balking temporarily but for an unknown amount of time * only in a state that is prone to balking temporarily but for an unknown amount of time
* *
* In this example implementation WashingMachine is an object that has two states * <p>In this example implementation WashingMachine is an object that has two states in which it
* in which it can be: ENABLED and WASHING. If the machine is ENABLED * can be: ENABLED and WASHING. If the machine is ENABLED the state is changed into WASHING that any
* the state is changed into WASHING that any other thread can't invoke this action on this and then do the job. * other thread can't invoke this action on this and then do the job. On the other hand if it have
* On the other hand if it have been already washing and any other thread execute wash() * been already washing and any other thread execute wash() it can't do that once again and returns
* it can't do that once again and returns doing nothing. * doing nothing.
*/ */
public class App { public class App {
@ -47,6 +46,8 @@ public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class); private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
/** /**
* Entry Point.
*
* @param args the command line arguments - not used * @param args the command line arguments - not used
*/ */
public static void main(String... args) { public static void main(String... args) {

View File

@ -23,13 +23,12 @@
package com.iluwatar.balking; package com.iluwatar.balking;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
/** /**
* Washing machine class * Washing machine class.
*/ */
public class WashingMachine { public class WashingMachine {
@ -38,7 +37,7 @@ public class WashingMachine {
private WashingMachineState washingMachineState; private WashingMachineState washingMachineState;
/** /**
* Creates a new instance of WashingMachine * Creates a new instance of WashingMachine.
*/ */
public WashingMachine() { public WashingMachine() {
this((interval, timeUnit, task) -> { this((interval, timeUnit, task) -> {
@ -52,8 +51,8 @@ public class WashingMachine {
} }
/** /**
* Creates a new instance of WashingMachine using provided delayProvider. This constructor is used only for * Creates a new instance of WashingMachine using provided delayProvider. This constructor is used
* unit testing purposes. * only for unit testing purposes.
*/ */
public WashingMachine(DelayProvider delayProvider) { public WashingMachine(DelayProvider delayProvider) {
this.delayProvider = delayProvider; this.delayProvider = delayProvider;
@ -65,17 +64,17 @@ public class WashingMachine {
} }
/** /**
* Method responsible for washing * Method responsible for washing if the object is in appropriate state.
* if the object is in appropriate state
*/ */
public void wash() { public void wash() {
synchronized (this) { synchronized (this) {
LOGGER.info("{}: Actual machine state: {}", Thread.currentThread().getName(), getWashingMachineState()); WashingMachineState machineState = getWashingMachineState();
if (washingMachineState == WashingMachineState.WASHING) { LOGGER.info("{}: Actual machine state: {}", Thread.currentThread().getName(), machineState);
if (this.washingMachineState == WashingMachineState.WASHING) {
LOGGER.error("ERROR: Cannot wash if the machine has been already washing!"); LOGGER.error("ERROR: Cannot wash if the machine has been already washing!");
return; return;
} }
washingMachineState = WashingMachineState.WASHING; this.washingMachineState = WashingMachineState.WASHING;
} }
LOGGER.info("{}: Doing the washing", Thread.currentThread().getName()); LOGGER.info("{}: Doing the washing", Thread.currentThread().getName());
@ -83,8 +82,7 @@ public class WashingMachine {
} }
/** /**
* Method responsible of ending the washing * Method responsible of ending the washing by changing machine state.
* by changing machine state
*/ */
public synchronized void endOfWashing() { public synchronized void endOfWashing() {
washingMachineState = WashingMachineState.ENABLED; washingMachineState = WashingMachineState.ENABLED;

View File

@ -24,10 +24,9 @@
package com.iluwatar.balking; package com.iluwatar.balking;
/** /**
* WashingMachineState enum describes in which state machine is, * WashingMachineState enum describes in which state machine is, it can be enabled and ready to work
* it can be enabled and ready to work as well as during washing * as well as during washing.
*/ */
public enum WashingMachineState { public enum WashingMachineState {
ENABLED, WASHING ENABLED, WASHING
} }

View File

@ -23,11 +23,10 @@
package com.iluwatar.balking; package com.iluwatar.balking;
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
* Tests for {@link WashingMachine} * Tests for {@link WashingMachine}

View File

@ -27,25 +27,25 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* * Composition over inheritance. The Bridge pattern can also be thought of as two layers of
* Composition over inheritance. The Bridge pattern can also be thought of as two layers of abstraction. * abstraction. With Bridge, you can decouple an abstraction from its implementation so that the two
* With Bridge, you can decouple an abstraction from its implementation so that the two can vary independently. * can vary independently.
* <p> *
* In Bridge pattern both abstraction ({@link Weapon}) and implementation ( * <p>In Bridge pattern both abstraction ({@link Weapon}) and implementation ( {@link Enchantment})
* {@link Enchantment}) have their own class hierarchies. The interface of the implementations * have their own class hierarchies. The interface of the implementations can be changed without
* can be changed without affecting the clients. * affecting the clients.
* <p> *
* In this example we have two class hierarchies. One of weapons and another one of enchantments. We can easily * <p>In this example we have two class hierarchies. One of weapons and another one of
* combine any weapon with any enchantment using composition instead of creating deep class hierarchy. * enchantments. We can easily combine any weapon with any enchantment using composition instead of
* * creating deep class hierarchy.
*/ */
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
*/ */
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -24,9 +24,7 @@
package com.iluwatar.bridge; package com.iluwatar.bridge;
/** /**
* * Enchantment.
* Enchantment
*
*/ */
public interface Enchantment { public interface Enchantment {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* * FlyingEnchantment.
* FlyingEnchantment
*
*/ */
public class FlyingEnchantment implements Enchantment { public class FlyingEnchantment implements Enchantment {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* * Hammer.
* Hammer
*
*/ */
public class Hammer implements Weapon { public class Hammer implements Weapon {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* * SoulEatingEnchantment.
* SoulEatingEnchantment
*
*/ */
public class SoulEatingEnchantment implements Enchantment { public class SoulEatingEnchantment implements Enchantment {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* * Sword.
* Sword
*
*/ */
public class Sword implements Weapon { public class Sword implements Weapon {

View File

@ -24,9 +24,7 @@
package com.iluwatar.bridge; package com.iluwatar.bridge;
/** /**
* * Weapon.
* Weapon
*
*/ */
public interface Weapon { public interface Weapon {

View File

@ -28,36 +28,33 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
*
* The intention of the Builder pattern is to find a solution to the telescoping constructor * The intention of the Builder pattern is to find a solution to the telescoping constructor
* anti-pattern. The telescoping constructor anti-pattern occurs when the increase of object * anti-pattern. The telescoping constructor anti-pattern occurs when the increase of object
* constructor parameter combination leads to an exponential list of constructors. Instead of using * constructor parameter combination leads to an exponential list of constructors. Instead of using
* numerous constructors, the builder pattern uses another object, a builder, that receives each * numerous constructors, the builder pattern uses another object, a builder, that receives each
* initialization parameter step by step and then returns the resulting constructed object at once. * initialization parameter step by step and then returns the resulting constructed object at once.
* <p> *
* The Builder pattern has another benefit. It can be used for objects that contain flat data (html * <p>The Builder pattern has another benefit. It can be used for objects that contain flat data
* code, SQL query, X.509 certificate...), that is to say, data that can't be easily edited. This * (html code, SQL query, X.509 certificate...), that is to say, data that can't be easily edited.
* type of data cannot be edited step by step and must be edited at once. The best way to construct * This type of data cannot be edited step by step and must be edited at once. The best way to
* such an object is to use a builder class. * construct such an object is to use a builder class.
* <p> *
* In this example we have the Builder pattern variation as described by Joshua Bloch in Effective * <p>In this example we have the Builder pattern variation as described by Joshua Bloch in
* Java 2nd Edition. * Effective Java 2nd Edition.
* <p> *
* We want to build {@link Hero} objects, but its construction is complex because of the many * <p>We want to build {@link Hero} objects, but its construction is complex because of the many
* parameters needed. To aid the user we introduce {@link Builder} class. {@link Hero.Builder} * parameters needed. To aid the user we introduce {@link Builder} class. {@link Hero.Builder} takes
* takes the minimum parameters to build {@link Hero} object in its constructor. After that * the minimum parameters to build {@link Hero} object in its constructor. After that additional
* additional configuration for the {@link Hero} object can be done using the fluent * configuration for the {@link Hero} object can be done using the fluent {@link Builder} interface.
* {@link Builder} interface. When configuration is ready the build method is called to receive * When configuration is ready the build method is called to receive the final {@link Hero} object.
* the final {@link Hero} object.
*
*/ */
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
*/ */
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -24,9 +24,7 @@
package com.iluwatar.builder; package com.iluwatar.builder;
/** /**
* * Armor enumeration.
* Armor enumeration
*
*/ */
public enum Armor { public enum Armor {

View File

@ -24,9 +24,7 @@
package com.iluwatar.builder; package com.iluwatar.builder;
/** /**
* * HairColor enumeration.
* HairColor enumeration
*
*/ */
public enum HairColor { public enum HairColor {

View File

@ -24,9 +24,7 @@
package com.iluwatar.builder; package com.iluwatar.builder;
/** /**
* * HairType enumeration.
* HairType enumeration
*
*/ */
public enum HairType { public enum HairType {

View File

@ -24,9 +24,7 @@
package com.iluwatar.builder; package com.iluwatar.builder;
/** /**
*
* Hero, the class with many parameters. * Hero, the class with many parameters.
*
*/ */
public final class Hero { public final class Hero {
@ -75,9 +73,9 @@ public final class Hero {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("This is a ") sb.append("This is a ")
.append(profession) .append(profession)
.append(" named ") .append(" named ")
.append(name); .append(name);
if (hairColor != null || hairType != null) { if (hairColor != null || hairType != null) {
sb.append(" with "); sb.append(" with ");
if (hairColor != null) { if (hairColor != null) {
@ -99,9 +97,7 @@ public final class Hero {
} }
/** /**
*
* The builder class. * The builder class.
*
*/ */
public static class Builder { public static class Builder {
@ -113,7 +109,7 @@ public final class Hero {
private Weapon weapon; private Weapon weapon;
/** /**
* Constructor * Constructor.
*/ */
public Builder(Profession profession, String name) { public Builder(Profession profession, String name) {
if (profession == null || name == null) { if (profession == null || name == null) {

View File

@ -24,9 +24,7 @@
package com.iluwatar.builder; package com.iluwatar.builder;
/** /**
* * Profession enumeration.
* Profession enumeration
*
*/ */
public enum Profession { public enum Profession {

View File

@ -24,9 +24,7 @@
package com.iluwatar.builder; package com.iluwatar.builder;
/** /**
* * Weapon enumeration.
* Weapon enumeration
*
*/ */
public enum Weapon { public enum Weapon {