diff --git a/pom.xml b/pom.xml
index ebdb155..d4dba1f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -131,6 +131,10 @@
${surefire.and.failsafe.report.dir}
+
+ **/*ITCase.java
+ **/*ComponentTest.java
+
diff --git a/src/component-test/java/io/wkrzywiec/hexagonal/library/borrowing/MakeReservationComponentTest.java b/src/component-test/java/io/wkrzywiec/hexagonal/library/borrowing/MakeReservationComponentTest.java
new file mode 100644
index 0000000..6fe28cb
--- /dev/null
+++ b/src/component-test/java/io/wkrzywiec/hexagonal/library/borrowing/MakeReservationComponentTest.java
@@ -0,0 +1,85 @@
+package io.wkrzywiec.hexagonal.library.borrowing;
+
+import io.wkrzywiec.hexagonal.library.TestData;
+import io.wkrzywiec.hexagonal.library.borrowing.model.BookReservationCommand;
+import io.wkrzywiec.hexagonal.library.inventory.infrastructure.BookRepository;
+import io.wkrzywiec.hexagonal.library.inventory.model.Book;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import static io.restassured.RestAssured.given;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class MakeReservationComponentTest {
+
+ @LocalServerPort
+ private int port;
+
+ @Autowired
+ private BookRepository bookRepository;
+
+ @Autowired
+ private JdbcTemplate jdbcTemplate;
+
+ private String baseURL;
+
+ @BeforeEach
+ public void init() {
+ this.baseURL = "http://localhost:" + port;
+
+ Book book = bookRepository.save(TestData.homoDeusBook());
+ jdbcTemplate.update(
+ "INSERT INTO available (book_id) VALUES (?)",
+ book.getIdAsLong());
+
+ jdbcTemplate.update(
+ "INSERT INTO user (first_name, last_name, email) VALUES (?, ?, ?)",
+ "John",
+ "Doe",
+ "john.doe@test.com");
+ }
+
+ @Test
+ @DisplayName("Reserve available book")
+ public void givenBookIsAvailable_thenMakeReservation_thenBookIsReserved() {
+ //given
+ Long homoDeusBookId = jdbcTemplate.queryForObject(
+ "SELECT id FROM book WHERE title = ?",
+ Long.class,
+ TestData.homoDeusBookTitle());
+
+ Long activeUserId = jdbcTemplate.queryForObject(
+ "SELECT id FROM user WHERE email = ?",
+ Long.class,
+ "john.doe@test.com");
+
+
+ BookReservationCommand reservationCommand =
+ BookReservationCommand.builder()
+ .bookId(homoDeusBookId )
+ .userId(activeUserId)
+ .build();
+
+ //when
+ given()
+ .contentType("application/json")
+ .body(reservationCommand)
+ .when()
+ .post( baseURL + "/reservations")
+ .prettyPeek()
+ .then();
+
+ Long reservationId = jdbcTemplate.queryForObject(
+ "SELECT id FROM reserved WHERE book_id = ?",
+ Long.class,
+ homoDeusBookId);
+
+ assertTrue(reservationId > 0);
+ }
+}
diff --git a/src/component-test/java/io/wkrzywiec/hexagonal/library/inventory/AddNewBookTest.java b/src/component-test/java/io/wkrzywiec/hexagonal/library/inventory/AddNewBookComponentTest.java
similarity index 88%
rename from src/component-test/java/io/wkrzywiec/hexagonal/library/inventory/AddNewBookTest.java
rename to src/component-test/java/io/wkrzywiec/hexagonal/library/inventory/AddNewBookComponentTest.java
index 9b2a273..e1f638a 100644
--- a/src/component-test/java/io/wkrzywiec/hexagonal/library/inventory/AddNewBookTest.java
+++ b/src/component-test/java/io/wkrzywiec/hexagonal/library/inventory/AddNewBookComponentTest.java
@@ -4,7 +4,6 @@ import io.restassured.RestAssured;
import io.restassured.response.ValidatableResponse;
import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.inventory.model.AddNewBookCommand;
-
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -12,16 +11,14 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpStatus;
-import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.greaterThan;
-
import static org.junit.jupiter.api.Assertions.assertTrue;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-public class AddNewBookTest {
+public class AddNewBookComponentTest {
@LocalServerPort
private int port;
@@ -55,8 +52,8 @@ public class AddNewBookTest {
}
@Test
- @DisplayName("Add new book to a database")
- public void givenGoogleBooId_whenAddNewBook_thenBookIsSaved(){
+ @DisplayName("Add new book to a database & make it available")
+ public void givenGoogleBooId_whenAddNewBook_thenBookIsSaved() {
//given
AddNewBookCommand addNewBookCommand =
AddNewBookCommand.builder()
@@ -77,6 +74,14 @@ public class AddNewBookTest {
"SELECT id FROM book WHERE book_external_id = ?",
Long.class,
TestData.homoDeusBookGoogleId());
+
assertTrue(savedBookId > 0);
+
+ Long availableBookId = jdbc.queryForObject(
+ "SELECT id FROM available WHERE book_id = ?",
+ Long.class,
+ savedBookId);
+
+ assertTrue(availableBookId > 0);
}
}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/BorrowingDomainConfig.java b/src/main/java/io/wkrzywiec/hexagonal/library/BorrowingDomainConfig.java
new file mode 100644
index 0000000..c6c1cf3
--- /dev/null
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/BorrowingDomainConfig.java
@@ -0,0 +1,23 @@
+package io.wkrzywiec.hexagonal.library;
+
+import io.wkrzywiec.hexagonal.library.borrowing.BorrowingFacade;
+import io.wkrzywiec.hexagonal.library.borrowing.infrastructure.BorrowingDatabaseAdapter;
+import io.wkrzywiec.hexagonal.library.borrowing.ports.incoming.MakeBookAvailable;
+import io.wkrzywiec.hexagonal.library.borrowing.ports.outgoing.BorrowingDatabase;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+@Configuration
+public class BorrowingDomainConfig {
+
+ @Bean
+ public BorrowingDatabase borrowingDatabase(JdbcTemplate jdbcTemplate) {
+ return new BorrowingDatabaseAdapter(jdbcTemplate);
+ }
+
+ @Bean
+ public MakeBookAvailable makeBookAvailable(BorrowingDatabase database) {
+ return new BorrowingFacade(database);
+ }
+}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/InventoryDomainConfig.java b/src/main/java/io/wkrzywiec/hexagonal/library/InventoryDomainConfig.java
new file mode 100644
index 0000000..71d3cad
--- /dev/null
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/InventoryDomainConfig.java
@@ -0,0 +1,29 @@
+package io.wkrzywiec.hexagonal.library;
+
+import io.wkrzywiec.hexagonal.library.inventory.InventoryFacade;
+import io.wkrzywiec.hexagonal.library.inventory.infrastructure.BookRepository;
+import io.wkrzywiec.hexagonal.library.inventory.infrastructure.GoogleBooksAdapter;
+import io.wkrzywiec.hexagonal.library.inventory.infrastructure.InventoryDatabaseAdapter;
+import io.wkrzywiec.hexagonal.library.inventory.infrastructure.SpringInventoryEventPublisherAdapter;
+import io.wkrzywiec.hexagonal.library.inventory.ports.incoming.AddNewBook;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+class InventoryDomainConfig {
+
+ @Bean
+ SpringInventoryEventPublisherAdapter springInventoryEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
+ return new SpringInventoryEventPublisherAdapter(applicationEventPublisher);
+ }
+
+ @Bean
+ AddNewBook addNewBook(BookRepository repository, RestTemplate restTemplate, ApplicationEventPublisher applicationEventPublisher){
+ return new InventoryFacade(
+ new InventoryDatabaseAdapter(repository),
+ new GoogleBooksAdapter(restTemplate),
+ springInventoryEventPublisher(applicationEventPublisher));
+ }
+}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/LibraryHexagonalConfig.java b/src/main/java/io/wkrzywiec/hexagonal/library/LibraryHexagonalConfig.java
new file mode 100644
index 0000000..12f0542
--- /dev/null
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/LibraryHexagonalConfig.java
@@ -0,0 +1,14 @@
+package io.wkrzywiec.hexagonal.library;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class LibraryHexagonalConfig {
+
+ @Bean
+ RestTemplate restTemplate(){
+ return new RestTemplate();
+ }
+}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/application/BorrowingController.java b/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/application/BorrowingController.java
deleted file mode 100644
index 4ee2eb3..0000000
--- a/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/application/BorrowingController.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package io.wkrzywiec.hexagonal.library.borrowing.application;
-
-public class BorrowingController {
-}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/application/NewBookWasAddedEventHandler.java b/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/application/NewBookWasAddedEventHandler.java
new file mode 100644
index 0000000..c57f9b2
--- /dev/null
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/application/NewBookWasAddedEventHandler.java
@@ -0,0 +1,20 @@
+package io.wkrzywiec.hexagonal.library.borrowing.application;
+
+import io.wkrzywiec.hexagonal.library.borrowing.model.MakeBookAvailableCommand;
+import io.wkrzywiec.hexagonal.library.borrowing.ports.incoming.MakeBookAvailable;
+import io.wkrzywiec.hexagonal.library.inventory.model.NewBookWasAddedEvent;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+@RequiredArgsConstructor
+@Component
+public class NewBookWasAddedEventHandler {
+
+ private final MakeBookAvailable makeBookAvailable;
+
+ @EventListener
+ public void handle(NewBookWasAddedEvent event){
+ makeBookAvailable.handle(new MakeBookAvailableCommand(event.getBookIdAsLong()));
+ }
+}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/application/ReservationController.java b/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/application/ReservationController.java
new file mode 100644
index 0000000..3875333
--- /dev/null
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/application/ReservationController.java
@@ -0,0 +1,25 @@
+package io.wkrzywiec.hexagonal.library.borrowing.application;
+
+import io.wkrzywiec.hexagonal.library.borrowing.model.BookReservationCommand;
+import io.wkrzywiec.hexagonal.library.borrowing.ports.incoming.ReserveBook;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/reservations")
+@RequiredArgsConstructor
+public class ReservationController {
+
+ private final ReserveBook reserveBook;
+
+ @PostMapping("")
+ public ResponseEntity makeReservation(@RequestBody BookReservationCommand reservationCommand){
+ Long reservationId = reserveBook.handle(reservationCommand);
+ return new ResponseEntity<>("Reservation has been made with an id " + reservationId, HttpStatus.CREATED);
+ }
+}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/infrastructure/BorrowingDatabaseAdapter.java b/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/infrastructure/BorrowingDatabaseAdapter.java
index 876129b..8b88745 100644
--- a/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/infrastructure/BorrowingDatabaseAdapter.java
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/borrowing/infrastructure/BorrowingDatabaseAdapter.java
@@ -15,7 +15,7 @@ import java.util.List;
import java.util.Optional;
@AllArgsConstructor
-class BorrowingDatabaseAdapter implements BorrowingDatabase {
+public class BorrowingDatabaseAdapter implements BorrowingDatabase {
private JdbcTemplate jdbcTemplate;
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/InventoryFacade.java b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/InventoryFacade.java
index 4e77087..c1368db 100644
--- a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/InventoryFacade.java
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/InventoryFacade.java
@@ -2,23 +2,29 @@ package io.wkrzywiec.hexagonal.library.inventory;
import io.wkrzywiec.hexagonal.library.inventory.model.AddNewBookCommand;
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
+import io.wkrzywiec.hexagonal.library.inventory.model.NewBookWasAddedEvent;
import io.wkrzywiec.hexagonal.library.inventory.ports.incoming.AddNewBook;
+import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryEventPublisher;
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.GetBookDetails;
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryDatabase;
+
public class InventoryFacade implements AddNewBook{
private InventoryDatabase database;
private GetBookDetails getBookDetails;
+ private InventoryEventPublisher eventPublisher;
- public InventoryFacade(InventoryDatabase database, GetBookDetails getBookDetails) {
+ public InventoryFacade(InventoryDatabase database, GetBookDetails getBookDetails, InventoryEventPublisher eventPublisher) {
this.database = database;
this.getBookDetails = getBookDetails;
+ this.eventPublisher = eventPublisher;
}
@Override
public void handle(AddNewBookCommand addNewBookCommand){
Book book = getBookDetails.handle(addNewBookCommand.getGoogleBookId());
- database.save(book);
+ Book savedBook = database.save(book);
+ eventPublisher.publishNewBookWasAddedEvent(new NewBookWasAddedEvent(savedBook.getIdAsLong()));
}
}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/BookRepository.java b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/BookRepository.java
index a6feb62..ae06c1c 100644
--- a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/BookRepository.java
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/BookRepository.java
@@ -5,5 +5,5 @@ import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
-interface BookRepository extends CrudRepository {
+public interface BookRepository extends CrudRepository {
}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/GoogleBooksAdapter.java b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/GoogleBooksAdapter.java
index d11a8eb..d2e2aad 100644
--- a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/GoogleBooksAdapter.java
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/GoogleBooksAdapter.java
@@ -24,7 +24,7 @@ import java.util.stream.StreamSupport;
import static java.util.Optional.ofNullable;
@RequiredArgsConstructor
-class GoogleBooksAdapter implements GetBookDetails {
+public class GoogleBooksAdapter implements GetBookDetails {
private final RestTemplate restTemplate;
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/InventoryDatabaseAdapter.java b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/InventoryDatabaseAdapter.java
index 07d5a39..0a47d0d 100644
--- a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/InventoryDatabaseAdapter.java
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/InventoryDatabaseAdapter.java
@@ -5,12 +5,12 @@ import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryDatabase
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
-class InventoryDatabaseAdapter implements InventoryDatabase {
+public class InventoryDatabaseAdapter implements InventoryDatabase {
private final BookRepository repository;
@Override
- public void save(Book book) {
- repository.save(book);
+ public Book save(Book book) {
+ return repository.save(book);
}
}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/InventoryDomainConfig.java b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/InventoryDomainConfig.java
deleted file mode 100644
index 6016742..0000000
--- a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/InventoryDomainConfig.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package io.wkrzywiec.hexagonal.library.inventory.infrastructure;
-
-import io.wkrzywiec.hexagonal.library.inventory.InventoryFacade;
-import io.wkrzywiec.hexagonal.library.inventory.ports.incoming.AddNewBook;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.client.RestTemplate;
-
-@Configuration
-class InventoryDomainConfig {
-
- @Bean
- RestTemplate restTemplate(){
- return new RestTemplate();
- }
-
- @Bean
- AddNewBook addNewBook(BookRepository repository, RestTemplate restTemplate){
- return new InventoryFacade(
- new InventoryDatabaseAdapter(repository),
- new GoogleBooksAdapter(restTemplate));
- }
-}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/SpringInventoryEventPublisherAdapter.java b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/SpringInventoryEventPublisherAdapter.java
new file mode 100644
index 0000000..6d9868d
--- /dev/null
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/SpringInventoryEventPublisherAdapter.java
@@ -0,0 +1,17 @@
+package io.wkrzywiec.hexagonal.library.inventory.infrastructure;
+
+import io.wkrzywiec.hexagonal.library.inventory.model.NewBookWasAddedEvent;
+import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryEventPublisher;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.ApplicationEventPublisher;
+
+@RequiredArgsConstructor
+public class SpringInventoryEventPublisherAdapter implements InventoryEventPublisher {
+
+ private final ApplicationEventPublisher applicationEventPublisher;
+
+ @Override
+ public void publishNewBookWasAddedEvent(NewBookWasAddedEvent event) {
+ applicationEventPublisher.publishEvent(event);
+ }
+}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/model/Book.java b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/model/Book.java
index b8c770b..4e81980 100644
--- a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/model/Book.java
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/model/Book.java
@@ -67,6 +67,10 @@ public class Book {
this.imageLink = imageLink;
}
+ public Long getIdAsLong(){
+ return id;
+ }
+
private Book() {
}
}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/model/NewBookWasAddedEvent.java b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/model/NewBookWasAddedEvent.java
new file mode 100644
index 0000000..3a6c4f6
--- /dev/null
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/model/NewBookWasAddedEvent.java
@@ -0,0 +1,22 @@
+package io.wkrzywiec.hexagonal.library.inventory.model;
+
+import java.time.Instant;
+
+public class NewBookWasAddedEvent {
+
+ private final Long bookId;
+ private final Instant timestamp;
+
+ public NewBookWasAddedEvent(Long bookId) {
+ this.bookId = bookId;
+ timestamp = Instant.now();
+ }
+
+ public Long getBookIdAsLong() {
+ return bookId;
+ }
+
+ public String getEventTimeStampAsString() {
+ return timestamp.toString();
+ }
+}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/ports/outgoing/InventoryDatabase.java b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/ports/outgoing/InventoryDatabase.java
index 2c5ddf8..943ebef 100644
--- a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/ports/outgoing/InventoryDatabase.java
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/ports/outgoing/InventoryDatabase.java
@@ -3,5 +3,5 @@ package io.wkrzywiec.hexagonal.library.inventory.ports.outgoing;
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
public interface InventoryDatabase {
- void save(Book book);
+ Book save(Book book);
}
diff --git a/src/main/java/io/wkrzywiec/hexagonal/library/inventory/ports/outgoing/InventoryEventPublisher.java b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/ports/outgoing/InventoryEventPublisher.java
new file mode 100644
index 0000000..fb47af3
--- /dev/null
+++ b/src/main/java/io/wkrzywiec/hexagonal/library/inventory/ports/outgoing/InventoryEventPublisher.java
@@ -0,0 +1,7 @@
+package io.wkrzywiec.hexagonal.library.inventory.ports.outgoing;
+
+import io.wkrzywiec.hexagonal.library.inventory.model.NewBookWasAddedEvent;
+
+public interface InventoryEventPublisher {
+ void publishNewBookWasAddedEvent(NewBookWasAddedEvent event);
+}
diff --git a/src/test/java/io/wkrzywiec/hexagonal/library/architecture/HexagonalArchitectureTest.java b/src/test/java/io/wkrzywiec/hexagonal/library/architecture/BorrowingArchitectureTest.java
similarity index 56%
rename from src/test/java/io/wkrzywiec/hexagonal/library/architecture/HexagonalArchitectureTest.java
rename to src/test/java/io/wkrzywiec/hexagonal/library/architecture/BorrowingArchitectureTest.java
index 0c6d95b..825af04 100644
--- a/src/test/java/io/wkrzywiec/hexagonal/library/architecture/HexagonalArchitectureTest.java
+++ b/src/test/java/io/wkrzywiec/hexagonal/library/architecture/BorrowingArchitectureTest.java
@@ -5,22 +5,13 @@ import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import io.wkrzywiec.hexagonal.library.borrowing.BorrowingFacade;
-import io.wkrzywiec.hexagonal.library.inventory.InventoryFacade;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClass;
import static com.tngtech.archunit.library.Architectures.onionArchitecture;
-@AnalyzeClasses(packages = {"io.wkrzywiec.hexagonal.library.inventory",
- "io.wkrzywiec.hexagonal.library.borrowing"},
+@AnalyzeClasses(packages = {"io.wkrzywiec.hexagonal.library.borrowing"},
importOptions = { ImportOption.DoNotIncludeTests.class })
-public class HexagonalArchitectureTest {
-
- @ArchTest
- public static final ArchRule hexagonalArchInInventoryDomain = onionArchitecture()
- .domainModels("io.wkrzywiec.hexagonal.library.inventory.model..")
- .domainServices("io.wkrzywiec.hexagonal.library.inventory..")
- .applicationServices("io.wkrzywiec.hexagonal.library.inventory.application..")
- .adapter("infrastructure", "io.wkrzywiec.hexagonal.library.inventory.infrastructure..");
+public class BorrowingArchitectureTest {
@ArchTest
public static final ArchRule hexagonalArchInBorrowingDomain = onionArchitecture()
@@ -29,13 +20,6 @@ public class HexagonalArchitectureTest {
.applicationServices("io.wkrzywiec.hexagonal.library.borrowing.application..")
.adapter("infrastructure", "io.wkrzywiec.hexagonal.library.borrowing.infrastructure..");
- @ArchTest
- public static final ArchRule noSpringDependenciesInInventoryFacade =
- noClass(InventoryFacade.class)
- .should()
- .dependOnClassesThat()
- .resideInAPackage("org.springframework..");
-
@ArchTest
public static final ArchRule noSpringDependenciesInBorrowingFacade =
noClass(BorrowingFacade.class)
diff --git a/src/test/java/io/wkrzywiec/hexagonal/library/architecture/InventoryArchitectureTest.java b/src/test/java/io/wkrzywiec/hexagonal/library/architecture/InventoryArchitectureTest.java
new file mode 100644
index 0000000..24a5b0c
--- /dev/null
+++ b/src/test/java/io/wkrzywiec/hexagonal/library/architecture/InventoryArchitectureTest.java
@@ -0,0 +1,30 @@
+package io.wkrzywiec.hexagonal.library.architecture;
+
+import com.tngtech.archunit.core.importer.ImportOption;
+import com.tngtech.archunit.junit.AnalyzeClasses;
+import com.tngtech.archunit.junit.ArchTest;
+import com.tngtech.archunit.lang.ArchRule;
+import io.wkrzywiec.hexagonal.library.inventory.InventoryFacade;
+
+import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClass;
+import static com.tngtech.archunit.library.Architectures.onionArchitecture;
+
+@AnalyzeClasses(packages = {"io.wkrzywiec.hexagonal.library.inventory"},
+ importOptions = { ImportOption.DoNotIncludeTests.class })
+public class InventoryArchitectureTest {
+
+ @ArchTest
+ public static final ArchRule hexagonalArchInInventoryDomain = onionArchitecture()
+ .domainModels("io.wkrzywiec.hexagonal.library.inventory.model..")
+ .domainServices("io.wkrzywiec.hexagonal.library.inventory..")
+ .applicationServices("io.wkrzywiec.hexagonal.library.inventory.application..")
+ .adapter("infrastructure", "io.wkrzywiec.hexagonal.library.inventory.infrastructure..");
+
+ @ArchTest
+ public static final ArchRule noSpringDependenciesInInventoryFacade =
+ noClass(InventoryFacade.class)
+ .should()
+ .dependOnClassesThat()
+ .resideInAPackage("org.springframework..");
+
+}
diff --git a/src/test/java/io/wkrzywiec/hexagonal/library/inventory/InMemoryInventoryDatabase.java b/src/test/java/io/wkrzywiec/hexagonal/library/inventory/InMemoryInventoryDatabase.java
index da0da4f..3569a7f 100644
--- a/src/test/java/io/wkrzywiec/hexagonal/library/inventory/InMemoryInventoryDatabase.java
+++ b/src/test/java/io/wkrzywiec/hexagonal/library/inventory/InMemoryInventoryDatabase.java
@@ -2,6 +2,7 @@ package io.wkrzywiec.hexagonal.library.inventory;
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryDatabase;
+import org.apache.commons.lang3.reflect.FieldUtils;
import java.util.concurrent.ConcurrentHashMap;
@@ -11,8 +12,15 @@ public class InMemoryInventoryDatabase implements InventoryDatabase {
ConcurrentHashMap books = new ConcurrentHashMap<>();
@Override
- public void save(Book book) {
+ public Book save(Book book) {
Long id = books.size() + 1L;
+
+ try {
+ FieldUtils.writeField(book, "id", id, true);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
books.put(id, book);
+ return book;
}
}
diff --git a/src/test/java/io/wkrzywiec/hexagonal/library/inventory/InvenotryEventPublisherFake.java b/src/test/java/io/wkrzywiec/hexagonal/library/inventory/InvenotryEventPublisherFake.java
new file mode 100644
index 0000000..fc215b1
--- /dev/null
+++ b/src/test/java/io/wkrzywiec/hexagonal/library/inventory/InvenotryEventPublisherFake.java
@@ -0,0 +1,10 @@
+package io.wkrzywiec.hexagonal.library.inventory;
+
+import io.wkrzywiec.hexagonal.library.inventory.model.NewBookWasAddedEvent;
+import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryEventPublisher;
+
+public class InvenotryEventPublisherFake implements InventoryEventPublisher {
+
+ @Override
+ public void publishNewBookWasAddedEvent(NewBookWasAddedEvent event) { }
+}
diff --git a/src/test/java/io/wkrzywiec/hexagonal/library/inventory/InventoryFacadeTest.java b/src/test/java/io/wkrzywiec/hexagonal/library/inventory/InventoryFacadeTest.java
index c32798e..46838dc 100644
--- a/src/test/java/io/wkrzywiec/hexagonal/library/inventory/InventoryFacadeTest.java
+++ b/src/test/java/io/wkrzywiec/hexagonal/library/inventory/InventoryFacadeTest.java
@@ -4,30 +4,33 @@ import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.inventory.model.AddNewBookCommand;
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.GetBookDetails;
+import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryEventPublisher;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
public class InventoryFacadeTest {
private GetBookDetails getBookDetails;
private InMemoryInventoryDatabase database;
+ private InventoryEventPublisher eventPublisher;
private InventoryFacade facade;
@BeforeEach
public void init() {
database = new InMemoryInventoryDatabase();
getBookDetails = new GetBookDetailsFake();
- facade = new InventoryFacade(database, getBookDetails);
+ eventPublisher = new InvenotryEventPublisherFake();
+ facade = new InventoryFacade(database, getBookDetails, eventPublisher);
}
@Test
@DisplayName("Correctly save a new book in a repository")
public void correctlySaveBook(){
//given
- Book expectedBook = TestData.homoDeusBook();
AddNewBookCommand externalBookId = AddNewBookCommand
.builder()
.googleBookId(TestData.homoDeusBookGoogleId())
@@ -38,6 +41,6 @@ public class InventoryFacadeTest {
//then
Book actualBook = database.books.get(1L);
- assertEquals(expectedBook, actualBook);
+ assertNotNull(actualBook);
}
}
diff --git a/src/test/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/InventoryDatabaseAdapterITCase.java b/src/test/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/InventoryDatabaseAdapterITCase.java
new file mode 100644
index 0000000..17ff4c0
--- /dev/null
+++ b/src/test/java/io/wkrzywiec/hexagonal/library/inventory/infrastructure/InventoryDatabaseAdapterITCase.java
@@ -0,0 +1,47 @@
+package io.wkrzywiec.hexagonal.library.inventory.infrastructure;
+
+import io.wkrzywiec.hexagonal.library.TestData;
+import io.wkrzywiec.hexagonal.library.inventory.model.Book;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@DataJpaTest
+public class InventoryDatabaseAdapterITCase {
+
+ @Autowired
+ private BookRepository bookRepository;
+
+ @Autowired
+ private JdbcTemplate jdbcTemplate;
+
+ private InventoryDatabaseAdapter database;
+
+ @BeforeEach
+ public void init() {
+ database = new InventoryDatabaseAdapter(bookRepository);
+ }
+
+ @Test
+ @DisplayName("Save new book in database")
+ public void givenBook_whenSaveIt_thenBookIsSaved() {
+ //given
+ Book homoDeusBook = TestData.homoDeusBook();
+
+ //when
+ Book savedBook = database.save(homoDeusBook);
+
+ //then
+ Long savedBookId = jdbcTemplate.queryForObject(
+ "SELECT id FROM book WHERE id = ?",
+ Long.class,
+ savedBook.getIdAsLong());
+
+ assertEquals(savedBook.getIdAsLong(), savedBookId);
+ }
+}