From e0f29fca4b85014e7f229333c31f9d3477b401b2 Mon Sep 17 00:00:00 2001 From: Ilia_Isakhin Date: Fri, 1 Nov 2019 19:01:04 +0400 Subject: [PATCH 1/7] Added task --- README.md | 75 ++++++++++++++++++- .../core/template/SpringCoreTemplate.java | 7 +- .../spring/core/template/entity/MyEntity.java | 4 + 3 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/epam/edu/spring/core/template/entity/MyEntity.java diff --git a/README.md b/README.md index eb76daf..6cff878 100644 --- a/README.md +++ b/README.md @@ -1 +1,74 @@ -# spring-core-template \ No newline at end of file +# Шаблон для практической работы по теме Spring Core + +### Задание +Вы создаете Спринг-приложение для управления кинотеатром, которое предостовляет следующий функционал: ++ Для пользователей: + + регистрироваться + + просматривать киносеансы + + смотреть наличие билетов + + покупать билеты + ++ Для администраторов: + + то же самое, что и для пользователей + + создавать киносеансы + + просматривать купленные билеты + +Вам необходимо: +1. Реализовать Java/Annotation-based config +1. Использовать имеющиеся классы и создавать новые для реализации функционала +1. Разбить сущности на слои: храните ваши данные в объектах типа Map, которые будут находиться в DAO-классах +1. Создать консольное приложение. В мейне получить бины по типу и вызвать несколько бизнес-методов + +Используйте мавен для подключения зависимостей, и последнюю версию Spring (5.x.x) + +Сервисы должны реализовывать: +1. EventService - управляет киносеансами. Методы + + save + + remove + + getById + + getByName + + getAll + + getForDateRange + + getNextEvents +2. UserService - управляет юзерами. Методы + + save + + remove + + getById + + getUserByEmail + + getAll +3. AuditoriumService - управляет залами и местами в них. Так как информация о кинозалах статическая, храните её в +проперти-файлах и загружайте в приложение. Поля: + + getAll + + getByName +4. BookingService - управляет билетами, ценами и заказами + + getTicketsPrice + + bookTicket + + getPurchasedTicketsForEvent +5. DiscountService - ответственнен за скидки, которые распространяются на билеты + 1. DiscountStrategy - отдельный класс, который задает скидку. Реализуйте DiscountService и его стратегии в отдельной + конфигурации. Существуют: + + Скидка в честь для рождения юзера (5%) + + Скидка "Каждый 10-й билет за полцены" + +Существуют следующие сущности: +1. Event - киносеанс. Поля: + + Название фильма + + Цена билета + + Рейтинг + + Дата начала сеанса + + Продолжительность +1. Auditorium - зал. Поля: + + Кодовое название + + Число мест + + Число вип мест (увеличенная цена в 2 раза) +1. User - пользователь + + Имя + + Фамилия + + Почта + + Дата рождения + + Роль + +> +> Если вы считаете, что в описании задачи не хватет какой-либо информации, вы вольны импровизировать. Допускается добавление +> новых методов, полей, сервисов и сущностей, если вы чувствуете, что это поможет вам в выполнении задачи +> \ No newline at end of file diff --git a/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java b/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java index 7d6ea06..ae56ffb 100644 --- a/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java +++ b/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java @@ -1,14 +1,17 @@ package com.epam.edu.spring.core.template; +import org.springframework.boot.ApplicationArguments; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContext; @SpringBootApplication public class SpringCoreTemplate { public static void main(String[] args) { - SpringApplication.run(SpringCoreTemplate.class, args); - //TODO get service bean and do some business logic with DTO`s + ApplicationContext context = SpringApplication.run(SpringCoreTemplate.class); + + //TODO } } diff --git a/src/main/java/com/epam/edu/spring/core/template/entity/MyEntity.java b/src/main/java/com/epam/edu/spring/core/template/entity/MyEntity.java new file mode 100644 index 0000000..a628848 --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/entity/MyEntity.java @@ -0,0 +1,4 @@ +package com.epam.edu.spring.core.template.entity; + +public class MyEntity { +} From f396a10f47b9aa59eee64832089f13aa6ffb40d6 Mon Sep 17 00:00:00 2001 From: Ilia_Isakhin Date: Wed, 6 Nov 2019 16:17:58 +0400 Subject: [PATCH 2/7] improving task definitions --- README.md | 72 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6cff878..fcd225d 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,58 @@ Вам необходимо: 1. Реализовать Java/Annotation-based config + + Пример Java Config: + ```java + @Configuration + public class MyConfiguration { + + @Bean + public MyService myService(MyRepository myRepository) { + MyService myService = new MyServiceImpl(); + myService.setMyRepostiory(myRepository); + //... + return myService; + } + } + ``` + + Пример Annotation-based config + ```java + @Service + public class MyServiceImpl implements MyService { + + @Autowired + MyRepository myRepository; + } + ``` 1. Использовать имеющиеся классы и создавать новые для реализации функционала 1. Разбить сущности на слои: храните ваши данные в объектах типа Map, которые будут находиться в DAO-классах -1. Создать консольное приложение. В мейне получить бины по типу и вызвать несколько бизнес-методов - -Используйте мавен для подключения зависимостей, и последнюю версию Spring (5.x.x) +1. Создать консольное приложение. В мейне получить бины по типу и вызвать несколько бизнес-методов. Пример: +```java +@SpringBootApplication +public class SpringCoreTemplate { + public static void main(String[] args){ + ApplicationContext context = SpringApplication.run(SpringCoreTemplate.class); + + MyService myService = context.getBean(MyService.class); + myService.getAllEntitys(); + } +} +``` +Что происходит в данном куске кода: +1. Получаем контейнер с бинами, которые существуют в нашем приложении. +1. Получаем бин типа `MyService` из контейнера. Полученный бин **обязан** быть синглтоном. +1. Вызываем у `MyService` метод `getAllEntitys`. Внутри себя данный сервис не должен хранить данные `Entity`, для этого +в нем есть приватное поле типа `MyRepository`. `Dependency Injection` обеспечивает предоставление бина данного типа в наш ++ `MyService`. В результате схема получается следующая: ++ `MyService - валидация параметров` ++ `MyService - вызов репозитория` ++ `MyRepository - вызов действия с объектом хранения (Коллекция) экземпяров ентити` ++ `MyRepository - возврат результата в сервис` ++ `MyService - обработка ентити, выполнение бизнес-логики` ++ `MyService - возврат результата` -Сервисы должны реализовывать: -1. EventService - управляет киносеансами. Методы +Репозитории должны реализовывать: +1. EventRepository - управляет киносеансами. Методы + save + remove + getById @@ -30,21 +74,25 @@ + getAll + getForDateRange + getNextEvents -2. UserService - управляет юзерами. Методы +1. UserRepository - управляет юзерами. Методы + save + remove + getById + getUserByEmail + getAll -3. AuditoriumService - управляет залами и местами в них. Так как информация о кинозалах статическая, храните её в -проперти-файлах и загружайте в приложение. Поля: - + getAll - + getByName -4. BookingService - управляет билетами, ценами и заказами +1. BookingRepository - управляет билетами, ценами и заказами + getTicketsPrice + bookTicket + getPurchasedTicketsForEvent -5. DiscountService - ответственнен за скидки, которые распространяются на билеты + +> **Это важно!** Для каждого репозитория необходимо создать слой сервисов, который будет инкапсулировать валидацию входных +>параметров и совершать нужную нам бизнес-логику. + +1. AuditoriumService - управляет залами и местами в них. Так как информация о кинозалах статическая, храните её в +проперти-файлах и загружайте в приложение. Поля: + + getAll + + getByName +1. DiscountService - ответственнен за скидки, которые распространяются на билеты 1. DiscountStrategy - отдельный класс, который задает скидку. Реализуйте DiscountService и его стратегии в отдельной конфигурации. Существуют: + Скидка в честь для рождения юзера (5%) From 635f345260298cf39d4a7279dc7ecca409c605f2 Mon Sep 17 00:00:00 2001 From: Ilia_Isakhin Date: Tue, 17 Dec 2019 17:17:02 +0400 Subject: [PATCH 3/7] reworked task --- README.md | 135 +++--------------- pom.xml | 34 +---- .../core/template/SpringCoreTemplate.java | 8 -- .../template/annotation/InjectRandomInt.java | 4 + .../bpp/InjectRandomIntBeanPostProcessor.java | 4 + ...ion.java => InitializerConfiguration.java} | 3 +- .../configuration/MainConfiguration.java | 4 + .../RepositoryConfiguration.java | 4 + .../edu/spring/core/template/entity/Item.java | 38 +++++ .../spring/core/template/entity/MyEntity.java | 4 - .../repository/AbstractRepository.java | 20 +++ .../repository/ArrayListItemRepository.java | 28 ++++ .../template/repository/ItemRepository.java | 11 ++ .../repository/LinkedListItemRepository.java | 28 ++++ .../template/repository/MyRepository.java | 5 - .../core/template/service/ItemService.java | 11 ++ .../core/template/service/MyService.java | 5 - .../template/service/SimpleItemService.java | 4 + .../core/template/validation/MyValidator.java | 5 - src/main/resources/application.properties | 2 +- 20 files changed, 181 insertions(+), 176 deletions(-) create mode 100644 src/main/java/com/epam/edu/spring/core/template/annotation/InjectRandomInt.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/bpp/InjectRandomIntBeanPostProcessor.java rename src/main/java/com/epam/edu/spring/core/template/configuration/{MyConfiguration.java => InitializerConfiguration.java} (51%) create mode 100644 src/main/java/com/epam/edu/spring/core/template/configuration/MainConfiguration.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/configuration/RepositoryConfiguration.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/entity/Item.java delete mode 100644 src/main/java/com/epam/edu/spring/core/template/entity/MyEntity.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/repository/AbstractRepository.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/repository/ArrayListItemRepository.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/repository/ItemRepository.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/repository/LinkedListItemRepository.java delete mode 100644 src/main/java/com/epam/edu/spring/core/template/repository/MyRepository.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/service/ItemService.java delete mode 100644 src/main/java/com/epam/edu/spring/core/template/service/MyService.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java delete mode 100644 src/main/java/com/epam/edu/spring/core/template/validation/MyValidator.java diff --git a/README.md b/README.md index fcd225d..1debdd8 100644 --- a/README.md +++ b/README.md @@ -1,122 +1,27 @@ # Шаблон для практической работы по теме Spring Core ### Задание -Вы создаете Спринг-приложение для управления кинотеатром, которое предостовляет следующий функционал: -+ Для пользователей: - + регистрироваться - + просматривать киносеансы - + смотреть наличие билетов - + покупать билеты +1. Добавьте в `pom.xml` зависимость `'org.springframework:spring-context:5.2.1.RELEASE` -+ Для администраторов: - + то же самое, что и для пользователей - + создавать киносеансы - + просматривать купленные билеты +1. Реализуйте `ArrayListItemRepository` и `LinkedListItemRepository`: + * В `ArrayListItemRepository` итемы должны храниться в `ArrayList` и `initialSequence` считываться из пропертей + * В `ArrayListItemRepository` итемы должны храниться в `LinkedList` и `initialSequence` генерироваться случайно -Вам необходимо: -1. Реализовать Java/Annotation-based config - + Пример Java Config: - ```java - @Configuration - public class MyConfiguration { - - @Bean - public MyService myService(MyRepository myRepository) { - MyService myService = new MyServiceImpl(); - myService.setMyRepostiory(myRepository); - //... - return myService; - } - } - ``` - + Пример Annotation-based config - ```java - @Service - public class MyServiceImpl implements MyService { - - @Autowired - MyRepository myRepository; - } - ``` -1. Использовать имеющиеся классы и создавать новые для реализации функционала -1. Разбить сущности на слои: храните ваши данные в объектах типа Map, которые будут находиться в DAO-классах -1. Создать консольное приложение. В мейне получить бины по типу и вызвать несколько бизнес-методов. Пример: -```java -@SpringBootApplication -public class SpringCoreTemplate { - public static void main(String[] args){ - ApplicationContext context = SpringApplication.run(SpringCoreTemplate.class); - - MyService myService = context.getBean(MyService.class); - myService.getAllEntitys(); - } -} -``` -Что происходит в данном куске кода: -1. Получаем контейнер с бинами, которые существуют в нашем приложении. -1. Получаем бин типа `MyService` из контейнера. Полученный бин **обязан** быть синглтоном. -1. Вызываем у `MyService` метод `getAllEntitys`. Внутри себя данный сервис не должен хранить данные `Entity`, для этого -в нем есть приватное поле типа `MyRepository`. `Dependency Injection` обеспечивает предоставление бина данного типа в наш -+ `MyService`. В результате схема получается следующая: -+ `MyService - валидация параметров` -+ `MyService - вызов репозитория` -+ `MyRepository - вызов действия с объектом хранения (Коллекция) экземпяров ентити` -+ `MyRepository - возврат результата в сервис` -+ `MyService - обработка ентити, выполнение бизнес-логики` -+ `MyService - возврат результата` +1. Сделайте так, чтобы используемая реализация `ItemRepository` выбиралась +исходя из проперти `item.repository.implementation` из значений `array` или `linked`. При отсутствии проперти использовать +`ArrayListItemRepository`. -Репозитории должны реализовывать: -1. EventRepository - управляет киносеансами. Методы - + save - + remove - + getById - + getByName - + getAll - + getForDateRange - + getNextEvents -1. UserRepository - управляет юзерами. Методы - + save - + remove - + getById - + getUserByEmail - + getAll -1. BookingRepository - управляет билетами, ценами и заказами - + getTicketsPrice - + bookTicket - + getPurchasedTicketsForEvent - -> **Это важно!** Для каждого репозитория необходимо создать слой сервисов, который будет инкапсулировать валидацию входных ->параметров и совершать нужную нам бизнес-логику. +1. В классе `InitializerRepository` реализуйте заполнение используемой `ItemRepository` тестовыми данными. -1. AuditoriumService - управляет залами и местами в них. Так как информация о кинозалах статическая, храните её в -проперти-файлах и загружайте в приложение. Поля: - + getAll - + getByName -1. DiscountService - ответственнен за скидки, которые распространяются на билеты - 1. DiscountStrategy - отдельный класс, который задает скидку. Реализуйте DiscountService и его стратегии в отдельной - конфигурации. Существуют: - + Скидка в честь для рождения юзера (5%) - + Скидка "Каждый 10-й билет за полцены" - -Существуют следующие сущности: -1. Event - киносеанс. Поля: - + Название фильма - + Цена билета - + Рейтинг - + Дата начала сеанса - + Продолжительность -1. Auditorium - зал. Поля: - + Кодовое название - + Число мест - + Число вип мест (увеличенная цена в 2 раза) -1. User - пользователь - + Имя - + Фамилия - + Почта - + Дата рождения - + Роль - -> -> Если вы считаете, что в описании задачи не хватет какой-либо информации, вы вольны импровизировать. Допускается добавление -> новых методов, полей, сервисов и сущностей, если вы чувствуете, что это поможет вам в выполнении задачи -> \ No newline at end of file +1. В классе `MainConfiguration` сделайте импорт всех конфигурационных файлов и объявите factory-bean для создания бина +`ItemService` + +1. Допишите аннотацию `InjectRandomInt`, добавьте 2 поля `min` и `max` - минимальное и максимальное значение, из которого +будет случайно выбрано число для инжектирования в целевое поле. Сделайте так, чтобы её можно было ставить только над полями. +Предусмотрите возможность считать её во время выполенния программы. + +1. Допишите класс `InjectRandomIntBeanPostProcessor`. Этот класс должен имплементировать интерфейс `BeanPostProcessor`. +Его главная задача - обрабатывать поля с аннотацией `InjectRandomInt`. + +1. В классе `SpringCoreTemplate` в методе `main` создайте экземпляр `ApplicationContext` и передайте ему на вход +`MainConfiguration`. Напишите немного бизнес-логики, чтобы убедиться, что все бины создались и корректно работают \ No newline at end of file diff --git a/pom.xml b/pom.xml index a98d368..541b54d 100644 --- a/pom.xml +++ b/pom.xml @@ -2,42 +2,14 @@ 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.6.RELEASE - - + com.epam.edu spring-core-template 0.0.1-SNAPSHOT - spring-core-template - Demo project for Spring Boot - 1.8 + 1.8 + 1.8 - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - diff --git a/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java b/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java index ae56ffb..ea1a0a1 100644 --- a/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java +++ b/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java @@ -1,17 +1,9 @@ package com.epam.edu.spring.core.template; -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ApplicationContext; - -@SpringBootApplication public class SpringCoreTemplate { public static void main(String[] args) { - ApplicationContext context = SpringApplication.run(SpringCoreTemplate.class); - //TODO } } diff --git a/src/main/java/com/epam/edu/spring/core/template/annotation/InjectRandomInt.java b/src/main/java/com/epam/edu/spring/core/template/annotation/InjectRandomInt.java new file mode 100644 index 0000000..08bf472 --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/annotation/InjectRandomInt.java @@ -0,0 +1,4 @@ +package com.epam.edu.spring.core.template.annotation; + +public @interface InjectRandomInt { +} diff --git a/src/main/java/com/epam/edu/spring/core/template/bpp/InjectRandomIntBeanPostProcessor.java b/src/main/java/com/epam/edu/spring/core/template/bpp/InjectRandomIntBeanPostProcessor.java new file mode 100644 index 0000000..13d4469 --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/bpp/InjectRandomIntBeanPostProcessor.java @@ -0,0 +1,4 @@ +package com.epam.edu.spring.core.template.bpp; + +public class InjectRandomIntBeanPostProcessor { +} diff --git a/src/main/java/com/epam/edu/spring/core/template/configuration/MyConfiguration.java b/src/main/java/com/epam/edu/spring/core/template/configuration/InitializerConfiguration.java similarity index 51% rename from src/main/java/com/epam/edu/spring/core/template/configuration/MyConfiguration.java rename to src/main/java/com/epam/edu/spring/core/template/configuration/InitializerConfiguration.java index 12e5eab..444cc01 100644 --- a/src/main/java/com/epam/edu/spring/core/template/configuration/MyConfiguration.java +++ b/src/main/java/com/epam/edu/spring/core/template/configuration/InitializerConfiguration.java @@ -1,5 +1,4 @@ package com.epam.edu.spring.core.template.configuration; -//TODO add configuration -public class MyConfiguration { +public class InitializerConfiguration { } diff --git a/src/main/java/com/epam/edu/spring/core/template/configuration/MainConfiguration.java b/src/main/java/com/epam/edu/spring/core/template/configuration/MainConfiguration.java new file mode 100644 index 0000000..f1b7446 --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/configuration/MainConfiguration.java @@ -0,0 +1,4 @@ +package com.epam.edu.spring.core.template.configuration; + +public class MainConfiguration { +} diff --git a/src/main/java/com/epam/edu/spring/core/template/configuration/RepositoryConfiguration.java b/src/main/java/com/epam/edu/spring/core/template/configuration/RepositoryConfiguration.java new file mode 100644 index 0000000..40fb52c --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/configuration/RepositoryConfiguration.java @@ -0,0 +1,4 @@ +package com.epam.edu.spring.core.template.configuration; + +public class RepositoryConfiguration { +} diff --git a/src/main/java/com/epam/edu/spring/core/template/entity/Item.java b/src/main/java/com/epam/edu/spring/core/template/entity/Item.java new file mode 100644 index 0000000..ff22cde --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/entity/Item.java @@ -0,0 +1,38 @@ +package com.epam.edu.spring.core.template.entity; + +public class Item { + + private long id; + private String name; + private double price; + + public Item(long id, String name, double price) { + this.id = id; + this.name = name; + this.price = price; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } +} diff --git a/src/main/java/com/epam/edu/spring/core/template/entity/MyEntity.java b/src/main/java/com/epam/edu/spring/core/template/entity/MyEntity.java deleted file mode 100644 index a628848..0000000 --- a/src/main/java/com/epam/edu/spring/core/template/entity/MyEntity.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.epam.edu.spring.core.template.entity; - -public class MyEntity { -} diff --git a/src/main/java/com/epam/edu/spring/core/template/repository/AbstractRepository.java b/src/main/java/com/epam/edu/spring/core/template/repository/AbstractRepository.java new file mode 100644 index 0000000..494e526 --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/repository/AbstractRepository.java @@ -0,0 +1,20 @@ +package com.epam.edu.spring.core.template.repository; + +import java.util.List; + +/** + * Абстрактный класс для хранения сущностей. + * ID сущности генерируется, исходя из initialSequence + * @param + */ +public abstract class AbstractRepository { + + protected long initialSequence = 0; + + protected List holder; + + abstract void setInitialSequence(int val); + + abstract void setHolder(); + +} diff --git a/src/main/java/com/epam/edu/spring/core/template/repository/ArrayListItemRepository.java b/src/main/java/com/epam/edu/spring/core/template/repository/ArrayListItemRepository.java new file mode 100644 index 0000000..edcb085 --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/repository/ArrayListItemRepository.java @@ -0,0 +1,28 @@ +package com.epam.edu.spring.core.template.repository; + +import com.epam.edu.spring.core.template.entity.Item; + +/** + * Репозиторий, основанный на классе ArrayList. + * initialSequence должен браться из application.properties + */ +public class ArrayListItemRepository extends AbstractRepository implements ItemRepository { + + @Override + public Item getById(long id) { + return null; + } + + @Override + public boolean createItem(Item item) { + return false; + } + + void setInitialSequence(int val) { + //TODO + } + + void setHolder() { + //TODO + } +} diff --git a/src/main/java/com/epam/edu/spring/core/template/repository/ItemRepository.java b/src/main/java/com/epam/edu/spring/core/template/repository/ItemRepository.java new file mode 100644 index 0000000..27cf445 --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/repository/ItemRepository.java @@ -0,0 +1,11 @@ +package com.epam.edu.spring.core.template.repository; + +import com.epam.edu.spring.core.template.entity.Item; + +public interface ItemRepository { + + Item getById(long id); + + boolean createItem(Item item); + +} diff --git a/src/main/java/com/epam/edu/spring/core/template/repository/LinkedListItemRepository.java b/src/main/java/com/epam/edu/spring/core/template/repository/LinkedListItemRepository.java new file mode 100644 index 0000000..aa000f8 --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/repository/LinkedListItemRepository.java @@ -0,0 +1,28 @@ +package com.epam.edu.spring.core.template.repository; + +import com.epam.edu.spring.core.template.entity.Item; + +/** + * Репозиторий, основанный на классе LinkedList. + * initialSequence должен случайно генерироваться из диапазона от 1 до 100 + */ +public class LinkedListItemRepository extends AbstractRepository implements ItemRepository { + + @Override + public Item getById(long id) { + return null; + } + + @Override + public boolean createItem(Item item) { + return false; + } + + void setInitialSequence(int val) { + //TODO + } + + void setHolder() { + //TODO + } +} diff --git a/src/main/java/com/epam/edu/spring/core/template/repository/MyRepository.java b/src/main/java/com/epam/edu/spring/core/template/repository/MyRepository.java deleted file mode 100644 index ab9bbaa..0000000 --- a/src/main/java/com/epam/edu/spring/core/template/repository/MyRepository.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.epam.edu.spring.core.template.repository; - -//TODO add logic for CRUD operations -public class MyRepository { -} diff --git a/src/main/java/com/epam/edu/spring/core/template/service/ItemService.java b/src/main/java/com/epam/edu/spring/core/template/service/ItemService.java new file mode 100644 index 0000000..fb664a0 --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/service/ItemService.java @@ -0,0 +1,11 @@ +package com.epam.edu.spring.core.template.service; + +import com.epam.edu.spring.core.template.entity.Item; + +public interface ItemService { + + Item getById(long id); + + boolean createItem(Item item); + +} diff --git a/src/main/java/com/epam/edu/spring/core/template/service/MyService.java b/src/main/java/com/epam/edu/spring/core/template/service/MyService.java deleted file mode 100644 index 4254f76..0000000 --- a/src/main/java/com/epam/edu/spring/core/template/service/MyService.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.epam.edu.spring.core.template.service; - -//TODO add logic for access to business objects -public class MyService { -} diff --git a/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java b/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java new file mode 100644 index 0000000..04d95b8 --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java @@ -0,0 +1,4 @@ +package com.epam.edu.spring.core.template.service; + +public class SimpleItemService implements ItemService { +} diff --git a/src/main/java/com/epam/edu/spring/core/template/validation/MyValidator.java b/src/main/java/com/epam/edu/spring/core/template/validation/MyValidator.java deleted file mode 100644 index 676bb35..0000000 --- a/src/main/java/com/epam/edu/spring/core/template/validation/MyValidator.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.epam.edu.spring.core.template.validation; - -//TODO add logic for validation -public class MyValidator { -} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8b13789..735a8ff 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1 @@ - +initial.sequence=14 From 71633eca335d99ef3fc0b0027c0df4bfd8c1bb73 Mon Sep 17 00:00:00 2001 From: Ilia_Isakhin Date: Tue, 17 Dec 2019 17:30:53 +0400 Subject: [PATCH 4/7] improvements --- README.md | 12 +++++++++--- .../epam/edu/spring/core/template/entity/Item.java | 12 +++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1debdd8..c5e5750 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,16 @@ исходя из проперти `item.repository.implementation` из значений `array` или `linked`. При отсутствии проперти использовать `ArrayListItemRepository`. -1. В классе `InitializerRepository` реализуйте заполнение используемой `ItemRepository` тестовыми данными. +1. В классе `InitializerConfiguration` реализуйте заполнение используемой `ItemRepository` тестовыми данными. -1. В классе `MainConfiguration` сделайте импорт всех конфигурационных файлов и объявите factory-bean для создания бина -`ItemService` +1. В классе `InitializerConfiguration` реализуйте factory-bean `ColorFactory`, который умеет выдавать следующие цвета в +виде списка строк: + * Yellow + * Red + * Black +Данные значения цветов должны быть объявлены в проперти файле под значением `colors.value[0]` + +1. В классе `MainConfiguration` сделайте импорт всех конфигурационных файлов и объявите бин `ItemService` как `Lazy`. 1. Допишите аннотацию `InjectRandomInt`, добавьте 2 поля `min` и `max` - минимальное и максимальное значение, из которого будет случайно выбрано число для инжектирования в целевое поле. Сделайте так, чтобы её можно было ставить только над полями. diff --git a/src/main/java/com/epam/edu/spring/core/template/entity/Item.java b/src/main/java/com/epam/edu/spring/core/template/entity/Item.java index ff22cde..00d6dd3 100644 --- a/src/main/java/com/epam/edu/spring/core/template/entity/Item.java +++ b/src/main/java/com/epam/edu/spring/core/template/entity/Item.java @@ -5,11 +5,13 @@ public class Item { private long id; private String name; private double price; + private String color; - public Item(long id, String name, double price) { + public Item(long id, String name, double price, String color) { this.id = id; this.name = name; this.price = price; + this.color = color; } public long getId() { @@ -35,4 +37,12 @@ public double getPrice() { public void setPrice(double price) { this.price = price; } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } } From 414277bf9d457d7b14306ff490634c8a5a9dc0d3 Mon Sep 17 00:00:00 2001 From: Ilia_Isakhin Date: Thu, 27 Feb 2020 17:08:14 +0400 Subject: [PATCH 5/7] refactored task --- README.md | 45 +++++++++---------- .../template/annotation/InjectRandomInt.java | 4 -- .../bpp/InjectRandomIntBeanPostProcessor.java | 4 -- .../spring/core/template/entity/Color.java | 5 +++ .../edu/spring/core/template/entity/Item.java | 8 ++-- .../template/service/SimpleItemService.java | 16 +++++++ .../template/validator/ItemValidator.java | 8 ++++ .../validator/SimpleItemValidator.java | 11 +++++ src/main/resources/application.properties | 3 +- ...ringEducationSkeletonApplicationTests.java | 16 ------- 10 files changed, 67 insertions(+), 53 deletions(-) delete mode 100644 src/main/java/com/epam/edu/spring/core/template/annotation/InjectRandomInt.java delete mode 100644 src/main/java/com/epam/edu/spring/core/template/bpp/InjectRandomIntBeanPostProcessor.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/entity/Color.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/validator/ItemValidator.java create mode 100644 src/main/java/com/epam/edu/spring/core/template/validator/SimpleItemValidator.java delete mode 100644 src/test/java/com/epam/edu/spring/core/template/SpringEducationSkeletonApplicationTests.java diff --git a/README.md b/README.md index c5e5750..4c489f5 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,30 @@ # Шаблон для практической работы по теме Spring Core ### Задание -1. Добавьте в `pom.xml` зависимость `'org.springframework:spring-context:5.2.1.RELEASE` +1. В `pom.xml` добавьте зависимость `org.springframework:spring-context:5.2.1.RELEASE`. -1. Реализуйте `ArrayListItemRepository` и `LinkedListItemRepository`: - * В `ArrayListItemRepository` итемы должны храниться в `ArrayList` и `initialSequence` считываться из пропертей - * В `ArrayListItemRepository` итемы должны храниться в `LinkedList` и `initialSequence` генерироваться случайно - -1. Сделайте так, чтобы используемая реализация `ItemRepository` выбиралась -исходя из проперти `item.repository.implementation` из значений `array` или `linked`. При отсутствии проперти использовать -`ArrayListItemRepository`. - -1. В классе `InitializerConfiguration` реализуйте заполнение используемой `ItemRepository` тестовыми данными. - -1. В классе `InitializerConfiguration` реализуйте factory-bean `ColorFactory`, который умеет выдавать следующие цвета в -виде списка строк: - * Yellow - * Red - * Black -Данные значения цветов должны быть объявлены в проперти файле под значением `colors.value[0]` +1. В методе main создайте новый экземпляр класса `AnnotationConfigApplicationContext` - контейнер, в котором +будут храниться ваши бины. На вход ему будет передаваться класс `MainConfiguration`. В конфигурации используйте такие +аннотации, как `@Configuration` и `@Bean`. -1. В классе `MainConfiguration` сделайте импорт всех конфигурационных файлов и объявите бин `ItemService` как `Lazy`. +1. В классе `MainConfiguration` сделайте импорт двух других классов-конфигураций: + * В классе `RepositoryConfiguration` сделайте описание бинов `ArrayListItemRepository` и `LinkedListItemRepository` + 1. В `ArrayListItemRepository` объекты `Item` должны храниться в `ArrayList` и `initialSequence` считываться из пропертей. + 1. В `ArrayListItemRepository` объекты `Item` должны храниться в `LinkedList` и `initialSequence` генерироваться случайно. + * В классе `InitializerConfiguration` реализуйте factory-bean `ColorFactory`, который умеет выдавать сущности + бинов `Color` по запросу `getColor`. Бин `Color` обязан создаваться каждый раз заново. -1. Допишите аннотацию `InjectRandomInt`, добавьте 2 поля `min` и `max` - минимальное и максимальное значение, из которого -будет случайно выбрано число для инжектирования в целевое поле. Сделайте так, чтобы её можно было ставить только над полями. -Предусмотрите возможность считать её во время выполенния программы. +1. Имплементируйте `SimpleItemService` - сделайте так, чтобы необходимые зависимости добавлялись к нему через метод `set..` +и конструктор. В чём разница этих подходов? -1. Допишите класс `InjectRandomIntBeanPostProcessor`. Этот класс должен имплементировать интерфейс `BeanPostProcessor`. -Его главная задача - обрабатывать поля с аннотацией `InjectRandomInt`. +1. Сделайте так, чтобы бин `ColorFactory` создавался не на этапе создания контекста, а при первом обращении к нему. + +1. Сделайте так, чтобы используемая реализация `ItemRepository` выбиралась исходя из проперти `item.repository.implementation` +из значений `array` или `linked`. При отсутствии проперти необходимо использовать `ArrayListItemRepository`. 1. В классе `SpringCoreTemplate` в методе `main` создайте экземпляр `ApplicationContext` и передайте ему на вход -`MainConfiguration`. Напишите немного бизнес-логики, чтобы убедиться, что все бины создались и корректно работают \ No newline at end of file +созданный экземпляр `AnnotationConfigApplicationContext`. Сделайте парочку вызовов метода `getBean`, чтобы убедиться, +что все бины создались и корректно работают. + +1. Подключите зависимость `org.springframework:spring-test:jar:5.2.1.RELEASE`. Напишите тесты, которые проверяют основную +бизнес-логику и то, что ваш контекст загружается успешно. diff --git a/src/main/java/com/epam/edu/spring/core/template/annotation/InjectRandomInt.java b/src/main/java/com/epam/edu/spring/core/template/annotation/InjectRandomInt.java deleted file mode 100644 index 08bf472..0000000 --- a/src/main/java/com/epam/edu/spring/core/template/annotation/InjectRandomInt.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.epam.edu.spring.core.template.annotation; - -public @interface InjectRandomInt { -} diff --git a/src/main/java/com/epam/edu/spring/core/template/bpp/InjectRandomIntBeanPostProcessor.java b/src/main/java/com/epam/edu/spring/core/template/bpp/InjectRandomIntBeanPostProcessor.java deleted file mode 100644 index 13d4469..0000000 --- a/src/main/java/com/epam/edu/spring/core/template/bpp/InjectRandomIntBeanPostProcessor.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.epam.edu.spring.core.template.bpp; - -public class InjectRandomIntBeanPostProcessor { -} diff --git a/src/main/java/com/epam/edu/spring/core/template/entity/Color.java b/src/main/java/com/epam/edu/spring/core/template/entity/Color.java new file mode 100644 index 0000000..f5fe91d --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/entity/Color.java @@ -0,0 +1,5 @@ +package com.epam.edu.spring.core.template.entity; + +public enum Color { + +} diff --git a/src/main/java/com/epam/edu/spring/core/template/entity/Item.java b/src/main/java/com/epam/edu/spring/core/template/entity/Item.java index 00d6dd3..d07b653 100644 --- a/src/main/java/com/epam/edu/spring/core/template/entity/Item.java +++ b/src/main/java/com/epam/edu/spring/core/template/entity/Item.java @@ -5,9 +5,9 @@ public class Item { private long id; private String name; private double price; - private String color; + private Color color; - public Item(long id, String name, double price, String color) { + public Item(long id, String name, double price, Color color) { this.id = id; this.name = name; this.price = price; @@ -38,11 +38,11 @@ public void setPrice(double price) { this.price = price; } - public String getColor() { + public Color getColor() { return color; } - public void setColor(String color) { + public void setColor(Color color) { this.color = color; } } diff --git a/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java b/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java index 04d95b8..cb83f39 100644 --- a/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java +++ b/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java @@ -1,4 +1,20 @@ package com.epam.edu.spring.core.template.service; +import com.epam.edu.spring.core.template.entity.Item; +import com.epam.edu.spring.core.template.validator.ItemValidator; + public class SimpleItemService implements ItemService { + + private ItemService itemService; + private ItemValidator itemValidator; + + @Override + public Item getById(long id) { + return null; + } + + @Override + public boolean createItem(Item item) { + return false; + } } diff --git a/src/main/java/com/epam/edu/spring/core/template/validator/ItemValidator.java b/src/main/java/com/epam/edu/spring/core/template/validator/ItemValidator.java new file mode 100644 index 0000000..b7c887f --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/validator/ItemValidator.java @@ -0,0 +1,8 @@ +package com.epam.edu.spring.core.template.validator; + +import com.epam.edu.spring.core.template.entity.Item; + +public interface ItemValidator { + + boolean isItemValid(Item item); +} diff --git a/src/main/java/com/epam/edu/spring/core/template/validator/SimpleItemValidator.java b/src/main/java/com/epam/edu/spring/core/template/validator/SimpleItemValidator.java new file mode 100644 index 0000000..003600b --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/validator/SimpleItemValidator.java @@ -0,0 +1,11 @@ +package com.epam.edu.spring.core.template.validator; + +import com.epam.edu.spring.core.template.entity.Item; + +public class SimpleItemValidator implements ItemValidator { + + @Override + public boolean isItemValid(Item item) { + return false; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 735a8ff..69c2e92 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,2 @@ -initial.sequence=14 +initial.sequence=42 +item.repository.implementation= \ No newline at end of file diff --git a/src/test/java/com/epam/edu/spring/core/template/SpringEducationSkeletonApplicationTests.java b/src/test/java/com/epam/edu/spring/core/template/SpringEducationSkeletonApplicationTests.java deleted file mode 100644 index 128e270..0000000 --- a/src/test/java/com/epam/edu/spring/core/template/SpringEducationSkeletonApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.epam.edu.spring.core.template; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class SpringEducationSkeletonApplicationTests { - - @Test - public void contextLoads() { - } - -} From c382ec4d5dd0f41f4af2f530d67968e137ff38c7 Mon Sep 17 00:00:00 2001 From: ilia_isakhin Date: Tue, 14 Jul 2020 22:41:46 +0400 Subject: [PATCH 6/7] fixed wrong field --- .../edu/spring/core/template/service/SimpleItemService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java b/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java index cb83f39..802d512 100644 --- a/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java +++ b/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java @@ -1,11 +1,12 @@ package com.epam.edu.spring.core.template.service; import com.epam.edu.spring.core.template.entity.Item; +import com.epam.edu.spring.core.template.repository.ItemRepository; import com.epam.edu.spring.core.template.validator.ItemValidator; public class SimpleItemService implements ItemService { - private ItemService itemService; + private ItemRepository itemRepository; private ItemValidator itemValidator; @Override From 04f2d475ed9ecb9f406f192ca7b1ddc2656d6db9 Mon Sep 17 00:00:00 2001 From: EvVlF Date: Wed, 23 Aug 2023 19:18:34 +0400 Subject: [PATCH 7/7] Spring core with tests --- pom.xml | 101 +++++++++++++++-- .../core/template/SpringCoreTemplate.java | 11 +- .../InitializerConfiguration.java | 16 +++ .../configuration/MainConfiguration.java | 10 +- .../RepositoryConfiguration.java | 22 ++++ .../spring/core/template/entity/Color.java | 5 +- .../edu/spring/core/template/entity/Item.java | 102 ++++++++++-------- .../template/factory/ColorFactoryBean.java | 32 ++++++ .../repository/AbstractRepository.java | 13 ++- .../repository/ArrayListItemRepository.java | 54 +++++++--- .../template/repository/ItemRepository.java | 5 +- .../repository/LinkedListItemRepository.java | 51 ++++++--- .../core/template/service/ItemService.java | 5 +- .../template/service/SimpleItemService.java | 38 +++++-- .../template/validator/ItemValidator.java | 2 +- .../validator/SimpleItemValidator.java | 10 +- src/main/resources/application.properties | 2 +- .../core/template/SpringCoreTemplateTest.java | 93 ++++++++++++++++ 18 files changed, 451 insertions(+), 121 deletions(-) create mode 100644 src/main/java/com/epam/edu/spring/core/template/factory/ColorFactoryBean.java create mode 100644 src/test/java/com/epam/edu/spring/core/template/SpringCoreTemplateTest.java diff --git a/pom.xml b/pom.xml index 541b54d..bd8e1e8 100644 --- a/pom.xml +++ b/pom.xml @@ -1,15 +1,94 @@ - - 4.0.0 + + 4.0.0 - com.epam.edu - spring-core-template - 0.0.1-SNAPSHOT + com.EvDroid + spring-core-template + 1.0-SNAPSHOT - - 1.8 - 1.8 - + + 8 + 8 + + 5.3.29 + 5.3.29 + + 5.10.0 + 1.10.0 + + 3.1.2 + + 3.1.2 + - + + + org.springframework + spring-context + ${spring-context.version} + + + org.springframework + spring-test + ${spring-test-version} + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.junit.platform + junit-platform-launcher + ${junit-platform-launcher.version} + test + + + + + + org.junit + junit-bom + ${junit-bom.version} + pom + import + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + true + + + junit.platform.output.capture.stdout=true + junit.platform.output.capture.stderr=true + junit.platform.output.capture.maxBuffer=8192 + + + + + + + + + + org.apache.maven.plugins + maven-surefire-report-plugin + ${maven-surefire-report-plugin.version} + + + + \ No newline at end of file diff --git a/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java b/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java index ea1a0a1..c64bf01 100644 --- a/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java +++ b/src/main/java/com/epam/edu/spring/core/template/SpringCoreTemplate.java @@ -1,9 +1,12 @@ package com.epam.edu.spring.core.template; -public class SpringCoreTemplate { - - public static void main(String[] args) { +import com.epam.edu.spring.core.template.configuration.MainConfiguration; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; - } +public class SpringCoreTemplate { + public static void main(String[] args) { + ApplicationContext context = new AnnotationConfigApplicationContext(MainConfiguration.class); + } } diff --git a/src/main/java/com/epam/edu/spring/core/template/configuration/InitializerConfiguration.java b/src/main/java/com/epam/edu/spring/core/template/configuration/InitializerConfiguration.java index 444cc01..4eb25f5 100644 --- a/src/main/java/com/epam/edu/spring/core/template/configuration/InitializerConfiguration.java +++ b/src/main/java/com/epam/edu/spring/core/template/configuration/InitializerConfiguration.java @@ -1,4 +1,20 @@ package com.epam.edu.spring.core.template.configuration; +import com.epam.edu.spring.core.template.factory.ColorFactoryBean; +import com.epam.edu.spring.core.template.entity.Color; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Scope; + +@Configuration public class InitializerConfiguration { + + @Bean + @Lazy + @Scope(BeanDefinition.SCOPE_PROTOTYPE) + public Color colorBean(ColorFactoryBean colorFactoryBean) { + return colorFactoryBean.getObject(); + } } diff --git a/src/main/java/com/epam/edu/spring/core/template/configuration/MainConfiguration.java b/src/main/java/com/epam/edu/spring/core/template/configuration/MainConfiguration.java index f1b7446..9547c75 100644 --- a/src/main/java/com/epam/edu/spring/core/template/configuration/MainConfiguration.java +++ b/src/main/java/com/epam/edu/spring/core/template/configuration/MainConfiguration.java @@ -1,4 +1,10 @@ package com.epam.edu.spring.core.template.configuration; -public class MainConfiguration { -} +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@ComponentScan(basePackages = {"com.epam.edu.spring.core.template"}) +@Import({RepositoryConfiguration.class, InitializerConfiguration.class}) +public class MainConfiguration {} diff --git a/src/main/java/com/epam/edu/spring/core/template/configuration/RepositoryConfiguration.java b/src/main/java/com/epam/edu/spring/core/template/configuration/RepositoryConfiguration.java index 40fb52c..1ab6e5e 100644 --- a/src/main/java/com/epam/edu/spring/core/template/configuration/RepositoryConfiguration.java +++ b/src/main/java/com/epam/edu/spring/core/template/configuration/RepositoryConfiguration.java @@ -1,4 +1,26 @@ package com.epam.edu.spring.core.template.configuration; +import com.epam.edu.spring.core.template.repository.ArrayListItemRepository; +import com.epam.edu.spring.core.template.repository.ItemRepository; +import com.epam.edu.spring.core.template.repository.LinkedListItemRepository; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +@Configuration +@PropertySource("classpath:application.properties") public class RepositoryConfiguration { + + @Bean + public ItemRepository itemRepository( + @Value("${item.repository.implementation}") String repository) { + ItemRepository itemRepository; + if ("link".equalsIgnoreCase(repository)) { + itemRepository = new LinkedListItemRepository(); + } else { + itemRepository = new ArrayListItemRepository(); + } + return itemRepository; + } } diff --git a/src/main/java/com/epam/edu/spring/core/template/entity/Color.java b/src/main/java/com/epam/edu/spring/core/template/entity/Color.java index f5fe91d..6d73f7e 100644 --- a/src/main/java/com/epam/edu/spring/core/template/entity/Color.java +++ b/src/main/java/com/epam/edu/spring/core/template/entity/Color.java @@ -1,5 +1,8 @@ package com.epam.edu.spring.core.template.entity; public enum Color { - + THIS_COLOR, + THAT_COLOR, + SOME_COLOR, + MORE_COLOR } diff --git a/src/main/java/com/epam/edu/spring/core/template/entity/Item.java b/src/main/java/com/epam/edu/spring/core/template/entity/Item.java index d07b653..79f2fe7 100644 --- a/src/main/java/com/epam/edu/spring/core/template/entity/Item.java +++ b/src/main/java/com/epam/edu/spring/core/template/entity/Item.java @@ -1,48 +1,62 @@ package com.epam.edu.spring.core.template.entity; public class Item { - - private long id; - private String name; - private double price; - private Color color; - - public Item(long id, String name, double price, Color color) { - this.id = id; - this.name = name; - this.price = price; - this.color = color; - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public double getPrice() { - return price; - } - - public void setPrice(double price) { - this.price = price; - } - - public Color getColor() { - return color; - } - - public void setColor(Color color) { - this.color = color; - } + private long id; + private String name; + private double price; + private Color color; + + public Item(long id, String name, double price, Color color) { + this.id = id; + this.name = name; + this.price = price; + this.color = color; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + public Color getColor() { + return color; + } + + public void setColor(Color color) { + this.color = color; + } + + @Override + public String toString() { + return "Item{" + + "id=" + + id + + ", name='" + + name + + '\'' + + ", price=" + + price + + ", color=" + + color + + '}'; + } } diff --git a/src/main/java/com/epam/edu/spring/core/template/factory/ColorFactoryBean.java b/src/main/java/com/epam/edu/spring/core/template/factory/ColorFactoryBean.java new file mode 100644 index 0000000..012b1af --- /dev/null +++ b/src/main/java/com/epam/edu/spring/core/template/factory/ColorFactoryBean.java @@ -0,0 +1,32 @@ +package com.epam.edu.spring.core.template.factory; + +import com.epam.edu.spring.core.template.entity.Color; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.stereotype.Component; + +import java.util.Random; +import java.util.stream.Stream; + +@Component +public class ColorFactoryBean implements FactoryBean { + + private final Random random = new Random(); + + @Override + public Color getObject() { + return Stream.of(Color.values()) + .filter(color -> color.ordinal() == random.nextInt(Color.values().length)) + .findAny() + .orElseThrow(IllegalStateException::new); + } + + @Override + public Class getObjectType() { + return Color.class; + } + + @Override + public boolean isSingleton() { + return FactoryBean.super.isSingleton(); + } +} diff --git a/src/main/java/com/epam/edu/spring/core/template/repository/AbstractRepository.java b/src/main/java/com/epam/edu/spring/core/template/repository/AbstractRepository.java index 494e526..48e06e2 100644 --- a/src/main/java/com/epam/edu/spring/core/template/repository/AbstractRepository.java +++ b/src/main/java/com/epam/edu/spring/core/template/repository/AbstractRepository.java @@ -3,18 +3,17 @@ import java.util.List; /** - * Абстрактный класс для хранения сущностей. - * ID сущности генерируется, исходя из initialSequence + * Абстрактный класс для хранения сущностей. ID сущности генерируется, исходя из initialSequence + * * @param */ public abstract class AbstractRepository { - protected long initialSequence = 0; + protected long initialSequence = 0; - protected List holder; + protected List holder; - abstract void setInitialSequence(int val); - - abstract void setHolder(); + abstract void setInitialSequence(int val); + abstract void setHolder(); } diff --git a/src/main/java/com/epam/edu/spring/core/template/repository/ArrayListItemRepository.java b/src/main/java/com/epam/edu/spring/core/template/repository/ArrayListItemRepository.java index edcb085..0a50fc5 100644 --- a/src/main/java/com/epam/edu/spring/core/template/repository/ArrayListItemRepository.java +++ b/src/main/java/com/epam/edu/spring/core/template/repository/ArrayListItemRepository.java @@ -1,28 +1,52 @@ package com.epam.edu.spring.core.template.repository; import com.epam.edu.spring.core.template.entity.Item; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.stream.Collectors; /** - * Репозиторий, основанный на классе ArrayList. - * initialSequence должен браться из application.properties + * Репозиторий, основанный на классе ArrayList. initialSequence должен браться из + * application.properties */ +@Component +@PropertySource("classpath:application.properties") public class ArrayListItemRepository extends AbstractRepository implements ItemRepository { - @Override - public Item getById(long id) { - return null; - } + private ArrayList holder; - @Override - public boolean createItem(Item item) { - return false; - } + @Value("${initial.sequence}") + int initialSequence; - void setInitialSequence(int val) { - //TODO + @Override + public Item getById(long id) { + if (holder.stream().filter(item -> item.getId() == id).count() > 1) { + throw new IllegalStateException("More than 1 element found"); } + return holder.stream().filter(item -> item.getId() == id).collect(Collectors.toList()).get(0); + } - void setHolder() { - //TODO - } + @Override + public boolean createItem(Item item) { + item.setId(initialSequence); + return holder.add(Objects.requireNonNull(item)); + } + + @Override + void setInitialSequence(int val) { + this.initialSequence += val; + } + + public int getInitialSequence() { + return this.initialSequence; + } + + @Override + void setHolder() { + this.holder = new ArrayList<>(); + } } diff --git a/src/main/java/com/epam/edu/spring/core/template/repository/ItemRepository.java b/src/main/java/com/epam/edu/spring/core/template/repository/ItemRepository.java index 27cf445..a8e4437 100644 --- a/src/main/java/com/epam/edu/spring/core/template/repository/ItemRepository.java +++ b/src/main/java/com/epam/edu/spring/core/template/repository/ItemRepository.java @@ -4,8 +4,7 @@ public interface ItemRepository { - Item getById(long id); - - boolean createItem(Item item); + Item getById(long id); + boolean createItem(Item item); } diff --git a/src/main/java/com/epam/edu/spring/core/template/repository/LinkedListItemRepository.java b/src/main/java/com/epam/edu/spring/core/template/repository/LinkedListItemRepository.java index aa000f8..0eb8b73 100644 --- a/src/main/java/com/epam/edu/spring/core/template/repository/LinkedListItemRepository.java +++ b/src/main/java/com/epam/edu/spring/core/template/repository/LinkedListItemRepository.java @@ -1,28 +1,49 @@ package com.epam.edu.spring.core.template.repository; import com.epam.edu.spring.core.template.entity.Item; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.LinkedList; +import java.util.Objects; +import java.util.stream.Collectors; /** - * Репозиторий, основанный на классе LinkedList. - * initialSequence должен случайно генерироваться из диапазона от 1 до 100 + * Репозиторий, основанный на классе LinkedList. initialSequence должен случайно генерироваться из + * диапазона от 1 до 100 */ +@Component public class LinkedListItemRepository extends AbstractRepository implements ItemRepository { - @Override - public Item getById(long id) { - return null; - } + private LinkedList holder; - @Override - public boolean createItem(Item item) { - return false; - } + @Value("#{T(java.lang.Math).random() * 100.0 }") + int initialSequence; - void setInitialSequence(int val) { - //TODO + @Override + public Item getById(long id) { + if (holder.stream().filter(item -> item.getId() == id).count() > 1) { + throw new IllegalStateException("More than 1 element found"); } + return holder.stream().filter(item -> item.getId() == id).collect(Collectors.toList()).get(0); + } - void setHolder() { - //TODO - } + @Override + public boolean createItem(Item item) { + return holder.add(Objects.requireNonNull(item)); + } + + @Override + void setInitialSequence(int val) { + this.initialSequence += val; + } + + public int getInitialSequence() { + return this.initialSequence; + } + + @Override + void setHolder() { + this.holder = new LinkedList<>(); + } } diff --git a/src/main/java/com/epam/edu/spring/core/template/service/ItemService.java b/src/main/java/com/epam/edu/spring/core/template/service/ItemService.java index fb664a0..7c5af6d 100644 --- a/src/main/java/com/epam/edu/spring/core/template/service/ItemService.java +++ b/src/main/java/com/epam/edu/spring/core/template/service/ItemService.java @@ -4,8 +4,7 @@ public interface ItemService { - Item getById(long id); - - boolean createItem(Item item); + Item getById(long id); + boolean createItem(Item item); } diff --git a/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java b/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java index 802d512..24438e0 100644 --- a/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java +++ b/src/main/java/com/epam/edu/spring/core/template/service/SimpleItemService.java @@ -3,19 +3,37 @@ import com.epam.edu.spring.core.template.entity.Item; import com.epam.edu.spring.core.template.repository.ItemRepository; import com.epam.edu.spring.core.template.validator.ItemValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +@Service public class SimpleItemService implements ItemService { - private ItemRepository itemRepository; - private ItemValidator itemValidator; + private ItemRepository itemRepository; + private ItemValidator itemValidator; - @Override - public Item getById(long id) { - return null; - } + @Autowired + public SimpleItemService(ItemRepository itemRepository, ItemValidator itemValidator) { + this.itemRepository = itemRepository; + this.itemValidator = itemValidator; + } + + @Override + public Item getById(long id) { + return null; + } + + @Override + public boolean createItem(Item item) { + return false; + } + + public void setItemRepository(ItemRepository itemRepository) { + this.itemRepository = itemRepository; + } + + public void setItemRepository(ItemValidator itemValidator) { + this.itemValidator = itemValidator; + } - @Override - public boolean createItem(Item item) { - return false; - } } diff --git a/src/main/java/com/epam/edu/spring/core/template/validator/ItemValidator.java b/src/main/java/com/epam/edu/spring/core/template/validator/ItemValidator.java index b7c887f..55cda3e 100644 --- a/src/main/java/com/epam/edu/spring/core/template/validator/ItemValidator.java +++ b/src/main/java/com/epam/edu/spring/core/template/validator/ItemValidator.java @@ -4,5 +4,5 @@ public interface ItemValidator { - boolean isItemValid(Item item); + boolean isItemValid(Item item); } diff --git a/src/main/java/com/epam/edu/spring/core/template/validator/SimpleItemValidator.java b/src/main/java/com/epam/edu/spring/core/template/validator/SimpleItemValidator.java index 003600b..4f08ebe 100644 --- a/src/main/java/com/epam/edu/spring/core/template/validator/SimpleItemValidator.java +++ b/src/main/java/com/epam/edu/spring/core/template/validator/SimpleItemValidator.java @@ -1,11 +1,13 @@ package com.epam.edu.spring.core.template.validator; import com.epam.edu.spring.core.template.entity.Item; +import org.springframework.stereotype.Component; +@Component public class SimpleItemValidator implements ItemValidator { - @Override - public boolean isItemValid(Item item) { - return false; - } + @Override + public boolean isItemValid(Item item) { + return item != null && item.getId() >= 0 && item.getName() != null && item.getPrice() > 0; + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 69c2e92..27d53ac 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,2 +1,2 @@ initial.sequence=42 -item.repository.implementation= \ No newline at end of file +item.repository.implementation=link \ No newline at end of file diff --git a/src/test/java/com/epam/edu/spring/core/template/SpringCoreTemplateTest.java b/src/test/java/com/epam/edu/spring/core/template/SpringCoreTemplateTest.java new file mode 100644 index 0000000..fdb5d72 --- /dev/null +++ b/src/test/java/com/epam/edu/spring/core/template/SpringCoreTemplateTest.java @@ -0,0 +1,93 @@ +package com.epam.edu.spring.core.template; + +import com.epam.edu.spring.core.template.configuration.MainConfiguration; +import com.epam.edu.spring.core.template.entity.Color; +import com.epam.edu.spring.core.template.repository.ArrayListItemRepository; +import com.epam.edu.spring.core.template.repository.LinkedListItemRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.util.ClassUtils; + +import java.util.Arrays; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringJUnitConfig(classes = {MainConfiguration.class}) +@DisplayName("Spring beans tests") +class SpringCoreTemplateTest { + + @Autowired + private final ApplicationContext context = + new AnnotationConfigApplicationContext(MainConfiguration.class); + + @DisplayName("Test beans exists") + @ParameterizedTest + @MethodSource("getBeansWithClasses") + void testCorrectBeansInstance(String beanName, String clazz) { + assertTrue(isCorrectBean(context.getBean(beanName), clazz)); + } + + @Test + @DisplayName("Test array list initial sequence value") + void testInitialSequenceArrayList(@Value("${initial.sequence}") int propertyValue) { + ArrayListItemRepository arrayListItemRepository = + context.getBean("arrayListItemRepository", ArrayListItemRepository.class); + assertEquals(propertyValue, arrayListItemRepository.getInitialSequence()); + } + + @Test + @DisplayName("Test linked list initial sequence value") + void testRandomInitialSequenceLinkedList() { + LinkedListItemRepository linkedListItemRepository = + context.getBean("linkedListItemRepository", LinkedListItemRepository.class); + int initialSequence = linkedListItemRepository.getInitialSequence(); + assertTrue(initialSequence >= 0 && initialSequence < 100); + } + + @Test + @DisplayName("Test Color Bean") + void testColorFactoryBean() { + Color color = context.getBean("colorFactoryBean", Color.class); + boolean colorCheck = false; + colorCheck = Arrays.stream(Color.values()).anyMatch(Predicate.isEqual(color)); + assertTrue(colorCheck); + } + + @Test + @DisplayName("Test item repository type") + void testItemRepositoryType( + @Value("${item.repository.implementation=link}") String itemRepositoryProperty) { + Object itemRepository = context.getBean("itemRepository"); + if ("link".equalsIgnoreCase(itemRepositoryProperty)) { + assertTrue(isCorrectBean(itemRepository, "LinkedListItemRepository")); + } else { + assertTrue(isCorrectBean(itemRepository, "ArrayListItemRepository")); + } + } + + private boolean isCorrectBean(Object bean, String clazz) { + return Objects.nonNull(bean) && ClassUtils.getUserClass(bean).getSimpleName().equals(clazz); + } + + private static Stream getBeansWithClasses() { + return Stream.of( + Arguments.of("mainConfiguration", "MainConfiguration"), + Arguments.of("initializerConfiguration", "InitializerConfiguration"), + Arguments.of("repositoryConfiguration", "RepositoryConfiguration"), + Arguments.of("arrayListItemRepository", "ArrayListItemRepository"), + Arguments.of("linkedListItemRepository", "LinkedListItemRepository"), + Arguments.of("simpleItemService", "SimpleItemService"), + Arguments.of("simpleItemValidator", "SimpleItemValidator")); + } +}