From 3f697fe4c7cd80cbe9e44640e9026c1d583c804c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Mon, 29 Apr 2024 21:59:24 +0300 Subject: [PATCH] docs: update Hexagonal docs (#2932) --- hexagonal/README.md | 149 ++++++++++++++++-- .../ConsoleAdministrationSrvImpl.java | 1 - .../iluwatar/hexagonal/banking/MongoBank.java | 32 +--- .../database/MongoTicketRepository.java | 31 +--- .../domain/LotteryAdministration.java | 4 +- .../hexagonal/domain/LotteryService.java | 4 +- .../hexagonal/domain/LotteryTicket.java | 14 +- .../hexagonal/domain/LotteryUtils.java | 2 +- .../hexagonal/domain/PlayerDetails.java | 17 +- .../hexagonal/eventlog/MongoEventLog.java | 62 +++----- .../hexagonal/eventlog/StdOutEventLog.java | 10 +- .../MongoConnectionPropertiesLoader.java | 4 +- .../hexagonal/sampledata/SampleData.java | 2 +- .../database/MongoTicketRepositoryTest.java | 8 +- 14 files changed, 189 insertions(+), 151 deletions(-) diff --git a/hexagonal/README.md b/hexagonal/README.md index 754528ef7..6ebdec6cd 100644 --- a/hexagonal/README.md +++ b/hexagonal/README.md @@ -3,35 +3,162 @@ title: Hexagonal Architecture category: Architectural language: en tag: - - Decoupling + - Decoupling + - Layered architecture --- ## Also known as * Ports and Adapters -* Clean Architecture -* Onion Architecture ## Intent -Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases. + +Hexagonal Architecture, often applied within the Java ecosystem, is designed to promote the decoupling of application's core logic from external interfaces, such as databases, user interfaces, or third-party services, thus allowing an application to be at the center of input/output systems. + +## Explanation + +Real world example + +> A real-world analogous example of Hexagonal Architecture can be seen in online banking systems. In such systems, the core banking logic (like processing transactions, managing accounts, and calculating interest) represents the application's core. This core is then surrounded by various adapters that allow the system to interact with different external interfaces without affecting the business logic. For instance, customers might access their accounts through a web interface, a mobile app, or even through ATM services. Meanwhile, the banking system also needs to interface with external services for credit checks, fraud detection, and interbank transactions. Each of these interfaces interacts with the core banking logic through specific adapters designed to translate the external calls to and from the application's internal APIs. This setup allows the bank to modify or extend its external interfaces without having to alter the core business logic, enhancing flexibility and maintainability. + +In plain words + +> Hexagonal Architecture organizes an application into a central core of business logic surrounded by ports and adapters that manage interactions with external systems like user interfaces and databases, allowing the core to remain independent of external concerns. + +Wikipedia says + +> The hexagonal architecture, or ports and adapters architecture, is an architectural pattern used in software design. It aims at creating loosely coupled application components that can be easily connected to their software environment by means of ports and adapters. This makes components exchangeable at any level and facilitates test automation. + +## Programmatic Example + +The Hexagonal Architecture, also known as Ports and Adapters, is a design pattern that aims to create a loosely coupled application where the core business logic is isolated from external interfaces like databases, user interfaces, or third-party services. This allows the core application to be independent and easily testable. + +In the provided code, we can see an example of the Hexagonal Architecture pattern in the `App` class and the use of Google's Guice for dependency injection. + +The `App` class is the entry point of the application. It creates an instance of `LotteryAdministration` and `LotteryService` through dependency injection and uses them to handle various tasks. + +```java +public class App { + + public static void main(String[] args) { + + var injector = Guice.createInjector(new LotteryTestingModule()); + + // start new lottery round + var administration = injector.getInstance(LotteryAdministration.class); + administration.resetLottery(); + + // submit some lottery tickets + var service = injector.getInstance(LotteryService.class); + SampleData.submitTickets(service, 20); + + // perform lottery + administration.performLottery(); + } +} +``` + +The `LotteryAdministration` class is responsible for managing the lottery rounds. It has methods to start a new round, perform the lottery, and reset the lottery. + +```java +public class LotteryAdministration { + + private final LotteryTicketRepository repository; + private final LotteryEventLog notifications; + private final WireTransfers wireTransfers; + + @Inject + public LotteryAdministration(LotteryTicketRepository repository, LotteryEventLog notifications, + WireTransfers wireTransfers) { + this.repository = repository; + this.notifications = notifications; + this.wireTransfers = wireTransfers; + } + + public Map getAllSubmittedTickets() { + return repository.findAll(); + } + + public LotteryNumbers performLottery() { + // Implementation details... + } + + public void resetLottery() { + repository.deleteAll(); + } +} +``` + +The `LotteryService` class is responsible for managing the lottery tickets. It has methods to submit a ticket, check a ticket's status, and get the winning ticket. + +```java +public class LotteryService { + + private final LotteryTicketRepository repository; + private final LotteryEventLog notifications; + private final WireTransfers wireTransfers; + + @Inject + public LotteryService(LotteryTicketRepository repository, LotteryEventLog notifications, + WireTransfers wireTransfers) { + this.repository = repository; + this.notifications = notifications; + this.wireTransfers = wireTransfers; + } + + public Optional submitTicket(LotteryTicket ticket) { + // Implementation details... + } + + public LotteryTicketCheckResult checkTicketForPrize( + LotteryTicketId id, + LotteryNumbers winningNumbers + ) { + // Implementation details... + } +} +``` + +In this example, the `LotteryAdministration` and `LotteryService` classes are the core of the application. They interact with external interfaces like `LotteryTicketRepository`, `LotteryEventLog`, and `WireTransfers` through dependency injection, keeping the core business logic decoupled from external concerns. This is a basic example of the Hexagonal Architecture pattern, where the core application is at the center of input/output systems. ## Class diagram + ![Hexagonal Architecture class diagram](./etc/hexagonal.png) ## Applicability -Use Hexagonal Architecture pattern when -* When the application needs to be independent of any frameworks -* When it is important that the application highly maintainable and fully testable +This pattern is particularly effective in environments where: -## Tutorials +* The application needs to interact with multiple external systems. +* There is a requirement for high testability and maintainability. +* The application should remain unaffected by changes in external interfaces. -* [Build Maintainable Systems With Hexagonal Architecture](http://java-design-patterns.com/blog/build-maintainable-systems-with-hexagonal-architecture/) +## Known Uses -## Real world examples +* Implemented extensively within enterprise applications that leverage frameworks like Spring. +* Used in microservices architectures to maintain clear boundaries and protocols between services. +* Adopted in systems that require integration with various databases or external APIs without impacting the business logic. -* [Apache Isis](https://isis.apache.org/) builds generic UI and REST API directly from the underlying domain objects +## Consequences + +Benefits: + +* Improved Testability: Allows the core functionality to be tested independently of external components. +* Flexibility: Facilitates the addition or replacement of components that interact with the application without modifying the core business logic. +* Maintainability: Reduces dependencies on external interfaces, simplifying upgrades and maintenance. + +Trade-offs: + +* Complexity: Introduces more abstractions and layers, which can complicate the system design and understanding. +* Overhead: Might be an over-engineering for simple applications, where simpler architectural patterns could suffice. + +## Related Patterns + +* Layered Architecture: Shares the concept of organizing code into responsibilities; however, Hexagonal emphasizes port-based interaction with external elements. +* Microservices: Often used in conjunction with Hexagonal Architecture to define clear boundaries and protocols between services. ## Credits * [Alistair Cockburn - Hexagonal Architecture](http://alistair.cockburn.us/Hexagonal+architecture) +* [Implementing Domain-Driven Design](https://amzn.to/4dmBjrB) +* [Building Microservices](https://amzn.to/3UACtrU) diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministrationSrvImpl.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministrationSrvImpl.java index 8617bd305..8808f507c 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministrationSrvImpl.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministrationSrvImpl.java @@ -25,7 +25,6 @@ package com.iluwatar.hexagonal.administration; import com.iluwatar.hexagonal.domain.LotteryAdministration; -import com.iluwatar.hexagonal.domain.LotteryNumbers; import org.slf4j.Logger; /** diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/MongoBank.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/MongoBank.java index e13a249d4..23f1cc8fc 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/MongoBank.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/MongoBank.java @@ -29,6 +29,7 @@ import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.UpdateOptions; import java.util.ArrayList; +import lombok.Getter; import org.bson.Document; /** @@ -39,8 +40,11 @@ public class MongoBank implements WireTransfers { private static final String DEFAULT_DB = "lotteryDB"; private static final String DEFAULT_ACCOUNTS_COLLECTION = "accounts"; + @Getter private MongoClient mongoClient; + @Getter private MongoDatabase database; + @Getter private MongoCollection accountsCollection; /** @@ -77,34 +81,6 @@ public class MongoBank implements WireTransfers { accountsCollection = database.getCollection(accountsCollectionName); } - /** - * Get mongo client. - * - * @return mongo client - */ - public MongoClient getMongoClient() { - return mongoClient; - } - - /** - * Get mongo database. - * - * @return mongo database - */ - public MongoDatabase getMongoDatabase() { - return database; - } - - /** - * Get accounts collection. - * - * @return accounts collection - */ - public MongoCollection getAccountsCollection() { - return accountsCollection; - } - - @Override public void setFunds(String bankAccount, int amount) { var search = new Document("_id", bankAccount); diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/database/MongoTicketRepository.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/database/MongoTicketRepository.java index a8d7ecdb8..9817a14a7 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/database/MongoTicketRepository.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/database/MongoTicketRepository.java @@ -37,6 +37,7 @@ import java.util.Map; import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; +import lombok.Getter; import org.bson.Document; /** @@ -51,7 +52,9 @@ public class MongoTicketRepository implements LotteryTicketRepository { private MongoClient mongoClient; private MongoDatabase database; + @Getter private MongoCollection ticketsCollection; + @Getter private MongoCollection countersCollection; /** @@ -112,24 +115,6 @@ public class MongoTicketRepository implements LotteryTicketRepository { return result.getInteger("seq"); } - /** - * Get tickets collection. - * - * @return tickets collection - */ - public MongoCollection getTicketsCollection() { - return ticketsCollection; - } - - /** - * Get counters collection. - * - * @return counters collection - */ - public MongoCollection getCountersCollection() { - return countersCollection; - } - @Override public Optional findById(LotteryTicketId id) { return ticketsCollection @@ -145,10 +130,10 @@ public class MongoTicketRepository implements LotteryTicketRepository { public Optional save(LotteryTicket ticket) { var ticketId = getNextId(); var doc = new Document(TICKET_ID, ticketId); - doc.put("email", ticket.getPlayerDetails().getEmail()); - doc.put("bank", ticket.getPlayerDetails().getBankAccount()); - doc.put("phone", ticket.getPlayerDetails().getPhoneNumber()); - doc.put("numbers", ticket.getLotteryNumbers().getNumbersAsString()); + doc.put("email", ticket.playerDetails().email()); + doc.put("bank", ticket.playerDetails().bankAccount()); + doc.put("phone", ticket.playerDetails().phoneNumber()); + doc.put("numbers", ticket.lotteryNumbers().getNumbersAsString()); ticketsCollection.insertOne(doc); return Optional.of(new LotteryTicketId(ticketId)); } @@ -160,7 +145,7 @@ public class MongoTicketRepository implements LotteryTicketRepository { .into(new ArrayList<>()) .stream() .map(this::docToTicket) - .collect(Collectors.toMap(LotteryTicket::getId, Function.identity())); + .collect(Collectors.toMap(LotteryTicket::id, Function.identity())); } @Override diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryAdministration.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryAdministration.java index 5ce6c8884..e21b028cc 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryAdministration.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryAdministration.java @@ -68,8 +68,8 @@ public class LotteryAdministration { var tickets = getAllSubmittedTickets(); for (var id : tickets.keySet()) { var lotteryTicket = tickets.get(id); - var playerDetails = lotteryTicket.getPlayerDetails(); - var playerAccount = playerDetails.getBankAccount(); + var playerDetails = lotteryTicket.playerDetails(); + var playerAccount = playerDetails.bankAccount(); var result = LotteryUtils.checkTicketForPrize(repository, id, numbers).getResult(); if (result == LotteryTicketCheckResult.CheckResult.WIN_PRIZE) { if (wireTransfers.transferFunds(PRIZE_AMOUNT, SERVICE_BANK_ACCOUNT, playerAccount)) { diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryService.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryService.java index 61185f32a..8b6521498 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryService.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryService.java @@ -57,8 +57,8 @@ public class LotteryService { * Submit lottery ticket to participate in the lottery. */ public Optional submitTicket(LotteryTicket ticket) { - var playerDetails = ticket.getPlayerDetails(); - var playerAccount = playerDetails.getBankAccount(); + var playerDetails = ticket.playerDetails(); + var playerAccount = playerDetails.bankAccount(); var result = wireTransfers.transferFunds(TICKET_PRIZE, playerAccount, SERVICE_BANK_ACCOUNT); if (!result) { notifications.ticketSubmitError(playerDetails); diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java index 1205b3af3..bc031f660 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java @@ -24,21 +24,10 @@ */ package com.iluwatar.hexagonal.domain; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.ToString; - /** * Immutable value object representing lottery ticket. */ -@Getter -@ToString -@RequiredArgsConstructor -public class LotteryTicket { - - private final LotteryTicketId id; - private final PlayerDetails playerDetails; - private final LotteryNumbers lotteryNumbers; +public record LotteryTicket(LotteryTicketId id, PlayerDetails playerDetails, LotteryNumbers lotteryNumbers) { @Override public int hashCode() { @@ -74,5 +63,4 @@ public class LotteryTicket { return playerDetails.equals(other.playerDetails); } } - } diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryUtils.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryUtils.java index d1b0eb9c5..d14c7ce48 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryUtils.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryUtils.java @@ -45,7 +45,7 @@ public class LotteryUtils { ) { var optional = repository.findById(id); if (optional.isPresent()) { - if (optional.get().getLotteryNumbers().equals(winningNumbers)) { + if (optional.get().lotteryNumbers().equals(winningNumbers)) { return new LotteryTicketCheckResult(CheckResult.WIN_PRIZE, 1000); } else { return new LotteryTicketCheckResult(CheckResult.NO_PRIZE); diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java index 76f338e60..fe638ae32 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java @@ -24,22 +24,7 @@ */ package com.iluwatar.hexagonal.domain; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.ToString; - /** * Immutable value object containing lottery player details. */ -@EqualsAndHashCode -@ToString -@Getter -@RequiredArgsConstructor -public class PlayerDetails { - - private final String email; - private final String bankAccount; - private final String phoneNumber; - -} +public record PlayerDetails(String email, String bankAccount, String phoneNumber) {} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/MongoEventLog.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/MongoEventLog.java index 84e91e8b1..bc3c621e9 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/MongoEventLog.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/MongoEventLog.java @@ -28,6 +28,7 @@ import com.iluwatar.hexagonal.domain.PlayerDetails; import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; +import lombok.Getter; import org.bson.Document; /** @@ -41,8 +42,11 @@ public class MongoEventLog implements LotteryEventLog { private static final String PHONE = "phone"; public static final String MESSAGE = "message"; + @Getter private MongoClient mongoClient; + @Getter private MongoDatabase database; + @Getter private MongoCollection eventsCollection; private final StdOutEventLog stdOutEventLog = new StdOutEventLog(); @@ -81,39 +85,11 @@ public class MongoEventLog implements LotteryEventLog { eventsCollection = database.getCollection(eventsCollectionName); } - /** - * Get mongo client. - * - * @return mongo client - */ - public MongoClient getMongoClient() { - return mongoClient; - } - - /** - * Get mongo database. - * - * @return mongo database - */ - public MongoDatabase getMongoDatabase() { - return database; - } - - /** - * Get events collection. - * - * @return events collection - */ - public MongoCollection getEventsCollection() { - return eventsCollection; - } - - @Override public void ticketSubmitted(PlayerDetails details) { - var document = new Document(EMAIL, details.getEmail()); - document.put(PHONE, details.getPhoneNumber()); - document.put("bank", details.getBankAccount()); + var document = new Document(EMAIL, details.email()); + document.put(PHONE, details.phoneNumber()); + document.put("bank", details.bankAccount()); document .put(MESSAGE, "Lottery ticket was submitted and bank account was charged for 3 credits."); eventsCollection.insertOne(document); @@ -122,9 +98,9 @@ public class MongoEventLog implements LotteryEventLog { @Override public void ticketSubmitError(PlayerDetails details) { - var document = new Document(EMAIL, details.getEmail()); - document.put(PHONE, details.getPhoneNumber()); - document.put("bank", details.getBankAccount()); + var document = new Document(EMAIL, details.email()); + document.put(PHONE, details.phoneNumber()); + document.put("bank", details.bankAccount()); document.put(MESSAGE, "Lottery ticket could not be submitted because lack of funds."); eventsCollection.insertOne(document); stdOutEventLog.ticketSubmitError(details); @@ -132,9 +108,9 @@ public class MongoEventLog implements LotteryEventLog { @Override public void ticketDidNotWin(PlayerDetails details) { - var document = new Document(EMAIL, details.getEmail()); - document.put(PHONE, details.getPhoneNumber()); - document.put("bank", details.getBankAccount()); + var document = new Document(EMAIL, details.email()); + document.put(PHONE, details.phoneNumber()); + document.put("bank", details.bankAccount()); document.put(MESSAGE, "Lottery ticket was checked and unfortunately did not win this time."); eventsCollection.insertOne(document); stdOutEventLog.ticketDidNotWin(details); @@ -142,9 +118,9 @@ public class MongoEventLog implements LotteryEventLog { @Override public void ticketWon(PlayerDetails details, int prizeAmount) { - var document = new Document(EMAIL, details.getEmail()); - document.put(PHONE, details.getPhoneNumber()); - document.put("bank", details.getBankAccount()); + var document = new Document(EMAIL, details.email()); + document.put(PHONE, details.phoneNumber()); + document.put("bank", details.bankAccount()); document.put(MESSAGE, String .format("Lottery ticket won! The bank account was deposited with %d credits.", prizeAmount)); @@ -154,9 +130,9 @@ public class MongoEventLog implements LotteryEventLog { @Override public void prizeError(PlayerDetails details, int prizeAmount) { - var document = new Document(EMAIL, details.getEmail()); - document.put(PHONE, details.getPhoneNumber()); - document.put("bank", details.getBankAccount()); + var document = new Document(EMAIL, details.email()); + document.put(PHONE, details.phoneNumber()); + document.put("bank", details.bankAccount()); document.put(MESSAGE, String .format("Lottery ticket won! Unfortunately the bank credit transfer of %d failed.", prizeAmount)); diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java index 40afe687d..d57645115 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java @@ -36,30 +36,30 @@ public class StdOutEventLog implements LotteryEventLog { @Override public void ticketSubmitted(PlayerDetails details) { LOGGER.info("Lottery ticket for {} was submitted. Bank account {} was charged for 3 credits.", - details.getEmail(), details.getBankAccount()); + details.email(), details.bankAccount()); } @Override public void ticketDidNotWin(PlayerDetails details) { LOGGER.info("Lottery ticket for {} was checked and unfortunately did not win this time.", - details.getEmail()); + details.email()); } @Override public void ticketWon(PlayerDetails details, int prizeAmount) { LOGGER.info("Lottery ticket for {} has won! The bank account {} was deposited with {} credits.", - details.getEmail(), details.getBankAccount(), prizeAmount); + details.email(), details.bankAccount(), prizeAmount); } @Override public void prizeError(PlayerDetails details, int prizeAmount) { LOGGER.error("Lottery ticket for {} has won! Unfortunately the bank credit transfer of" - + " {} failed.", details.getEmail(), prizeAmount); + + " {} failed.", details.email(), prizeAmount); } @Override public void ticketSubmitError(PlayerDetails details) { LOGGER.error("Lottery ticket for {} could not be submitted because the credit transfer" - + " of 3 credits failed.", details.getEmail()); + + " of 3 credits failed.", details.email()); } } diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/mongo/MongoConnectionPropertiesLoader.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/mongo/MongoConnectionPropertiesLoader.java index fc735b9f6..40261090e 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/mongo/MongoConnectionPropertiesLoader.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/mongo/MongoConnectionPropertiesLoader.java @@ -26,10 +26,12 @@ package com.iluwatar.hexagonal.mongo; import java.io.FileInputStream; import java.util.Properties; +import lombok.extern.slf4j.Slf4j; /** * Mongo connection properties loader. */ +@Slf4j public class MongoConnectionPropertiesLoader { private static final String DEFAULT_HOST = "localhost"; @@ -50,7 +52,7 @@ public class MongoConnectionPropertiesLoader { port = Integer.parseInt(properties.getProperty("mongo-port")); } catch (Exception e) { // error occurred, use default properties - e.printStackTrace(); + LOGGER.error("Error occurred: ", e); } } System.setProperty("mongo-host", host); diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/sampledata/SampleData.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/sampledata/SampleData.java index 6549e10db..2dc191604 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/sampledata/SampleData.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/sampledata/SampleData.java @@ -88,7 +88,7 @@ public class SampleData { ); var wireTransfers = new InMemoryBank(); PLAYERS.stream() - .map(PlayerDetails::getBankAccount) + .map(PlayerDetails::bankAccount) .map(e -> new SimpleEntry<>(e, RANDOM.nextInt(LotteryConstants.PLAYER_MAX_BALANCE))) .collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue)) .forEach(wireTransfers::setFunds); diff --git a/hexagonal/src/test/java/com/iluwatar/hexagonal/database/MongoTicketRepositoryTest.java b/hexagonal/src/test/java/com/iluwatar/hexagonal/database/MongoTicketRepositoryTest.java index 9a3785f50..ee8329bd9 100644 --- a/hexagonal/src/test/java/com/iluwatar/hexagonal/database/MongoTicketRepositoryTest.java +++ b/hexagonal/src/test/java/com/iluwatar/hexagonal/database/MongoTicketRepositoryTest.java @@ -86,10 +86,10 @@ class MongoTicketRepositoryTest { var found = repository.findById(saved.get()); assertTrue(found.isPresent()); var ticket = found.get(); - assertEquals("foo@bar.com", ticket.getPlayerDetails().getEmail()); - assertEquals("123-123", ticket.getPlayerDetails().getBankAccount()); - assertEquals("07001234", ticket.getPlayerDetails().getPhoneNumber()); - assertEquals(original.getLotteryNumbers(), ticket.getLotteryNumbers()); + assertEquals("foo@bar.com", ticket.playerDetails().email()); + assertEquals("123-123", ticket.playerDetails().bankAccount()); + assertEquals("07001234", ticket.playerDetails().phoneNumber()); + assertEquals(original.lotteryNumbers(), ticket.lotteryNumbers()); // clear the collection repository.deleteAll(); assertEquals(0, repository.getTicketsCollection().countDocuments());