mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-20 10:24:53 +00:00
deps: Refactor dependencies (#3224)
* remove spring dep move junit, logging, mockito under dep mgmt * upgrade anti-corruption-layer deps * async method invocation * balking, bloc * bridge to bytecode * caching * callback - cqrs * component - health check * hexagonal - metadata mapping * rest of the patterns * remove checkstyle, take spotless into use
This commit is contained in:
@@ -31,18 +31,18 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Transaction Script (TS) is one of the simplest domain logic pattern.
|
||||
* It needs less work to implement than other domain logic patterns, and therefore
|
||||
* it’s perfect fit for smaller applications that don't need big architecture behind them.
|
||||
* Transaction Script (TS) is one of the simplest domain logic pattern. It needs less work to
|
||||
* implement than other domain logic patterns, and therefore it’s perfect fit for smaller
|
||||
* applications that don't need big architecture behind them.
|
||||
*
|
||||
* <p>In this example we will use the TS pattern to implement booking and cancellation
|
||||
* methods for a Hotel management App. The main method will initialise an instance of
|
||||
* {@link Hotel} and add rooms to it. After that it will book and cancel a couple of rooms
|
||||
* and that will be printed by the logger.</p>
|
||||
* <p>In this example we will use the TS pattern to implement booking and cancellation methods for a
|
||||
* Hotel management App. The main method will initialise an instance of {@link Hotel} and add rooms
|
||||
* to it. After that it will book and cancel a couple of rooms and that will be printed by the
|
||||
* logger.
|
||||
*
|
||||
* <p>The thing we have to note here is that all the operations related to booking or cancelling
|
||||
* a room like checking the database if the room exists, checking the booking status or the
|
||||
* room, calculating refund price are all clubbed inside a single transaction script method.</p>
|
||||
* <p>The thing we have to note here is that all the operations related to booking or cancelling a
|
||||
* room like checking the database if the room exists, checking the booking status or the room,
|
||||
* calculating refund price are all clubbed inside a single transaction script method.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
@@ -50,9 +50,9 @@ public class App {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
||||
|
||||
/**
|
||||
* Program entry point.
|
||||
* Initialises an instance of Hotel and adds rooms to it.
|
||||
* Carries out booking and cancel booking transactions.
|
||||
* Program entry point. Initialises an instance of Hotel and adds rooms to it. Carries out booking
|
||||
* and cancel booking transactions.
|
||||
*
|
||||
* @param args command line arguments
|
||||
* @throws Exception if any error occurs
|
||||
*/
|
||||
@@ -87,7 +87,6 @@ public class App {
|
||||
getRoomStatus(dao);
|
||||
|
||||
deleteSchema(dataSource);
|
||||
|
||||
}
|
||||
|
||||
private static void getRoomStatus(HotelDaoImpl dao) throws Exception {
|
||||
@@ -98,14 +97,14 @@ public class App {
|
||||
|
||||
private static void deleteSchema(DataSource dataSource) throws java.sql.SQLException {
|
||||
try (var connection = dataSource.getConnection();
|
||||
var statement = connection.createStatement()) {
|
||||
var statement = connection.createStatement()) {
|
||||
statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL);
|
||||
}
|
||||
}
|
||||
|
||||
private static void createSchema(DataSource dataSource) throws Exception {
|
||||
try (var connection = dataSource.getConnection();
|
||||
var statement = connection.createStatement()) {
|
||||
var statement = connection.createStatement()) {
|
||||
statement.execute(RoomSchemaSql.CREATE_SCHEMA_SQL);
|
||||
} catch (Exception e) {
|
||||
throw new Exception(e.getMessage(), e);
|
||||
|
||||
@@ -26,9 +26,7 @@ package com.iluwatar.transactionscript;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Hotel class to implement TS pattern.
|
||||
*/
|
||||
/** Hotel class to implement TS pattern. */
|
||||
@Slf4j
|
||||
public class Hotel {
|
||||
|
||||
|
||||
@@ -27,9 +27,7 @@ package com.iluwatar.transactionscript;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* DAO interface for hotel transactions.
|
||||
*/
|
||||
/** DAO interface for hotel transactions. */
|
||||
public interface HotelDao {
|
||||
|
||||
Stream<Room> getAll() throws Exception;
|
||||
|
||||
@@ -36,9 +36,7 @@ import java.util.stream.StreamSupport;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Implementation of database operations for Hotel class.
|
||||
*/
|
||||
/** Implementation of database operations for Hotel class. */
|
||||
@Slf4j
|
||||
public class HotelDaoImpl implements HotelDao {
|
||||
|
||||
@@ -54,28 +52,31 @@ public class HotelDaoImpl implements HotelDao {
|
||||
var connection = getConnection();
|
||||
var statement = connection.prepareStatement("SELECT * FROM ROOMS"); // NOSONAR
|
||||
var resultSet = statement.executeQuery(); // NOSONAR
|
||||
return StreamSupport.stream(new Spliterators.AbstractSpliterator<Room>(Long.MAX_VALUE,
|
||||
Spliterator.ORDERED) {
|
||||
return StreamSupport.stream(
|
||||
new Spliterators.AbstractSpliterator<Room>(Long.MAX_VALUE, Spliterator.ORDERED) {
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(Consumer<? super Room> action) {
|
||||
try {
|
||||
if (!resultSet.next()) {
|
||||
return false;
|
||||
}
|
||||
action.accept(createRoom(resultSet));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e); // NOSONAR
|
||||
}
|
||||
}
|
||||
}, false).onClose(() -> {
|
||||
try {
|
||||
mutedClose(connection, statement, resultSet);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public boolean tryAdvance(Consumer<? super Room> action) {
|
||||
try {
|
||||
if (!resultSet.next()) {
|
||||
return false;
|
||||
}
|
||||
action.accept(createRoom(resultSet));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e); // NOSONAR
|
||||
}
|
||||
}
|
||||
},
|
||||
false)
|
||||
.onClose(
|
||||
() -> {
|
||||
try {
|
||||
mutedClose(connection, statement, resultSet);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new Exception(e.getMessage(), e);
|
||||
}
|
||||
@@ -86,7 +87,7 @@ public class HotelDaoImpl implements HotelDao {
|
||||
ResultSet resultSet = null;
|
||||
|
||||
try (var connection = getConnection();
|
||||
var statement = connection.prepareStatement("SELECT * FROM ROOMS WHERE ID = ?")) {
|
||||
var statement = connection.prepareStatement("SELECT * FROM ROOMS WHERE ID = ?")) {
|
||||
|
||||
statement.setInt(1, id);
|
||||
resultSet = statement.executeQuery();
|
||||
@@ -111,7 +112,7 @@ public class HotelDaoImpl implements HotelDao {
|
||||
}
|
||||
|
||||
try (var connection = getConnection();
|
||||
var statement = connection.prepareStatement("INSERT INTO ROOMS VALUES (?,?,?,?)")) {
|
||||
var statement = connection.prepareStatement("INSERT INTO ROOMS VALUES (?,?,?,?)")) {
|
||||
statement.setInt(1, room.getId());
|
||||
statement.setString(2, room.getRoomType());
|
||||
statement.setInt(3, room.getPrice());
|
||||
@@ -126,10 +127,9 @@ public class HotelDaoImpl implements HotelDao {
|
||||
@Override
|
||||
public Boolean update(Room room) throws Exception {
|
||||
try (var connection = getConnection();
|
||||
var statement =
|
||||
connection
|
||||
.prepareStatement("UPDATE ROOMS SET ROOM_TYPE = ?, PRICE = ?, BOOKED = ?"
|
||||
+ " WHERE ID = ?")) {
|
||||
var statement =
|
||||
connection.prepareStatement(
|
||||
"UPDATE ROOMS SET ROOM_TYPE = ?, PRICE = ?, BOOKED = ?" + " WHERE ID = ?")) {
|
||||
statement.setString(1, room.getRoomType());
|
||||
statement.setInt(2, room.getPrice());
|
||||
statement.setBoolean(3, room.isBooked());
|
||||
@@ -143,7 +143,7 @@ public class HotelDaoImpl implements HotelDao {
|
||||
@Override
|
||||
public Boolean delete(Room room) throws Exception {
|
||||
try (var connection = getConnection();
|
||||
var statement = connection.prepareStatement("DELETE FROM ROOMS WHERE ID = ?")) {
|
||||
var statement = connection.prepareStatement("DELETE FROM ROOMS WHERE ID = ?")) {
|
||||
statement.setInt(1, room.getId());
|
||||
return statement.executeUpdate() > 0;
|
||||
} catch (Exception e) {
|
||||
@@ -167,7 +167,8 @@ public class HotelDaoImpl implements HotelDao {
|
||||
}
|
||||
|
||||
private Room createRoom(ResultSet resultSet) throws Exception {
|
||||
return new Room(resultSet.getInt("ID"),
|
||||
return new Room(
|
||||
resultSet.getInt("ID"),
|
||||
resultSet.getString("ROOM_TYPE"),
|
||||
resultSet.getInt("PRICE"),
|
||||
resultSet.getBoolean("BOOKED"));
|
||||
|
||||
@@ -30,9 +30,7 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* A room POJO that represents the data that will be read from the data source.
|
||||
*/
|
||||
/** A room POJO that represents the data that will be read from the data source. */
|
||||
@Setter
|
||||
@Getter
|
||||
@ToString
|
||||
@@ -44,5 +42,4 @@ public class Room {
|
||||
private String roomType;
|
||||
private int price;
|
||||
private boolean booked;
|
||||
|
||||
}
|
||||
|
||||
@@ -24,16 +24,12 @@
|
||||
*/
|
||||
package com.iluwatar.transactionscript;
|
||||
|
||||
/**
|
||||
* Customer Schema SQL Class.
|
||||
*/
|
||||
/** Customer Schema SQL Class. */
|
||||
public final class RoomSchemaSql {
|
||||
|
||||
public static final String CREATE_SCHEMA_SQL =
|
||||
"CREATE TABLE ROOMS (ID NUMBER, ROOM_TYPE VARCHAR(100), PRICE INT, BOOKED VARCHAR(100))";
|
||||
public static final String DELETE_SCHEMA_SQL = "DROP TABLE ROOMS IF EXISTS";
|
||||
|
||||
private RoomSchemaSql() {
|
||||
}
|
||||
|
||||
private RoomSchemaSql() {}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,15 @@
|
||||
*/
|
||||
package com.iluwatar.transactionscript;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
/**
|
||||
* Tests that Transaction script example runs without errors.
|
||||
*/
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Tests that Transaction script example runs without errors. */
|
||||
class AppTest {
|
||||
|
||||
@Test
|
||||
void shouldExecuteWithoutException() {
|
||||
assertDoesNotThrow(() -> App.main(new String[]{}));
|
||||
assertDoesNotThrow(() -> App.main(new String[] {}));
|
||||
}
|
||||
}
|
||||
|
||||
+12
-17
@@ -44,9 +44,7 @@ import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
/**
|
||||
* Tests {@link HotelDaoImpl}.
|
||||
*/
|
||||
/** Tests {@link HotelDaoImpl}. */
|
||||
class HotelDaoImplTest {
|
||||
|
||||
private static final String DB_URL = "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1";
|
||||
@@ -61,15 +59,13 @@ class HotelDaoImplTest {
|
||||
@BeforeEach
|
||||
void createSchema() throws SQLException {
|
||||
try (var connection = DriverManager.getConnection(DB_URL);
|
||||
var statement = connection.createStatement()) {
|
||||
var statement = connection.createStatement()) {
|
||||
statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL);
|
||||
statement.execute(RoomSchemaSql.CREATE_SCHEMA_SQL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the scenario where DB connectivity is present.
|
||||
*/
|
||||
/** Represents the scenario where DB connectivity is present. */
|
||||
@Nested
|
||||
class ConnectionSuccess {
|
||||
|
||||
@@ -87,9 +83,7 @@ class HotelDaoImplTest {
|
||||
Assertions.assertTrue(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the scenario when DAO operations are being performed on a non-existing room.
|
||||
*/
|
||||
/** Represents the scenario when DAO operations are being performed on a non-existing room. */
|
||||
@Nested
|
||||
class NonExistingRoom {
|
||||
|
||||
@@ -135,8 +129,7 @@ class HotelDaoImplTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a scenario where DAO operations are being performed on an already existing
|
||||
* room.
|
||||
* Represents a scenario where DAO operations are being performed on an already existing room.
|
||||
*/
|
||||
@Nested
|
||||
class ExistingRoom {
|
||||
@@ -161,8 +154,8 @@ class HotelDaoImplTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void updationShouldBeSuccessAndAccessingTheSameRoomShouldReturnUpdatedInformation() throws
|
||||
Exception {
|
||||
void updationShouldBeSuccessAndAccessingTheSameRoomShouldReturnUpdatedInformation()
|
||||
throws Exception {
|
||||
final var newRoomType = "Double";
|
||||
final var newPrice = 80;
|
||||
final var newBookingStatus = false;
|
||||
@@ -222,7 +215,10 @@ class HotelDaoImplTest {
|
||||
final var newRoomType = "Double";
|
||||
final var newPrice = 80;
|
||||
final var newBookingStatus = false;
|
||||
assertThrows(Exception.class, () -> dao.update(new Room(existingRoom.getId(), newRoomType, newPrice, newBookingStatus)));
|
||||
assertThrows(
|
||||
Exception.class,
|
||||
() ->
|
||||
dao.update(new Room(existingRoom.getId(), newRoomType, newPrice, newBookingStatus)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -234,7 +230,6 @@ class HotelDaoImplTest {
|
||||
void retrievingAllRoomsFailsWithExceptionAsFeedbackToClient() {
|
||||
assertThrows(Exception.class, () -> dao.getAll());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -245,7 +240,7 @@ class HotelDaoImplTest {
|
||||
@AfterEach
|
||||
void deleteSchema() throws SQLException {
|
||||
try (var connection = DriverManager.getConnection(DB_URL);
|
||||
var statement = connection.createStatement()) {
|
||||
var statement = connection.createStatement()) {
|
||||
statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,9 +35,7 @@ import org.h2.jdbcx.JdbcDataSource;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link Hotel}
|
||||
*/
|
||||
/** Tests {@link Hotel} */
|
||||
class HotelTest {
|
||||
|
||||
private static final String H2_DB_URL = "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1";
|
||||
@@ -53,7 +51,6 @@ class HotelTest {
|
||||
dao = new HotelDaoImpl(dataSource);
|
||||
addRooms(dao);
|
||||
hotel = new Hotel(dao);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -68,7 +65,6 @@ class HotelTest {
|
||||
assertThrows(Exception.class, () -> hotel.bookRoom(getNonExistingRoomId()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
void bookingRoomAgainShouldRaiseException() {
|
||||
@@ -103,17 +99,16 @@ class HotelTest {
|
||||
assertThrows(Exception.class, () -> hotel.cancelRoomBooking(1));
|
||||
}
|
||||
|
||||
|
||||
private static void deleteSchema(DataSource dataSource) throws java.sql.SQLException {
|
||||
try (var connection = dataSource.getConnection();
|
||||
var statement = connection.createStatement()) {
|
||||
var statement = connection.createStatement()) {
|
||||
statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL);
|
||||
}
|
||||
}
|
||||
|
||||
private static void createSchema(DataSource dataSource) throws Exception {
|
||||
try (var connection = dataSource.getConnection();
|
||||
var statement = connection.createStatement()) {
|
||||
var statement = connection.createStatement()) {
|
||||
statement.execute(RoomSchemaSql.CREATE_SCHEMA_SQL);
|
||||
} catch (Exception e) {
|
||||
throw new Exception(e.getMessage(), e);
|
||||
@@ -150,4 +145,4 @@ class HotelTest {
|
||||
private int getNonExistingRoomId() {
|
||||
return 999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,7 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link Room}.
|
||||
*/
|
||||
/** Tests {@link Room}. */
|
||||
class RoomTest {
|
||||
|
||||
private Room room;
|
||||
@@ -90,7 +88,10 @@ class RoomTest {
|
||||
|
||||
@Test
|
||||
void testToString() {
|
||||
assertEquals(String.format("Room(id=%s, roomType=%s, price=%s, booked=%s)",
|
||||
room.getId(), room.getRoomType(), room.getPrice(), room.isBooked()), room.toString());
|
||||
assertEquals(
|
||||
String.format(
|
||||
"Room(id=%s, roomType=%s, price=%s, booked=%s)",
|
||||
room.getId(), room.getRoomType(), room.getPrice(), room.isBooked()),
|
||||
room.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user