applicationa layer for borrowing books

This commit is contained in:
Wojtek Krzywiec
2020-06-04 08:15:48 +02:00
parent 8dc64f2c79
commit e5e4767a9c
7 changed files with 144 additions and 3 deletions

View File

@@ -0,0 +1,83 @@
package io.wkrzywiec.hexagonal.library.domain.borrowing;
import io.restassured.RestAssured;
import io.wkrzywiec.hexagonal.library.BookTestData;
import io.wkrzywiec.hexagonal.library.UserTestData;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.model.BookReservationCommand;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.model.BorrowBookCommand;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
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 org.springframework.test.context.jdbc.Sql;
import static io.restassured.RestAssured.given;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class BorrowBookComponentTest {
@LocalServerPort
private int port;
private String baseURL;
@Autowired
private JdbcTemplate jdbcTemplate;
@BeforeEach
public void init() {
this.baseURL = "http://localhost:" + port;
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
}
@Test
@Disabled
@DisplayName("Borrow reserved book")
@Sql({"/book-and-user.sql", "/available-book.sql"})
@Sql(scripts = "/clean-database.sql", executionPhase = AFTER_TEST_METHOD)
public void givenBookIsReserved_thenBorrowIt_thenBookIsBorrowed() {
//given
Long homoDeusBookId = jdbcTemplate.queryForObject(
"SELECT id FROM book WHERE title = ?",
Long.class,
BookTestData.homoDeusBookTitle());
Long activeUserId = jdbcTemplate.queryForObject(
"SELECT id FROM user WHERE email = ?",
Long.class,
UserTestData.johnDoeEmail());
jdbcTemplate.update(
"INSERT INTO public.reserved (book_id, user_id) VALUES (?, ?)",
homoDeusBookId,
activeUserId);
BorrowBookCommand borrowBookCommand =
BorrowBookCommand.builder()
.bookId(homoDeusBookId )
.userId(activeUserId)
.build();
//when
given()
.contentType("application/json")
.body(borrowBookCommand)
.when()
.post( baseURL + "/borrow")
.prettyPeek()
.then();
Long reservationId = jdbcTemplate.queryForObject(
"SELECT id FROM borrowed WHERE book_id = ?",
Long.class,
homoDeusBookId);
assertTrue(reservationId > 0);
}
}

View File

@@ -2,6 +2,7 @@ package io.wkrzywiec.hexagonal.library.domain.borrowing;
import io.restassured.RestAssured;
import io.wkrzywiec.hexagonal.library.BookTestData;
import io.wkrzywiec.hexagonal.library.UserTestData;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.model.BookReservationCommand;
import io.wkrzywiec.hexagonal.library.domain.inventory.infrastructure.BookRepository;
import org.junit.jupiter.api.BeforeEach;
@@ -51,7 +52,7 @@ public class MakeReservationComponentTest {
Long activeUserId = jdbcTemplate.queryForObject(
"SELECT id FROM user WHERE email = ?",
Long.class,
"john.doe@test.com");
UserTestData.johnDoeEmail());
BookReservationCommand reservationCommand =
BookReservationCommand.builder()

View File

@@ -0,0 +1,27 @@
package io.wkrzywiec.hexagonal.library.domain.borrowing.application;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.model.BorrowBookCommand;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.ports.incoming.BorrowBook;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Qualifier;
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("/borrow")
@RequiredArgsConstructor
public class BorrowBookController {
@Qualifier("BorrowBook")
private final BorrowBook borrowBook;
@PostMapping("")
public ResponseEntity<String> borrowBook(@RequestBody BorrowBookCommand borrowBookCommand){
borrowBook.handle(borrowBookCommand);
return new ResponseEntity<>("Book with an id " + borrowBookCommand.getBookId() + " was borrowed", HttpStatus.CREATED);
}
}

View File

@@ -4,6 +4,7 @@ import io.wkrzywiec.hexagonal.library.domain.borrowing.core.model.MakeBookAvaila
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.ports.incoming.MakeBookAvailable;
import io.wkrzywiec.hexagonal.library.domain.inventory.core.model.NewBookWasAddedEvent;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@@ -11,6 +12,7 @@ import org.springframework.stereotype.Component;
@Component
public class NewBookWasAddedEventHandler {
@Qualifier("MakeBookAvailable")
private final MakeBookAvailable makeBookAvailable;
@EventListener

View File

@@ -2,11 +2,13 @@ package io.wkrzywiec.hexagonal.library.domain.borrowing.application;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.ports.incoming.CancelOverdueReservations;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Scheduled;
@RequiredArgsConstructor
public class OverdueReservationScheduler {
@Qualifier("CancelOverdueReservations")
private final CancelOverdueReservations overdueReservations;
@Scheduled(fixedRate = 10 * 1000)

View File

@@ -3,6 +3,7 @@ package io.wkrzywiec.hexagonal.library.domain.borrowing.application;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.model.BookReservationCommand;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.ports.incoming.ReserveBook;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
@@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
public class ReservationController {
@Qualifier("ReserveBook")
private final ReserveBook reserveBook;
@PostMapping("")

View File

@@ -1,13 +1,18 @@
package io.wkrzywiec.hexagonal.library.infrastructure;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.BorrowingFacade;
import io.wkrzywiec.hexagonal.library.domain.borrowing.infrastructure.BorrowingDatabaseAdapter;
import io.wkrzywiec.hexagonal.library.domain.borrowing.infrastructure.SpringBorrowingEventPublisherAdapter;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.ports.incoming.BorrowBook;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.ports.incoming.CancelOverdueReservations;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.ports.incoming.MakeBookAvailable;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.ports.incoming.ReserveBook;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.ports.outgoing.BorrowingDatabase;
import io.wkrzywiec.hexagonal.library.domain.borrowing.core.ports.outgoing.BorrowingEventPublisher;
import io.wkrzywiec.hexagonal.library.domain.borrowing.infrastructure.BorrowingDatabaseAdapter;
import io.wkrzywiec.hexagonal.library.domain.borrowing.infrastructure.SpringBorrowingEventPublisherAdapter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
public class BorrowingDomainConfig {
@@ -23,7 +28,26 @@ public class BorrowingDomainConfig {
}
@Bean
@Qualifier("MakeBookAvailable")
public MakeBookAvailable makeBookAvailable(BorrowingDatabase database, BorrowingEventPublisher borrowingEventPublisher) {
return new BorrowingFacade(database, borrowingEventPublisher);
}
@Bean
@Qualifier("ReserveBook")
public ReserveBook reserveBook(BorrowingDatabase database, BorrowingEventPublisher borrowingEventPublisher){
return new BorrowingFacade(database, borrowingEventPublisher);
}
@Bean
@Qualifier("BorrowBook")
public BorrowBook borrowBook(BorrowingDatabase database, BorrowingEventPublisher borrowingEventPublisher){
return new BorrowingFacade(database, borrowingEventPublisher);
}
@Bean
@Qualifier("CancelOverdueReservations")
public CancelOverdueReservations cancelOverdueReservations(BorrowingDatabase database, BorrowingEventPublisher borrowingEventPublisher){
return new BorrowingFacade(database, borrowingEventPublisher);
}
}