diff --git a/CODE_COVERAGE.md b/CODE_COVERAGE.md index 589c7ad79..d1ce7afd2 100644 --- a/CODE_COVERAGE.md +++ b/CODE_COVERAGE.md @@ -1,7 +1,7 @@ # Code Coverage Report generation To generate the code coverage report, execute the following command: -> mvn clean verify +> mvn clean verify jacoco:report This will generate code coverage report in each of the modules. In order to view the same, open the following file in your browser. > target/site/jacoco/index.html diff --git a/README.md b/README.md index 03aea2bf6..4ec0f33bd 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Build status](https://travis-ci.org/iluwatar/java-design-patterns.svg?branch=master)](https://travis-ci.org/iluwatar/java-design-patterns) [![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md) [![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Quality Gate](https://sonarcloud.io/api/badges/gate?key=com.iluwatar%3Ajava-design-patterns)](https://sonarcloud.io/dashboard/index/com.iluwatar%3Ajava-design-patterns) +[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=com.iluwatar%3Ajava-design-patterns&metric=alert_status)](https://sonarcloud.io/dashboard/index/com.iluwatar%3Ajava-design-patterns) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1503/badge)](https://bestpractices.coreinfrastructure.org/projects/1503) # Introduction diff --git a/abstract-document/pom.xml b/abstract-document/pom.xml index a249f0d07..d1b10a9fd 100644 --- a/abstract-document/pom.xml +++ b/abstract-document/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT abstract-document diff --git a/abstract-factory/README.md b/abstract-factory/README.md index 423988b58..0bf86dfa6 100644 --- a/abstract-factory/README.md +++ b/abstract-factory/README.md @@ -34,7 +34,7 @@ Wikipedia says Translating the kingdom example above. First of all we have some interfaces and implementation for the objects in the kingdom -``` +```java public interface Castle { String getDescription(); } @@ -74,7 +74,7 @@ public class ElfArmy implements Army { Then we have the abstraction and implementations for the kingdom factory -``` +```java public interface KingdomFactory { Castle createCastle(); King createKing(); @@ -108,7 +108,7 @@ public class OrcKingdomFactory implements KingdomFactory { Now we have our abstract factory that lets us make family of related objects i.e. Elven kingdom factory creates Elven castle, king and army etc. -``` +```java KingdomFactory factory = new ElfKingdomFactory(); Castle castle = factory.createCastle(); King king = factory.createKing(); @@ -123,7 +123,7 @@ Now, we can design a factory for our different kingdom factories. In this exampl The client can use FactoryMaker to create the desired concrete factory which, in turn, will produce different concrete objects (Army, King, Castle). In this example, we also used an enum to parameterize which type of kingdom factory the client will ask for. -``` +```java public static class FactoryMaker { public enum KingdomType { diff --git a/abstract-factory/pom.xml b/abstract-factory/pom.xml index 073879acc..6d94e70ce 100644 --- a/abstract-factory/pom.xml +++ b/abstract-factory/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT abstract-factory diff --git a/adapter/README.md b/adapter/README.md index 3344490ff..e943baba5 100644 --- a/adapter/README.md +++ b/adapter/README.md @@ -40,7 +40,7 @@ Consider a captain that can only use rowing boats and cannot sail at all. First we have interfaces `RowingBoat` and `FishingBoat` -``` +```java public interface RowingBoat { void row(); } @@ -55,7 +55,7 @@ public class FishingBoat { And captain expects an implementation of `RowingBoat` interface to be able to move -``` +```java public class Captain implements RowingBoat { private RowingBoat rowingBoat; @@ -73,7 +73,7 @@ public class Captain implements RowingBoat { Now let's say the pirates are coming and our captain needs to escape but there is only fishing boat available. We need to create an adapter that allows the captain to operate the fishing boat with his rowing boat skills. -``` +```java public class FishingBoatAdapter implements RowingBoat { private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoatAdapter.class); @@ -93,7 +93,7 @@ public class FishingBoatAdapter implements RowingBoat { And now the `Captain` can use the `FishingBoat` to escape the pirates. -``` +```java Captain captain = new Captain(new FishingBoatAdapter()); captain.row(); ``` diff --git a/adapter/pom.xml b/adapter/pom.xml index 95b9a3e99..95ccee3a9 100644 --- a/adapter/pom.xml +++ b/adapter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT adapter diff --git a/adapter/src/main/java/com/iluwatar/adapter/Captain.java b/adapter/src/main/java/com/iluwatar/adapter/Captain.java index 369016980..8593ca321 100644 --- a/adapter/src/main/java/com/iluwatar/adapter/Captain.java +++ b/adapter/src/main/java/com/iluwatar/adapter/Captain.java @@ -26,7 +26,7 @@ package com.iluwatar.adapter; * The Captain uses {@link RowingBoat} to sail.
* This is the client in the pattern. */ -public class Captain implements RowingBoat { +public class Captain { private RowingBoat rowingBoat; @@ -40,7 +40,6 @@ public class Captain implements RowingBoat { this.rowingBoat = rowingBoat; } - @Override public void row() { rowingBoat.row(); } diff --git a/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java b/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java index 033440b81..82a951e30 100644 --- a/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java +++ b/adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java @@ -66,7 +66,7 @@ public class AdapterPatternTest { */ @Test public void testAdapter() { - RowingBoat captain = (RowingBoat) beans.get(ROWING_BEAN); + Captain captain = (Captain) beans.get(ROWING_BEAN); // when captain moves captain.row(); diff --git a/aggregator-microservices/aggregator-service/pom.xml b/aggregator-microservices/aggregator-service/pom.xml index d338f47b9..fb26ff954 100644 --- a/aggregator-microservices/aggregator-service/pom.xml +++ b/aggregator-microservices/aggregator-service/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/aggregator-microservices/information-microservice/pom.xml b/aggregator-microservices/information-microservice/pom.xml index 3879681b7..7afce1e9b 100644 --- a/aggregator-microservices/information-microservice/pom.xml +++ b/aggregator-microservices/information-microservice/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/aggregator-microservices/inventory-microservice/pom.xml b/aggregator-microservices/inventory-microservice/pom.xml index 3f212e2e9..0d44b037e 100644 --- a/aggregator-microservices/inventory-microservice/pom.xml +++ b/aggregator-microservices/inventory-microservice/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/aggregator-microservices/pom.xml b/aggregator-microservices/pom.xml index 364b02566..ed48768f2 100644 --- a/aggregator-microservices/pom.xml +++ b/aggregator-microservices/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 aggregator-microservices diff --git a/api-gateway/api-gateway-service/pom.xml b/api-gateway/api-gateway-service/pom.xml index a035f11a2..609fca88d 100644 --- a/api-gateway/api-gateway-service/pom.xml +++ b/api-gateway/api-gateway-service/pom.xml @@ -29,7 +29,7 @@ api-gateway com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 api-gateway-service diff --git a/api-gateway/image-microservice/pom.xml b/api-gateway/image-microservice/pom.xml index ad248943d..e90747eb9 100644 --- a/api-gateway/image-microservice/pom.xml +++ b/api-gateway/image-microservice/pom.xml @@ -29,7 +29,7 @@ api-gateway com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/api-gateway/pom.xml b/api-gateway/pom.xml index c151d59a1..72468c7eb 100644 --- a/api-gateway/pom.xml +++ b/api-gateway/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 api-gateway diff --git a/api-gateway/price-microservice/pom.xml b/api-gateway/price-microservice/pom.xml index cdd8b4c3c..deb0627f4 100644 --- a/api-gateway/price-microservice/pom.xml +++ b/api-gateway/price-microservice/pom.xml @@ -29,7 +29,7 @@ api-gateway com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/async-method-invocation/pom.xml b/async-method-invocation/pom.xml index a686e3e68..c29062630 100644 --- a/async-method-invocation/pom.xml +++ b/async-method-invocation/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT async-method-invocation diff --git a/balking/pom.xml b/balking/pom.xml index 276dc397d..e16065359 100644 --- a/balking/pom.xml +++ b/balking/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java b/balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java index 47957835d..9a13b8b2d 100644 --- a/balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java +++ b/balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java @@ -22,6 +22,7 @@ */ package com.iluwatar.balking; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.util.concurrent.ExecutorService; @@ -37,6 +38,7 @@ public class WashingMachineTest { private volatile WashingMachineState machineStateGlobal; + @Disabled @Test public void wash() throws Exception { WashingMachine washingMachine = new WashingMachine(); diff --git a/bridge/README.md b/bridge/README.md index bce723971..cfbbcf0d9 100644 --- a/bridge/README.md +++ b/bridge/README.md @@ -34,7 +34,7 @@ Wikipedia says Translating our weapon example from above. Here we have the `Weapon` hierarchy -``` +```java public interface Weapon { void wield(); void swing(); @@ -109,7 +109,7 @@ public class Hammer implements Weapon { And the separate enchantment hierarchy -``` +```java public interface Enchantment { void onActivate(); void apply(); @@ -155,7 +155,7 @@ public class SoulEatingEnchantment implements Enchantment { And both the hierarchies in action -``` +```java Sword enchantedSword = new Sword(new SoulEatingEnchantment()); enchantedSword.wield(); enchantedSword.swing(); diff --git a/bridge/pom.xml b/bridge/pom.xml index 0cef80258..8ab24c159 100644 --- a/bridge/pom.xml +++ b/bridge/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT bridge diff --git a/builder/README.md b/builder/README.md index 51495619b..b775f1064 100644 --- a/builder/README.md +++ b/builder/README.md @@ -31,7 +31,7 @@ Wikipedia says Having said that let me add a bit about what telescoping constructor anti-pattern is. At one point or the other we have all seen a constructor like below: -``` +```java public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) { } ``` @@ -42,7 +42,7 @@ As you can see the number of constructor parameters can quickly get out of hand The sane alternative is to use the Builder pattern. First of all we have our hero that we want to create -``` +```java public final class Hero { private final Profession profession; private final String name; @@ -64,7 +64,7 @@ public final class Hero { And then we have the builder -``` +```java public static class Builder { private final Profession profession; private final String name; @@ -109,7 +109,7 @@ And then we have the builder And then it can be used as: -``` +```java Hero mage = new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build(); ``` diff --git a/builder/pom.xml b/builder/pom.xml index a7d5c9d70..b17d53030 100644 --- a/builder/pom.xml +++ b/builder/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT builder diff --git a/business-delegate/pom.xml b/business-delegate/pom.xml index 0bc02827b..d48faeff4 100644 --- a/business-delegate/pom.xml +++ b/business-delegate/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT business-delegate diff --git a/caching/pom.xml b/caching/pom.xml index f76778840..57f8f0119 100644 --- a/caching/pom.xml +++ b/caching/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT caching diff --git a/caching/src/main/java/com/iluwatar/caching/App.java b/caching/src/main/java/com/iluwatar/caching/App.java index 589b26245..fced38b59 100644 --- a/caching/src/main/java/com/iluwatar/caching/App.java +++ b/caching/src/main/java/com/iluwatar/caching/App.java @@ -52,12 +52,12 @@ import org.slf4j.LoggerFactory; * whether the data is coming from the cache or the DB (i.e. separation of concern). The AppManager * ({@link AppManager}) handles the transaction of data to-and-from the underlying data store * (depending on the preferred caching policy/strategy). - * - * App --> AppManager --> CacheStore/LRUCache/CachingPolicy --> DBManager + *

+ * {@literal App --> AppManager --> CacheStore/LRUCache/CachingPolicy --> DBManager} *

* * @see CacheStore - * @See LRUCache + * @see LruCache * @see CachingPolicy * */ diff --git a/callback/pom.xml b/callback/pom.xml index aa1039789..387c8a667 100644 --- a/callback/pom.xml +++ b/callback/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT callback diff --git a/chain/README.md b/chain/README.md index 6bca81610..eb434aea8 100644 --- a/chain/README.md +++ b/chain/README.md @@ -33,7 +33,7 @@ Wikipedia says Translating our example with orcs from above. First we have the request class -``` +```java public class Request { private final RequestType requestType; @@ -64,7 +64,7 @@ public enum RequestType { Then the request handler hierarchy -``` +```java public abstract class RequestHandler { private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class); private RequestHandler next; @@ -114,7 +114,7 @@ public class OrcCommander extends RequestHandler { Then we have the Orc King who gives the orders and forms the chain -``` +```java public class OrcKing { RequestHandler chain; @@ -134,7 +134,7 @@ public class OrcKing { Then it is used as follows -``` +```java OrcKing king = new OrcKing(); king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); // Orc commander handling request "defend castle" king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); // Orc officer handling request "torture prisoner" diff --git a/chain/pom.xml b/chain/pom.xml index 51c83f1ae..07b1a5e4a 100644 --- a/chain/pom.xml +++ b/chain/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT chain diff --git a/command/pom.xml b/command/pom.xml index 9a819bb6c..68d4b2064 100644 --- a/command/pom.xml +++ b/command/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT command diff --git a/composite/README.md b/composite/README.md index e4f45ddd0..05ee70cbb 100644 --- a/composite/README.md +++ b/composite/README.md @@ -33,7 +33,7 @@ Wikipedia says Taking our sentence example from above. Here we have the base class and different printable types -``` +```java public abstract class LetterComposite { private List children = new ArrayList<>(); public void add(LetterComposite letter) { @@ -91,7 +91,7 @@ public class Sentence extends LetterComposite { Then we have a messenger to carry messages -``` +```java public class Messenger { LetterComposite messageFromOrcs() { List words = new ArrayList<>(); @@ -122,7 +122,7 @@ public class Messenger { And then it can be used as -``` +```java LetterComposite orcMessage = new Messenger().messageFromOrcs(); orcMessage.print(); // Where there is a whip there is a way. LetterComposite elfMessage = new Messenger().messageFromElves(); diff --git a/composite/pom.xml b/composite/pom.xml index eb3b5d7b4..944aa1456 100644 --- a/composite/pom.xml +++ b/composite/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT composite diff --git a/converter/pom.xml b/converter/pom.xml index 69005d7d6..f696048f5 100644 --- a/converter/pom.xml +++ b/converter/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/converter/src/main/java/com/iluwatar/converter/Converter.java b/converter/src/main/java/com/iluwatar/converter/Converter.java index 918d2d503..4a2bb7381 100644 --- a/converter/src/main/java/com/iluwatar/converter/Converter.java +++ b/converter/src/main/java/com/iluwatar/converter/Converter.java @@ -50,37 +50,37 @@ public class Converter { } /** - * @param userDto DTO entity + * @param dto DTO entity * @return The domain representation - the result of the converting function application on dto entity. */ - public final U convertFromDto(final T userDto) { - return fromDto.apply(userDto); + public final U convertFromDto(final T dto) { + return fromDto.apply(dto); } /** - * @param user domain entity + * @param entity domain entity * @return The DTO representation - the result of the converting function application on domain entity. */ - public final T convertFromEntity(final U user) { - return fromEntity.apply(user); + public final T convertFromEntity(final U entity) { + return fromEntity.apply(entity); } /** - * @param dtoUsers collection of DTO entities + * @param dtos collection of DTO entities * @return List of domain representation of provided entities retrieved by * mapping each of them with the conversion function */ - public final List createFromDtos(final Collection dtoUsers) { - return dtoUsers.stream().map(this::convertFromDto).collect(Collectors.toList()); + public final List createFromDtos(final Collection dtos) { + return dtos.stream().map(this::convertFromDto).collect(Collectors.toList()); } /** - * @param users collection of domain entities + * @param entities collection of domain entities * @return List of domain representation of provided entities retrieved by * mapping each of them with the conversion function */ - public final List createFromEntities(final Collection users) { - return users.stream().map(this::convertFromEntity).collect(Collectors.toList()); + public final List createFromEntities(final Collection entities) { + return entities.stream().map(this::convertFromEntity).collect(Collectors.toList()); } } diff --git a/cqrs/pom.xml b/cqrs/pom.xml index 2ed0809f6..7ed2e1208 100644 --- a/cqrs/pom.xml +++ b/cqrs/pom.xml @@ -21,7 +21,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT cqrs diff --git a/dao/pom.xml b/dao/pom.xml index 621af6baf..3700d76a7 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT dao diff --git a/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java b/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java index 38acca60f..947da23ca 100644 --- a/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java +++ b/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java @@ -31,7 +31,7 @@ import java.util.stream.Stream; /** * An in memory implementation of {@link CustomerDao}, which stores the customers in JVM memory * and data is lost when the application exits. - *
+ *
* This implementation is useful as temporary database or for testing. */ public class InMemoryCustomerDao implements CustomerDao { diff --git a/data-bus/pom.xml b/data-bus/pom.xml index 11d945268..6292b71fb 100644 --- a/data-bus/pom.xml +++ b/data-bus/pom.xml @@ -33,7 +33,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT data-bus diff --git a/data-bus/src/main/java/com/iluwatar/databus/App.java b/data-bus/src/main/java/com/iluwatar/databus/App.java index 748bb6af0..b599bdc57 100644 --- a/data-bus/src/main/java/com/iluwatar/databus/App.java +++ b/data-bus/src/main/java/com/iluwatar/databus/App.java @@ -34,8 +34,7 @@ import java.time.LocalDateTime; /** * The Data Bus pattern *

- *

{@see http://wiki.c2.com/?DataBusPattern}

- *

+ * @see http://wiki.c2.com/?DataBusPattern *

The Data-Bus pattern provides a method where different parts of an application may * pass messages between each other without needing to be aware of the other's existence.

*

Similar to the {@code ObserverPattern}, members register themselves with the {@link DataBus} diff --git a/data-mapper/pom.xml b/data-mapper/pom.xml index ac0d78c33..aadcabd3d 100644 --- a/data-mapper/pom.xml +++ b/data-mapper/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT data-mapper diff --git a/data-transfer-object/pom.xml b/data-transfer-object/pom.xml index 8a484e919..17ad1f83f 100644 --- a/data-transfer-object/pom.xml +++ b/data-transfer-object/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT data-transfer-object diff --git a/decorator/README.md b/decorator/README.md index dcf49dbf5..9998b9938 100644 --- a/decorator/README.md +++ b/decorator/README.md @@ -36,7 +36,7 @@ Wikipedia says Let's take the troll example. First of all we have a simple troll implementing the troll interface -``` +```java public interface Troll { void attack(); int getAttackPower(); @@ -66,7 +66,7 @@ public class SimpleTroll implements Troll { Next we want to add club for the troll. We can do it dynamically by using a decorator -``` +```java public class ClubbedTroll implements Troll { private static final Logger LOGGER = LoggerFactory.getLogger(ClubbedTroll.class); @@ -97,7 +97,7 @@ public class ClubbedTroll implements Troll { Here's the troll in action -``` +```java // simple troll Troll troll = new SimpleTroll(); troll.attack(); // The troll tries to grab you! diff --git a/decorator/pom.xml b/decorator/pom.xml index 687de3ad8..d4e2a887d 100644 --- a/decorator/pom.xml +++ b/decorator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT decorator diff --git a/delegation/pom.xml b/delegation/pom.xml index 118f9f75b..6c7c710d5 100644 --- a/delegation/pom.xml +++ b/delegation/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml index 127a9b2b8..e8a499918 100644 --- a/dependency-injection/pom.xml +++ b/dependency-injection/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT dependency-injection diff --git a/double-checked-locking/pom.xml b/double-checked-locking/pom.xml index d7e8414c0..7efd3c31e 100644 --- a/double-checked-locking/pom.xml +++ b/double-checked-locking/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT double-checked-locking diff --git a/double-dispatch/pom.xml b/double-dispatch/pom.xml index 85a85d831..c64ab4ce9 100644 --- a/double-dispatch/pom.xml +++ b/double-dispatch/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT double-dispatch diff --git a/eip-aggregator/pom.xml b/eip-aggregator/pom.xml index 8a51b8218..3b043ad7e 100644 --- a/eip-aggregator/pom.xml +++ b/eip-aggregator/pom.xml @@ -26,7 +26,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT diff --git a/message-channel/.gitignore b/eip-message-channel/.gitignore similarity index 100% rename from message-channel/.gitignore rename to eip-message-channel/.gitignore diff --git a/message-channel/README.md b/eip-message-channel/README.md similarity index 84% rename from message-channel/README.md rename to eip-message-channel/README.md index 09361dd4a..606619619 100644 --- a/message-channel/README.md +++ b/eip-message-channel/README.md @@ -1,8 +1,8 @@ --- layout: pattern -title: Message Channel -folder: message-channel -permalink: /patterns/message-channel/ +title: EIP Message Channel +folder: eip-message-channel +permalink: /patterns/eip-message-channel/ categories: Integration tags: - Java diff --git a/message-channel/etc/message-channel.png b/eip-message-channel/etc/message-channel.png similarity index 100% rename from message-channel/etc/message-channel.png rename to eip-message-channel/etc/message-channel.png diff --git a/message-channel/etc/message-channel.ucls b/eip-message-channel/etc/message-channel.ucls similarity index 100% rename from message-channel/etc/message-channel.ucls rename to eip-message-channel/etc/message-channel.ucls diff --git a/message-channel/pom.xml b/eip-message-channel/pom.xml similarity index 96% rename from message-channel/pom.xml rename to eip-message-channel/pom.xml index 3e3028f2a..84cde7e2e 100644 --- a/message-channel/pom.xml +++ b/eip-message-channel/pom.xml @@ -30,9 +30,9 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT - message-channel + eip-message-channel org.apache.camel diff --git a/message-channel/src/main/java/com/iluwatar/message/channel/App.java b/eip-message-channel/src/main/java/com/iluwatar/eip/message/channel/App.java similarity index 98% rename from message-channel/src/main/java/com/iluwatar/message/channel/App.java rename to eip-message-channel/src/main/java/com/iluwatar/eip/message/channel/App.java index d2974e20b..d5929d0db 100644 --- a/message-channel/src/main/java/com/iluwatar/message/channel/App.java +++ b/eip-message-channel/src/main/java/com/iluwatar/eip/message/channel/App.java @@ -20,7 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.iluwatar.message.channel; +package com.iluwatar.eip.message.channel; import org.apache.camel.CamelContext; import org.apache.camel.builder.RouteBuilder; diff --git a/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java b/eip-message-channel/src/test/java/com/iluwatar/eip/message/channel/AppTest.java similarity index 96% rename from publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java rename to eip-message-channel/src/test/java/com/iluwatar/eip/message/channel/AppTest.java index 128385faf..127f427b8 100644 --- a/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java +++ b/eip-message-channel/src/test/java/com/iluwatar/eip/message/channel/AppTest.java @@ -20,7 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.iluwatar.publish.subscribe; +package com.iluwatar.eip.message.channel; import org.junit.jupiter.api.Test; diff --git a/publish-subscribe/.gitignore b/eip-publish-subscribe/.gitignore similarity index 100% rename from publish-subscribe/.gitignore rename to eip-publish-subscribe/.gitignore diff --git a/publish-subscribe/README.md b/eip-publish-subscribe/README.md similarity index 83% rename from publish-subscribe/README.md rename to eip-publish-subscribe/README.md index 462209074..90ac02c9b 100644 --- a/publish-subscribe/README.md +++ b/eip-publish-subscribe/README.md @@ -1,8 +1,8 @@ --- layout: pattern -title: Publish Subscribe -folder: publish-subscribe -permalink: /patterns/publish-subscribe/ +title: EIP Publish Subscribe +folder: eip-publish-subscribe +permalink: /patterns/eip-publish-subscribe/ categories: Integration tags: - Java diff --git a/publish-subscribe/etc/publish-subscribe.png b/eip-publish-subscribe/etc/publish-subscribe.png similarity index 100% rename from publish-subscribe/etc/publish-subscribe.png rename to eip-publish-subscribe/etc/publish-subscribe.png diff --git a/publish-subscribe/etc/publish-subscribe.ucls b/eip-publish-subscribe/etc/publish-subscribe.ucls similarity index 100% rename from publish-subscribe/etc/publish-subscribe.ucls rename to eip-publish-subscribe/etc/publish-subscribe.ucls diff --git a/publish-subscribe/pom.xml b/eip-publish-subscribe/pom.xml similarity index 95% rename from publish-subscribe/pom.xml rename to eip-publish-subscribe/pom.xml index 688cda903..82763b22b 100644 --- a/publish-subscribe/pom.xml +++ b/eip-publish-subscribe/pom.xml @@ -28,9 +28,9 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT - publish-subscribe + eip-publish-subscribe org.apache.camel @@ -51,4 +51,4 @@ test - \ No newline at end of file + diff --git a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java b/eip-publish-subscribe/src/main/java/com/iluwatar/eip/publish/subscribe/App.java similarity index 98% rename from publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java rename to eip-publish-subscribe/src/main/java/com/iluwatar/eip/publish/subscribe/App.java index d642846fb..7c7e77a18 100644 --- a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java +++ b/eip-publish-subscribe/src/main/java/com/iluwatar/eip/publish/subscribe/App.java @@ -20,7 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.iluwatar.publish.subscribe; +package com.iluwatar.eip.publish.subscribe; import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; diff --git a/publish-subscribe/src/main/resources/logback.xml b/eip-publish-subscribe/src/main/resources/logback.xml similarity index 100% rename from publish-subscribe/src/main/resources/logback.xml rename to eip-publish-subscribe/src/main/resources/logback.xml diff --git a/message-channel/src/test/java/com/iluwatar/message/channel/AppTest.java b/eip-publish-subscribe/src/test/java/com/iluwatar/eip/publish/subscribe/AppTest.java similarity index 96% rename from message-channel/src/test/java/com/iluwatar/message/channel/AppTest.java rename to eip-publish-subscribe/src/test/java/com/iluwatar/eip/publish/subscribe/AppTest.java index 97094b864..783c796ac 100644 --- a/message-channel/src/test/java/com/iluwatar/message/channel/AppTest.java +++ b/eip-publish-subscribe/src/test/java/com/iluwatar/eip/publish/subscribe/AppTest.java @@ -20,7 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.iluwatar.message.channel; +package com.iluwatar.eip.publish.subscribe; import org.junit.jupiter.api.Test; diff --git a/eip-splitter/pom.xml b/eip-splitter/pom.xml index 54661f946..ed16337da 100644 --- a/eip-splitter/pom.xml +++ b/eip-splitter/pom.xml @@ -26,7 +26,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT diff --git a/eip-wire-tap/pom.xml b/eip-wire-tap/pom.xml index 688f4ad6d..752d43077 100644 --- a/eip-wire-tap/pom.xml +++ b/eip-wire-tap/pom.xml @@ -26,7 +26,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT diff --git a/event-aggregator/pom.xml b/event-aggregator/pom.xml index c28fded6f..a39738bf8 100644 --- a/event-aggregator/pom.xml +++ b/event-aggregator/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT event-aggregator diff --git a/event-asynchronous/pom.xml b/event-asynchronous/pom.xml index 3c07f47bc..9398d25ce 100644 --- a/event-asynchronous/pom.xml +++ b/event-asynchronous/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT event-asynchronous diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml index 4eb2a6946..87aae0070 100644 --- a/event-driven-architecture/pom.xml +++ b/event-driven-architecture/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT event-driven-architecture diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java index 5ed2b2ad8..c41b0ed5a 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/App.java @@ -33,7 +33,7 @@ import com.iluwatar.eda.model.User; /** * An event-driven architecture (EDA) is a framework that orchestrates behavior around the * production, detection and consumption of events as well as the responses they evoke. An event is - * any identifiable occurrence that has significance for system hardware or software.

The + * any identifiable occurrence that has significance for system hardware or software.

The * example below uses an {@link EventDispatcher} to link/register {@link Event} objects to their * respective handlers once an {@link Event} is dispatched, it's respective handler is invoked and * the {@link Event} is handled accordingly. diff --git a/event-queue/pom.xml b/event-queue/pom.xml index 1ef8e28af..a0c1913a7 100644 --- a/event-queue/pom.xml +++ b/event-queue/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT event-queue diff --git a/event-sourcing/pom.xml b/event-sourcing/pom.xml index a17d02379..785d72c68 100644 --- a/event-sourcing/pom.xml +++ b/event-sourcing/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT event-sourcing diff --git a/execute-around/pom.xml b/execute-around/pom.xml index 2e43c3e4b..358f4eae4 100644 --- a/execute-around/pom.xml +++ b/execute-around/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT execute-around diff --git a/extension-objects/pom.xml b/extension-objects/pom.xml index bd68a2758..74f233775 100644 --- a/extension-objects/pom.xml +++ b/extension-objects/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/facade/README.md b/facade/README.md index 7caa89d94..505ceee39 100644 --- a/facade/README.md +++ b/facade/README.md @@ -32,7 +32,7 @@ Wikipedia says Taking our goldmine example from above. Here we have the dwarven mine worker hierarchy -``` +```java public abstract class DwarvenMineWorker { private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenMineWorker.class); @@ -140,7 +140,7 @@ public class DwarvenCartOperator extends DwarvenMineWorker { To operate all these goldmine workers we have the facade -``` +```java public class DwarvenGoldmineFacade { private final List workers; @@ -175,7 +175,7 @@ public class DwarvenGoldmineFacade { Now to use the facade -``` +```java DwarvenGoldmineFacade facade = new DwarvenGoldmineFacade(); facade.startNewDay(); // Dwarf gold digger wakes up. diff --git a/facade/pom.xml b/facade/pom.xml index deb56a382..d0c459428 100644 --- a/facade/pom.xml +++ b/facade/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT facade diff --git a/factory-kit/pom.xml b/factory-kit/pom.xml index 71973928f..1c8f4248e 100644 --- a/factory-kit/pom.xml +++ b/factory-kit/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT factory-kit diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/App.java b/factory-kit/src/main/java/com/iluwatar/factorykit/App.java index 03a4ece83..766370111 100644 --- a/factory-kit/src/main/java/com/iluwatar/factorykit/App.java +++ b/factory-kit/src/main/java/com/iluwatar/factorykit/App.java @@ -45,7 +45,7 @@ public class App { /** * Program entry point. * - * @param args @param args command line args + * @param args command line args */ public static void main(String[] args) { WeaponFactory factory = WeaponFactory.factory(builder -> { diff --git a/factory-method/README.md b/factory-method/README.md index ab3739ac3..087221fb9 100644 --- a/factory-method/README.md +++ b/factory-method/README.md @@ -35,7 +35,7 @@ Wikipedia says Taking our blacksmith example above. First of all we have a blacksmith interface and some implementations for it -``` +```java public interface Blacksmith { Weapon manufactureWeapon(WeaponType weaponType); } @@ -55,7 +55,7 @@ public class OrcBlacksmith implements Blacksmith { Now as the customers come the correct type of blacksmith is summoned and requested weapons are manufactured -``` +```java Blacksmith blacksmith = new ElfBlacksmith(); blacksmith.manufactureWeapon(WeaponType.SPEAR); blacksmith.manufactureWeapon(WeaponType.AXE); diff --git a/factory-method/pom.xml b/factory-method/pom.xml index 4cad86fdd..124b1a73c 100644 --- a/factory-method/pom.xml +++ b/factory-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT factory-method diff --git a/feature-toggle/pom.xml b/feature-toggle/pom.xml index 665847e5e..3c6c7af94 100644 --- a/feature-toggle/pom.xml +++ b/feature-toggle/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java index 97c184fec..351936b2c 100644 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java @@ -67,7 +67,7 @@ public class App { * @see UserGroup * @see Service * @see PropertiesFeatureToggleVersion - * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion; + * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion */ public static void main(String[] args) { diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java index 9650b9f67..284ccf2ab 100644 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java @@ -47,7 +47,7 @@ public interface Service { /** * Returns if the welcome message to be displayed will be the enhanced version. * - * @return Boolean {@value true} if enhanced. + * @return Boolean {@code true} if enhanced. */ boolean isEnhanced(); diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java index a474423db..1ded334ec 100644 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java @@ -91,7 +91,7 @@ public class PropertiesFeatureToggleVersion implements Service { * see the value of the boolean that was set in the constructor * {@link PropertiesFeatureToggleVersion#PropertiesFeatureToggleVersion(Properties)} * - * @return Boolean value {@value true} if enhanced. + * @return Boolean value {@code true} if enhanced. */ @Override public boolean isEnhanced() { diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java index 42b7412c0..887c9f663 100644 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java @@ -65,7 +65,7 @@ public class TieredFeatureToggleVersion implements Service { * is driven by the user group. This method is a little redundant. However can be used to show that there is an * enhanced version available. * - * @return Boolean value {@value true} if enhanced. + * @return Boolean value {@code true} if enhanced. */ @Override public boolean isEnhanced() { diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml index 234504396..a91832786 100644 --- a/fluentinterface/pom.xml +++ b/fluentinterface/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/flux/pom.xml b/flux/pom.xml index 6b9b968c8..59d105b39 100644 --- a/flux/pom.xml +++ b/flux/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT flux diff --git a/flyweight/README.md b/flyweight/README.md index d65995755..e008fc346 100644 --- a/flyweight/README.md +++ b/flyweight/README.md @@ -32,7 +32,7 @@ Wikipedia says Translating our alchemist shop example from above. First of all we have different potion types -``` +```java public interface Potion { void drink(); } @@ -64,7 +64,7 @@ public class InvisibilityPotion implements Potion { Then the actual Flyweight object which is the factory for creating potions -``` +```java public class PotionFactory { private final Map potions; @@ -100,7 +100,7 @@ public class PotionFactory { And it can be used as below -``` +```java PotionFactory factory = new PotionFactory(); factory.createPotion(PotionType.INVISIBILITY).drink(); // You become invisible. (Potion=6566818) factory.createPotion(PotionType.HEALING).drink(); // You feel healed. (Potion=648129364) diff --git a/flyweight/pom.xml b/flyweight/pom.xml index 58bbd95a8..adf675b57 100644 --- a/flyweight/pom.xml +++ b/flyweight/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT flyweight diff --git a/front-controller/pom.xml b/front-controller/pom.xml index 966e5becc..b76852e02 100644 --- a/front-controller/pom.xml +++ b/front-controller/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT front-controller diff --git a/guarded-suspension/pom.xml b/guarded-suspension/pom.xml index 5ac0a6e32..6b8b977eb 100644 --- a/guarded-suspension/pom.xml +++ b/guarded-suspension/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT jar guarded-suspension diff --git a/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java b/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java index bf6142dd9..e75fc6c49 100644 --- a/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java +++ b/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java @@ -32,7 +32,7 @@ import java.util.Queue; * Guarded Queue is an implementation for Guarded Suspension Pattern * Guarded suspension pattern is used to handle a situation when you want to execute a method * on an object which is not in a proper state. - * @see http://java-design-patterns.com/patterns/guarded-suspension/ + * @see http://java-design-patterns.com/patterns/guarded-suspension/ */ public class GuardedQueue { private static final Logger LOGGER = LoggerFactory.getLogger(GuardedQueue.class); diff --git a/half-sync-half-async/pom.xml b/half-sync-half-async/pom.xml index 3ed2da411..e6df33018 100644 --- a/half-sync-half-async/pom.xml +++ b/half-sync-half-async/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT half-sync-half-async diff --git a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java index bf35416ca..90cb5ecbf 100644 --- a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java +++ b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java @@ -33,31 +33,31 @@ import java.util.concurrent.LinkedBlockingQueue; * {@link AsyncTask} and {@link AsynchronousService}. * *

- * PROBLEM
+ * PROBLEM
* A concurrent system have a mixture of short duration, mid duration and long duration tasks. Mid * or long duration tasks should be performed asynchronously to meet quality of service * requirements. * *

- * INTENT
+ * INTENT
* The intent of this pattern is to separate the the synchronous and asynchronous processing in the * concurrent application by introducing two intercommunicating layers - one for sync and one for * async. This simplifies the programming without unduly affecting the performance. * *

- * APPLICABILITY
+ * APPLICABILITY
* UNIX network subsystems - In operating systems network operations are carried out - * asynchronously with help of hardware level interrupts.
+ * asynchronously with help of hardware level interrupts.
* CORBA - At the asynchronous layer one thread is associated with each socket that is connected * to the client. Thread blocks waiting for CORBA requests from the client. On receiving request it * is inserted in the queuing layer which is then picked up by synchronous layer which processes the - * request and sends response back to the client.
+ * request and sends response back to the client.
* Android AsyncTask framework - Framework provides a way to execute long running blocking * calls, such as downloading a file, in background threads so that the UI thread remains free to - * respond to user inputs.
+ * respond to user inputs.
* *

- * IMPLEMENTATION
+ * IMPLEMENTATION
* The main method creates an asynchronous service which does not block the main thread while the * task is being performed. The main thread continues its work which is similar to Async Method * Invocation pattern. The difference between them is that there is a queuing layer between diff --git a/hexagonal/pom.xml b/hexagonal/pom.xml index 6907ca10c..e6084ac70 100644 --- a/hexagonal/pom.xml +++ b/hexagonal/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT hexagonal diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/App.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/App.java index 651498607..6e226a1e1 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/App.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/App.java @@ -50,13 +50,13 @@ import com.iluwatar.hexagonal.sampledata.SampleData; * from the services it uses.

* * The primary ports for the application are console interfaces - * {@link ConsoleAdministration} through which the lottery round is - * initiated and run and {@link ConsoleLottery} that allows players to + * {@link com.iluwatar.hexagonal.administration.ConsoleAdministration} through which the lottery round is + * initiated and run and {@link com.iluwatar.hexagonal.service.ConsoleLottery} that allows players to * submit lottery tickets for the draw.

* - * The secondary ports that application core uses are {@link WireTransfers} - * which is a banking service, {@link LotteryEventLog} that delivers - * eventlog as lottery events occur and {@link LotteryTicketRepository} + * The secondary ports that application core uses are {@link com.iluwatar.hexagonal.banking.WireTransfers} + * which is a banking service, {@link com.iluwatar.hexagonal.eventlog.LotteryEventLog} that delivers + * eventlog as lottery events occur and {@link com.iluwatar.hexagonal.database.LotteryTicketRepository} * that is the storage for the lottery tickets. * */ diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml index dc4d6a923..658dba671 100644 --- a/intercepting-filter/pom.xml +++ b/intercepting-filter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT intercepting-filter diff --git a/interpreter/pom.xml b/interpreter/pom.xml index 99e399159..1e61dfb48 100644 --- a/interpreter/pom.xml +++ b/interpreter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT interpreter diff --git a/iterator/pom.xml b/iterator/pom.xml index 2afca644c..6581b8224 100644 --- a/iterator/pom.xml +++ b/iterator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT iterator diff --git a/layers/pom.xml b/layers/pom.xml index 772c53a30..9ca1c58e7 100644 --- a/layers/pom.xml +++ b/layers/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT com.iluwatar.layers layers diff --git a/lazy-loading/pom.xml b/lazy-loading/pom.xml index 8d799d07c..6664ddcc7 100644 --- a/lazy-loading/pom.xml +++ b/lazy-loading/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT lazy-loading diff --git a/marker/pom.xml b/marker/pom.xml index 708072d8c..138ab0c30 100644 --- a/marker/pom.xml +++ b/marker/pom.xml @@ -24,7 +24,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/mediator/pom.xml b/mediator/pom.xml index c9369b1a9..77c29adda 100644 --- a/mediator/pom.xml +++ b/mediator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT mediator diff --git a/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java b/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java index 61f926c31..03db825e9 100644 --- a/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java +++ b/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java @@ -110,7 +110,7 @@ public class PartyMemberTest { } /** - * Verify if {@link PartyMember#toString()} generate the expected output + * Verify if {@link PartyMemberBase#toString()} generate the expected output */ @ParameterizedTest @MethodSource("dataProvider") diff --git a/memento/pom.xml b/memento/pom.xml index 2ad5321ba..ad4a55236 100644 --- a/memento/pom.xml +++ b/memento/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT memento diff --git a/model-view-controller/pom.xml b/model-view-controller/pom.xml index f873107fa..89f7bd825 100644 --- a/model-view-controller/pom.xml +++ b/model-view-controller/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT model-view-controller diff --git a/model-view-presenter/pom.xml b/model-view-presenter/pom.xml index 60a379996..d4db8a633 100644 --- a/model-view-presenter/pom.xml +++ b/model-view-presenter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT model-view-presenter model-view-presenter diff --git a/module/pom.xml b/module/pom.xml index dde967bc6..1b1ecb6af 100644 --- a/module/pom.xml +++ b/module/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT module diff --git a/monad/pom.xml b/monad/pom.xml index 316c4ff9b..947259602 100644 --- a/monad/pom.xml +++ b/monad/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT monad diff --git a/monad/src/main/java/com/iluwatar/monad/App.java b/monad/src/main/java/com/iluwatar/monad/App.java index 9b1ed5096..29dd1d31f 100644 --- a/monad/src/main/java/com/iluwatar/monad/App.java +++ b/monad/src/main/java/com/iluwatar/monad/App.java @@ -50,7 +50,7 @@ public class App { /** * Program entry point. * - * @param args @param args command line args + * @param args command line args */ public static void main(String[] args) { User user = new User("user", 24, Sex.FEMALE, "foobar.com"); diff --git a/monostate/pom.xml b/monostate/pom.xml index 5aa68e75b..94935cbf0 100644 --- a/monostate/pom.xml +++ b/monostate/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT monostate diff --git a/multiton/pom.xml b/multiton/pom.xml index 4ee128a1d..cc5103e74 100644 --- a/multiton/pom.xml +++ b/multiton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT multiton diff --git a/multiton/src/main/java/com/iluwatar/multiton/App.java b/multiton/src/main/java/com/iluwatar/multiton/App.java index 28b89e6ab..18821af66 100644 --- a/multiton/src/main/java/com/iluwatar/multiton/App.java +++ b/multiton/src/main/java/com/iluwatar/multiton/App.java @@ -31,9 +31,12 @@ import org.slf4j.LoggerFactory; * pattern defines many globally accessible objects. The client asks for the correct instance from * the Multiton by passing an enumeration as parameter. *

- * In this example {@link Nazgul} is the Multiton and we can ask single {@link Nazgul} from it using - * {@link NazgulName}. The {@link Nazgul}s are statically initialized and stored in concurrent hash - * map. + * There is more than one way to implement the multiton design pattern. In the first example + * {@link Nazgul} is the Multiton and we can ask single {@link Nazgul} from it using {@link NazgulName}. + * The {@link Nazgul}s are statically initialized and stored in concurrent hash map. + *

+ * In the enum implementation {@link NazgulEnum} is the multiton. It is static and mutable because + * of the way java supports enums. * */ public class App { @@ -46,6 +49,7 @@ public class App { * @param args command line args */ public static void main(String[] args) { + // eagerly initialized multiton LOGGER.info("KHAMUL={}", Nazgul.getInstance(NazgulName.KHAMUL)); LOGGER.info("MURAZOR={}", Nazgul.getInstance(NazgulName.MURAZOR)); LOGGER.info("DWAR={}", Nazgul.getInstance(NazgulName.DWAR)); @@ -55,5 +59,16 @@ public class App { LOGGER.info("ADUNAPHEL={}", Nazgul.getInstance(NazgulName.ADUNAPHEL)); LOGGER.info("REN={}", Nazgul.getInstance(NazgulName.REN)); LOGGER.info("UVATHA={}", Nazgul.getInstance(NazgulName.UVATHA)); + + // enum multiton + LOGGER.info("KHAMUL={}", NazgulEnum.KHAMUL); + LOGGER.info("MURAZOR={}", NazgulEnum.MURAZOR); + LOGGER.info("DWAR={}", NazgulEnum.DWAR); + LOGGER.info("JI_INDUR={}", NazgulEnum.JI_INDUR); + LOGGER.info("AKHORAHIL={}", NazgulEnum.AKHORAHIL); + LOGGER.info("HOARMURATH={}", NazgulEnum.HOARMURATH); + LOGGER.info("ADUNAPHEL={}", NazgulEnum.ADUNAPHEL); + LOGGER.info("REN={}", NazgulEnum.REN); + LOGGER.info("UVATHA={}", NazgulEnum.UVATHA); } } diff --git a/multiton/src/main/java/com/iluwatar/multiton/NazgulEnum.java b/multiton/src/main/java/com/iluwatar/multiton/NazgulEnum.java new file mode 100644 index 000000000..375176c4f --- /dev/null +++ b/multiton/src/main/java/com/iluwatar/multiton/NazgulEnum.java @@ -0,0 +1,33 @@ +/** + * The MIT License + * Copyright (c) 2014-2016 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.multiton; + +/** + * enum based multiton implementation + * + */ +public enum NazgulEnum { + + KHAMUL, MURAZOR, DWAR, JI_INDUR, AKHORAHIL, HOARMURATH, ADUNAPHEL, REN, UVATHA; + +} diff --git a/multiton/src/test/java/com/iluwatar/multiton/NazgulEnumTest.java b/multiton/src/test/java/com/iluwatar/multiton/NazgulEnumTest.java new file mode 100644 index 000000000..b718b9c68 --- /dev/null +++ b/multiton/src/test/java/com/iluwatar/multiton/NazgulEnumTest.java @@ -0,0 +1,50 @@ +/** + * The MIT License + * Copyright (c) 2014-2016 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.multiton; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +/** + * @author anthony + * + */ +class NazgulEnumTest { + + /** + * Check that multiple calls to any one of the instances in the multiton returns + * only that one particular instance, and do that for all instances in multiton + */ + @Test + public void testTheSameObjectIsReturnedWithMultipleCalls() { + for (int i = 0; i < NazgulEnum.values().length; i++) { + NazgulEnum instance1 = NazgulEnum.values()[i]; + NazgulEnum instance2 = NazgulEnum.values()[i]; + NazgulEnum instance3 = NazgulEnum.values()[i]; + assertSame(instance1, instance2); + assertSame(instance1, instance3); + assertSame(instance2, instance3); + } + } +} diff --git a/mute-idiom/pom.xml b/mute-idiom/pom.xml index 905909384..ec2935e3c 100644 --- a/mute-idiom/pom.xml +++ b/mute-idiom/pom.xml @@ -21,7 +21,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT mute-idiom diff --git a/mutex/pom.xml b/mutex/pom.xml index 5c65d6305..84a8f58b6 100644 --- a/mutex/pom.xml +++ b/mutex/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT mutex diff --git a/naked-objects/dom/pom.xml b/naked-objects/dom/pom.xml index 3efcecdca..9be69d7b2 100644 --- a/naked-objects/dom/pom.xml +++ b/naked-objects/dom/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT naked-objects-dom diff --git a/naked-objects/fixture/pom.xml b/naked-objects/fixture/pom.xml index bf3cc4de8..ff15d19d8 100644 --- a/naked-objects/fixture/pom.xml +++ b/naked-objects/fixture/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT naked-objects-fixture diff --git a/naked-objects/integtests/pom.xml b/naked-objects/integtests/pom.xml index 8d2cf3b55..20cb9868d 100644 --- a/naked-objects/integtests/pom.xml +++ b/naked-objects/integtests/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT naked-objects-integtests diff --git a/naked-objects/pom.xml b/naked-objects/pom.xml index 222a9d321..1672bd579 100644 --- a/naked-objects/pom.xml +++ b/naked-objects/pom.xml @@ -15,7 +15,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT naked-objects @@ -350,17 +350,17 @@ ${project.groupId} naked-objects-dom - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT ${project.groupId} naked-objects-fixture - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT ${project.groupId} naked-objects-webapp - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT diff --git a/naked-objects/webapp/pom.xml b/naked-objects/webapp/pom.xml index 0f9d33bc4..6bc7184b9 100644 --- a/naked-objects/webapp/pom.xml +++ b/naked-objects/webapp/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT naked-objects-webapp diff --git a/naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java b/naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java index 89d316d20..459e4b7de 100644 --- a/naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java +++ b/naked-objects/webapp/src/main/java/domainapp/webapp/SimpleApplication.java @@ -51,14 +51,14 @@ import de.agilecoders.wicket.themes.markup.html.bootswatch.BootswatchThemeProvid * See: * *

- * <filter>
- *   <filter-name>wicket</filter-name>
- *    <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
- *    <init-param>
- *      <param-name>applicationClassName</param-name>
- *      <param-value>webapp.SimpleApplication</param-value>
- *    </init-param>
- * </filter>
+ * <filter>
+ *   <filter-name>wicket</filter-name>
+ *    <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
+ *    <init-param>
+ *      <param-name>applicationClassName</param-name>
+ *      <param-value>webapp.SimpleApplication</param-value>
+ *    </init-param>
+ * </filter>
  * 
* */ @@ -69,7 +69,7 @@ public class SimpleApplication extends IsisWicketApplication { /** * uncomment for a (slightly hacky) way of allowing logins using query args, eg: * - * ?user=sven&pass=pass + * {@code ?user=sven&pass=pass} * *

* for demos only, obvious. diff --git a/null-object/pom.xml b/null-object/pom.xml index 92831afb0..b471b86d4 100644 --- a/null-object/pom.xml +++ b/null-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT null-object diff --git a/object-mother/pom.xml b/object-mother/pom.xml index e58d36f7d..d59799e0c 100644 --- a/object-mother/pom.xml +++ b/object-mother/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT object-mother diff --git a/object-pool/pom.xml b/object-pool/pom.xml index 5e59bbfd9..75fa63163 100644 --- a/object-pool/pom.xml +++ b/object-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT object-pool diff --git a/observer/pom.xml b/observer/pom.xml index 20e4aa659..3843c60c8 100644 --- a/observer/pom.xml +++ b/observer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT observer diff --git a/observer/src/main/java/com/iluwatar/observer/generic/Observable.java b/observer/src/main/java/com/iluwatar/observer/generic/Observable.java index ff204437d..6c14eabec 100644 --- a/observer/src/main/java/com/iluwatar/observer/generic/Observable.java +++ b/observer/src/main/java/com/iluwatar/observer/generic/Observable.java @@ -26,7 +26,7 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; /** - * Generic observer inspired by Java Generics and Collection by Naftalin & Wadler + * Generic observer inspired by Java Generics and Collection by {@literal Naftalin & Wadler} * * @param Subject * @param Observer diff --git a/page-object/pom.xml b/page-object/pom.xml index a54998d70..f14050849 100644 --- a/page-object/pom.xml +++ b/page-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT page-object diff --git a/partial-response/pom.xml b/partial-response/pom.xml index db0a922ee..afe04012b 100644 --- a/partial-response/pom.xml +++ b/partial-response/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/poison-pill/pom.xml b/poison-pill/pom.xml index 5b9d48126..2ae5c7b31 100644 --- a/poison-pill/pom.xml +++ b/poison-pill/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT poison-pill diff --git a/pom.xml b/pom.xml index 59572ce44..e1d025c13 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 4.0.0 com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT pom 2014 @@ -48,6 +48,11 @@ 3.3.0 1.7.21 1.1.7 + 1.1.0 + 1.11.289 + 1.0.0 + 2.0.1 + 2.8.5 abstract-factory @@ -112,11 +117,11 @@ business-delegate half-sync-half-async layers - message-channel + eip-message-channel fluentinterface reactor caching - publish-subscribe + eip-publish-subscribe delegation event-driven-architecture api-gateway @@ -153,8 +158,9 @@ eip-splitter eip-aggregator retry - dirty-flag - trampoline + dirty-flag + trampoline + serverless @@ -470,4 +476,4 @@ - \ No newline at end of file + diff --git a/private-class-data/pom.xml b/private-class-data/pom.xml index ddf9cef28..570b01935 100644 --- a/private-class-data/pom.xml +++ b/private-class-data/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT private-class-data diff --git a/producer-consumer/pom.xml b/producer-consumer/pom.xml index ea9734518..9ef208f99 100644 --- a/producer-consumer/pom.xml +++ b/producer-consumer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT producer-consumer diff --git a/promise/pom.xml b/promise/pom.xml index 9b600d5fb..4ae5566b2 100644 --- a/promise/pom.xml +++ b/promise/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT promise diff --git a/property/pom.xml b/property/pom.xml index b3bc915e9..d07153e32 100644 --- a/property/pom.xml +++ b/property/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT property diff --git a/prototype/README.md b/prototype/README.md index 4bfeebe19..483a5e469 100644 --- a/prototype/README.md +++ b/prototype/README.md @@ -33,7 +33,7 @@ In short, it allows you to create a copy of an existing object and modify it to In Java, it can be easily done by implementing `Cloneable` and overriding `clone` from `Object` -``` +```java class Sheep implements Cloneable { private String name; public Sheep(String name) { this.name = name; } @@ -48,7 +48,7 @@ class Sheep implements Cloneable { Then it can be cloned like below -``` +```java Sheep original = new Sheep("Jolly"); System.out.println(original.getName()); // Jolly diff --git a/prototype/pom.xml b/prototype/pom.xml index 54c9ac987..9674eabb0 100644 --- a/prototype/pom.xml +++ b/prototype/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT prototype diff --git a/proxy/README.md b/proxy/README.md index 80593c75e..e0628344a 100644 --- a/proxy/README.md +++ b/proxy/README.md @@ -34,7 +34,7 @@ Wikipedia says Taking our wizard tower example from above. Firstly we have the wizard tower interface and the ivory tower class -``` +```java public interface WizardTower { void enter(Wizard wizard); @@ -53,7 +53,7 @@ public class IvoryTower implements WizardTower { Then a simple wizard class -``` +```java public class Wizard { private final String name; @@ -71,7 +71,7 @@ public class Wizard { Then we have the proxy to add access control to wizard tower -``` +```java public class WizardTowerProxy implements WizardTower { private static final Logger LOGGER = LoggerFactory.getLogger(WizardTowerProxy.class); @@ -100,7 +100,7 @@ public class WizardTowerProxy implements WizardTower { And here is tower entering scenario -``` +```java WizardTowerProxy proxy = new WizardTowerProxy(new IvoryTower()); proxy.enter(new Wizard("Red wizard")); // Red wizard enters the tower. proxy.enter(new Wizard("White wizard")); // White wizard enters the tower. diff --git a/proxy/pom.xml b/proxy/pom.xml index 31e87c04b..600285dd1 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT proxy diff --git a/queue-load-leveling/pom.xml b/queue-load-leveling/pom.xml index 681409e96..11d178dca 100644 --- a/queue-load-leveling/pom.xml +++ b/queue-load-leveling/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT queue-load-leveling diff --git a/reactor/pom.xml b/reactor/pom.xml index e8a145f7b..f05edc244 100644 --- a/reactor/pom.xml +++ b/reactor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT reactor diff --git a/reactor/src/main/java/com/iluwatar/reactor/app/App.java b/reactor/src/main/java/com/iluwatar/reactor/app/App.java index 5208dea02..03b4a747f 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/app/App.java +++ b/reactor/src/main/java/com/iluwatar/reactor/app/App.java @@ -39,13 +39,13 @@ import com.iluwatar.reactor.framework.ThreadPoolDispatcher; * Service where it listens on multiple TCP or UDP sockets for incoming log requests. * *

- * INTENT
+ * INTENT
* The Reactor design pattern handles service requests that are delivered concurrently to an * application by one or more clients. The application can register specific handlers for processing * which are called by reactor on specific events. * *

- * PROBLEM
+ * PROBLEM
* Server applications in a distributed system must handle multiple clients that send them service * requests. Following forces need to be resolved: *

    @@ -56,31 +56,37 @@ import com.iluwatar.reactor.framework.ThreadPoolDispatcher; *
* *

- * PARTICIPANTS
+ * PARTICIPANTS
*

    - *
  • Synchronous Event De-multiplexer
  • {@link NioReactor} plays the role of synchronous event - * de-multiplexer. It waits for events on multiple channels registered to it in an event loop. - * + *
  • Synchronous Event De-multiplexer *

    - *

  • Initiation Dispatcher
  • {@link NioReactor} plays this role as the application specific - * {@link ChannelHandler}s are registered to the reactor. - * + * {@link NioReactor} plays the role of synchronous event de-multiplexer. + * It waits for events on multiple channels registered to it in an event loop. + *

    + * + *
  • Initiation Dispatcher *

    - *

  • Handle
  • {@link AbstractNioChannel} acts as a handle that is registered to the reactor. + * {@link NioReactor} plays this role as the application specific {@link ChannelHandler}s + * are registered to the reactor. + *

    + * + *
  • Handle + *

    + * {@link AbstractNioChannel} acts as a handle that is registered to the reactor. * When any events occur on a handle, reactor calls the appropriate handler. - * + *

    + *
  • + *
  • Event Handler *

    - *

  • Event Handler
  • {@link ChannelHandler} acts as an event handler, which is bound to a + * {@link ChannelHandler} acts as an event handler, which is bound to a * channel and is called back when any event occurs on any of its associated handles. Application * logic resides in event handlers. + *

    + * *
- * - *

* The application utilizes single thread to listen for requests on all ports. It does not create a * separate thread for each client, which provides better scalability under load (number of clients * increase). - * - *

* The example uses Java NIO framework to implement the Reactor. * */ diff --git a/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java b/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java index 446628769..1ffa9325b 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java +++ b/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java @@ -108,7 +108,7 @@ public class AppClient { * Creates a new TCP logging client. * * @param clientName the name of the client to be sent in logging requests. - * @param port the port on which client will send logging requests. + * @param serverPort the port on which client will send logging requests. */ public TcpLoggingClient(String clientName, int serverPort) { this.clientName = clientName; diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java b/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java index aa7d703ce..5cfab9a95 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java +++ b/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java @@ -141,7 +141,7 @@ public abstract class AbstractNioChannel { * when this method returns. It will be written when the channel is flushed. * *

- * This method is used by the {@link ChannelHandler} to send reply back to the client.
+ * This method is used by the {@link ChannelHandler} to send reply back to the client.
* Example: * *

diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/Dispatcher.java b/reactor/src/main/java/com/iluwatar/reactor/framework/Dispatcher.java
index a3fe187a3..1cb50a197 100644
--- a/reactor/src/main/java/com/iluwatar/reactor/framework/Dispatcher.java
+++ b/reactor/src/main/java/com/iluwatar/reactor/framework/Dispatcher.java
@@ -28,7 +28,7 @@ import java.nio.channels.SelectionKey;
  * Represents the event dispatching strategy. When {@link NioReactor} senses any event on the
  * registered {@link AbstractNioChannel}s then it de-multiplexes the event type, read or write or
  * connect, and then calls the {@link Dispatcher} to dispatch the read events. This decouples the
- * I/O processing from application specific processing. 
+ * I/O processing from application specific processing.
* Dispatcher should call the {@link ChannelHandler} associated with the channel on which event * occurred. * diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java b/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java index a315389a3..7fcffa0ac 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java +++ b/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java @@ -84,11 +84,8 @@ public class NioReactor { /** * Starts the reactor event loop in a new thread. - * - * @throws IOException - * if any I/O error occurs. */ - public void start() throws IOException { + public void start() { reactorMain.execute(() -> { try { LOGGER.info("Reactor started, waiting for events..."); diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java b/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java index 4721d292a..1d91c4eb7 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java +++ b/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java @@ -98,9 +98,9 @@ public class NioServerSocketChannel extends AbstractNioChannel { */ @Override public void bind() throws IOException { - ((ServerSocketChannel) getJavaChannel()).socket().bind( + getJavaChannel().socket().bind( new InetSocketAddress(InetAddress.getLocalHost(), port)); - ((ServerSocketChannel) getJavaChannel()).configureBlocking(false); + getJavaChannel().configureBlocking(false); LOGGER.info("Bound TCP socket at port: {}", port); } diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/SameThreadDispatcher.java b/reactor/src/main/java/com/iluwatar/reactor/framework/SameThreadDispatcher.java index 3db4f1e9a..41dd0f684 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/SameThreadDispatcher.java +++ b/reactor/src/main/java/com/iluwatar/reactor/framework/SameThreadDispatcher.java @@ -37,7 +37,7 @@ import java.nio.channels.SelectionKey; public class SameThreadDispatcher implements Dispatcher { /** - * Dispatches the read event in the context of caller thread.
+ * Dispatches the read event in the context of caller thread.
* Note this is a blocking call. It returns only after the associated handler has handled the read * event. */ diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/ThreadPoolDispatcher.java b/reactor/src/main/java/com/iluwatar/reactor/framework/ThreadPoolDispatcher.java index a43a974c9..82fca0206 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/ThreadPoolDispatcher.java +++ b/reactor/src/main/java/com/iluwatar/reactor/framework/ThreadPoolDispatcher.java @@ -47,7 +47,7 @@ public class ThreadPoolDispatcher implements Dispatcher { /** * Submits the work of dispatching the read event to worker pool, where it gets picked up by - * worker threads.
+ * worker threads.
* Note that this is a non-blocking call and returns immediately. It is not guaranteed that the * event has been handled by associated handler. */ diff --git a/reader-writer-lock/pom.xml b/reader-writer-lock/pom.xml index b0dc137e4..4114c88d3 100644 --- a/reader-writer-lock/pom.xml +++ b/reader-writer-lock/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT reader-writer-lock diff --git a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java index b377b2273..f0f5a0090 100644 --- a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java +++ b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/ReaderWriterLock.java @@ -50,9 +50,9 @@ public class ReaderWriterLock implements ReadWriteLock { /** * Global mutex is used to indicate that whether reader or writer gets the lock in the moment. *

- * 1. When it contains the reference of {@link readerLock}, it means that the lock is acquired by the reader, another + * 1. When it contains the reference of {@link #readerLock}, it means that the lock is acquired by the reader, another * reader can also do the read operation concurrently.
- * 2. When it contains the reference of reference of {@link writerLock}, it means that the lock is acquired by the + * 2. When it contains the reference of reference of {@link #writerLock}, it means that the lock is acquired by the * writer exclusively, no more reader or writer can get the lock. *

* This is the most important field in this class to control the access for reader/writer. diff --git a/repository/pom.xml b/repository/pom.xml index cf08ba4a5..02761f524 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT repository diff --git a/resource-acquisition-is-initialization/pom.xml b/resource-acquisition-is-initialization/pom.xml index 3d68966c5..c69db9500 100644 --- a/resource-acquisition-is-initialization/pom.xml +++ b/resource-acquisition-is-initialization/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT resource-acquisition-is-initialization diff --git a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java b/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java index 75d5dff27..9817fea44 100644 --- a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java +++ b/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java @@ -33,13 +33,13 @@ import org.slf4j.LoggerFactory; * In RAII resource is tied to object lifetime: resource allocation is done during object creation * while resource deallocation is done during object destruction. *

- * In Java RAII is achieved with try-with-resources statement and interfaces {@link Closeable} and + * In Java RAII is achieved with try-with-resources statement and interfaces {@link java.io.Closeable} and * {@link AutoCloseable}. The try-with-resources statement ensures that each resource is closed at * the end of the statement. Any object that implements {@link java.lang.AutoCloseable}, which * includes all objects which implement {@link java.io.Closeable}, can be used as a resource. * * In this example, {@link SlidingDoor} implements {@link AutoCloseable} and {@link TreasureChest} - * implements {@link Closeable}. Running the example, we can observe that both resources are + * implements {@link java.io.Closeable}. Running the example, we can observe that both resources are * automatically closed. *

* http://docs.oracle.com/javase/7/docs/technotes/guides/language/try-with-resources.html diff --git a/retry/pom.xml b/retry/pom.xml index 9fb98d42a..9999e0c3b 100644 --- a/retry/pom.xml +++ b/retry/pom.xml @@ -26,7 +26,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT retry jar diff --git a/semaphore/pom.xml b/semaphore/pom.xml index 6337951a4..fc4a6e362 100644 --- a/semaphore/pom.xml +++ b/semaphore/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT semaphore diff --git a/servant/pom.xml b/servant/pom.xml index 220e197f1..d72fde86f 100644 --- a/servant/pom.xml +++ b/servant/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT servant diff --git a/serverless/README.md b/serverless/README.md new file mode 100644 index 000000000..b0a29fe66 --- /dev/null +++ b/serverless/README.md @@ -0,0 +1,199 @@ +--- +layout: pattern +title: serverless +folder: serverless +permalink: /patterns/serverless/ +categories: Architectural +tags: + - Java + - Difficulty-Intermediate +--- + +## Serverless + +Serverless eliminates the need to plan for infrastructure and let's you focus on your +application. + +Following are optimization katas you should be aware of while building a serverless +applications + +* The Lean function + * Concise logic - Use functions to transform, not transport (utilize some of the + integration available from the provider to transport), and make sure you read only + what you need + * Efficient/single purpose code - avoid conditional/routing logic and break down + into individual functions, avoid "fat"/monolithic functions and control the + dependencies in the function deployment package to reduce the load time for your + function + * ephemeral environment - Utilize container start for expensive initializations +* Eventful Invocations + * Succinct payloads - Scrutinize the event as much as possible, and watch for + payload constraints (async - 128K) + * resilient routing - Understand retry policies and leverage dead letter queues + (SQS or SNS for replays) and remember retries count as invocations + * concurrent execution - lambda thinks of it's scale in terms of concurrency and + its not request based/duration based. Lambda will spin up the number of instances + based on the request. +* Coordinated calls + * Decoupled via APIs - best practice to setup your application is to have API's as + contracts that ensures separation of concerns + * scale-matched downstream - make sure when Lambda is calling downstream + components, you are matching scale configuration to it (by specifying max + concurrency based on downstream services) + * secured - Always ask a question, do I need a VPC? +* Serviceful operations + * Automated - use automated tools to manage and maintain the stack + * monitored applications - use monitoring services to get holistic view of your + serverless applications + +## Intent + +Whether to reduce your infrastructure costs, shrink the time you spend on ops tasks, +simplify your deployment processes, reach infinite scalability, serverless cuts time +to market in half. + +## Explanation + +Serverless computing is a cloud computing execution model in which the cloud provider +dynamically manages the allocation of machine resources. Pricing is based on the +actual amount of resources consumed by an application, rather than on pre-purchased +units of capacity. + +## Serverless framework + +[Serverless](https://serverless.com/) is a toolkit for deploying and operating serverless architectures. + +## (Function as a Service or "FaaS") + +The term ‘Serverless’ is confusing since with such applications there are both server +hardware and server processes running somewhere, but the difference to normal +approaches is that the organization building and supporting a ‘Serverless’ application + is not looking after the hardware or the processes - they are outsourcing this to a vendor. + +Some of the Serverless Cloud Providers are + +![https://serverless.com/framework/docs/providers/aws/](./etc/aws-black.png "aws") +![https://serverless.com/framework/docs/providers/azure/](./etc/azure-black.png "azure") +![https://serverless.com/framework/docs/providers/openwhisk/](./etc/openwhisk-black.png "openwhisk") +![https://serverless.com/framework/docs/providers/google/](./etc/gcf-black.png "google") +![https://serverless.com/framework/docs/providers/kubeless/](./etc/kubeless-logos-black.png "kubeless") +![https://serverless.com/framework/docs/providers/spotinst/](./etc/spotinst-logos-black-small.png "spotinst") +![https://serverless.com/framework/docs/providers/webtasks/](./etc/webtask-small-grayscale.png "webtask") +... + +Anything that triggers an Lambda Function to execute is regarded by the Framework as +an Event. Most of the Serverless Cloud Providers support following Events +- Http +- PubSub Events +- scheduled + +AWS supports processing event generated from AWS Services (S3/Cloudwatch/etc) and +using aws as a compute engine is our first choice. + +## (Backend as a Service or "BaaS") +This example creates a backend for ‘persons’ collection which uses DynamoDB NoSQL +database service also provided by Amazon. + +## AWS lambda function implementation + +[AWS Lambda SDK](https://aws.amazon.com/sdk-for-java/) provides pre-defined interface +`com.amazonaws.services.lambda.runtime +.RequestHandler` to implement our lambda function. + +```java +public class LambdaInfoApiHandler implements RequestHandler, ApiGatewayResponse> { + + private static final Logger LOG = Logger.getLogger(LambdaInfoApiHandler.class); + private static final Integer SUCCESS_STATUS_CODE = 200; + + + @Override + public ApiGatewayResponse handleRequest(Map input, Context context) { + + } +} +``` +handleRequest method is where the function code is implemented. Context provides +useful information about Lambda execution environment. AWS Lambda function needs a +deployment package. This package is either a .zip or .jar file that contains all the +dependencies of the function. + +`serverless.yml` contains configuration to manage deployments for your functions. + +## Run example in local + +# Pre-requisites +* Node.js v6.5.0 or later. +* Serverless CLI v1.9.0 or later. You can run npm install -g serverless to install it. +* An AWS account. If you don't already have one, you can sign up for a free trial that includes 1 million free Lambda requests per month. +* [Set-up](https://serverless.com/framework/docs/providers/aws/guide/credentials/) your Provider Credentials. Watch the video on setting up credentials + +# build and deploy + +* `cd serverless` +* `mvn clean package` +* `serverless deploy --stage=dev --verbose` + +Based on the configuration in `serverless.yml` serverless framework creates following +resources +* CloudFormation stack for S3 (ServerlessDeploymentBucket) +* IAM Role (IamRoleLambdaExecution) +* CloudWatch (log groups) +* API Gateway (ApiGatewayRestApi) +* Lambda function +* DynamoDB collection + +The command will print out Stack Outputs which looks something like this + +```yaml +endpoints: + GET - https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/info + POST - https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/api/person + GET - https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/api/person/{id} + +``` + +```yaml +CurrentTimeLambdaFunctionQualifiedArn: arn:aws:lambda:us-east-1:xxxxxxxxxxx:function:lambda-info-http-endpoint-dev-currentTime:4 +ServiceEndpoint: https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev +ServerlessDeploymentBucketName: lambda-info-http-endpoin-serverlessdeploymentbuck-2u8uz2i7cap2 +``` +access the endpoint to invoke the function. + +Use the following cURL commands to test the endpoints + +```cURL +curl -X GET \ + https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/info \ + -H 'cache-control: no-cache' +``` + +```cURL +curl -X POST \ + https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/api/person \ + -H 'cache-control: no-cache' \ + -H 'content-type: application/json' \ + -d '{ + "firstName": "Thor", + "lastName": "Odinson", + "address": { + "addressLineOne": "1 Odin ln", + "addressLineTwo": "100", + "city": "Asgard", + "state": "country of the Gods", + "zipCode": "00001" + } +}' +``` + +```cURL +curl -X GET \ + https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/api/person/{id} \ + -H 'cache-control: no-cache' +``` + +## Credits + +* [serverless docs](https://serverless.com/framework/docs/) +* [Serverless Architectures](https://martinfowler.com/articles/serverless.html) +* [Serverless Black Belt](https://youtu.be/oQFORsso2go) \ No newline at end of file diff --git a/serverless/etc/aws-black.png b/serverless/etc/aws-black.png new file mode 100644 index 000000000..7b5ba3178 Binary files /dev/null and b/serverless/etc/aws-black.png differ diff --git a/serverless/etc/azure-black.png b/serverless/etc/azure-black.png new file mode 100644 index 000000000..95ceb7e82 Binary files /dev/null and b/serverless/etc/azure-black.png differ diff --git a/serverless/etc/gcf-black.png b/serverless/etc/gcf-black.png new file mode 100644 index 000000000..b4e22982c Binary files /dev/null and b/serverless/etc/gcf-black.png differ diff --git a/serverless/etc/kubeless-logos-black.png b/serverless/etc/kubeless-logos-black.png new file mode 100644 index 000000000..dd6523c51 Binary files /dev/null and b/serverless/etc/kubeless-logos-black.png differ diff --git a/serverless/etc/openwhisk-black.png b/serverless/etc/openwhisk-black.png new file mode 100644 index 000000000..e70139088 Binary files /dev/null and b/serverless/etc/openwhisk-black.png differ diff --git a/serverless/etc/spotinst-logos-black-small.png b/serverless/etc/spotinst-logos-black-small.png new file mode 100644 index 000000000..b748f80c7 Binary files /dev/null and b/serverless/etc/spotinst-logos-black-small.png differ diff --git a/serverless/etc/webtask-small-grayscale.png b/serverless/etc/webtask-small-grayscale.png new file mode 100644 index 000000000..8e2180935 Binary files /dev/null and b/serverless/etc/webtask-small-grayscale.png differ diff --git a/serverless/pom.xml b/serverless/pom.xml new file mode 100644 index 000000000..cfaf6f23c --- /dev/null +++ b/serverless/pom.xml @@ -0,0 +1,133 @@ + + + + 4.0.0 + serverless + + com.iluwatar + java-design-patterns + 1.20.0-SNAPSHOT + + + + + com.amazonaws + aws-lambda-java-core + ${aws-lambda-core.version} + + + com.amazonaws + aws-java-sdk-dynamodb + ${aws-java-sdk-dynamodb.version} + + + com.amazonaws + aws-java-sdk-s3 + + + com.amazonaws + aws-java-sdk-kms + + + + + com.amazonaws + aws-lambda-java-events + ${aws-lambda-java-events.version} + + + com.amazonaws + aws-lambda-java-log4j + ${aws-lambda-log4j.version} + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.mockito + mockito-core + test + + + junit + junit + test + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + false + + + + package + + shade + + + ${project.artifactId} + + + + + + + + \ No newline at end of file diff --git a/serverless/serverless.yml b/serverless/serverless.yml new file mode 100644 index 000000000..c463395df --- /dev/null +++ b/serverless/serverless.yml @@ -0,0 +1,102 @@ +# +# The MIT License +# Copyright (c) 2014 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. +# + +service: serverless-services + +frameworkVersion: ">=1.2.0 <2.0.0" + +provider: + name: aws + runtime: java8 + usagePlan: + quota: + limit: 500 + offset: 2 + period: MONTH + throttle: + burstLimit: 20 + rateLimit: 10 + +package: + artifact: target/serverless.jar + +functions: + lambdaInfoApi: + handler: com.iluwatar.serverless.faas.api.LambdaInfoApiHandler + events: + - http: + path: info + method: get + + savePerson: + handler: com.iluwatar.serverless.baas.api.SavePersonApiHandler + events: + - http: + path: api/person + method: post + cors: true + integration: lambda-proxy + + getPerson: + handler: com.iluwatar.serverless.baas.api.FindPersonApiHandler + events: + - http: + path: api/person/{id} + method: get + cors: true + integration: lambda-proxy + +resources: + Resources: + DynamoDbTable: + Type: AWS::DynamoDB::Table + Properties: + TableName: persons + AttributeDefinitions: + - AttributeName: id + AttributeType: S + KeySchema: + - AttributeName: id + KeyType: HASH + ProvisionedThroughput: + ReadCapacityUnits: 1 + WriteCapacityUnits: 1 + DynamoDBIamPolicy: + Type: AWS::IAM::Policy + DependsOn: DynamoDbTable + Properties: + PolicyName: lambda-dynamodb + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + - dynamodb:UpdateItem + - dynamodb:DeleteItem + - dynamodb:Query + - dynamodb:Scan + Resource: arn:aws:dynamodb:*:*:table/persons + Roles: + - Ref: IamRoleLambdaExecution \ No newline at end of file diff --git a/serverless/src/main/java/com/iluwatar/serverless/baas/api/AbstractDynamoDbHandler.java b/serverless/src/main/java/com/iluwatar/serverless/baas/api/AbstractDynamoDbHandler.java new file mode 100644 index 000000000..ac27a9a4a --- /dev/null +++ b/serverless/src/main/java/com/iluwatar/serverless/baas/api/AbstractDynamoDbHandler.java @@ -0,0 +1,101 @@ +/** + * The MIT License + * Copyright (c) 2014 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.serverless.baas.api; + +import com.amazonaws.regions.Regions; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/** + * abstract dynamodb handler + * @param - serializable collection + */ +public abstract class AbstractDynamoDbHandler { + private DynamoDBMapper dynamoDbMapper; + + private ObjectMapper objectMapper; + + public AbstractDynamoDbHandler() { + this.initAmazonDynamoDb(); + this.objectMapper = new ObjectMapper(); + } + + private void initAmazonDynamoDb() { + AmazonDynamoDB amazonDynamoDb = AmazonDynamoDBClientBuilder + .standard() + .withRegion(Regions.US_EAST_1) + .build(); + + this.dynamoDbMapper = new DynamoDBMapper(amazonDynamoDb); + } + + protected DynamoDBMapper getDynamoDbMapper() { + return this.dynamoDbMapper; + } + + protected ObjectMapper getObjectMapper() { + return objectMapper; + } + + public void setDynamoDbMapper(DynamoDBMapper dynamoDbMapper) { + this.dynamoDbMapper = dynamoDbMapper; + } + + protected Map headers() { + Map headers = new HashMap<>(); + headers.put("Content-Type", "application/json"); + + return headers; + } + + /** + * API Gateway response + * + * @param statusCode - status code + * @param body - Object body + * @return - api gateway proxy response + */ + protected APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent(Integer statusCode, T body) { + APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent = + new APIGatewayProxyResponseEvent().withHeaders(headers()); + try { + apiGatewayProxyResponseEvent + .withStatusCode(statusCode) + .withBody(getObjectMapper() + .writeValueAsString(body)); + + } catch (JsonProcessingException jsonProcessingException) { + throw new RuntimeException(jsonProcessingException); + } + + return apiGatewayProxyResponseEvent; + } +} diff --git a/serverless/src/main/java/com/iluwatar/serverless/baas/api/FindPersonApiHandler.java b/serverless/src/main/java/com/iluwatar/serverless/baas/api/FindPersonApiHandler.java new file mode 100644 index 000000000..2eb1613f8 --- /dev/null +++ b/serverless/src/main/java/com/iluwatar/serverless/baas/api/FindPersonApiHandler.java @@ -0,0 +1,51 @@ +/** + * The MIT License + * Copyright (c) 2014 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.serverless.baas.api; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import com.iluwatar.serverless.baas.model.Person; +import org.apache.log4j.Logger; + +/** + * find person from persons collection + * Created by dheeraj.mummar on 3/5/18. + */ +public class FindPersonApiHandler extends AbstractDynamoDbHandler + implements RequestHandler { + + private static final Logger LOG = Logger.getLogger(FindPersonApiHandler.class); + private static final Integer SUCCESS_STATUS_CODE = 200; + + @Override + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent, + Context context) { + LOG.info(apiGatewayProxyRequestEvent.getPathParameters()); + Person person = this.getDynamoDbMapper().load(Person.class, apiGatewayProxyRequestEvent + .getPathParameters().get("id")); + + return apiGatewayProxyResponseEvent(SUCCESS_STATUS_CODE, person); + } +} diff --git a/serverless/src/main/java/com/iluwatar/serverless/baas/api/SavePersonApiHandler.java b/serverless/src/main/java/com/iluwatar/serverless/baas/api/SavePersonApiHandler.java new file mode 100644 index 000000000..f00d28b96 --- /dev/null +++ b/serverless/src/main/java/com/iluwatar/serverless/baas/api/SavePersonApiHandler.java @@ -0,0 +1,61 @@ +/** + * The MIT License + * Copyright (c) 2014 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.serverless.baas.api; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import com.iluwatar.serverless.baas.model.Person; +import org.apache.log4j.Logger; + +import java.io.IOException; + +/** + * save person into persons collection + * Created by dheeraj.mummar on 3/4/18. + */ +public class SavePersonApiHandler extends AbstractDynamoDbHandler + implements RequestHandler { + + private static final Logger LOG = Logger.getLogger(SavePersonApiHandler.class); + private static final Integer CREATED_STATUS_CODE = 201; + private static final Integer BAD_REQUEST_STATUS_CODE = 400; + + @Override + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent + apiGatewayProxyRequestEvent, Context context) { + APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent; + Person person; + try { + person = getObjectMapper().readValue(apiGatewayProxyRequestEvent.getBody(), Person.class); + getDynamoDbMapper().save(person); + apiGatewayProxyResponseEvent = apiGatewayProxyResponseEvent(CREATED_STATUS_CODE, person); + } catch (IOException ioException) { + LOG.error("unable to parse body", ioException); + apiGatewayProxyResponseEvent = apiGatewayProxyResponseEvent(BAD_REQUEST_STATUS_CODE, null); + } + + return apiGatewayProxyResponseEvent; + } +} diff --git a/serverless/src/main/java/com/iluwatar/serverless/baas/model/Address.java b/serverless/src/main/java/com/iluwatar/serverless/baas/model/Address.java new file mode 100644 index 000000000..7331cea2b --- /dev/null +++ b/serverless/src/main/java/com/iluwatar/serverless/baas/model/Address.java @@ -0,0 +1,141 @@ +/** + * The MIT License + * Copyright (c) 2014 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.serverless.baas.model; + +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBDocument; + +import java.io.Serializable; + +/** + * Address class + * Created by dheeraj.mummarareddy on 3/4/18. + */ +@DynamoDBDocument +public class Address implements Serializable { + + private static final long serialVersionUID = 6760844284799736970L; + + private String addressLineOne; + private String addressLineTwo; + private String city; + private String state; + private String zipCode; + + @DynamoDBAttribute(attributeName = "addressLineOne") + public String getAddressLineOne() { + return addressLineOne; + } + + public void setAddressLineOne(String addressLineOne) { + this.addressLineOne = addressLineOne; + } + + @DynamoDBAttribute(attributeName = "addressLineTwo") + public String getAddressLineTwo() { + return addressLineTwo; + } + + public void setAddressLineTwo(String addressLineTwo) { + this.addressLineTwo = addressLineTwo; + } + + @DynamoDBAttribute(attributeName = "city") + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + @DynamoDBAttribute(attributeName = "state") + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + @DynamoDBAttribute(attributeName = "zipCode") + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + Address address = (Address) o; + + if (addressLineOne != null ? !addressLineOne.equals(address.addressLineOne) : + address.addressLineOne != null) { + return false; + } + + if (addressLineTwo != null ? !addressLineTwo.equals(address.addressLineTwo) : + address.addressLineTwo != null) { + return false; + } + + if (city != null ? !city.equals(address.city) : address.city != null) { + return false; + } + if (state != null ? !state.equals(address.state) : address.state != null) { + return false; + } + return zipCode != null ? zipCode.equals(address.zipCode) : address.zipCode == null; + } + + @Override + public int hashCode() { + int result = addressLineOne != null ? addressLineOne.hashCode() : 0; + result = 31 * result + (addressLineTwo != null ? addressLineTwo.hashCode() : 0); + result = 31 * result + (city != null ? city.hashCode() : 0); + result = 31 * result + (state != null ? state.hashCode() : 0); + result = 31 * result + (zipCode != null ? zipCode.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Address{" + + "addressLineOne='" + addressLineOne + '\'' + + ", addressLineTwo='" + addressLineTwo + '\'' + + ", city='" + city + '\'' + + ", state='" + state + '\'' + + ", zipCode='" + zipCode + '\'' + + '}'; + } +} diff --git a/serverless/src/main/java/com/iluwatar/serverless/baas/model/Person.java b/serverless/src/main/java/com/iluwatar/serverless/baas/model/Person.java new file mode 100644 index 000000000..75604999e --- /dev/null +++ b/serverless/src/main/java/com/iluwatar/serverless/baas/model/Person.java @@ -0,0 +1,124 @@ +/** + * The MIT License + * Copyright (c) 2014 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.serverless.baas.model; + +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedKey; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.io.Serializable; + +/** + * Person class + * Created by dheeraj.mummarareddy on 3/4/18. + */ +@DynamoDBTable(tableName = "persons") +public class Person implements Serializable { + + private static final long serialVersionUID = -3413087924608627075L; + + private String id; + private String firstName; + private String lastName; + private Address address; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + @DynamoDBHashKey(attributeName = "id") + @DynamoDBAutoGeneratedKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @DynamoDBAttribute(attributeName = "firstName") + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + @DynamoDBAttribute(attributeName = "lastName") + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @DynamoDBAttribute(attributeName = "address") + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Person person = (Person) o; + + if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) { + return false; + } + + if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) { + return false; + } + + return address != null ? address.equals(person.address) : person.address == null; + } + + @Override + public int hashCode() { + int result = firstName != null ? firstName.hashCode() : 0; + result = 31 * result + (lastName != null ? lastName.hashCode() : 0); + result = 31 * result + (address != null ? address.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Person{" + + "id='" + id + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", address=" + address + + '}'; + } +} diff --git a/serverless/src/main/java/com/iluwatar/serverless/faas/ApiGatewayResponse.java b/serverless/src/main/java/com/iluwatar/serverless/faas/ApiGatewayResponse.java new file mode 100644 index 000000000..98e2de64f --- /dev/null +++ b/serverless/src/main/java/com/iluwatar/serverless/faas/ApiGatewayResponse.java @@ -0,0 +1,166 @@ +/** + * The MIT License + * Copyright (c) 2014 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.serverless.faas; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.Serializable; +import java.util.Map; + +/** + * Api gateway response + * + * @param serializable object + */ +public class ApiGatewayResponse implements Serializable { + + private static final long serialVersionUID = 1181159426782844892L; + + private final Integer statusCode; + private final String body; + private final Map headers; + private final Boolean isBase64Encoded; + + /** + * api gateway response + * + * @param statusCode - http status code + * @param body - response body + * @param headers - response headers + * @param isBase64Encoded - base64Encoded flag + */ + public ApiGatewayResponse(Integer statusCode, String body, Map headers, + Boolean isBase64Encoded) { + this.statusCode = statusCode; + this.body = body; + this.headers = headers; + this.isBase64Encoded = isBase64Encoded; + } + + /** + * http status code + * + * @return statusCode - http status code + */ + public Integer getStatusCode() { + return statusCode; + } + + /** + * response body + * + * @return string body + */ + public String getBody() { + return body; + } + + /** + * response headers + * + * @return response headers + */ + public Map getHeaders() { + return headers; + } + + /** + * base64Encoded flag, API Gateway expects the property to be called "isBase64Encoded" + * + * @return base64Encoded flag + */ + public Boolean isBase64Encoded() { + return isBase64Encoded; + } + + /** + * ApiGatewayResponse Builder class + * @param Serializable object + */ + public static class ApiGatewayResponseBuilder { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private Integer statusCode; + private T body; + private Map headers; + private Boolean isBase64Encoded; + + /** + * http status code + * @param statusCode - http status code + * @return ApiGatewayResponseBuilder + */ + public ApiGatewayResponseBuilder statusCode(Integer statusCode) { + this.statusCode = statusCode; + return this; + } + + /** + * Serializable body + * @param body - Serializable object + * @return ApiGatewayResponseBuilder + */ + public ApiGatewayResponseBuilder body(T body) { + this.body = body; + return this; + } + + /** + * response headers + * @param headers - response headers + * @return ApiGatewayResponseBuilder + */ + public ApiGatewayResponseBuilder headers(Map headers) { + this.headers = headers; + return this; + } + + /** + * base64Encoded glag + * @param isBase64Encoded - base64Encoded flag + * @return ApiGatewayResponseBuilder + */ + public ApiGatewayResponseBuilder base64Encoded(Boolean isBase64Encoded) { + this.isBase64Encoded = isBase64Encoded; + return this; + } + + /** + * build ApiGatewayResponse + * + * @return ApiGatewayResponse + */ + public ApiGatewayResponse build() { + String strBody = null; + if (this.body != null) { + try { + strBody = OBJECT_MAPPER.writeValueAsString(body); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + return new ApiGatewayResponse(this.statusCode, strBody, this.headers, this.isBase64Encoded); + } + } +} diff --git a/serverless/src/main/java/com/iluwatar/serverless/faas/LambdaInfo.java b/serverless/src/main/java/com/iluwatar/serverless/faas/LambdaInfo.java new file mode 100644 index 000000000..03932a9f0 --- /dev/null +++ b/serverless/src/main/java/com/iluwatar/serverless/faas/LambdaInfo.java @@ -0,0 +1,140 @@ +/** + * The MIT License + * Copyright (c) 2014 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.serverless.faas; + +import java.io.Serializable; + +/** + * Lambda context information + */ +public class LambdaInfo implements Serializable { + + private static final long serialVersionUID = 3936130599040848923L; + + private String awsRequestId; + private String logGroupName; + private String logStreamName; + private String functionName; + private String functionVersion; + private Integer memoryLimitInMb; + + public String getAwsRequestId() { + return awsRequestId; + } + + public void setAwsRequestId(String awsRequestId) { + this.awsRequestId = awsRequestId; + } + + public String getLogGroupName() { + return logGroupName; + } + + public void setLogGroupName(String logGroupName) { + this.logGroupName = logGroupName; + } + + public String getLogStreamName() { + return logStreamName; + } + + public void setLogStreamName(String logStreamName) { + this.logStreamName = logStreamName; + } + + public String getFunctionName() { + return functionName; + } + + public void setFunctionName(String functionName) { + this.functionName = functionName; + } + + public String getFunctionVersion() { + return functionVersion; + } + + public void setFunctionVersion(String functionVersion) { + this.functionVersion = functionVersion; + } + + public Integer getMemoryLimitInMb() { + return memoryLimitInMb; + } + + public void setMemoryLimitInMb(Integer memoryLimitInMb) { + this.memoryLimitInMb = memoryLimitInMb; + } + + @Override + public String toString() { + return "LambdaInfo{" + + "awsRequestId='" + awsRequestId + '\'' + + ", logGroupName='" + logGroupName + '\'' + + ", logStreamName='" + logStreamName + '\'' + + ", functionName='" + functionName + '\'' + + ", functionVersion='" + functionVersion + '\'' + + ", memoryLimitInMb=" + memoryLimitInMb + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + LambdaInfo that = (LambdaInfo) o; + + if (awsRequestId != null ? !awsRequestId.equals(that.awsRequestId) : that.awsRequestId != null) { + return false; + } + if (logGroupName != null ? !logGroupName.equals(that.logGroupName) : that.logGroupName != null) { + return false; + } + if (logStreamName != null ? !logStreamName.equals(that.logStreamName) : that.logStreamName != null) { + return false; + } + if (functionName != null ? !functionName.equals(that.functionName) : that.functionName != null) { + return false; + } + if (functionVersion != null ? !functionVersion.equals(that.functionVersion) : that.functionVersion != null) { + return false; + } + return memoryLimitInMb != null ? memoryLimitInMb.equals(that.memoryLimitInMb) : that.memoryLimitInMb == null; + } + + @Override + public int hashCode() { + int result = awsRequestId != null ? awsRequestId.hashCode() : 0; + result = 31 * result + (logGroupName != null ? logGroupName.hashCode() : 0); + result = 31 * result + (logStreamName != null ? logStreamName.hashCode() : 0); + result = 31 * result + (functionName != null ? functionName.hashCode() : 0); + result = 31 * result + (functionVersion != null ? functionVersion.hashCode() : 0); + result = 31 * result + (memoryLimitInMb != null ? memoryLimitInMb.hashCode() : 0); + return result; + } +} diff --git a/serverless/src/main/java/com/iluwatar/serverless/faas/api/LambdaInfoApiHandler.java b/serverless/src/main/java/com/iluwatar/serverless/faas/api/LambdaInfoApiHandler.java new file mode 100644 index 000000000..67e1835f9 --- /dev/null +++ b/serverless/src/main/java/com/iluwatar/serverless/faas/api/LambdaInfoApiHandler.java @@ -0,0 +1,83 @@ +/** + * The MIT License + * Copyright (c) 2014 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.serverless.faas.api; + +import com.iluwatar.serverless.faas.ApiGatewayResponse; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.iluwatar.serverless.faas.LambdaInfo; +import org.apache.log4j.BasicConfigurator; +import org.apache.log4j.Logger; + +import java.util.HashMap; +import java.util.Map; + +/** + * LambdaInfoApiHandler - simple api to get lambda context + * Created by dheeraj.mummar on 2/5/18. + */ +public class LambdaInfoApiHandler implements RequestHandler, ApiGatewayResponse> { + + private static final Logger LOG = Logger.getLogger(LambdaInfoApiHandler.class); + private static final Integer SUCCESS_STATUS_CODE = 200; + + + @Override + public ApiGatewayResponse handleRequest(Map input, Context context) { + BasicConfigurator.configure(); + LOG.info("received: " + input); + + return new ApiGatewayResponse + .ApiGatewayResponseBuilder() + .headers(headers()) + .statusCode(SUCCESS_STATUS_CODE) + .body(lambdaInfo(context)) + .build(); + + } + + /** + * lambdaInfo + * @param context - Lambda context + * @return LambdaInfo + */ + private LambdaInfo lambdaInfo(Context context) { + LambdaInfo lambdaInfo = new LambdaInfo(); + lambdaInfo.setAwsRequestId(context.getAwsRequestId()); + lambdaInfo.setFunctionName(context.getFunctionName()); + lambdaInfo.setFunctionVersion(context.getFunctionVersion()); + lambdaInfo.setLogGroupName(context.getLogGroupName()); + lambdaInfo.setLogStreamName(context.getLogStreamName()); + lambdaInfo.setMemoryLimitInMb(context.getMemoryLimitInMB()); + + return lambdaInfo; + } + + private Map headers() { + Map headers = new HashMap<>(); + headers.put("Content-Type", "application/json"); + + return headers; + } +} diff --git a/serverless/src/main/resources/log4j.properties b/serverless/src/main/resources/log4j.properties new file mode 100644 index 000000000..15a25e61b --- /dev/null +++ b/serverless/src/main/resources/log4j.properties @@ -0,0 +1,29 @@ +# +# The MIT License +# Copyright (c) 2014 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. +# + +log = . +log4j.rootLogger = DEBUG, LAMBDA + +log4j.appender.LAMBDA=com.amazonaws.services.lambda.runtime.log4j.LambdaAppender +log4j.appender.LAMBDA.layout=org.apache.log4j.PatternLayout +log4j.appender.LAMBDA.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss} <%X{AWSRequestId}> %-5p %c:%L - %m%n diff --git a/serverless/src/test/java/com/iluwatar/serverless/baas/api/FindPersonApiHandlerTest.java b/serverless/src/test/java/com/iluwatar/serverless/baas/api/FindPersonApiHandlerTest.java new file mode 100644 index 000000000..561281ab3 --- /dev/null +++ b/serverless/src/test/java/com/iluwatar/serverless/baas/api/FindPersonApiHandlerTest.java @@ -0,0 +1,72 @@ +/** + * The MIT License + * Copyright (c) 2014 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.serverless.baas.api; + +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.iluwatar.serverless.baas.api.FindPersonApiHandler; +import com.iluwatar.serverless.baas.api.SavePersonApiHandler; +import com.iluwatar.serverless.baas.model.Person; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.util.Collections; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * Unit tests for FindPersonApiHandler + * Created by dheeraj.mummar on 3/5/18. + */ +@RunWith(MockitoJUnitRunner.class) +public class FindPersonApiHandlerTest { + + private FindPersonApiHandler findPersonApiHandler; + + @Mock + private DynamoDBMapper dynamoDbMapper; + + @Before + public void setUp() { + this.findPersonApiHandler = new FindPersonApiHandler(); + this.findPersonApiHandler.setDynamoDbMapper(dynamoDbMapper); + } + + @Test + public void handleRequest() { + findPersonApiHandler.handleRequest(apiGatewayProxyRequestEvent(), mock(Context.class)); + verify(dynamoDbMapper, times(1)).load(Person.class, "37e7a1fe-3544-473d-b764-18128f02d72d"); + } + + private APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent() { + return new APIGatewayProxyRequestEvent() + .withPathParamters(Collections + .singletonMap("id", "37e7a1fe-3544-473d-b764-18128f02d72d")); + } +} diff --git a/serverless/src/test/java/com/iluwatar/serverless/baas/api/SavePersonApiHandlerTest.java b/serverless/src/test/java/com/iluwatar/serverless/baas/api/SavePersonApiHandlerTest.java new file mode 100644 index 000000000..83008bdff --- /dev/null +++ b/serverless/src/test/java/com/iluwatar/serverless/baas/api/SavePersonApiHandlerTest.java @@ -0,0 +1,101 @@ +/** + * The MIT License + * Copyright (c) 2014 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.serverless.baas.api; + +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.iluwatar.serverless.baas.api.SavePersonApiHandler; +import com.iluwatar.serverless.baas.model.Address; +import com.iluwatar.serverless.baas.model.Person; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import static org.mockito.Mockito.*; + +/** + * Unit tests for SavePersonApiHandler + * Created by dheeraj.mummar on 3/4/18. + */ +@RunWith(MockitoJUnitRunner.class) +public class SavePersonApiHandlerTest { + + private SavePersonApiHandler savePersonApiHandler; + + @Mock + private DynamoDBMapper dynamoDbMapper; + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Before + public void setUp() { + this.savePersonApiHandler = new SavePersonApiHandler(); + this.savePersonApiHandler.setDynamoDbMapper(dynamoDbMapper); + } + + @Test + public void handleRequestSavePersonSuccessful() throws JsonProcessingException { + Person person = newPerson(); + APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent = + this.savePersonApiHandler + .handleRequest(apiGatewayProxyRequestEvent(objectMapper.writeValueAsString(person)), mock(Context.class)); + verify(dynamoDbMapper, times(1)).save(person); + Assert.assertNotNull(apiGatewayProxyResponseEvent); + Assert.assertEquals(new Integer(201), apiGatewayProxyResponseEvent.getStatusCode()); + } + + @Test + public void handleRequestSavePersonException() { + APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent = + this.savePersonApiHandler + .handleRequest(apiGatewayProxyRequestEvent("invalid sample request"), mock(Context.class)); + Assert.assertNotNull(apiGatewayProxyResponseEvent); + Assert.assertEquals(new Integer(400), apiGatewayProxyResponseEvent.getStatusCode()); + } + + private APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent(String body) { + APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent = new APIGatewayProxyRequestEvent(); + return apiGatewayProxyRequestEvent.withBody(body); + } + + private Person newPerson() { + Person person = new Person(); + person.setFirstName("Thor"); + person.setLastName("Odinson"); + Address address = new Address(); + address.setAddressLineOne("1 Odin ln"); + address.setCity("Asgard"); + address.setState("country of the Gods"); + address.setZipCode("00001"); + person.setAddress(address); + + return person; + } +} diff --git a/serverless/src/test/java/com/iluwatar/serverless/faas/api/LambdaInfoApiHandlerTest.java b/serverless/src/test/java/com/iluwatar/serverless/faas/api/LambdaInfoApiHandlerTest.java new file mode 100644 index 000000000..876489ed2 --- /dev/null +++ b/serverless/src/test/java/com/iluwatar/serverless/faas/api/LambdaInfoApiHandlerTest.java @@ -0,0 +1,49 @@ +/** + * The MIT License + * Copyright (c) 2014 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.serverless.faas.api; + +import com.amazonaws.services.lambda.runtime.Context; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Unit tests for LambdaInfoApiHandler + */ +@RunWith(MockitoJUnitRunner.class) +public class LambdaInfoApiHandlerTest { + + @Test + public void handleRequestWithMockContext() { + LambdaInfoApiHandler lambdaInfoApiHandler = new LambdaInfoApiHandler(); + Context context = mock(Context.class); + when(context.getAwsRequestId()).thenReturn("mock aws request id"); + + assertThat(lambdaInfoApiHandler.handleRequest(null, context), notNullValue()); + } +} \ No newline at end of file diff --git a/service-layer/pom.xml b/service-layer/pom.xml index 1a654e048..940629be5 100644 --- a/service-layer/pom.xml +++ b/service-layer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT service-layer diff --git a/service-locator/pom.xml b/service-locator/pom.xml index a8fc5ceb1..f78436585 100644 --- a/service-locator/pom.xml +++ b/service-locator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT service-locator diff --git a/service-locator/src/main/java/com/iluwatar/servicelocator/Service.java b/service-locator/src/main/java/com/iluwatar/servicelocator/Service.java index 006d98ba8..e46e3976a 100644 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/Service.java +++ b/service-locator/src/main/java/com/iluwatar/servicelocator/Service.java @@ -24,7 +24,7 @@ package com.iluwatar.servicelocator; /** * This is going to be the parent service interface which we will use to create our services. All - * services will have a

  • service name
  • unique id
  • execution work flow
  • + * services will have a
    • service name
    • unique id
    • execution work flow
    * * @author saifasif * diff --git a/singleton/README.md b/singleton/README.md index 90a845846..52aca8e16 100644 --- a/singleton/README.md +++ b/singleton/README.md @@ -34,7 +34,7 @@ Joshua Bloch, Effective Java 2nd Edition p.18 > A single-element enum type is the best way to implement a singleton -``` +```java public enum EnumIvoryTower { INSTANCE; } @@ -42,7 +42,7 @@ public enum EnumIvoryTower { Then in order to use -``` +```java EnumIvoryTower enumIvoryTower1 = EnumIvoryTower.INSTANCE; EnumIvoryTower enumIvoryTower2 = EnumIvoryTower.INSTANCE; assertEquals(enumIvoryTower1, enumIvoryTower2); // true diff --git a/singleton/pom.xml b/singleton/pom.xml index f83f5e50c..2f8a55265 100644 --- a/singleton/pom.xml +++ b/singleton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT singleton diff --git a/singleton/src/main/java/com/iluwatar/singleton/App.java b/singleton/src/main/java/com/iluwatar/singleton/App.java index 377c56cca..aa40ee300 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/App.java +++ b/singleton/src/main/java/com/iluwatar/singleton/App.java @@ -28,18 +28,18 @@ import org.slf4j.LoggerFactory; /** * Singleton pattern ensures that the class can have only one existing instance per Java classloader * instance and provides global access to it. - *

    + *

    * 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 out synchronous and only become async with time, so you it may * not be clear why you are seeing certain changes in behaviour. - *

    + *

    * 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 giving up control of the instantiation moment, then this implementation will suit * you fine. - *

    + *

    * 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 @@ -47,16 +47,16 @@ import org.slf4j.LoggerFactory; * Overflow: * http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing * -a-singleton-with-javas-enum - *

    + *

    * {@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. - *

    + *

    * 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. - *

    + *

    * 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. diff --git a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java index 5cfcc1bdc..a7557fda3 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java +++ b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java @@ -24,9 +24,9 @@ package com.iluwatar.singleton; /** * Double check locking - *

    + *

    * http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html - *

    + *

    * Broken under Java 1.4. * * @author mortezaadi@gmail.com diff --git a/specification/pom.xml b/specification/pom.xml index cfd28ae93..ddd9ebde4 100644 --- a/specification/pom.xml +++ b/specification/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT specification diff --git a/state/pom.xml b/state/pom.xml index 478e888bf..fee910c55 100644 --- a/state/pom.xml +++ b/state/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT state diff --git a/step-builder/pom.xml b/step-builder/pom.xml index 00a8006de..0a5d1a560 100644 --- a/step-builder/pom.xml +++ b/step-builder/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT step-builder diff --git a/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java b/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java index b5354e04a..309833e37 100644 --- a/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java +++ b/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java @@ -29,16 +29,16 @@ import org.slf4j.LoggerFactory; * Step Builder Pattern * *

    - * Intent
    + * Intent
    * An extension of the Builder pattern that fully guides the user through the creation of the object - * with no chances of confusion.
    + * with no chances of confusion.
    * The user experience will be much more improved by the fact that he will only see the next step * methods available, NO build method until is the right time to build the object. * *

    - * Implementation - *

      + * Implementation
      * The concept is simple: + *
        * *
      • Write creational steps inner classes or interfaces where each method knows what can be * displayed next.
      • @@ -49,13 +49,13 @@ import org.slf4j.LoggerFactory; *
      * *

      - * Applicability
      + * Applicability
      * Use the Step Builder pattern when the algorithm for creating a complex object should be * independent of the parts that make up the object and how they're assembled the construction * process must allow different representations for the object that's constructed when in the * process of constructing the order is important. *

      - * http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html + * @see http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html */ public class App { diff --git a/strategy/pom.xml b/strategy/pom.xml index 8bae9c46a..1ca63da0b 100644 --- a/strategy/pom.xml +++ b/strategy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT strategy diff --git a/template-method/pom.xml b/template-method/pom.xml index edfc2e2c6..4d0703858 100644 --- a/template-method/pom.xml +++ b/template-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT template-method diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml index 61701e40b..517651596 100644 --- a/thread-pool/pom.xml +++ b/thread-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT thread-pool diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java b/thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java index 578800108..9f67a82c9 100644 --- a/thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java +++ b/thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java @@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory; /** * - * Worker implements {@link Runnable} and thus can be executed by {@link ExecutorService} + * Worker implements {@link Runnable} and thus can be executed by {@link java.util.concurrent.ExecutorService} * */ public class Worker implements Runnable { diff --git a/throttling/pom.xml b/throttling/pom.xml index 4ac14493d..1d7677c37 100644 --- a/throttling/pom.xml +++ b/throttling/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/throttling/src/main/java/com/iluwatar/throttling/App.java b/throttling/src/main/java/com/iluwatar/throttling/App.java index 2dce68ab9..d6c619359 100644 --- a/throttling/src/main/java/com/iluwatar/throttling/App.java +++ b/throttling/src/main/java/com/iluwatar/throttling/App.java @@ -72,7 +72,6 @@ public class App { /** * Make calls to the B2BService dummy API - * @param service an instance of B2BService */ private static void makeServiceCalls(Tenant tenant) { Throttler timer = new ThrottleTimerImpl(10); diff --git a/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java b/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java index 0c15bac6e..18dee50a0 100644 --- a/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java +++ b/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java @@ -24,6 +24,7 @@ package com.iluwatar.throttling; import com.iluwatar.throttling.timer.ThrottleTimerImpl; import com.iluwatar.throttling.timer.Throttler; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -32,7 +33,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; * B2BServiceTest class to test the B2BService */ public class B2BServiceTest { - + + @Disabled @Test public void dummyCustomerApiTest() { Tenant tenant = new Tenant("testTenant", 2); diff --git a/tls/pom.xml b/tls/pom.xml index a25904707..291527967 100644 --- a/tls/pom.xml +++ b/tls/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT tls diff --git a/tolerant-reader/pom.xml b/tolerant-reader/pom.xml index 3acc0b188..adbb4d48e 100644 --- a/tolerant-reader/pom.xml +++ b/tolerant-reader/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT tolerant-reader diff --git a/trampoline/pom.xml b/trampoline/pom.xml index 71de3f8f2..e5d4c25c9 100644 --- a/trampoline/pom.xml +++ b/trampoline/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT trampoline diff --git a/trampoline/src/main/java/com/iluwatar/trampoline/Trampoline.java b/trampoline/src/main/java/com/iluwatar/trampoline/Trampoline.java index 277ae9ffb..b4b7c2b2f 100644 --- a/trampoline/src/main/java/com/iluwatar/trampoline/Trampoline.java +++ b/trampoline/src/main/java/com/iluwatar/trampoline/Trampoline.java @@ -1,3 +1,25 @@ +/** + * The MIT License + * Copyright (c) 2014 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.trampoline; import java.util.stream.Stream; diff --git a/trampoline/src/test/java/com/iluwatar/trampoline/TrampolineAppTest.java b/trampoline/src/test/java/com/iluwatar/trampoline/TrampolineAppTest.java index 553e583e1..3680be72e 100644 --- a/trampoline/src/test/java/com/iluwatar/trampoline/TrampolineAppTest.java +++ b/trampoline/src/test/java/com/iluwatar/trampoline/TrampolineAppTest.java @@ -1,3 +1,25 @@ +/** + * The MIT License + * Copyright (c) 2014 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.trampoline; import org.junit.Test; diff --git a/twin/pom.xml b/twin/pom.xml index ed7c9a77f..bc9d976aa 100644 --- a/twin/pom.xml +++ b/twin/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT twin diff --git a/unit-of-work/pom.xml b/unit-of-work/pom.xml index 8a75b16af..cd6f10a0c 100644 --- a/unit-of-work/pom.xml +++ b/unit-of-work/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT 4.0.0 diff --git a/value-object/pom.xml b/value-object/pom.xml index 82fca9508..99ca02195 100644 --- a/value-object/pom.xml +++ b/value-object/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT value-object diff --git a/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java b/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java index 0274bc47f..b65fb000e 100644 --- a/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java +++ b/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java @@ -25,7 +25,9 @@ package com.iluwatar.value.object; /** * HeroStat is a value object * - * {@link http://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html} + * @see + * http://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html + * */ public class HeroStat { diff --git a/value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java b/value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java index f19382d4e..9bfe2d396 100644 --- a/value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java +++ b/value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java @@ -37,8 +37,11 @@ public class HeroStatTest { /** * Tester for equals() and hashCode() methods of a class. Using guava's EqualsTester. * - * @see http://static.javadoc.io/com.google.guava/guava-testlib/19.0/com/google/common/testing/ - * EqualsTester.html + * @see + * http://static.javadoc.io/com.google.guava/guava-testlib/19.0/com/google/common/testing/EqualsTester.html + * + * + * */ @Test public void testEquals() { diff --git a/visitor/pom.xml b/visitor/pom.xml index 01f0d4143..73c8457ec 100644 --- a/visitor/pom.xml +++ b/visitor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.19.0-SNAPSHOT + 1.20.0-SNAPSHOT visitor