From e899c5222f22a8593ba18f2a6f37376d376ee506 Mon Sep 17 00:00:00 2001 From: avp02 Date: Wed, 25 May 2022 15:53:16 +0300 Subject: [PATCH 1/9] create table model_specification in H2 database and filled it, and added Mongodb in README.md --- README.md | 7 +++++-- test-db/src/main/resources/create-tables.sql | 11 ++++++++++- test-db/src/main/resources/init-tables.sql | 5 +++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4e5d5ec..e151135 100644 --- a/README.md +++ b/README.md @@ -22,16 +22,19 @@ This is sample 'Motor depot' web application. - - **Data Access:** - [Spring JDBC](https://docs.spring.io/spring-framework/docs/5.3.x/reference/html/data-access.html#jdbc) spring +- [Spring Data MongoDB](https://spring.io/projects/spring-data-mongodb) + spring - **Build System:** [Maven](https://maven.apache.org/) - **Control System:** [Git](https://git-scm.com/) git - **License:** [Apache license, version 2.0](http://www.apache.org/licenses/LICENSE-2.0) - **Automated Testing:** - [JUnit5](https://junit.org/junit5/) - - [Mockito](http://site.mockito.org/) + - [Mockito](http://site.mockito.org/) - **Log:** [Log4j 2](https://logging.apache.org/log4j/2.x/) - **Database:** - - [H2](http://www.h2database.com/html/main.html) + - [H2](http://www.h2database.com/html/main.html) - [PostgreSQL](https://www.postgresql.org/) postgresql + - [MongoDB](https://www.mongodb.com/) - **API documentation generation:** - [Swagger UI](https://swagger.io/tools/swagger-ui/) - **Code generation:** diff --git a/test-db/src/main/resources/create-tables.sql b/test-db/src/main/resources/create-tables.sql index b46dd7d..6193c9c 100644 --- a/test-db/src/main/resources/create-tables.sql +++ b/test-db/src/main/resources/create-tables.sql @@ -1,5 +1,6 @@ DROP TABLE IF EXISTS car; DROP TABLE IF EXISTS driver; +DROP TABLE IF EXISTS model_specifications; CREATE TABLE driver ( driver_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -13,4 +14,12 @@ CREATE TABLE car ( model VARCHAR(20) NOT NULL, driver_id INT NOT NULL, CONSTRAINT car_driver_fk FOREIGN KEY (driver_id) REFERENCES driver(driver_id) -); \ No newline at end of file +); + +CREATE TABLE model_specifications ( + model_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + model_name VARCHAR(20) NOT NULL , + description VARCHAR(255) NOT NULL , + max_speed INT NOT NULL , + carrying_capacity INT NOT NULL +) \ No newline at end of file diff --git a/test-db/src/main/resources/init-tables.sql b/test-db/src/main/resources/init-tables.sql index 7ab72ef..172c4b1 100644 --- a/test-db/src/main/resources/init-tables.sql +++ b/test-db/src/main/resources/init-tables.sql @@ -6,3 +6,8 @@ INSERT INTO `car` (`car_id`, `model`, `driver_id`) VALUES (1, 'GAZ', 1), (3, 'LADA', 3), (4, 'GIGA', 1), (5, 'URAL', 3); +INSERT INTO `model_specifications` (`model_id`, `model_name`, `description`, `max_speed`, `carrying_capacity`) VALUES (1, 'GAZ', 'Truck: made in Russia', 90, 7500), + (2, 'ZIL', 'Truck: made in Russia', 80, 8500), + (3, 'LADA', 'Passenger car: made in Russia', 180, 1450), + (4, 'GIGA', 'Passenger car: made in Russia', 150, 1200), + (5, 'URAL', 'Truck: made in Russia', 80, 10400); From d5c8e350497b7be70034c3700b230438d343728b Mon Sep 17 00:00:00 2001 From: avp02 Date: Thu, 26 May 2022 15:07:58 +0300 Subject: [PATCH 2/9] added table model_specification in database H2, created ModelSpecification entity, and created DAo layer and tested it --- .../brest/dao_api/ModelSpecificationDao.java | 15 ++ .../brest/dao/ModelSpecificationDaoImpl.java | 53 +++++++ .../main/java/com/epam/brest/dao/Queries.java | 10 ++ .../dao/ModelSpecificationDaoImplTest.java | 74 ++++++++++ .../epam/brest/model/ModelSpecification.java | 138 ++++++++++++++++++ test-db/src/main/resources/create-tables.sql | 2 +- 6 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 dao-api/src/main/java/com/epam/brest/dao_api/ModelSpecificationDao.java create mode 100644 dao-jdbc/src/main/java/com/epam/brest/dao/ModelSpecificationDaoImpl.java create mode 100644 dao-jdbc/src/test/java/com/epam/brest/dao/ModelSpecificationDaoImplTest.java create mode 100644 model/src/main/java/com/epam/brest/model/ModelSpecification.java diff --git a/dao-api/src/main/java/com/epam/brest/dao_api/ModelSpecificationDao.java b/dao-api/src/main/java/com/epam/brest/dao_api/ModelSpecificationDao.java new file mode 100644 index 0000000..c983899 --- /dev/null +++ b/dao-api/src/main/java/com/epam/brest/dao_api/ModelSpecificationDao.java @@ -0,0 +1,15 @@ +package com.epam.brest.dao_api; + +import com.epam.brest.model.ModelSpecification; + +public interface ModelSpecificationDao { + + /** + * Getting car's model specification by model name. + * + * @param carModel String; + * @return ModelSpecification. + */ + + ModelSpecification getModelSpecificationByCarModel(String carModel); +} diff --git a/dao-jdbc/src/main/java/com/epam/brest/dao/ModelSpecificationDaoImpl.java b/dao-jdbc/src/main/java/com/epam/brest/dao/ModelSpecificationDaoImpl.java new file mode 100644 index 0000000..8ea4b50 --- /dev/null +++ b/dao-jdbc/src/main/java/com/epam/brest/dao/ModelSpecificationDaoImpl.java @@ -0,0 +1,53 @@ +package com.epam.brest.dao; + +import com.epam.brest.dao_api.ModelSpecificationDao; +import com.epam.brest.model.ModelSpecification; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.jdbc.core.BeanPropertyRowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.stereotype.Repository; + +import static com.epam.brest.dao.Queries.FIND_MODEL_SPECIFICATION_BY_CAR_MODEL; + +@Repository +public class ModelSpecificationDaoImpl implements ModelSpecificationDao { + + public static final Logger LOG = LogManager.getLogger(ModelSpecificationDaoImpl.class); + + /** + * Field namedParameterJdbcTemplate. + */ + + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; + + /** + * @Constructor + * + * @param namedParameterJdbcTemplate NamedParameterJdbcTemplate. + */ + + public ModelSpecificationDaoImpl(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { + this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; + } + + /** + * Getting car's model specification by model name. + * + * @param carModel String; + * @return instance of ModelSpecification. + */ + + @Override + public ModelSpecification getModelSpecificationByCarModel(String carModel) { + LOG.info("Method getModelSpecificationByCarModel() of class {} started", + getClass().getName()); + + SqlParameterSource sqlParameterSource = + new MapSqlParameterSource("modelName", carModel); + return namedParameterJdbcTemplate.queryForObject(FIND_MODEL_SPECIFICATION_BY_CAR_MODEL, + sqlParameterSource, BeanPropertyRowMapper.newInstance(ModelSpecification.class)); + } +} diff --git a/dao-jdbc/src/main/java/com/epam/brest/dao/Queries.java b/dao-jdbc/src/main/java/com/epam/brest/dao/Queries.java index 70e21d8..5c442f7 100644 --- a/dao-jdbc/src/main/java/com/epam/brest/dao/Queries.java +++ b/dao-jdbc/src/main/java/com/epam/brest/dao/Queries.java @@ -126,4 +126,14 @@ public class Queries { public static final String CARS_LIST_ASSIGN_TO_DRIVER = "SELECT * FROM car c WHERE c.driver_id = :driverId"; + + /** + * Field constant FIND_MODEL_SPECIFICATION_BY_CAR_MODEL. + */ + + public static final String FIND_MODEL_SPECIFICATION_BY_CAR_MODEL = + "SELECT ms.model_name AS modelName, ms.description AS description," + + " ms.max_speed AS maxSpeed, ms.carrying_capacity AS carryingCapacity" + + " FROM model_specifications AS ms WHERE ms.model_name=:modelName"; + } diff --git a/dao-jdbc/src/test/java/com/epam/brest/dao/ModelSpecificationDaoImplTest.java b/dao-jdbc/src/test/java/com/epam/brest/dao/ModelSpecificationDaoImplTest.java new file mode 100644 index 0000000..7227a13 --- /dev/null +++ b/dao-jdbc/src/test/java/com/epam/brest/dao/ModelSpecificationDaoImplTest.java @@ -0,0 +1,74 @@ +package com.epam.brest.dao; + +import com.epam.brest.model.ModelSpecification; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.*; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.jdbc.core.BeanPropertyRowMapper; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; + +import static com.epam.brest.dao.Queries.FIND_MODEL_SPECIFICATION_BY_CAR_MODEL; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class ModelSpecificationDaoImplTest { + + public static final Logger LOG = LogManager.getLogger(ModelSpecificationDaoImplTest.class); + + @InjectMocks + private ModelSpecificationDaoImpl modelSpecificationDao; + + @Mock + private NamedParameterJdbcTemplate namedParameterJdbcTemplate; + + @Captor + private ArgumentCaptor sqlParameterSourceArgumentCaptor; + + @Captor + private ArgumentCaptor> beanPropertyRowMapperArgumentCaptor; + + private ModelSpecification modelSpecification; + + + @BeforeEach + void setUp() { + modelSpecification = new ModelSpecification( + "NISSAN", "Passenger car: made in Japan", 200, 1870); + } + + @Test + void getModelSpecificationByCarModel() { + LOG.info("Method getModelSpecificationByCarModel() of class {} started", + getClass().getName()); + assertNotNull(namedParameterJdbcTemplate); + + lenient().when(namedParameterJdbcTemplate.queryForObject(anyString(), + ArgumentMatchers.any(), + any(BeanPropertyRowMapper.class))).thenReturn(modelSpecification); + + ModelSpecification modelSpecificationDst = modelSpecificationDao.getModelSpecificationByCarModel(modelSpecification.getModelName()); + + verify(namedParameterJdbcTemplate).queryForObject(eq(FIND_MODEL_SPECIFICATION_BY_CAR_MODEL), + sqlParameterSourceArgumentCaptor.capture(), beanPropertyRowMapperArgumentCaptor.capture()); + + BeanPropertyRowMapper rowMapper = beanPropertyRowMapperArgumentCaptor.getValue(); + SqlParameterSource sqlParameterSource = sqlParameterSourceArgumentCaptor.getValue(); + + assertNotNull(modelSpecificationDst); + assertNotNull(rowMapper); + assertNotNull(sqlParameterSource); + assertEquals(modelSpecificationDst, modelSpecification); + LOG.info("ModelSpecification was received after getModelSpecificationByCarModel() {} equals modelSpecification till it {}", + modelSpecificationDst, modelSpecification); + + } +} \ No newline at end of file diff --git a/model/src/main/java/com/epam/brest/model/ModelSpecification.java b/model/src/main/java/com/epam/brest/model/ModelSpecification.java new file mode 100644 index 0000000..831e6b4 --- /dev/null +++ b/model/src/main/java/com/epam/brest/model/ModelSpecification.java @@ -0,0 +1,138 @@ +package com.epam.brest.model; + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.util.Objects; + +@Schema(name = "model-specification", description = "Specification of car model") +public class ModelSpecification { + + /** + * @serialField modelId Integer. + */ + + @Schema(hidden = true) + private Integer modelId; + + /** + * @serialField modelName String. + */ + + @Schema(name = "modelName", description = "Car's model name", example = "NISSAN") + private String modelName; + + /** + * @serialField description String. + */ + + @Schema(name = "description", description = "Model's description", + example = "Passenger car: made in Japan") + private String description; + + /** + * @serialField maxSpeed Integer. + */ + + @Schema(name = "max-speed", description = "Model's max speed", example = "200") + private Integer maxSpeed; + + /** + * @serialField carryingCapacity Integer. + */ + + @Schema(name = "carrying-capacity", description = "Model's max carrying capacity", + example = "12000") + private Integer carryingCapacity; + + public ModelSpecification(Integer modelId, String modelName, String description, Integer maxSpeed, Integer carryingCapacity) { + this.modelId = modelId; + this.modelName = modelName; + this.description = description; + this.maxSpeed = maxSpeed; + this.carryingCapacity = carryingCapacity; + } + + public ModelSpecification() { + } + + /** + * @Constructor + * + * @param modelName String. + * @param description String. + * @param maxSpeed Integer. + * @param carryingCapacity Integer. + */ + + public ModelSpecification(final String modelName, final String description, + final Integer maxSpeed, final Integer carryingCapacity) { + this.modelName = modelName; + this.description = description; + this.maxSpeed = maxSpeed; + this.carryingCapacity = carryingCapacity; + } + + public Integer getModelId() { + return modelId; + } + + public void setModelId(Integer modelId) { + this.modelId = modelId; + } + + public String getModelName() { + return modelName; + } + + public void setModelName(String modelName) { + this.modelName = modelName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Integer getMaxSpeed() { + return maxSpeed; + } + + public void setMaxSpeed(Integer maxSpeed) { + this.maxSpeed = maxSpeed; + } + + public Integer getCarryingCapacity() { + return carryingCapacity; + } + + public void setCarryingCapacity(Integer carryingCapacity) { + this.carryingCapacity = carryingCapacity; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ModelSpecification that = (ModelSpecification) o; + return Objects.equals(modelId, that.modelId) && Objects.equals(modelName, that.modelName) && Objects.equals(description, that.description) && Objects.equals(maxSpeed, that.maxSpeed) && Objects.equals(carryingCapacity, that.carryingCapacity); + } + + @Override + public int hashCode() { + return Objects.hash(modelId, modelName, description, maxSpeed, carryingCapacity); + } + + @Override + public String toString() { + return "ModelSpecification{" + + "modelId=" + modelId + + ", modelName='" + modelName + '\'' + + ", description='" + description + '\'' + + ", maxSpeed=" + maxSpeed + + ", carryingCapacity=" + carryingCapacity + + '}'; + } +} diff --git a/test-db/src/main/resources/create-tables.sql b/test-db/src/main/resources/create-tables.sql index 6193c9c..274eac2 100644 --- a/test-db/src/main/resources/create-tables.sql +++ b/test-db/src/main/resources/create-tables.sql @@ -18,7 +18,7 @@ CREATE TABLE car ( CREATE TABLE model_specifications ( model_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - model_name VARCHAR(20) NOT NULL , + model_name VARCHAR(20) NOT NULL UNIQUE , description VARCHAR(255) NOT NULL , max_speed INT NOT NULL , carrying_capacity INT NOT NULL From b0f6200da6dfe341766ccb0abd313e93bdc2283f Mon Sep 17 00:00:00 2001 From: avp02 Date: Thu, 26 May 2022 23:05:00 +0300 Subject: [PATCH 3/9] created service layer and tested it --- .../dao/ModelSpecificationDaoImplTest.java | 1 - .../ModelSpecificationService.java | 15 +++++ .../impl/ModelSpecificationServiceImpl.java | 30 ++++++++++ .../ModelSpecificationServiceImplTest.java | 56 +++++++++++++++++++ 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 service-api/src/main/java/com/epam/brest/service_api/ModelSpecificationService.java create mode 100644 service/src/main/java/com/epam/brest/service/impl/ModelSpecificationServiceImpl.java create mode 100644 service/src/test/java/com/epam/brest/service/impl/ModelSpecificationServiceImplTest.java diff --git a/dao-jdbc/src/test/java/com/epam/brest/dao/ModelSpecificationDaoImplTest.java b/dao-jdbc/src/test/java/com/epam/brest/dao/ModelSpecificationDaoImplTest.java index 7227a13..f8ece63 100644 --- a/dao-jdbc/src/test/java/com/epam/brest/dao/ModelSpecificationDaoImplTest.java +++ b/dao-jdbc/src/test/java/com/epam/brest/dao/ModelSpecificationDaoImplTest.java @@ -69,6 +69,5 @@ void getModelSpecificationByCarModel() { assertEquals(modelSpecificationDst, modelSpecification); LOG.info("ModelSpecification was received after getModelSpecificationByCarModel() {} equals modelSpecification till it {}", modelSpecificationDst, modelSpecification); - } } \ No newline at end of file diff --git a/service-api/src/main/java/com/epam/brest/service_api/ModelSpecificationService.java b/service-api/src/main/java/com/epam/brest/service_api/ModelSpecificationService.java new file mode 100644 index 0000000..da5db94 --- /dev/null +++ b/service-api/src/main/java/com/epam/brest/service_api/ModelSpecificationService.java @@ -0,0 +1,15 @@ +package com.epam.brest.service_api; + +import com.epam.brest.model.ModelSpecification; + +public interface ModelSpecificationService { + + /** + * Getting car's model specification by model name. + * + * @param carModel String; + * @return ModelSpecification. + */ + + ModelSpecification getModelSpecificationByCarModel(String carModel); +} diff --git a/service/src/main/java/com/epam/brest/service/impl/ModelSpecificationServiceImpl.java b/service/src/main/java/com/epam/brest/service/impl/ModelSpecificationServiceImpl.java new file mode 100644 index 0000000..a315b2c --- /dev/null +++ b/service/src/main/java/com/epam/brest/service/impl/ModelSpecificationServiceImpl.java @@ -0,0 +1,30 @@ +package com.epam.brest.service.impl; + +import com.epam.brest.dao_api.ModelSpecificationDao; +import com.epam.brest.model.ModelSpecification; +import com.epam.brest.service_api.ModelSpecificationService; +import org.springframework.stereotype.Service; + +@Service +public class ModelSpecificationServiceImpl implements ModelSpecificationService { + + /** + * @Field modelSpecificationDao ModelSpecificationDao. + */ + + private final ModelSpecificationDao modelSpecificationDao; + + /** + * @Constructor + * @param modelSpecificationDao ModelSpecificationDao. + */ + + public ModelSpecificationServiceImpl(ModelSpecificationDao modelSpecificationDao) { + this.modelSpecificationDao = modelSpecificationDao; + } + + @Override + public ModelSpecification getModelSpecificationByCarModel(String carModel) { + return modelSpecificationDao.getModelSpecificationByCarModel(carModel); + } +} diff --git a/service/src/test/java/com/epam/brest/service/impl/ModelSpecificationServiceImplTest.java b/service/src/test/java/com/epam/brest/service/impl/ModelSpecificationServiceImplTest.java new file mode 100644 index 0000000..6b8a33e --- /dev/null +++ b/service/src/test/java/com/epam/brest/service/impl/ModelSpecificationServiceImplTest.java @@ -0,0 +1,56 @@ +package com.epam.brest.service.impl; + +import com.epam.brest.dao_api.ModelSpecificationDao; +import com.epam.brest.model.ModelSpecification; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class ModelSpecificationServiceImplTest { + + private static final Logger LOG = LogManager.getLogger(ModelSpecificationServiceImplTest.class); + + @InjectMocks + private ModelSpecificationServiceImpl modelSpecificationService; + + @Mock + private ModelSpecificationDao modelSpecificationDao; + + private ModelSpecification modelSpecification; + + @BeforeEach + void setUp() { + modelSpecification = new ModelSpecification( + "NISSAN", "Passenger car: made in Japan", 200, 1870); + } + + @Test + void getModelSpecificationByCarModel() { + LOG.info("Method getModelSpecificationByCarModel() of class {} started", getClass().getName()); + + lenient().when(modelSpecificationDao.getModelSpecificationByCarModel(anyString())) + .thenReturn(modelSpecification); + + ModelSpecification modelSpecificationDst = modelSpecificationService + .getModelSpecificationByCarModel(modelSpecification.getModelName()); + + verify(modelSpecificationDao, times(1)) + .getModelSpecificationByCarModel(eq(modelSpecification.getModelName())); + + assertNotNull(modelSpecificationDst); + assertEquals(modelSpecification, modelSpecificationDst); + LOG.info("ModelSpecification was received after getModelSpecificationByCarModel() {} equals modelSpecification till it {}", + modelSpecificationDst, modelSpecification); + } +} \ No newline at end of file From bf9864891f07fc4c2e21ba4a6eef3580dfc5c52e Mon Sep 17 00:00:00 2001 From: avp02 Date: Fri, 27 May 2022 19:15:00 +0300 Subject: [PATCH 4/9] created rest layer and tested it --- .../main/java/com/epam/brest/dao/Queries.java | 2 +- .../epam/brest/model/ModelSpecification.java | 4 +- .../brest/rest/config/SpringFoxConfig.java | 3 +- .../rest/controller/DriverController.java | 2 +- .../ModelSpecificationController.java | 69 +++++++++++++ .../ModelSpecificationControllerIT.java | 98 +++++++++++++++++++ .../impl/ModelSpecificationServiceImpl.java | 2 + 7 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java create mode 100644 rest-app/src/test/java/com/epam/brest/rest/controller/ModelSpecificationControllerIT.java diff --git a/dao-jdbc/src/main/java/com/epam/brest/dao/Queries.java b/dao-jdbc/src/main/java/com/epam/brest/dao/Queries.java index 5c442f7..294553f 100644 --- a/dao-jdbc/src/main/java/com/epam/brest/dao/Queries.java +++ b/dao-jdbc/src/main/java/com/epam/brest/dao/Queries.java @@ -132,7 +132,7 @@ public class Queries { */ public static final String FIND_MODEL_SPECIFICATION_BY_CAR_MODEL = - "SELECT ms.model_name AS modelName, ms.description AS description," + "SELECT ms.model_id AS modelId, ms.model_name AS modelName, ms.description AS description," + " ms.max_speed AS maxSpeed, ms.carrying_capacity AS carryingCapacity" + " FROM model_specifications AS ms WHERE ms.model_name=:modelName"; diff --git a/model/src/main/java/com/epam/brest/model/ModelSpecification.java b/model/src/main/java/com/epam/brest/model/ModelSpecification.java index 831e6b4..ba490d8 100644 --- a/model/src/main/java/com/epam/brest/model/ModelSpecification.java +++ b/model/src/main/java/com/epam/brest/model/ModelSpecification.java @@ -44,7 +44,9 @@ public class ModelSpecification { example = "12000") private Integer carryingCapacity; - public ModelSpecification(Integer modelId, String modelName, String description, Integer maxSpeed, Integer carryingCapacity) { + public ModelSpecification(final Integer modelId, final String modelName, + final String description, final Integer maxSpeed, + final Integer carryingCapacity) { this.modelId = modelId; this.modelName = modelName; this.description = description; diff --git a/rest-app/src/main/java/com/epam/brest/rest/config/SpringFoxConfig.java b/rest-app/src/main/java/com/epam/brest/rest/config/SpringFoxConfig.java index 18249a3..333663b 100644 --- a/rest-app/src/main/java/com/epam/brest/rest/config/SpringFoxConfig.java +++ b/rest-app/src/main/java/com/epam/brest/rest/config/SpringFoxConfig.java @@ -16,8 +16,9 @@ public class SpringFoxConfig { /** + * @Bean configure swagger openApi. + * * @return Docket class. - * @bean configure swagger openApi. */ @Bean diff --git a/rest-app/src/main/java/com/epam/brest/rest/controller/DriverController.java b/rest-app/src/main/java/com/epam/brest/rest/controller/DriverController.java index ec8d9fa..20fb7ac 100644 --- a/rest-app/src/main/java/com/epam/brest/rest/controller/DriverController.java +++ b/rest-app/src/main/java/com/epam/brest/rest/controller/DriverController.java @@ -51,7 +51,7 @@ public DriverController( @Operation(summary = "Allows to get list of all drivers") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Driver's list was provide", + @ApiResponse(responseCode = "200", description = "Driver's list was provided", content = {@Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = Driver.class)))}), @ApiResponse(responseCode = "404", description = diff --git a/rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java b/rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java new file mode 100644 index 0000000..0849bc0 --- /dev/null +++ b/rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java @@ -0,0 +1,69 @@ +package com.epam.brest.rest.controller; + +import com.epam.brest.model.ModelSpecification; +import com.epam.brest.service_api.ModelSpecificationService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@CrossOrigin +@Tag(name = "model-specification-controller", description = "Allows to get description of model specification") +public class ModelSpecificationController { + + public static final Logger LOG = LogManager.getLogger(ModelSpecificationController.class); + + /** + * @Field modelSpecificationService ModelSpecificationService. + */ + + private final ModelSpecificationService modelSpecificationService; + + /** + * @Constructor + * + * @param modelSpecificationService ModelSpecificationService. + */ + + public ModelSpecificationController(ModelSpecificationService modelSpecificationService) { + this.modelSpecificationService = modelSpecificationService; + } + + @Operation(summary = "Allows to get car's specification by its model") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Specification was provided", + content = {@Content(mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = ModelSpecification.class)))}), + @ApiResponse(responseCode = "404", description = + "Trying to get a non-existent model", + content = @Content), + @ApiResponse(responseCode = "500", description = + "Something is wrong! We'll sort this out soon.", + content = @Content)}) + @GetMapping("/model_info/{model}") + public ResponseEntity getModelSpecificationByCarModel( + @PathVariable("model") @Parameter(description = "Car's model", + example = "URAL") final String carModel) { + + LOG.info("Method getModelSpecificationByCarModel() with car's model {} started of class {}", + carModel, getClass().getName()); + + ModelSpecification modelSpecification = + modelSpecificationService.getModelSpecificationByCarModel(carModel); + + return new ResponseEntity<>(modelSpecification, HttpStatus.OK); + } +} diff --git a/rest-app/src/test/java/com/epam/brest/rest/controller/ModelSpecificationControllerIT.java b/rest-app/src/test/java/com/epam/brest/rest/controller/ModelSpecificationControllerIT.java new file mode 100644 index 0000000..ae591a9 --- /dev/null +++ b/rest-app/src/test/java/com/epam/brest/rest/controller/ModelSpecificationControllerIT.java @@ -0,0 +1,98 @@ +package com.epam.brest.rest.controller; + +import com.epam.brest.model.Driver; +import com.epam.brest.model.ModelSpecification; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Profile; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +import static com.epam.brest.model.constant.DriverConstants.DRIVER_NAME_SIZE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@ExtendWith(SpringExtension.class) +@AutoConfigureMockMvc +@Transactional +@Profile("dev, test") +class ModelSpecificationControllerIT { + + public static final Logger LOG = LogManager.getLogger(ModelSpecificationControllerIT.class); + + public static final String MODEL_ENDPOINT = "/model_info"; + + @Autowired + private ModelSpecificationController modelSpecificationController; + + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + MockMvcModelSpecificationService modelSpecificationService = new MockMvcModelSpecificationService(); + + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.standaloneSetup(modelSpecificationController) + .setMessageConverters(new MappingJackson2HttpMessageConverter()) +// .setControllerAdvice(customExceptionHandler) + .alwaysDo(MockMvcResultHandlers.print()) + .build(); + } + + @Test + void getModelSpecificationByCarModelTest() throws Exception { + LOG.info("Method getModelSpecificationByCarModelTest() started of class {}", getClass().getName()); + + // I should make CRUD operations for this test!!!!!!!! +// //given +// ModelSpecification specificationSrc = new ModelSpecification( +// "URAL", "Passenger car: made in Japan", 200, 1870); +// assertNotNull(specificationSrc); +//// Integer id = driverService.saveDriver(driver); +// String carModel = specificationSrc.getModelName(); +// assertNotNull(carModel); +// // when +// ModelSpecification specificationDst = modelSpecificationService.getSpecificationByModelName(carModel); +// // then +// assertNotNull(specificationDst); +// assertEquals(specificationDst.getModelName(), carModel); +// assertEquals(specificationSrc.getModelName(), specificationDst.getModelName()); + } + + class MockMvcModelSpecificationService { + + public ModelSpecification getSpecificationByModelName(final String carModel) throws Exception { + LOG.info("Method getSpecificationByModelName() with car's model: {} started of class {}", carModel, getClass().getName()); + + MockHttpServletResponse response = mockMvc.perform( + MockMvcRequestBuilders.get(MODEL_ENDPOINT + "/" + carModel) + .accept(MediaType.APPLICATION_JSON) + ).andExpect(status().isOk()) + .andReturn().getResponse(); + assertNotNull(response); + return objectMapper.readValue(response.getContentAsString(), ModelSpecification.class); + } + } +} \ No newline at end of file diff --git a/service/src/main/java/com/epam/brest/service/impl/ModelSpecificationServiceImpl.java b/service/src/main/java/com/epam/brest/service/impl/ModelSpecificationServiceImpl.java index a315b2c..23a3d56 100644 --- a/service/src/main/java/com/epam/brest/service/impl/ModelSpecificationServiceImpl.java +++ b/service/src/main/java/com/epam/brest/service/impl/ModelSpecificationServiceImpl.java @@ -4,6 +4,7 @@ import com.epam.brest.model.ModelSpecification; import com.epam.brest.service_api.ModelSpecificationService; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service public class ModelSpecificationServiceImpl implements ModelSpecificationService { @@ -23,6 +24,7 @@ public ModelSpecificationServiceImpl(ModelSpecificationDao modelSpecificationDao this.modelSpecificationDao = modelSpecificationDao; } + @Transactional(readOnly = true) @Override public ModelSpecification getModelSpecificationByCarModel(String carModel) { return modelSpecificationDao.getModelSpecificationByCarModel(carModel); From f6001bf67eee0f0a0c4cf6eca80f3bdb1222eda0 Mon Sep 17 00:00:00 2001 From: avp02 Date: Fri, 27 May 2022 19:41:36 +0300 Subject: [PATCH 5/9] created restService layer and tested it --- .../epam/brest/model/ModelSpecification.java | 10 +++ .../ModelSpecificationServiceRest.java | 62 ++++++++++++++ .../ModelSpecificationServiceRestTest.java | 80 +++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 service-rest/src/main/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRest.java create mode 100644 service-rest/src/test/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRestTest.java diff --git a/model/src/main/java/com/epam/brest/model/ModelSpecification.java b/model/src/main/java/com/epam/brest/model/ModelSpecification.java index ba490d8..cef2a2b 100644 --- a/model/src/main/java/com/epam/brest/model/ModelSpecification.java +++ b/model/src/main/java/com/epam/brest/model/ModelSpecification.java @@ -44,6 +44,16 @@ public class ModelSpecification { example = "12000") private Integer carryingCapacity; + /** + * @Constructor + * + * @param modelId Integer. + * @param modelName String. + * @param description String. + * @param maxSpeed Integer. + * @param carryingCapacity Integer. + */ + public ModelSpecification(final Integer modelId, final String modelName, final String description, final Integer maxSpeed, final Integer carryingCapacity) { diff --git a/service-rest/src/main/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRest.java b/service-rest/src/main/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRest.java new file mode 100644 index 0000000..f6d57ab --- /dev/null +++ b/service-rest/src/main/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRest.java @@ -0,0 +1,62 @@ +package com.epam.brest.service_rest.service; + +import com.epam.brest.model.ModelSpecification; +import com.epam.brest.service_api.ModelSpecificationService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Service +public class ModelSpecificationServiceRest implements ModelSpecificationService { + + public static final Logger LOG = LogManager.getLogger( + DriverServiceRest.class); + + /** + * Field url String. + */ + + private String url; + + /** + * Field restTemplate RestTemplate. + */ + + private RestTemplate restTemplate; + + /** + * Constructor without parameters. + */ + + public ModelSpecificationServiceRest() { + } + + /** + * @Constructor + * + * @param url String. + * @param restTemplate RestTemplate. + */ + + public ModelSpecificationServiceRest(final String url, + final RestTemplate restTemplate) { + this.url = url; + this.restTemplate = restTemplate; + } + + @Override + public ModelSpecification getModelSpecificationByCarModel(String carModel) { + LOG.info("Method getModelSpecificationByCarModel() with parameter {} started {}", + carModel, getClass().getName()); + ParameterizedTypeReference typeReference = + new ParameterizedTypeReference<>() {}; + + ResponseEntity responseEntity = restTemplate + .exchange(url + "/" + carModel, HttpMethod.GET, null, typeReference); + return responseEntity.getBody(); + } +} diff --git a/service-rest/src/test/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRestTest.java b/service-rest/src/test/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRestTest.java new file mode 100644 index 0000000..a82d0e6 --- /dev/null +++ b/service-rest/src/test/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRestTest.java @@ -0,0 +1,80 @@ +package com.epam.brest.service_rest.service; + +import com.epam.brest.model.ModelSpecification; +import com.epam.brest.service_rest.service.config.ServiceRestTestConfig; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.client.ExpectedCount; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.web.client.RestTemplate; + +import java.net.URI; +import java.net.URISyntaxException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; + +@ExtendWith(SpringExtension.class) +@Import({ServiceRestTestConfig.class}) +class ModelSpecificationServiceRestTest { + + public static final Logger LOG = LogManager.getLogger( + ModelSpecificationServiceRestTest.class); + + public static final String MODEL_INFO_URL = "http://localhost:8088/model_info"; + + @Autowired + private RestTemplate restTemplate; + + private ModelSpecificationServiceRest modelSpecificationServiceRest; + + private MockRestServiceServer mockRestServiceServer; + + private ObjectMapper objectMapper; + + @BeforeEach + void setUp() { + modelSpecificationServiceRest = new ModelSpecificationServiceRest(MODEL_INFO_URL, restTemplate); + mockRestServiceServer = MockRestServiceServer.createServer(restTemplate); + objectMapper = new ObjectMapper().findAndRegisterModules(); + } + + @Test + void getModelSpecificationByCarModel() throws URISyntaxException, JsonProcessingException { + LOG.info("Method getModelSpecificationByCarModel() started {}", + getClass().getName()); + // given + String carModel = "NISSAN"; + ModelSpecification modelSpecification = new ModelSpecification( + 1, carModel, "Passenger car: made in Japan", + 210, 1740); + + mockRestServiceServer.expect(ExpectedCount.once(), requestTo(new URI(MODEL_INFO_URL + "/" + carModel))) + .andExpect(method(HttpMethod.GET)) + .andRespond(withStatus(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(objectMapper.writeValueAsString(modelSpecification)) + ); + // when + ModelSpecification modelSpecificationDst = modelSpecificationServiceRest.getModelSpecificationByCarModel(carModel); + // then + mockRestServiceServer.verify(); + assertNotNull(modelSpecificationDst); + assertEquals(modelSpecificationDst.getModelName(), carModel); + assertEquals(modelSpecificationDst.getModelId(), modelSpecification.getModelId()); + } +} \ No newline at end of file From f10d33a46fae6020c71fd66abe81ffb69f2acb57 Mon Sep 17 00:00:00 2001 From: avp02 Date: Fri, 27 May 2022 23:30:17 +0300 Subject: [PATCH 6/9] created web layer and tested it --- .../epam/brest/model/ModelSpecification.java | 10 +- .../ModelSpecificationController.java | 3 +- .../ModelSpecificationController.java | 52 ++++++++++ .../brest/controller/config/WebMvcConfig.java | 14 +++ .../ModelSpecificationControllerTest.java | 99 +++++++++++++++++++ 5 files changed, 174 insertions(+), 4 deletions(-) create mode 100644 web-app/src/main/java/com/epam/brest/controller/ModelSpecificationController.java create mode 100644 web-app/src/test/java/com/epam/brest/controller/ModelSpecificationControllerTest.java diff --git a/model/src/main/java/com/epam/brest/model/ModelSpecification.java b/model/src/main/java/com/epam/brest/model/ModelSpecification.java index cef2a2b..29bdec5 100644 --- a/model/src/main/java/com/epam/brest/model/ModelSpecification.java +++ b/model/src/main/java/com/epam/brest/model/ModelSpecification.java @@ -44,6 +44,13 @@ public class ModelSpecification { example = "12000") private Integer carryingCapacity; + /** + * @Constructor without parameters. + */ + + public ModelSpecification() { + } + /** * @Constructor * @@ -64,9 +71,6 @@ public ModelSpecification(final Integer modelId, final String modelName, this.carryingCapacity = carryingCapacity; } - public ModelSpecification() { - } - /** * @Constructor * diff --git a/rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java b/rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java index 0849bc0..c2e359b 100644 --- a/rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java +++ b/rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java @@ -38,7 +38,8 @@ public class ModelSpecificationController { * @param modelSpecificationService ModelSpecificationService. */ - public ModelSpecificationController(ModelSpecificationService modelSpecificationService) { + public ModelSpecificationController( + final ModelSpecificationService modelSpecificationService) { this.modelSpecificationService = modelSpecificationService; } diff --git a/web-app/src/main/java/com/epam/brest/controller/ModelSpecificationController.java b/web-app/src/main/java/com/epam/brest/controller/ModelSpecificationController.java new file mode 100644 index 0000000..8ae2492 --- /dev/null +++ b/web-app/src/main/java/com/epam/brest/controller/ModelSpecificationController.java @@ -0,0 +1,52 @@ +package com.epam.brest.controller; + +import com.epam.brest.service_api.ModelSpecificationService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +@Controller +public class ModelSpecificationController { + + public static final Logger LOG = LogManager.getLogger( + ModelSpecificationController.class); + + /** + * @Field modelSpecificationService ModelSpecificationService. + */ + + private final ModelSpecificationService modelSpecificationService; + + /** + * @Constructor + * @param modelSpecificationService ModelSpecificationService + */ + + public ModelSpecificationController( + final ModelSpecificationService modelSpecificationService) { + this.modelSpecificationService = modelSpecificationService; + } + + /** + * Get specification of car by it name. + * + * @param carModel String. + * @param model Model. + * @return view String. + */ + + @GetMapping("/model_info/{model}") + public String getModelSpecificationByCarName( + @PathVariable("model") final String carModel, final Model model) { + LOG.info("Method getModelSpecificationByCarName() started in class {}", + getClass().getName()); + + model.addAttribute("specification", + modelSpecificationService.getModelSpecificationByCarModel(carModel)); + + return "cars/cars"; + } +} diff --git a/web-app/src/main/java/com/epam/brest/controller/config/WebMvcConfig.java b/web-app/src/main/java/com/epam/brest/controller/config/WebMvcConfig.java index 6bf74b5..a89b838 100644 --- a/web-app/src/main/java/com/epam/brest/controller/config/WebMvcConfig.java +++ b/web-app/src/main/java/com/epam/brest/controller/config/WebMvcConfig.java @@ -3,9 +3,11 @@ import com.epam.brest.mongodb_postgresql.service.DriverDtoMongodbService; import com.epam.brest.service_api.CarService; import com.epam.brest.service_api.DriverService; +import com.epam.brest.service_api.ModelSpecificationService; import com.epam.brest.service_api.dto.DriverDtoService; import com.epam.brest.service_rest.service.CarServiceRest; import com.epam.brest.service_rest.service.DriverServiceRest; +import com.epam.brest.service_rest.service.ModelSpecificationServiceRest; import com.epam.brest.service_rest.service.dto.DriverDtoMongodbServiceRest; import com.epam.brest.service_rest.service.dto.DriverDtoServiceRest; import org.springframework.beans.factory.annotation.Value; @@ -98,4 +100,16 @@ DriverDtoMongodbService driverDtoMongodbService() { String url = String.format("%s://%s:%d/mongo", protocol, host, port); return new DriverDtoMongodbServiceRest(url, restTemplate()); } + + /** + * ModelSpecificationService's bean. + * + * @return modelSpecificationService ModelSpecificationService. + */ + + @Bean + ModelSpecificationService modelSpecificationService() { + String url = String.format("%s://%s:%d/model_info", protocol, host, port); + return new ModelSpecificationServiceRest(url, restTemplate()); + } } diff --git a/web-app/src/test/java/com/epam/brest/controller/ModelSpecificationControllerTest.java b/web-app/src/test/java/com/epam/brest/controller/ModelSpecificationControllerTest.java new file mode 100644 index 0000000..d20eb40 --- /dev/null +++ b/web-app/src/test/java/com/epam/brest/controller/ModelSpecificationControllerTest.java @@ -0,0 +1,99 @@ +package com.epam.brest.controller; + +import com.epam.brest.model.Driver; +import com.epam.brest.model.ModelSpecification; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.test.web.client.ExpectedCount; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.context.WebApplicationContext; + +import java.math.BigDecimal; +import java.net.URI; +import java.net.URISyntaxException; +import java.time.Instant; + +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@SpringBootTest +class ModelSpecificationControllerTest { + + public static final Logger LOG = LogManager.getLogger(ModelSpecificationControllerTest.class); + + public static final String MODEL_INFO_URL = "http://localhost:8088/model_info"; + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Autowired + private RestTemplate restTemplate; + + private MockRestServiceServer mockRestServiceServer; + + @Autowired + private ObjectMapper objectMapper; + + @BeforeEach + void setUp() { + restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + mockRestServiceServer = MockRestServiceServer.createServer(restTemplate); + } + + @Test + void shouldGetModelSpecificationByCarName() throws Exception { + LOG.info("Method shouldGetModelSpecificationByCarName() started {}", + getClass().getName()); + + ModelSpecification modelSpecificationSrs = new ModelSpecification(1, "VOLVO", + "Truck: made in China", 150, 25000); + + mockRestServiceServer.expect(ExpectedCount.once(), requestTo(new URI(MODEL_INFO_URL + "/" + modelSpecificationSrs.getModelName()))) + .andExpect(method(HttpMethod.GET)) + .andRespond(withStatus(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(objectMapper.writeValueAsString(modelSpecificationSrs)) + ); + + mockMvc.perform( + MockMvcRequestBuilders.get("/model_info/" + modelSpecificationSrs.getModelName()) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .param("modelId", String.valueOf(modelSpecificationSrs.getModelId())) + .param("modelName", modelSpecificationSrs.getModelName()) + .param("description", modelSpecificationSrs.getDescription()) + .param("maxSpeed", String.valueOf(modelSpecificationSrs.getMaxSpeed())) + .param("carryingCapacity", String.valueOf(modelSpecificationSrs.getCarryingCapacity())) + ).andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) +// .andExpect(model().attribute("model", hasProperty("modelId", is(1)))) +// .andExpect(model().attribute("model", hasProperty("modelName", is("VOLVO")))) +// .andExpect(model().attribute("model", hasProperty("description", is("Truck: made in China")))) +// .andExpect(model().attribute("model", hasProperty("maxSpeed", is(150)))) +// .andExpect(model().attribute("model", hasProperty("carryingCapacity", is(25000)))) + .andExpect(view().name("cars/cars")); + mockRestServiceServer.verify(); + } +} \ No newline at end of file From 133b1273b8cd0b69f0ef6fbfc95963a5cbc63fa4 Mon Sep 17 00:00:00 2001 From: avp02 Date: Tue, 31 May 2022 11:48:41 +0300 Subject: [PATCH 7/9] changed model button delete --- rest-app/pom.xml | 5 +++++ web-app/src/main/resources/templates/cars/cars.html | 2 +- web-app/src/main/resources/templates/drivers/drivers.html | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/rest-app/pom.xml b/rest-app/pom.xml index 4043976..42867b4 100644 --- a/rest-app/pom.xml +++ b/rest-app/pom.xml @@ -33,6 +33,11 @@ org.springframework.boot spring-boot-starter-validation + + com.google.guava + guava + 31.1-jre + org.springframework.boot diff --git a/web-app/src/main/resources/templates/cars/cars.html b/web-app/src/main/resources/templates/cars/cars.html index c078698..a2fa283 100644 --- a/web-app/src/main/resources/templates/cars/cars.html +++ b/web-app/src/main/resources/templates/cars/cars.html @@ -114,7 +114,7 @@ Please confirm delete diff --git a/web-app/src/main/resources/templates/drivers/drivers.html b/web-app/src/main/resources/templates/drivers/drivers.html index a2ac2bf..2876a57 100644 --- a/web-app/src/main/resources/templates/drivers/drivers.html +++ b/web-app/src/main/resources/templates/drivers/drivers.html @@ -150,7 +150,7 @@ Please confirm delete From 8ca893fcb4049cf0bdd1412b0100099c8ae57574 Mon Sep 17 00:00:00 2001 From: avp02 Date: Thu, 2 Jun 2022 11:53:40 +0300 Subject: [PATCH 8/9] added modal window in cars.html for modelCar --- .../ModelSpecificationController.java | 21 ++++++-- .../ModelSpecificationService.java | 2 +- .../ModelSpecificationServiceRest.java | 23 +++++--- .../ModelSpecificationServiceRestTest.java | 2 +- .../main/resources/templates/cars/cars.html | 52 +++++++++++++++++-- .../resources/templates/drivers/drivers.html | 1 + .../ModelSpecificationControllerTest.java | 22 +++----- 7 files changed, 89 insertions(+), 34 deletions(-) diff --git a/rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java b/rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java index c2e359b..5242ec6 100644 --- a/rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java +++ b/rest-app/src/main/java/com/epam/brest/rest/controller/ModelSpecificationController.java @@ -1,6 +1,7 @@ package com.epam.brest.rest.controller; import com.epam.brest.model.ModelSpecification; +import com.epam.brest.rest.config.CacheModelSpecificationWithGuavaConfig; import com.epam.brest.service_api.ModelSpecificationService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -33,14 +34,23 @@ public class ModelSpecificationController { private final ModelSpecificationService modelSpecificationService; /** - * @Constructor - * + * @Field cacheModelSpecification CacheModelSpecificationWithGuavaConfig. + */ + + private final CacheModelSpecificationWithGuavaConfig cacheModelSpecification; + + /** * @param modelSpecificationService ModelSpecificationService. + * @param cacheModelSpecification CacheModelSpecificationWithGuavaConfig. + * @Constructor */ public ModelSpecificationController( - final ModelSpecificationService modelSpecificationService) { + final ModelSpecificationService modelSpecificationService, + final CacheModelSpecificationWithGuavaConfig cacheModelSpecification) { this.modelSpecificationService = modelSpecificationService; + this.cacheModelSpecification = cacheModelSpecification; + } @Operation(summary = "Allows to get car's specification by its model") @@ -54,7 +64,7 @@ public ModelSpecificationController( @ApiResponse(responseCode = "500", description = "Something is wrong! We'll sort this out soon.", content = @Content)}) - @GetMapping("/model_info/{model}") + @GetMapping(value = "/model_info/{model}") public ResponseEntity getModelSpecificationByCarModel( @PathVariable("model") @Parameter(description = "Car's model", example = "URAL") final String carModel) { @@ -62,9 +72,12 @@ public ResponseEntity getModelSpecificationByCarModel( LOG.info("Method getModelSpecificationByCarModel() with car's model {} started of class {}", carModel, getClass().getName()); + ModelSpecification modelSpecification = modelSpecificationService.getModelSpecificationByCarModel(carModel); + cacheModelSpecification.cacheRun(carModel); + return new ResponseEntity<>(modelSpecification, HttpStatus.OK); } } diff --git a/service-api/src/main/java/com/epam/brest/service_api/ModelSpecificationService.java b/service-api/src/main/java/com/epam/brest/service_api/ModelSpecificationService.java index da5db94..305c0e9 100644 --- a/service-api/src/main/java/com/epam/brest/service_api/ModelSpecificationService.java +++ b/service-api/src/main/java/com/epam/brest/service_api/ModelSpecificationService.java @@ -11,5 +11,5 @@ public interface ModelSpecificationService { * @return ModelSpecification. */ - ModelSpecification getModelSpecificationByCarModel(String carModel); + ModelSpecification getModelSpecificationByCarModel(final String carModel); } diff --git a/service-rest/src/main/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRest.java b/service-rest/src/main/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRest.java index f6d57ab..788009f 100644 --- a/service-rest/src/main/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRest.java +++ b/service-rest/src/main/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRest.java @@ -1,15 +1,17 @@ package com.epam.brest.service_rest.service; +import com.epam.brest.model.Car; import com.epam.brest.model.ModelSpecification; import com.epam.brest.service_api.ModelSpecificationService; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; +import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; +import java.util.List; + @Service public class ModelSpecificationServiceRest implements ModelSpecificationService { @@ -49,14 +51,19 @@ public ModelSpecificationServiceRest(final String url, } @Override - public ModelSpecification getModelSpecificationByCarModel(String carModel) { + public ModelSpecification getModelSpecificationByCarModel(final String carModel) { LOG.info("Method getModelSpecificationByCarModel() with parameter {} started {}", carModel, getClass().getName()); - ParameterizedTypeReference typeReference = - new ParameterizedTypeReference<>() {}; - - ResponseEntity responseEntity = restTemplate - .exchange(url + "/" + carModel, HttpMethod.GET, null, typeReference); +// ParameterizedTypeReference typeReference = +// new ParameterizedTypeReference<>() {}; +// +// ResponseEntity responseEntity = restTemplate +// .exchange(url + "/" + carModel, HttpMethod.GET, null, typeReference); + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(List.of(MediaType.APPLICATION_JSON)); + HttpEntity entity = new HttpEntity<>(carModel, headers); + ResponseEntity responseEntity = restTemplate.exchange( + url + "/" + carModel, HttpMethod.GET, entity, ModelSpecification.class); return responseEntity.getBody(); } } diff --git a/service-rest/src/test/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRestTest.java b/service-rest/src/test/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRestTest.java index a82d0e6..e300b01 100644 --- a/service-rest/src/test/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRestTest.java +++ b/service-rest/src/test/java/com/epam/brest/service_rest/service/ModelSpecificationServiceRestTest.java @@ -63,7 +63,7 @@ void getModelSpecificationByCarModel() throws URISyntaxException, JsonProcessing 1, carModel, "Passenger car: made in Japan", 210, 1740); - mockRestServiceServer.expect(ExpectedCount.once(), requestTo(new URI(MODEL_INFO_URL + "/" + carModel))) + mockRestServiceServer.expect(ExpectedCount.once(), requestTo(new URI(MODEL_INFO_URL + "/" + modelSpecification.getModelName()))) .andExpect(method(HttpMethod.GET)) .andRespond(withStatus(HttpStatus.OK) .contentType(MediaType.APPLICATION_JSON) diff --git a/web-app/src/main/resources/templates/cars/cars.html b/web-app/src/main/resources/templates/cars/cars.html index a2fa283..813d0fa 100644 --- a/web-app/src/main/resources/templates/cars/cars.html +++ b/web-app/src/main/resources/templates/cars/cars.html @@ -66,12 +66,28 @@ Unique number car Model Unique number driver + Edit and delete car - - + + - + + + + + + + + + + + +  Delete @@ -101,6 +117,25 @@

© 2021

+ + +