diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ApiGateway.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ApiGateway.java index 25c201521..18a071c09 100644 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ApiGateway.java +++ b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ApiGateway.java @@ -23,12 +23,11 @@ package com.iluwatar.api.gateway; +import javax.annotation.Resource; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; -import javax.annotation.Resource; - /** * The ApiGateway aggregates calls to microservices based on the needs of the individual clients. */ @@ -42,7 +41,8 @@ public class ApiGateway { private PriceClient priceClient; /** - * Retrieves product information that desktop clients need + * Retrieves product information that desktop clients need. + * * @return Product information for clients on a desktop */ @RequestMapping(path = "/desktop", method = RequestMethod.GET) @@ -54,7 +54,8 @@ public class ApiGateway { } /** - * Retrieves product information that mobile clients need + * Retrieves product information that mobile clients need. + * * @return Product information for clients on a mobile device */ @RequestMapping(path = "/mobile", method = RequestMethod.GET) diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/App.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/App.java index b92e3a7d0..1d72aaaec 100644 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/App.java +++ b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/App.java @@ -27,39 +27,36 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** - * With the Microservices pattern, a client may need data from multiple different microservices. - * If the client called each microservice directly, that could contribute to longer load times, - * since the client would have to make a network request for each microservice called. Moreover, - * having the client call each microservice directly ties the client to that microservice - if the - * internal implementations of the microservices change (for example, if two microservices are - * combined sometime in the future) or if the location (host and port) of a microservice changes, - * then every client that makes use of those microservices must be updated. + * With the Microservices pattern, a client may need data from multiple different microservices. If + * the client called each microservice directly, that could contribute to longer load times, since + * the client would have to make a network request for each microservice called. Moreover, having + * the client call each microservice directly ties the client to that microservice - if the internal + * implementations of the microservices change (for example, if two microservices are combined + * sometime in the future) or if the location (host and port) of a microservice changes, then every + * client that makes use of those microservices must be updated. * - *

- * The intent of the API Gateway pattern is to alleviate some of these issues. In the API Gateway - * pattern, an additional entity (the API Gateway) is placed between the client and the - * microservices. The job of the API Gateway is to aggregate the calls to the microservices. - * Rather than the client calling each microservice individually, the client calls the API Gateway - * a single time. The API Gateway then calls each of the microservices that the client needs. + *

The intent of the API Gateway pattern is to alleviate some of these issues. In the API + * Gateway pattern, an additional entity (the API Gateway) is placed between the client and the + * microservices. The job of the API Gateway is to aggregate the calls to the microservices. Rather + * than the client calling each microservice individually, the client calls the API Gateway a single + * time. The API Gateway then calls each of the microservices that the client needs. * - *

- * This implementation shows what the API Gateway pattern could look like for an e-commerce site. - * The {@link ApiGateway} makes calls to the Image and Price microservices using the - * {@link ImageClientImpl} and {@link PriceClientImpl} respectively. Customers viewing the site on a - * desktop device can see both price information and an image of a product, so the {@link ApiGateway} - * calls both of the microservices and aggregates the data in the {@link DesktopProduct} model. - * However, mobile users only see price information; they do not see a product image. For mobile - * users, the {@link ApiGateway} only retrieves price information, which it uses to populate the - * {@link MobileProduct}. + *

This implementation shows what the API Gateway pattern could look like for an e-commerce + * site. The {@link ApiGateway} makes calls to the Image and Price microservices using the {@link + * ImageClientImpl} and {@link PriceClientImpl} respectively. Customers viewing the site on a + * desktop device can see both price information and an image of a product, so the {@link + * ApiGateway} calls both of the microservices and aggregates the data in the {@link DesktopProduct} + * model. However, mobile users only see price information; they do not see a product image. For + * mobile users, the {@link ApiGateway} only retrieves price information, which it uses to populate + * the {@link MobileProduct}. */ @SpringBootApplication 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) { SpringApplication.run(App.class, args); diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/DesktopProduct.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/DesktopProduct.java index 06b9e9495..2f790bef5 100644 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/DesktopProduct.java +++ b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/DesktopProduct.java @@ -28,12 +28,12 @@ package com.iluwatar.api.gateway; */ public class DesktopProduct { /** - * The price of the product + * The price of the product. */ private String price; /** - * The path to the image of the product + * The path to the image of the product. */ private String imagePath; diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClient.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClient.java index 9c8c341cc..33e212b07 100644 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClient.java +++ b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClient.java @@ -24,7 +24,7 @@ package com.iluwatar.api.gateway; /** - * An interface used to communicate with the Image microservice + * An interface used to communicate with the Image microservice. */ public interface ImageClient { String getImagePath(); diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java index d2f80858c..6aa9698ef 100644 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java +++ b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java @@ -29,17 +29,16 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; - import org.springframework.stereotype.Component; /** - * An adapter to communicate with the Image microservice + * An adapter to communicate with the Image microservice. */ @Component public class ImageClientImpl implements ImageClient { /** - * Makes a simple HTTP Get request to the Image microservice - * + * Makes a simple HTTP Get request to the Image microservice. + * * @return The path to the image */ @Override @@ -47,7 +46,8 @@ public class ImageClientImpl implements ImageClient { String response = null; HttpClient httpClient = HttpClient.newHttpClient(); - HttpRequest httpGet = HttpRequest.newBuilder().GET().uri(URI.create("http://localhost:50005/image-path")).build(); + HttpRequest httpGet = + HttpRequest.newBuilder().GET().uri(URI.create("http://localhost:50005/image-path")).build(); try { HttpResponse httpResponse = httpClient.send(httpGet, BodyHandlers.ofString()); diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/MobileProduct.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/MobileProduct.java index b7edb1047..45fa4e486 100644 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/MobileProduct.java +++ b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/MobileProduct.java @@ -28,7 +28,7 @@ package com.iluwatar.api.gateway; */ public class MobileProduct { /** - * The price of the product + * The price of the product. */ private String price; diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClient.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClient.java index 74c564132..ebe5150ba 100644 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClient.java +++ b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClient.java @@ -24,7 +24,7 @@ package com.iluwatar.api.gateway; /** - * An interface used to communicate with the Price microservice + * An interface used to communicate with the Price microservice. */ public interface PriceClient { String getPrice(); diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java index 0a43c4b1f..0c63e57f4 100644 --- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java +++ b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java @@ -29,17 +29,16 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; - import org.springframework.stereotype.Component; /** - * An adapter to communicate with the Price microservice + * An adapter to communicate with the Price microservice. */ @Component public class PriceClientImpl implements PriceClient { /** - * Makes a simple HTTP Get request to the Price microservice - * + * Makes a simple HTTP Get request to the Price microservice. + * * @return The price of the product */ @Override @@ -48,7 +47,8 @@ public class PriceClientImpl implements PriceClient { String response = null; HttpClient httpClient = HttpClient.newHttpClient(); - HttpRequest httpGet = HttpRequest.newBuilder().GET().uri(URI.create("http://localhost:50006/price")).build(); + HttpRequest httpGet = + HttpRequest.newBuilder().GET().uri(URI.create("http://localhost:50006/price")).build(); try { HttpResponse httpResponse = httpClient.send(httpGet, BodyHandlers.ofString()); diff --git a/api-gateway/api-gateway-service/src/main/resources/application.properties b/api-gateway/api-gateway-service/src/main/resources/application.properties index 35bbf3471..f9e29f5a7 100644 --- a/api-gateway/api-gateway-service/src/main/resources/application.properties +++ b/api-gateway/api-gateway-service/src/main/resources/application.properties @@ -20,5 +20,4 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # - server.port=50004 \ No newline at end of file diff --git a/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageApplication.java b/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageApplication.java index bb551ac31..12c001976 100644 --- a/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageApplication.java +++ b/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageApplication.java @@ -27,16 +27,16 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** - * ImageApplication starts up Spring Boot, exposing endpoints for the Image microservice through - * the {@link ImageController}. + * ImageApplication starts up Spring Boot, exposing endpoints for the Image microservice through the + * {@link ImageController}. */ @SpringBootApplication public class ImageApplication { /** - * Microservice entry point - * @param args - * command line args + * Microservice entry point. + * + * @param args command line args */ public static void main(String[] args) { SpringApplication.run(ImageApplication.class, args); diff --git a/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageController.java b/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageController.java index 9781dbc01..b1f6dd3f7 100644 --- a/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageController.java +++ b/api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageController.java @@ -28,13 +28,14 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; /** - * Exposes the Image microservice's endpoints + * Exposes the Image microservice's endpoints. */ @RestController public class ImageController { /** - * An endpoint for a user to retrieve an image path + * An endpoint for a user to retrieve an image path. + * * @return An image path */ @RequestMapping(value = "/image-path", method = RequestMethod.GET) diff --git a/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceApplication.java b/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceApplication.java index 1a29e53c9..5fc6a0f96 100644 --- a/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceApplication.java +++ b/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceApplication.java @@ -27,16 +27,16 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** - * PriceApplication starts up Spring Boot, exposing endpoints for the Price microservice through - * the {@link PriceController}. + * PriceApplication starts up Spring Boot, exposing endpoints for the Price microservice through the + * {@link PriceController}. */ @SpringBootApplication public class PriceApplication { /** - * Microservice entry point - * @param args - * command line args + * Microservice entry point. + * + * @param args command line args */ public static void main(String[] args) { SpringApplication.run(PriceApplication.class, args); diff --git a/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceController.java b/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceController.java index efb982253..cf2f5eb4f 100644 --- a/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceController.java +++ b/api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceController.java @@ -28,13 +28,14 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; /** - * Exposes the Price microservice's endpoints + * Exposes the Price microservice's endpoints. */ @RestController public class PriceController { /** - * An endpoint for a user to retrieve a product's price + * An endpoint for a user to retrieve a product's price. + * * @return A product's price */ @RequestMapping(value = "/price", method = RequestMethod.GET) diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/App.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/App.java index ec795b40f..ace157154 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/App.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/App.java @@ -27,22 +27,20 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * * Lazy loading idiom defers object creation until needed. - *

- * This example shows different implementations of the pattern with increasing sophistication. - *

- * Additional information and lazy loading flavours are described in - * http://martinfowler.com/eaaCatalog/lazyLoad.html * + *

This example shows different implementations of the pattern with increasing sophistication. + * + *

Additional information and lazy loading flavours are described in + * http://martinfowler.com/eaaCatalog/lazyLoad.html */ public class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); /** - * Program entry point - * + * Program entry point. + * * @param args command line args */ public static void main(String[] args) { diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java index 1e2dd8ae7..dea2d6341 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java @@ -27,16 +27,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * * Heavy objects are expensive to create. - * */ public class Heavy { private static final Logger LOGGER = LoggerFactory.getLogger(Heavy.class); /** - * Constructor + * Constructor. */ public Heavy() { LOGGER.info("Creating Heavy ..."); diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java index a23f70fb7..c18ced6d4 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java @@ -27,9 +27,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * * Simple implementation of the lazy loading idiom. However, this is not thread safe. - * */ public class HolderNaive { @@ -38,14 +36,14 @@ public class HolderNaive { private Heavy heavy; /** - * Constructor + * Constructor. */ public HolderNaive() { LOGGER.info("HolderNaive created"); } /** - * Get heavy object + * Get heavy object. */ public Heavy getHeavy() { if (heavy == null) { diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java index b7c72e14c..ef6d5e663 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java @@ -27,10 +27,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * * Same as HolderNaive but with added synchronization. This implementation is thread safe, but each * {@link #getHeavy()} call costs additional synchronization overhead. - * */ public class HolderThreadSafe { @@ -39,14 +37,14 @@ public class HolderThreadSafe { private Heavy heavy; /** - * Constructor + * Constructor. */ public HolderThreadSafe() { LOGGER.info("HolderThreadSafe created"); } /** - * Get heavy object + * Get heavy object. */ public synchronized Heavy getHeavy() { if (heavy == null) { diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java index 5066b5479..2854a7822 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java @@ -23,16 +23,13 @@ package com.iluwatar.lazy.loading; +import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.function.Supplier; - /** - * * This lazy loader is thread safe and more efficient than {@link HolderThreadSafe}. It utilizes * Java 8 functional interface {@link Supplier} as {@link Heavy} factory. - * */ public class Java8Holder { @@ -57,9 +54,11 @@ public class Java8Holder { return heavyInstance; } } + if (!HeavyFactory.class.isInstance(heavy)) { heavy = new HeavyFactory(); } + return heavy.get(); } } diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractInstance.java b/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractInstance.java index d69a1f134..f30610597 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractInstance.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractInstance.java @@ -23,11 +23,10 @@ package com.iluwatar.leaderelection; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Abstract class of all the instance implementation classes. @@ -69,7 +68,9 @@ public abstract class AbstractInstance implements Instance, Runnable { } /** - * Once messages are sent to the certain instance, it will firstly be added to the queue and wait to be executed. + * Once messages are sent to the certain instance, it will firstly be added to the queue and wait + * to be executed. + * * @param message Message sent by other instances */ @Override @@ -79,6 +80,7 @@ public abstract class AbstractInstance implements Instance, Runnable { /** * Check if the instance is alive or not. + * * @return {@code true} if the instance is alive. */ @Override @@ -88,6 +90,7 @@ public abstract class AbstractInstance implements Instance, Runnable { /** * Set the health status of the certain instance. + * * @param alive {@code true} for alive. */ @Override @@ -97,6 +100,7 @@ public abstract class AbstractInstance implements Instance, Runnable { /** * Process the message according to its type. + * * @param message Message polled from queue. */ private void processMessage(Message message) { @@ -131,8 +135,8 @@ public abstract class AbstractInstance implements Instance, Runnable { } /** - * Abstract methods to handle different types of message. These methods need to be implemented in concrete instance - * class to implement corresponding leader-selection pattern. + * Abstract methods to handle different types of message. These methods need to be implemented in + * concrete instance class to implement corresponding leader-selection pattern. */ protected abstract void handleElectionMessage(Message message); diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractMessageManager.java b/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractMessageManager.java index c7e4fa598..ae2c2f380 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractMessageManager.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/AbstractMessageManager.java @@ -38,7 +38,7 @@ public abstract class AbstractMessageManager implements MessageManager { protected Map instanceMap; /** - * Construtor of AbstractMessageManager + * Construtor of AbstractMessageManager. */ public AbstractMessageManager(Map instanceMap) { this.instanceMap = instanceMap; @@ -46,15 +46,16 @@ public abstract class AbstractMessageManager implements MessageManager { /** * Find the next instance with smallest ID. + * * @return The next instance. */ protected Instance findNextInstance(int currentId) { Instance result = null; List candidateList = instanceMap.keySet() - .stream() - .filter((i) -> i > currentId && instanceMap.get(i).isAlive()) - .sorted() - .collect(Collectors.toList()); + .stream() + .filter((i) -> i > currentId && instanceMap.get(i).isAlive()) + .sorted() + .collect(Collectors.toList()); if (candidateList.isEmpty()) { int index = instanceMap.keySet() .stream() diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/Instance.java b/leader-election/src/main/java/com/iluwatar/leaderelection/Instance.java index 1b39dff83..3ea57c04b 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/Instance.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/Instance.java @@ -24,24 +24,27 @@ package com.iluwatar.leaderelection; /** - * Instance interface + * Instance interface. */ public interface Instance { /** * Check if the instance is alive or not. + * * @return {@code true} if the instance is alive. */ boolean isAlive(); /** * Set the health status of the certain instance. + * * @param alive {@code true} for alive. */ void setAlive(boolean alive); /** * Consume messages from other instances. + * * @param message Message sent by other instances */ void onMessage(Message message); diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/Message.java b/leader-election/src/main/java/com/iluwatar/leaderelection/Message.java index 1302d5588..21f021aff 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/Message.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/Message.java @@ -26,7 +26,7 @@ package com.iluwatar.leaderelection; import java.util.Objects; /** - * Message used to transport data between instances. + * Message used to transport data between instances. */ public class Message { @@ -34,7 +34,8 @@ public class Message { private String content; - public Message() {} + public Message() { + } public Message(MessageType type, String content) { this.type = type; diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/MessageManager.java b/leader-election/src/main/java/com/iluwatar/leaderelection/MessageManager.java index fbd41cac9..9f10de22e 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/MessageManager.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/MessageManager.java @@ -24,12 +24,13 @@ package com.iluwatar.leaderelection; /** - * MessageManager interface + * MessageManager interface. */ public interface MessageManager { /** * Send heartbeat message to leader instance to check whether the leader instance is alive. + * * @param leaderId Instance ID of leader instance. * @return {@code true} if leader instance is alive, or {@code false} if not. */ @@ -37,22 +38,25 @@ public interface MessageManager { /** * Send election message to other instances. + * * @param currentId Instance ID of which sends this message. - * @param content Election message content. + * @param content Election message content. * @return {@code true} if the message is accepted by the target instances. */ boolean sendElectionMessage(int currentId, String content); /** * Send new leader notification message to other instances. + * * @param currentId Instance ID of which sends this message. - * @param leaderId Leader message content. + * @param leaderId Leader message content. * @return {@code true} if the message is accepted by the target instances. */ boolean sendLeaderMessage(int currentId, int leaderId); /** * Send heartbeat invoke message. This will invoke heartbeat task in the target instance. + * * @param currentId Instance ID of which sends this message. */ void sendHeartbeatInvokeMessage(int currentId); diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/MessageType.java b/leader-election/src/main/java/com/iluwatar/leaderelection/MessageType.java index 1749ca15c..a82bfa38f 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/MessageType.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/MessageType.java @@ -24,7 +24,7 @@ package com.iluwatar.leaderelection; /** - * Message Type enum + * Message Type enum. */ public enum MessageType { diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyApp.java b/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyApp.java index c111f442e..34231b3d5 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyApp.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyApp.java @@ -27,19 +27,18 @@ import com.iluwatar.leaderelection.Instance; import com.iluwatar.leaderelection.Message; import com.iluwatar.leaderelection.MessageManager; import com.iluwatar.leaderelection.MessageType; - import java.util.HashMap; import java.util.Map; /** * Example of how to use bully leader election. Initially 5 instances is created in the clould - * system, and the instance with ID 1 is set as leader. After the system is started stop the - * leader instance, and the new leader will be elected. + * system, and the instance with ID 1 is set as leader. After the system is started stop the leader + * instance, and the new leader will be elected. */ public class BullyApp { /** - * Program entry point + * Program entry point. */ public static void main(String[] args) { @@ -60,11 +59,11 @@ public class BullyApp { instance4.onMessage(new Message(MessageType.HEARTBEAT_INVOKE, "")); - Thread thread1 = new Thread(instance1); - Thread thread2 = new Thread(instance2); - Thread thread3 = new Thread(instance3); - Thread thread4 = new Thread(instance4); - Thread thread5 = new Thread(instance5); + final Thread thread1 = new Thread(instance1); + final Thread thread2 = new Thread(instance2); + final Thread thread3 = new Thread(instance3); + final Thread thread4 = new Thread(instance4); + final Thread thread5 = new Thread(instance5); thread1.start(); thread2.start(); diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyInstance.java b/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyInstance.java index c2c497339..92cb18ab4 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyInstance.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyInstance.java @@ -32,11 +32,11 @@ import org.slf4j.LoggerFactory; /** * Impelemetation with bully algorithm. Each instance should have a sequential id and is able to * communicate with other instances in the system. Initially the instance with smallest (or largest) - * ID is selected to be the leader. All the other instances send heartbeat message to leader periodically - * to check its health. If one certain instance finds the server done, it will send an election message - * to all the instances of which the ID is larger. If the target instance is alive, it will return an - * alive message (in this sample return true) and then send election message with its ID. If not, - * the original instance will send leader message to all the other instances. + * ID is selected to be the leader. All the other instances send heartbeat message to leader + * periodically to check its health. If one certain instance finds the server done, it will send an + * election message to all the instances of which the ID is larger. If the target instance is alive, + * it will return an alive message (in this sample return true) and then send election message with + * its ID. If not, the original instance will send leader message to all the other instances. */ public class BullyInstance extends AbstractInstance { @@ -50,9 +50,9 @@ public class BullyInstance extends AbstractInstance { } /** - * Process the heartbeat invoke message. After receiving the message, the instance will send a heartbeat - * to leader to check its health. If alive, it will inform the next instance to do the heartbeat. If not, - * it will start the election process. + * Process the heartbeat invoke message. After receiving the message, the instance will send a + * heartbeat to leader to check its health. If alive, it will inform the next instance to do the + * heartbeat. If not, it will start the election process. */ @Override protected void handleHeartbeatInvokeMessage() { @@ -64,7 +64,8 @@ public class BullyInstance extends AbstractInstance { messageManager.sendHeartbeatInvokeMessage(localId); } else { LOGGER.info("Instance " + localId + "- Leader is not alive. Start election."); - boolean electionResult = messageManager.sendElectionMessage(localId, String.valueOf(localId)); + boolean electionResult = + messageManager.sendElectionMessage(localId, String.valueOf(localId)); if (electionResult) { LOGGER.info("Instance " + localId + "- Succeed in election. Start leader notification."); messageManager.sendLeaderMessage(localId, localId); @@ -76,9 +77,9 @@ public class BullyInstance extends AbstractInstance { } /** - * Process election invoke message. Send election message to all the instances with smaller ID. If any - * one of them is alive, do nothing. If no instance alive, send leader message to all the alive instance - * and restart heartbeat. + * Process election invoke message. Send election message to all the instances with smaller ID. If + * any one of them is alive, do nothing. If no instance alive, send leader message to all the + * alive instance and restart heartbeat. */ @Override protected void handleElectionInvokeMessage() { @@ -111,11 +112,14 @@ public class BullyInstance extends AbstractInstance { * Not used in Bully instance. */ @Override - protected void handleLeaderInvokeMessage() {} + protected void handleLeaderInvokeMessage() { + } @Override - protected void handleHeartbeatMessage(Message message) {} + protected void handleHeartbeatMessage(Message message) { + } @Override - protected void handleElectionMessage(Message message) {} + protected void handleElectionMessage(Message message) { + } } diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyMessageManager.java b/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyMessageManager.java index 907098f6b..d1e4c7db1 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyMessageManager.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyMessageManager.java @@ -27,13 +27,12 @@ import com.iluwatar.leaderelection.AbstractMessageManager; import com.iluwatar.leaderelection.Instance; import com.iluwatar.leaderelection.Message; import com.iluwatar.leaderelection.MessageType; - import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** - * Implementation of BullyMessageManager + * Implementation of BullyMessageManager. */ public class BullyMessageManager extends AbstractMessageManager { @@ -46,6 +45,7 @@ public class BullyMessageManager extends AbstractMessageManager { /** * Send heartbeat message to current leader instance to check the health. + * * @param leaderId leaderID * @return {@code true} if the leader is alive. */ @@ -58,8 +58,9 @@ public class BullyMessageManager extends AbstractMessageManager { /** * Send election message to all the instances with smaller ID. + * * @param currentId Instance ID of which sends this message. - * @param content Election message content. + * @param content Election message content. * @return {@code true} if no alive instance has smaller ID, so that the election is accepted. */ @Override @@ -70,29 +71,31 @@ public class BullyMessageManager extends AbstractMessageManager { } else { Message electionMessage = new Message(MessageType.ELECTION_INVOKE, ""); candidateList.stream() - .forEach((i) -> instanceMap.get(i).onMessage(electionMessage)); + .forEach((i) -> instanceMap.get(i).onMessage(electionMessage)); return false; } } /** * Send leader message to all the instances to notify the new leader. + * * @param currentId Instance ID of which sends this message. - * @param leaderId Leader message content. + * @param leaderId Leader message content. * @return {@code true} if the message is accepted. */ @Override public boolean sendLeaderMessage(int currentId, int leaderId) { Message leaderMessage = new Message(MessageType.LEADER, String.valueOf(leaderId)); instanceMap.keySet() - .stream() - .filter((i) -> i != currentId) - .forEach((i) -> instanceMap.get(i).onMessage(leaderMessage)); + .stream() + .filter((i) -> i != currentId) + .forEach((i) -> instanceMap.get(i).onMessage(leaderMessage)); return false; } /** * Send heartbeat invoke message to the next instance. + * * @param currentId Instance ID of which sends this message. */ @Override @@ -104,14 +107,15 @@ public class BullyMessageManager extends AbstractMessageManager { /** * Find all the alive instances with smaller ID than current instance. + * * @param currentId ID of current instance. * @return ID list of all the candidate instance. */ private List findElectionCandidateInstanceList(int currentId) { return instanceMap.keySet() - .stream() - .filter((i) -> i < currentId && instanceMap.get(i).isAlive()) - .collect(Collectors.toList()); + .stream() + .filter((i) -> i < currentId && instanceMap.get(i).isAlive()) + .collect(Collectors.toList()); } } diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingApp.java b/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingApp.java index a8a6271ea..096beb566 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingApp.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingApp.java @@ -27,19 +27,18 @@ import com.iluwatar.leaderelection.Instance; import com.iluwatar.leaderelection.Message; import com.iluwatar.leaderelection.MessageManager; import com.iluwatar.leaderelection.MessageType; - import java.util.HashMap; import java.util.Map; /** * Example of how to use ring leader election. Initially 5 instances is created in the clould - * system, and the instance with ID 1 is set as leader. After the system is started stop the - * leader instance, and the new leader will be elected. + * system, and the instance with ID 1 is set as leader. After the system is started stop the leader + * instance, and the new leader will be elected. */ public class RingApp { /** - * Program entry point + * Program entry point. */ public static void main(String[] args) { @@ -60,11 +59,11 @@ public class RingApp { instance2.onMessage(new Message(MessageType.HEARTBEAT_INVOKE, "")); - Thread thread1 = new Thread(instance1); - Thread thread2 = new Thread(instance2); - Thread thread3 = new Thread(instance3); - Thread thread4 = new Thread(instance4); - Thread thread5 = new Thread(instance5); + final Thread thread1 = new Thread(instance1); + final Thread thread2 = new Thread(instance2); + final Thread thread3 = new Thread(instance3); + final Thread thread4 = new Thread(instance4); + final Thread thread5 = new Thread(instance5); thread1.start(); thread2.start(); diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingInstance.java b/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingInstance.java index 4cdbb5709..903ac15ce 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingInstance.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingInstance.java @@ -26,23 +26,22 @@ package com.iluwatar.leaderelection.ring; import com.iluwatar.leaderelection.AbstractInstance; import com.iluwatar.leaderelection.Message; import com.iluwatar.leaderelection.MessageManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Implementation with token ring algorithm. The instances in the system are organized as a ring. * Each instance should have a sequential id and the instance with smallest (or largest) id should - * be the initial leader. All the other instances send heartbeat message to leader periodically - * to check its health. If one certain instance finds the server done, it will send an election - * message to the next alive instance in the ring, which contains its own ID. Then the next instance - * add its ID into the message and pass it to the next. After all the alive instances' ID are add - * to the message, the message is send back to the first instance and it will choose the instance - * with smallest ID to be the new leader, and then send a leader message to other instances to - * inform the result. + * be the initial leader. All the other instances send heartbeat message to leader periodically to + * check its health. If one certain instance finds the server done, it will send an election message + * to the next alive instance in the ring, which contains its own ID. Then the next instance add its + * ID into the message and pass it to the next. After all the alive instances' ID are add to the + * message, the message is send back to the first instance and it will choose the instance with + * smallest ID to be the new leader, and then send a leader message to other instances to inform the + * result. */ public class RingInstance extends AbstractInstance { @@ -56,9 +55,9 @@ public class RingInstance extends AbstractInstance { } /** - * Process the heartbeat invoke message. After receiving the message, the instance will send a heartbeat - * to leader to check its health. If alive, it will inform the next instance to do the heartbeat. If not, - * it will start the election process. + * Process the heartbeat invoke message. After receiving the message, the instance will send a + * heartbeat to leader to check its health. If alive, it will inform the next instance to do the + * heartbeat. If not, it will start the election process. */ @Override protected void handleHeartbeatInvokeMessage() { @@ -78,9 +77,10 @@ public class RingInstance extends AbstractInstance { } /** - * Process election message. If the local ID is contained in the ID list, the instance will select the - * alive instance with smallest ID to be the new leader, and send the leader inform message. If not, - * it will add its local ID to the list and send the message to the next instance in the ring. + * Process election message. If the local ID is contained in the ID list, the instance will select + * the alive instance with smallest ID to be the new leader, and send the leader inform message. + * If not, it will add its local ID to the list and send the message to the next instance in the + * ring. */ @Override protected void handleElectionMessage(Message message) { @@ -88,9 +88,9 @@ public class RingInstance extends AbstractInstance { LOGGER.info("Instance " + localId + " - Election Message: " + content); List candidateList = Arrays.stream(content.trim().split(",")) - .map(Integer::valueOf) - .sorted() - .collect(Collectors.toList()); + .map(Integer::valueOf) + .sorted() + .collect(Collectors.toList()); if (candidateList.contains(localId)) { int newLeaderId = candidateList.get(0); LOGGER.info("Instance " + localId + " - New leader should be " + newLeaderId + "."); @@ -102,8 +102,8 @@ public class RingInstance extends AbstractInstance { } /** - * Process leader Message. The instance will set the leader ID to be the new one and send the message to - * the next instance until all the alive instance in the ring is informed. + * Process leader Message. The instance will set the leader ID to be the new one and send the + * message to the next instance until all the alive instance in the ring is informed. */ @Override protected void handleLeaderMessage(Message message) { @@ -122,12 +122,15 @@ public class RingInstance extends AbstractInstance { * Not used in Ring instance. */ @Override - protected void handleLeaderInvokeMessage() {} + protected void handleLeaderInvokeMessage() { + } @Override - protected void handleHeartbeatMessage(Message message) {} + protected void handleHeartbeatMessage(Message message) { + } @Override - protected void handleElectionInvokeMessage() {} + protected void handleElectionInvokeMessage() { + } } diff --git a/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingMessageManager.java b/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingMessageManager.java index 344963633..6cbadf184 100644 --- a/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingMessageManager.java +++ b/leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingMessageManager.java @@ -27,11 +27,10 @@ import com.iluwatar.leaderelection.AbstractMessageManager; import com.iluwatar.leaderelection.Instance; import com.iluwatar.leaderelection.Message; import com.iluwatar.leaderelection.MessageType; - import java.util.Map; /** - * Implementation of RingMessageManager + * Implementation of RingMessageManager. */ public class RingMessageManager extends AbstractMessageManager { @@ -44,6 +43,7 @@ public class RingMessageManager extends AbstractMessageManager { /** * Send heartbeat message to current leader instance to check the health. + * * @param leaderId leaderID * @return {@code true} if the leader is alive. */ @@ -56,8 +56,10 @@ public class RingMessageManager extends AbstractMessageManager { /** * Send election message to the next instance. + * * @param currentId currentID - * @param content list contains all the IDs of instances which have received this election message. + * @param content list contains all the IDs of instances which have received this election + * message. * @return {@code true} if the election message is accepted by the target instance. */ @Override @@ -70,8 +72,9 @@ public class RingMessageManager extends AbstractMessageManager { /** * Send leader message to the next instance. + * * @param currentId Instance ID of which sends this message. - * @param leaderId Leader message content. + * @param leaderId Leader message content. * @return {@code true} if the leader message is accepted by the target instance. */ @Override @@ -84,6 +87,7 @@ public class RingMessageManager extends AbstractMessageManager { /** * Send heartbeat invoke message to the next instance. + * * @param currentId Instance ID of which sends this message. */ @Override